'admin-21.01.24:完成各布局导航处理、动画细节等'
This commit is contained in:
parent
a09bcf8e60
commit
94dd0f7439
@ -1,5 +1,5 @@
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"
|
||||
import { store } from "/@/store/index.ts";
|
||||
import { store } from "/@/store/index.ts"
|
||||
|
||||
// 定义动态路由
|
||||
export const dynamicRoutes = [
|
||||
@ -280,7 +280,8 @@ export const dynamicRoutes = [
|
||||
{
|
||||
path: '/fun',
|
||||
name: 'funIndex',
|
||||
component: () => import('/@/views/fun/index.vue'),
|
||||
component: () => import('/@/views/layout/routerView/parent.vue'),
|
||||
redirect: '/fun/tagsView',
|
||||
meta: {
|
||||
title: '功能',
|
||||
isLink: '',
|
||||
@ -288,7 +289,22 @@ export const dynamicRoutes = [
|
||||
isKeepAlive: true,
|
||||
isAffix: false,
|
||||
icon: 'iconfont icon-crew_feature'
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '/fun/tagsView',
|
||||
name: 'funTagsView',
|
||||
component: () => import('/@/views/fun/tagsView/index.vue'),
|
||||
meta: {
|
||||
title: 'tagsView 操作',
|
||||
isLink: '',
|
||||
isHide: false,
|
||||
isKeepAlive: true,
|
||||
isAffix: false,
|
||||
icon: 'el-icon-thumb'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/pages',
|
||||
|
@ -51,7 +51,6 @@ body,
|
||||
width: 100%;
|
||||
}
|
||||
.layout-el-aside-br-color {
|
||||
border-top: 1px solid rgb(238, 238, 238);
|
||||
border-right: 1px solid rgb(238, 238, 238);
|
||||
}
|
||||
.layout-aside-width-default {
|
||||
@ -78,6 +77,9 @@ body,
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
.layout-hide {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* element plus 全局样式
|
||||
|
@ -692,6 +692,10 @@
|
||||
|
||||
/* NavMenu 导航菜单
|
||||
------------------------------- */
|
||||
// 去掉默认 focus 时,背景的高亮
|
||||
.el-menu-item:focus {
|
||||
background: transparent !important;
|
||||
}
|
||||
// 默认样式修改
|
||||
.el-menu {
|
||||
border-right: none !important;
|
||||
@ -706,6 +710,7 @@
|
||||
// horizontal 水平方向时
|
||||
.el-menu--horizontal > .el-menu-item.is-active,
|
||||
.el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
|
||||
border-bottom: 3px solid !important;
|
||||
border-bottom-color: set-color(primary);
|
||||
color: set-color(primary);
|
||||
}
|
||||
@ -786,6 +791,10 @@
|
||||
width: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
// element plus 本身字体图标
|
||||
.el-submenu [class^='el-icon-'] {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
/* Tabs 标签页
|
||||
------------------------------- */
|
||||
|
@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
funIndex
|
||||
<el-input v-model="val"></el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive } from "vue";
|
||||
export default {
|
||||
name: "funIndex",
|
||||
setup() {
|
||||
const state = reactive({
|
||||
val: "",
|
||||
});
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
110
vue-admin-wonderful-next/src/views/fun/tagsView/index.vue
Normal file
110
vue-admin-wonderful-next/src/views/fun/tagsView/index.vue
Normal file
@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<el-card shadow="hover" header="tagsView 功能演示">
|
||||
<el-form :inline="true" :model="formInline" size="small" label-width="60px" style="margin-bottom:1px;">
|
||||
<el-form-item label="功能:">
|
||||
<el-select v-model="formInline.selectId" placeholder="请选择">
|
||||
<el-option v-for="item in selectOptions" :key="item.value" :label="item.label" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="路径:">
|
||||
<el-input v-model="formInline.path" placeholder="路径如:/fun/tagsView" style="max-width:203px;"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onImplementClick">点击执行</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-divider></el-divider>
|
||||
<el-button type="primary" size="small" icon="el-icon-refresh-right" @click="refreshCurrentTagsView">刷新当前页
|
||||
</el-button>
|
||||
<el-button type="info" size="small" icon="el-icon-close" @click="closeCurrentTagsView">关闭当前页</el-button>
|
||||
<el-button type="warning" size="small" icon="el-icon-circle-close" @click="closeOtherTagsView">关闭其它</el-button>
|
||||
<el-button type="danger" size="small" icon="el-icon-folder-delete" @click="closeAllTagsView">全部关闭</el-button>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { getCurrentInstance, reactive, toRefs } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
export default {
|
||||
name: "funTagsView",
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance();
|
||||
const route = useRoute();
|
||||
const state = reactive({
|
||||
formInline: {
|
||||
path: "",
|
||||
selectId: 0,
|
||||
},
|
||||
selectOptions: [
|
||||
{
|
||||
value: 0,
|
||||
label: "刷新当前",
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
label: "关闭当前",
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: "关闭其它",
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
label: "关闭全部",
|
||||
},
|
||||
],
|
||||
});
|
||||
// 0 刷新当前,1 关闭当前,2 关闭其它,3 关闭全部
|
||||
// 1、刷新当前 tagsView
|
||||
const refreshCurrentTagsView = () => {
|
||||
proxy.mittBus.emit("onCurrentContextmenuClick", {
|
||||
id: 0,
|
||||
path: route.path,
|
||||
});
|
||||
};
|
||||
// 2、关闭当前 tagsView
|
||||
const closeCurrentTagsView = () => {
|
||||
proxy.mittBus.emit("onCurrentContextmenuClick", {
|
||||
id: 1,
|
||||
path: route.path,
|
||||
});
|
||||
};
|
||||
// 3、关闭其它 tagsView
|
||||
const closeOtherTagsView = () => {
|
||||
proxy.mittBus.emit("onCurrentContextmenuClick", {
|
||||
id: 2,
|
||||
path: route.path,
|
||||
});
|
||||
};
|
||||
// 4、关闭全部 tagsView
|
||||
const closeAllTagsView = () => {
|
||||
proxy.mittBus.emit("onCurrentContextmenuClick", {
|
||||
id: 3,
|
||||
path: route.path,
|
||||
});
|
||||
};
|
||||
// 执行点击
|
||||
const onImplementClick = () => {
|
||||
proxy.mittBus.emit("onCurrentContextmenuClick", {
|
||||
id: state.formInline.selectId,
|
||||
path: state.formInline.path,
|
||||
});
|
||||
};
|
||||
return {
|
||||
refreshCurrentTagsView,
|
||||
closeCurrentTagsView,
|
||||
closeOtherTagsView,
|
||||
closeAllTagsView,
|
||||
onImplementClick,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-form-item {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
</style>
|
@ -2,7 +2,7 @@
|
||||
<el-aside :class="setCollapseWidth">
|
||||
<Logo v-if="setShowLogo" />
|
||||
<el-scrollbar class="flex-auto" ref="layoutAsideScrollbarRef">
|
||||
<Vertical :menuList="menuList" />
|
||||
<Vertical :menuList="menuList" :class="setCollapseWidth" />
|
||||
</el-scrollbar>
|
||||
</el-aside>
|
||||
</template>
|
||||
@ -16,6 +16,7 @@ import {
|
||||
getCurrentInstance,
|
||||
ref,
|
||||
onBeforeMount,
|
||||
onUnmounted,
|
||||
} from "vue";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
import { dynamicRoutes } from "/@/router/index.ts";
|
||||
@ -32,6 +33,7 @@ export default {
|
||||
});
|
||||
// 设置/过滤路由(非静态路由/是否显示在菜单中)
|
||||
const setFilterRoutes = () => {
|
||||
if (store.state.themeConfig.layout === "columns") return false;
|
||||
store.dispatch("setRoutes", dynamicRoutes[0].children);
|
||||
state.menuList = filterRoutesFun(store.state.routes);
|
||||
};
|
||||
@ -86,9 +88,26 @@ export default {
|
||||
proxy.$refs.layoutAsideScrollbarRef.update();
|
||||
}
|
||||
});
|
||||
// 初始化
|
||||
// 页面加载前
|
||||
onBeforeMount(() => {
|
||||
setFilterRoutes();
|
||||
proxy.mittBus.on("setSendColumnsChildren", (res) => {
|
||||
state.menuList = res.children;
|
||||
});
|
||||
proxy.mittBus.on("setSendClassicChildren", (res) => {
|
||||
let { layout, isClassicSplitMenu } = store.state.themeConfig;
|
||||
if (layout === "classic" && isClassicSplitMenu)
|
||||
state.menuList = res.children;
|
||||
});
|
||||
proxy.mittBus.on("getBreadcrumbIndexSetFilterRoutes", () => {
|
||||
setFilterRoutes();
|
||||
});
|
||||
});
|
||||
// 页面卸载时
|
||||
onUnmounted(() => {
|
||||
proxy.mittBus.off("setSendColumnsChildren");
|
||||
proxy.mittBus.off("setSendClassicChildren");
|
||||
proxy.mittBus.off("getBreadcrumbIndexSetFilterRoutes");
|
||||
});
|
||||
return {
|
||||
setCollapseWidth,
|
||||
|
@ -2,20 +2,21 @@
|
||||
<div class="layout-columns-aside">
|
||||
<el-scrollbar>
|
||||
<ul>
|
||||
<li v-for="(v,k) in columnsAsideList" :key="k" @click="onColumnsAsideDown(v,k)"
|
||||
:ref="el => { if (el) columnsAsideOffsetTopRefs[k] = el }" :class="{'layout-columns-active':liIndex === k} ">
|
||||
<li v-for="(v,k) in columnsAsideList" :key="k" @click="onColumnsAsideMenuClick(v,k)"
|
||||
:ref="el => { if (el) columnsAsideOffsetTopRefs[k] = el }" :class="{'layout-columns-active':liIndex === k}"
|
||||
:title="v.meta.title">
|
||||
<div class="layout-columns-aside-li-box">
|
||||
<template v-if="!v.meta.isLink">
|
||||
<i :class="v.meta.icon"></i>
|
||||
<div class="layout-columns-aside-li-box-title">
|
||||
{{v.meta.title}}
|
||||
{{v.meta.title && v.meta.title.length >= 2 ? v.meta.title.substr(0,2) : v.meta.title}}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a :href="v.meta.isLink" target="_blank">
|
||||
<i :class="v.meta.icon"></i>
|
||||
<div class="layout-columns-aside-li-box-title">
|
||||
{{v.meta.title}}
|
||||
{{v.meta.title && v.meta.title.length >= 2 ? v.meta.title.substr(0,2) : v.meta.title}}
|
||||
</div>
|
||||
</a>
|
||||
</template>
|
||||
@ -28,46 +29,29 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { reactive, toRefs, ref, computed } from "vue";
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
computed,
|
||||
onMounted,
|
||||
nextTick,
|
||||
getCurrentInstance,
|
||||
} from "vue";
|
||||
import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
import { dynamicRoutes } from "/@/router/index.ts";
|
||||
export default {
|
||||
name: "layoutColumnsAside",
|
||||
setup() {
|
||||
const columnsAsideOffsetTopRefs = ref([]);
|
||||
const columnsAsideActiveRef = ref();
|
||||
const { proxy } = getCurrentInstance();
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
columnsAsideList: [
|
||||
{
|
||||
path: "/home",
|
||||
meta: {
|
||||
title: "首页",
|
||||
icon: "el-icon-medal-1",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/home",
|
||||
meta: {
|
||||
title: "小米",
|
||||
icon: "el-icon-trophy",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/home",
|
||||
meta: {
|
||||
title: "谷歌",
|
||||
icon: "el-icon-basketball",
|
||||
isLink: "https://www.ele.me",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/home",
|
||||
meta: {
|
||||
title: "苹果",
|
||||
icon: "el-icon-coffee-cup",
|
||||
},
|
||||
},
|
||||
],
|
||||
columnsAsideList: [],
|
||||
liIndex: 0,
|
||||
difference: 0,
|
||||
});
|
||||
@ -82,18 +66,72 @@ export default {
|
||||
else if (columnsAsideStyle === "columnsCard")
|
||||
return "layout-columns-card-active";
|
||||
});
|
||||
// 设置高亮动态位置
|
||||
const onColumnsAsideDown = (v: Object, k: number) => {
|
||||
// 设置菜单高亮位置移动
|
||||
const setColumnsAsideMove = (v: Object, k: number) => {
|
||||
state.liIndex = k;
|
||||
columnsAsideActiveRef.value.style.top = `${
|
||||
columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference
|
||||
}px`;
|
||||
};
|
||||
// 菜单高亮点击事件
|
||||
const onColumnsAsideMenuClick = (v: Object, k: number) => {
|
||||
setColumnsAsideMove(v, k);
|
||||
let { path, redirect } = v;
|
||||
if (redirect) router.push(redirect);
|
||||
else router.push(path);
|
||||
};
|
||||
// 设置高亮动态位置
|
||||
const onColumnsAsideDown = (v: Object, k: number) => {
|
||||
nextTick(() => {
|
||||
setColumnsAsideMove(v, k);
|
||||
});
|
||||
};
|
||||
// 设置/过滤路由(非静态路由/是否显示在菜单中)
|
||||
const setFilterRoutes = () => {
|
||||
store.dispatch("setRoutes", dynamicRoutes[0].children);
|
||||
state.columnsAsideList = filterRoutesFun(store.state.routes);
|
||||
const resData = setSendChildren(route.path);
|
||||
onColumnsAsideDown(resData.item[0], resData.item[0].k);
|
||||
proxy.mittBus.emit("setSendColumnsChildren", resData);
|
||||
};
|
||||
// 传送当前子级数据到菜单中
|
||||
const setSendChildren = (path: string) => {
|
||||
const currentPathSplit = path.split("/");
|
||||
let currentData: object = {};
|
||||
state.columnsAsideList.map((v, k) => {
|
||||
if (v.path === `/${currentPathSplit[1]}`) {
|
||||
v["k"] = k;
|
||||
currentData["item"] = [{ ...v }];
|
||||
currentData["children"] = [{ ...v }];
|
||||
if (v.children) currentData["children"] = v.children;
|
||||
}
|
||||
});
|
||||
return currentData;
|
||||
};
|
||||
// 路由过滤递归函数
|
||||
const filterRoutesFun = (arr: Array<object>) => {
|
||||
return arr
|
||||
.filter((item) => !item.meta.isHide)
|
||||
.map((item) => {
|
||||
item = Object.assign({}, item);
|
||||
if (item.children) item.children = filterRoutesFun(item.children);
|
||||
return item;
|
||||
});
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
setFilterRoutes();
|
||||
});
|
||||
// 路由更新时
|
||||
onBeforeRouteUpdate((to) => {
|
||||
proxy.mittBus.emit("setSendColumnsChildren", setSendChildren(to.path));
|
||||
});
|
||||
return {
|
||||
columnsAsideOffsetTopRefs,
|
||||
columnsAsideActiveRef,
|
||||
onColumnsAsideDown,
|
||||
setColumnsAsideStyle,
|
||||
onColumnsAsideMenuClick,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
@ -118,6 +156,9 @@ export default {
|
||||
z-index: 1;
|
||||
.layout-columns-aside-li-box {
|
||||
margin: auto;
|
||||
.layout-columns-aside-li-box-title {
|
||||
padding-top: 1px;
|
||||
}
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
@ -37,7 +37,7 @@ export default {
|
||||
<style scoped lang="scss">
|
||||
.layout-logo {
|
||||
width: 220px;
|
||||
height: 49px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -20,13 +20,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
toRefs,
|
||||
reactive,
|
||||
onBeforeMount,
|
||||
computed,
|
||||
getCurrentInstance,
|
||||
} from "vue";
|
||||
import { toRefs, reactive, computed, getCurrentInstance, onMounted } from "vue";
|
||||
import { onBeforeRouteUpdate, useRoute, useRouter } from "vue-router";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
export default {
|
||||
@ -37,28 +31,55 @@ export default {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
breadcrumbList: [{ meta: { title: "", icon: "" } }], // 定义初始值,不能为空数组,否则 v-for 报错
|
||||
breadcrumbList: [],
|
||||
routeSplit: [],
|
||||
routeSplitFirst: "",
|
||||
routeSplitIndex: 1,
|
||||
});
|
||||
const getBreadcrumbList = (matched: any) => {
|
||||
state.breadcrumbList = matched;
|
||||
};
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return store.state.themeConfig;
|
||||
});
|
||||
// 面包屑点击时
|
||||
const onBreadcrumbClick = (v: object) => {
|
||||
const { redirect, path } = v;
|
||||
if (redirect) router.push(redirect);
|
||||
else router.push(path);
|
||||
};
|
||||
// 展开/收起左侧菜单点击
|
||||
const onThemeConfigChange = () => {
|
||||
proxy.mittBus.emit("onMenuClick");
|
||||
store.state.themeConfig.isCollapse = !store.state.themeConfig.isCollapse;
|
||||
};
|
||||
const getThemeConfig = computed(() => {
|
||||
return store.state.themeConfig;
|
||||
});
|
||||
onBeforeMount(() => {
|
||||
state.breadcrumbList = route.matched;
|
||||
// 处理面包屑数据
|
||||
const getBreadcrumbList = (arr: Array<object>) => {
|
||||
arr.map((item) => {
|
||||
state.routeSplit.map((v, k, arrs) => {
|
||||
if (state.routeSplitFirst === item.path) {
|
||||
state.routeSplitFirst += `/${arrs[state.routeSplitIndex]}`;
|
||||
state.breadcrumbList.push(item);
|
||||
state.routeSplitIndex++;
|
||||
if (item.children) getBreadcrumbList(item.children);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
// 当前路由字符串切割成数组,并删除第一项空内容
|
||||
const initRouteSplit = (path: string) => {
|
||||
state.breadcrumbList = [store.state.routes[0]];
|
||||
state.routeSplit = path.split("/");
|
||||
state.routeSplit.shift();
|
||||
state.routeSplitFirst = `/${state.routeSplit[0]}`;
|
||||
state.routeSplitIndex = 1;
|
||||
getBreadcrumbList(store.state.routes);
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initRouteSplit(route.path);
|
||||
});
|
||||
// 路由更新时
|
||||
onBeforeRouteUpdate((to) => {
|
||||
getBreadcrumbList(to.matched);
|
||||
initRouteSplit(to.path);
|
||||
});
|
||||
return {
|
||||
onThemeConfigChange,
|
||||
|
@ -8,8 +8,17 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, reactive, toRefs } from "vue";
|
||||
import {
|
||||
computed,
|
||||
reactive,
|
||||
toRefs,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
getCurrentInstance,
|
||||
} from "vue";
|
||||
import { useRoute, onBeforeRouteUpdate } from "vue-router";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
import { dynamicRoutes } from "/@/router/index.ts";
|
||||
import Breadcrumb from "/@/views/layout/navBars/breadcrumb/breadcrumb.vue";
|
||||
import User from "/@/views/layout/navBars/breadcrumb/user.vue";
|
||||
import Logo from "/@/views/layout/logo/index.vue";
|
||||
@ -18,59 +27,17 @@ export default {
|
||||
name: "layoutBreadcrumbIndex",
|
||||
components: { Breadcrumb, User, Logo, Horizontal },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance();
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const state = reactive({
|
||||
menuList: [
|
||||
{
|
||||
path: "/home",
|
||||
meta: {
|
||||
title: "首页",
|
||||
icon: "el-icon-s-home",
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/home",
|
||||
meta: {
|
||||
title: "微软",
|
||||
icon: "el-icon-s-flag",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/docs",
|
||||
meta: {
|
||||
title: "文档",
|
||||
icon: "el-icon-s-flag",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/docs1",
|
||||
meta: {
|
||||
title: "文档1",
|
||||
icon: "el-icon-s-flag",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/docs2",
|
||||
meta: {
|
||||
title: "文档2",
|
||||
icon: "el-icon-s-management",
|
||||
isLink: "https://www.ele.me",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/docs3",
|
||||
meta: {
|
||||
title: "文档3",
|
||||
icon: "el-icon-s-management",
|
||||
},
|
||||
},
|
||||
],
|
||||
menuList: [],
|
||||
});
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return store.state.themeConfig;
|
||||
});
|
||||
// 设置 logo 显示/隐藏
|
||||
const setIsShowLogo = computed(() => {
|
||||
let { isShowLogo, layout } = store.state.themeConfig;
|
||||
return (
|
||||
@ -78,12 +45,76 @@ export default {
|
||||
(isShowLogo && layout === "transverse")
|
||||
);
|
||||
});
|
||||
// 设置是否显示横向导航菜单
|
||||
const isLayoutTransverse = computed(() => {
|
||||
let { layout, isClassicSplitMenu } = store.state.themeConfig;
|
||||
return (
|
||||
layout === "transverse" || (isClassicSplitMenu && layout === "classic")
|
||||
);
|
||||
});
|
||||
// 设置/过滤路由(非静态路由/是否显示在菜单中)
|
||||
const setFilterRoutes = () => {
|
||||
let { layout, isClassicSplitMenu } = store.state.themeConfig;
|
||||
store.dispatch("setRoutes", dynamicRoutes[0].children);
|
||||
if (layout === "classic" && isClassicSplitMenu) {
|
||||
state.menuList = delClassicChildren(
|
||||
filterRoutesFun(store.state.routes)
|
||||
);
|
||||
const resData = setSendClassicChildren(route.path);
|
||||
proxy.mittBus.emit("setSendClassicChildren", resData);
|
||||
} else {
|
||||
state.menuList = filterRoutesFun(store.state.routes);
|
||||
}
|
||||
};
|
||||
// 设置了分割菜单时,删除底下 children
|
||||
const delClassicChildren = (arr: Array<object>) => {
|
||||
arr.map((v) => {
|
||||
if (v.children) delete v.children;
|
||||
});
|
||||
return arr;
|
||||
};
|
||||
// 路由过滤递归函数
|
||||
const filterRoutesFun = (arr: Array<object>) => {
|
||||
return arr
|
||||
.filter((item) => !item.meta.isHide)
|
||||
.map((item) => {
|
||||
item = Object.assign({}, item);
|
||||
if (item.children) item.children = filterRoutesFun(item.children);
|
||||
return item;
|
||||
});
|
||||
};
|
||||
// 传送当前子级数据到菜单中
|
||||
const setSendClassicChildren = (path: string) => {
|
||||
const currentPathSplit = path.split("/");
|
||||
let currentData: object = {};
|
||||
filterRoutesFun(store.state.routes).map((v, k) => {
|
||||
if (v.path === `/${currentPathSplit[1]}`) {
|
||||
v["k"] = k;
|
||||
currentData["item"] = [{ ...v }];
|
||||
currentData["children"] = [{ ...v }];
|
||||
if (v.children) currentData["children"] = v.children;
|
||||
}
|
||||
});
|
||||
return currentData;
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
setFilterRoutes();
|
||||
proxy.mittBus.on("getBreadcrumbIndexSetFilterRoutes", () => {
|
||||
setFilterRoutes();
|
||||
});
|
||||
});
|
||||
// 页面卸载时
|
||||
onUnmounted(() => {
|
||||
proxy.mittBus.off("getBreadcrumbIndexSetFilterRoutes");
|
||||
});
|
||||
// 路由更新时
|
||||
onBeforeRouteUpdate((to) => {
|
||||
proxy.mittBus.emit(
|
||||
"setSendClassicChildren",
|
||||
setSendClassicChildren(to.path)
|
||||
);
|
||||
});
|
||||
return {
|
||||
getThemeConfig,
|
||||
setIsShowLogo,
|
||||
@ -102,5 +133,6 @@ export default {
|
||||
padding-right: 15px;
|
||||
background: var(--bg-topBar);
|
||||
overflow: hidden;
|
||||
border-bottom: 1px solid rgb(238, 238, 238);
|
||||
}
|
||||
</style>
|
@ -40,6 +40,8 @@
|
||||
</el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 菜单 / 顶栏 -->
|
||||
<el-divider content-position="left">菜单 / 顶栏</el-divider>
|
||||
<div class="layout-breadcrumb-seting-bar-flex">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏背景</div>
|
||||
@ -158,10 +160,12 @@
|
||||
<el-switch v-model="getThemeConfig.isShowLogo" @change="onIsShowLogoChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15"
|
||||
:style="{opacity:getThemeConfig.layout === 'transverse' ? 0.5 : 1}">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">面包屑 Breadcrumb</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isBreadcrumb" @change="onIsBreadcrumbChange"></el-switch>
|
||||
<el-switch v-model="getThemeConfig.isBreadcrumb" :disabled="getThemeConfig.layout === 'transverse'"
|
||||
@change="onIsBreadcrumbChange"></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
@ -183,7 +187,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启缓存 TagsView</div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 TagsView 缓存 </div>
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-switch v-model="getThemeConfig.isCacheTagsView" @change="setLocalThemeConfig"></el-switch>
|
||||
</div>
|
||||
@ -432,6 +436,7 @@ export default defineComponent({
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
let els = document.querySelector(".el-menu-item.is-active");
|
||||
if (!els) return false;
|
||||
let attr = "el-menu-item is-active";
|
||||
if (getThemeConfig.value.isMenuBarColorHighlight)
|
||||
els.setAttribute("class", `${attr} add-is-active`);
|
||||
@ -458,6 +463,7 @@ export default defineComponent({
|
||||
const onClassicSplitMenuChange = () => {
|
||||
getThemeConfig.value.isBreadcrumb = false;
|
||||
setLocalThemeConfig();
|
||||
proxy.mittBus.emit("getBreadcrumbIndexSetFilterRoutes");
|
||||
};
|
||||
// 4、界面显示 --> 侧边栏 Logo
|
||||
const onIsShowLogoChange = () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="layout-navbars-breadcrumb-user">
|
||||
<div class="layout-navbars-breadcrumb-user" :style="setFlexAutoStyle">
|
||||
<div class="layout-navbars-breadcrumb-user-icon">
|
||||
<i class="el-icon-search" title="菜单搜索"></i>
|
||||
</div>
|
||||
@ -29,16 +29,27 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, getCurrentInstance } from "vue";
|
||||
import { ref, getCurrentInstance, computed } from "vue";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
export default {
|
||||
name: "layoutBreadcrumbUser",
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance();
|
||||
const store = useStore();
|
||||
const onLayoutSetingClick = () => {
|
||||
proxy.mittBus.emit("openSetingsDrawer");
|
||||
};
|
||||
const setFlexAutoStyle = computed(() => {
|
||||
if (
|
||||
!store.state.themeConfig.isBreadcrumb &&
|
||||
store.state.themeConfig.layout !== "transverse" &&
|
||||
!store.state.themeConfig.isClassicSplitMenu
|
||||
)
|
||||
return { flex: 1 };
|
||||
});
|
||||
return {
|
||||
onLayoutSetingClick,
|
||||
setFlexAutoStyle,
|
||||
};
|
||||
},
|
||||
};
|
||||
@ -48,7 +59,6 @@ export default {
|
||||
.layout-navbars-breadcrumb-user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
&-link {
|
||||
height: 100%;
|
||||
|
@ -5,7 +5,8 @@
|
||||
v-show="isShow">
|
||||
<ul class="el-dropdown-menu">
|
||||
<template v-for="(v,k) in dropdownList" :key="k">
|
||||
<li class="el-dropdown-menu__item" aria-disabled="false" tabindex="-1" v-if="!v.affix">
|
||||
<li class="el-dropdown-menu__item" aria-disabled="false" tabindex="-1" v-if="!v.affix"
|
||||
@click="onCurrentContextmenuClick(v.id)">
|
||||
<i :class="v.icon"></i>
|
||||
<span>{{v.txt}}</span>
|
||||
</li>
|
||||
@ -32,7 +33,7 @@ export default defineComponent({
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
setup(props, { emit }) {
|
||||
const state = reactive({
|
||||
isShow: false,
|
||||
dropdownList: [
|
||||
@ -41,14 +42,20 @@ export default defineComponent({
|
||||
{ id: 2, txt: "关闭其它", affix: false, icon: "el-icon-circle-close" },
|
||||
{ id: 3, txt: "全部关闭", affix: false, icon: "el-icon-folder-delete" },
|
||||
],
|
||||
path: {},
|
||||
});
|
||||
// 父级传过来的坐标 x,y 值
|
||||
const dropdown = computed(() => {
|
||||
return props.dropdown;
|
||||
});
|
||||
// 当前项菜单点击
|
||||
const onCurrentContextmenuClick = (id: number) => {
|
||||
emit("currentContextmenuClick", { id, path: state.path });
|
||||
};
|
||||
// 打开右键菜单:判断是否固定,固定则不显示关闭按钮
|
||||
const openContextmenu = (meta: object) => {
|
||||
meta.isAffix
|
||||
const openContextmenu = (item: object) => {
|
||||
state.path = item.path;
|
||||
item.meta.isAffix
|
||||
? (state.dropdownList[1].affix = true)
|
||||
: (state.dropdownList[1].affix = false);
|
||||
closeContextmenu();
|
||||
@ -72,6 +79,7 @@ export default defineComponent({
|
||||
dropdown,
|
||||
openContextmenu,
|
||||
closeContextmenu,
|
||||
onCurrentContextmenuClick,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
|
@ -59,10 +59,14 @@ export default {
|
||||
}
|
||||
}
|
||||
};
|
||||
const updateScrollbar = () => {
|
||||
proxy.$refs.elScrollbarRef.update();
|
||||
};
|
||||
return {
|
||||
setScrollLeft,
|
||||
onHandleScroll,
|
||||
moveToTarget,
|
||||
updateScrollbar,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
|
@ -3,7 +3,7 @@
|
||||
v-show="getThemeConfig.isTagsview">
|
||||
<Scroll ref="scrollRef">
|
||||
<ul class="layout-navbars-tagsview-ul" :class="setTagsStyle">
|
||||
<li v-for="(v,k) in tagsViewList" :key="k" class="layout-navbars-tagsview-ul-li"
|
||||
<li v-for="(v,k) in tagsViewList" :key="k" class="layout-navbars-tagsview-ul-li" :data-name="v.name"
|
||||
:class="{'is-active':isActive(v.path)}" @contextmenu.prevent="onContextmenu(v,$event)"
|
||||
@click="onTagsClick(v,k)" :ref="el => { if (el) tagsRefs[k] = el }">
|
||||
<i class="iconfont icon-webicon318 layout-navbars-tagsview-ul-li-iconfont font14" v-if="isActive(v.path)"></i>
|
||||
@ -11,15 +11,17 @@
|
||||
v-if="!isActive(v.path) && getThemeConfig.isTagsviewIcon"></i>
|
||||
<span>{{v.meta.title}}</span>
|
||||
<template v-if="isActive(v.path)">
|
||||
<i class="el-icon-refresh-right ml5"></i>
|
||||
<i class="el-icon-close layout-navbars-tagsview-ul-li-icon layout-icon-active" v-if="!v.meta.isAffix"></i>
|
||||
<i class="el-icon-refresh-right ml5" @click="refreshCurrentTagsView(v.path)"></i>
|
||||
<i class="el-icon-close layout-navbars-tagsview-ul-li-icon layout-icon-active" v-if="!v.meta.isAffix"
|
||||
@click="closeCurrentTagsView(v.path)"></i>
|
||||
</template>
|
||||
<i class="el-icon-close layout-navbars-tagsview-ul-li-icon layout-icon-three" v-if="!v.meta.isAffix"></i>
|
||||
<i class="el-icon-close layout-navbars-tagsview-ul-li-icon layout-icon-three" v-if="!v.meta.isAffix"
|
||||
@click="closeCurrentTagsView(v.path)"></i>
|
||||
</li>
|
||||
</ul>
|
||||
</Scroll>
|
||||
</div>
|
||||
<Contextmenu :dropdown="dropdown" ref="contextmenuRef" />
|
||||
<Contextmenu :dropdown="dropdown" ref="contextmenuRef" @currentContextmenuClick="onCurrentContextmenuClick" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@ -31,6 +33,9 @@ import {
|
||||
ref,
|
||||
nextTick,
|
||||
onBeforeUpdate,
|
||||
onBeforeMount,
|
||||
onUnmounted,
|
||||
getCurrentInstance,
|
||||
} from "vue";
|
||||
import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
@ -42,6 +47,7 @@ export default {
|
||||
name: "layoutTagsView",
|
||||
components: { Contextmenu, Scroll },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance();
|
||||
const tagsRefs = ref([]);
|
||||
const scrollRef = ref();
|
||||
const contextmenuRef = ref();
|
||||
@ -71,8 +77,8 @@ export default {
|
||||
return store.state.themeConfig;
|
||||
});
|
||||
// 存储 tagsViewList 到浏览器临时缓存中,页面刷新时,保留记录
|
||||
const addBrowserSetSession = () => {
|
||||
setSession("tagsViewList", state.tagsViewList);
|
||||
const addBrowserSetSession = (tagsViewList: Array<object>) => {
|
||||
setSession("tagsViewList", tagsViewList);
|
||||
};
|
||||
// vuex 中获取路由信息:如果是设置了固定的(isAffix),进行初始化显示
|
||||
const initTagsView = () => {
|
||||
@ -93,12 +99,71 @@ export default {
|
||||
getTagsRefsIndex(route.path);
|
||||
moveToCurrentTag();
|
||||
};
|
||||
// 添加 tagsView:未设置隐藏(isHide)也添加到在 tagsView 中
|
||||
// 1、添加 tagsView:未设置隐藏(isHide)也添加到在 tagsView 中
|
||||
const addTagsView = (path: string) => {
|
||||
if (state.tagsViewList.some((v) => v.path === path)) return false;
|
||||
const item = store.state.tagsViewRoutes.find((v) => v.path === path);
|
||||
if (!item.meta.isHide) state.tagsViewList.push({ ...item });
|
||||
addBrowserSetSession();
|
||||
addBrowserSetSession(state.tagsViewList);
|
||||
};
|
||||
// 2、刷新当前 tagsView:
|
||||
const refreshCurrentTagsView = (path: string) => {
|
||||
proxy.mittBus.emit("onTagsViewRefreshRouterView", path);
|
||||
};
|
||||
// 3、关闭当前 tagsView:如果是设置了固定的(isAffix),不可以关闭
|
||||
const closeCurrentTagsView = (path: string) => {
|
||||
state.tagsViewList.map((v, k, arr) => {
|
||||
if (!v.meta.isAffix) {
|
||||
if (v.path === path) {
|
||||
state.tagsViewList.splice(k, 1);
|
||||
setTimeout(() => {
|
||||
router.push(arr[arr.length - 1].path);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
addBrowserSetSession(state.tagsViewList);
|
||||
};
|
||||
// 4、关闭其它 tagsView:如果是设置了固定的(isAffix),不进行关闭
|
||||
const closeOtherTagsView = (path: string) => {
|
||||
state.tagsViewList = [];
|
||||
store.state.tagsViewRoutes.map((v) => {
|
||||
if (v.meta.isAffix && !v.meta.isHide) state.tagsViewList.push({ ...v });
|
||||
});
|
||||
addTagsView(path);
|
||||
};
|
||||
// 5、关闭全部 tagsView:如果是设置了固定的(isAffix),不进行关闭
|
||||
const closeAllTagsView = (path: string) => {
|
||||
state.tagsViewList = [];
|
||||
store.state.tagsViewRoutes.map((v) => {
|
||||
if (v.meta.isAffix && !v.meta.isHide) {
|
||||
state.tagsViewList.push({ ...v });
|
||||
if (state.tagsViewList.some((v) => v.path === path))
|
||||
router.push(path);
|
||||
else router.push(v.path);
|
||||
}
|
||||
});
|
||||
addBrowserSetSession(state.tagsViewList);
|
||||
};
|
||||
// 当前项右键菜单点击
|
||||
const onCurrentContextmenuClick = (data: object) => {
|
||||
let { id, path } = data;
|
||||
switch (id) {
|
||||
case 0:
|
||||
refreshCurrentTagsView(path);
|
||||
router.push(path);
|
||||
break;
|
||||
case 1:
|
||||
closeCurrentTagsView(path);
|
||||
break;
|
||||
case 2:
|
||||
router.push(path);
|
||||
closeOtherTagsView(path);
|
||||
break;
|
||||
case 3:
|
||||
closeAllTagsView(path);
|
||||
break;
|
||||
}
|
||||
};
|
||||
// 判断页面高亮
|
||||
const isActive = (path: string) => {
|
||||
@ -109,7 +174,7 @@ export default {
|
||||
const { clientX, clientY } = e;
|
||||
state.dropdown.x = clientX;
|
||||
state.dropdown.y = clientY;
|
||||
contextmenuRef.value.openContextmenu(v.meta);
|
||||
contextmenuRef.value.openContextmenu(v);
|
||||
};
|
||||
// 当前的 tagsView 项点击时
|
||||
const onTagsClick = (v: object, k: number) => {
|
||||
@ -120,21 +185,49 @@ export default {
|
||||
const moveToCurrentTag = () => {
|
||||
nextTick(() => {
|
||||
scrollRef.value.moveToTarget(tagsRefs.value[state.tagsRefsIndex]);
|
||||
scrollRef.value.updateScrollbar();
|
||||
});
|
||||
};
|
||||
// 获取 tagsView 的下标:用于处理 tagsView 点击时的横向滚动
|
||||
const getTagsRefsIndex = (path: string) => {
|
||||
if (state.tagsViewList.length > 0) {
|
||||
state.tagsRefsIndex = state.tagsViewList.findIndex(
|
||||
const tagsRefsFindIndex = state.tagsViewList.findIndex(
|
||||
(item) => item.path === path
|
||||
);
|
||||
if (tagsRefsFindIndex <= 0) return false;
|
||||
state.tagsRefsIndex = tagsRefsFindIndex;
|
||||
}
|
||||
};
|
||||
// 设置 tagsView 可以进行拖拽
|
||||
const initSortable = () => {
|
||||
const el = document.querySelector(".layout-navbars-tagsview-ul");
|
||||
const sortable = Sortable.create(el, { animation: 300 });
|
||||
if (!el) return false;
|
||||
const sortable = Sortable.create(el, {
|
||||
animation: 300,
|
||||
dataIdAttr: "data-name",
|
||||
onEnd: () => {
|
||||
const sortEndList = [];
|
||||
sortable.toArray().map((val) => {
|
||||
state.tagsViewList.map((v) => {
|
||||
if (v.name === val) sortEndList.push({ ...v });
|
||||
});
|
||||
});
|
||||
addBrowserSetSession(sortEndList);
|
||||
},
|
||||
});
|
||||
};
|
||||
// 数据加载前
|
||||
onBeforeMount(() => {
|
||||
// 监听非本页面调用 0 刷新当前,1 关闭当前,2 关闭其它,3 关闭全部
|
||||
proxy.mittBus.on("onCurrentContextmenuClick", (data: object) => {
|
||||
onCurrentContextmenuClick(data);
|
||||
});
|
||||
});
|
||||
// 页面卸载时
|
||||
onUnmounted(() => {
|
||||
// 取消非本页面调用监听
|
||||
proxy.mittBus.off("onCurrentContextmenuClick");
|
||||
});
|
||||
// 数据更新时
|
||||
onBeforeUpdate(() => {
|
||||
tagsRefs.value = [];
|
||||
@ -160,6 +253,9 @@ export default {
|
||||
scrollRef,
|
||||
getThemeConfig,
|
||||
setTagsStyle,
|
||||
refreshCurrentTagsView,
|
||||
closeCurrentTagsView,
|
||||
onCurrentContextmenuClick,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
@ -170,7 +266,6 @@ export default {
|
||||
.layout-navbars-tagsview {
|
||||
flex: 1;
|
||||
background-color: #ffffff;
|
||||
border-top: 1px solid rgb(238, 238, 238);
|
||||
&-ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
|
@ -1,20 +1,24 @@
|
||||
<template>
|
||||
<el-menu router :default-active="defaultActive" background-color="transparent" mode="horizontal">
|
||||
<template v-for="val in menuList">
|
||||
<el-submenu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
|
||||
<template #title>
|
||||
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
|
||||
<span>{{ val.meta.title }}</span>
|
||||
<div class="el-menu-horizontal-warp">
|
||||
<el-scrollbar @wheel.native.prevent="onElMenuHorizontalScroll" ref="elMenuHorizontalScrollRef">
|
||||
<el-menu router :default-active="defaultActive" background-color="transparent" mode="horizontal">
|
||||
<template v-for="val in menuList">
|
||||
<el-submenu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
|
||||
<template #title>
|
||||
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
|
||||
<span>{{ val.meta.title }}</span>
|
||||
</template>
|
||||
<SubItem :chil="val.children" />
|
||||
</el-submenu>
|
||||
<el-menu-item :index="val.path" :key="val.path" v-else>
|
||||
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
|
||||
<template #title v-if="!val.meta.isLink">{{ val.meta.title }}</template>
|
||||
<template #title v-else><a :href="val.meta.isLink" target="_blank">{{ val.meta.title }}</a></template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
<SubItem :chil="val.children" />
|
||||
</el-submenu>
|
||||
<el-menu-item :index="val.path" :key="val.path" v-else>
|
||||
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
|
||||
<template #title v-if="!val.meta.isLink">{{ val.meta.title }}</template>
|
||||
<template #title v-else><a :href="val.meta.isLink" target="_blank">{{ val.meta.title }}</a></template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-menu>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@ -24,8 +28,11 @@ import {
|
||||
computed,
|
||||
defineComponent,
|
||||
getCurrentInstance,
|
||||
onMounted,
|
||||
nextTick,
|
||||
} from "vue";
|
||||
import { useRoute, onBeforeRouteUpdate } from "vue-router";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
import SubItem from "/@/views/layout/navMenu/subItem.vue";
|
||||
export default defineComponent({
|
||||
name: "navMenuHorizontal",
|
||||
@ -41,20 +48,67 @@ export default defineComponent({
|
||||
setup(props) {
|
||||
const { proxy } = getCurrentInstance();
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
const state = reactive({
|
||||
defaultActive: route.path,
|
||||
defaultActive: null,
|
||||
});
|
||||
// 获取父级菜单数据
|
||||
const menuList = computed(() => {
|
||||
return props.menuList;
|
||||
});
|
||||
// 设置横向滚动条可以鼠标滚轮滚动
|
||||
const onElMenuHorizontalScroll = (e: object) => {
|
||||
const eventDelta = e.wheelDelta || -e.deltaY * 40;
|
||||
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft =
|
||||
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft +
|
||||
eventDelta / 4;
|
||||
};
|
||||
// 初始化数据,页面刷新时,滚动条滚动到对应位置
|
||||
const initElMenuOffsetLeft = () => {
|
||||
nextTick(() => {
|
||||
let els = document.querySelector(
|
||||
".el-menu.el-menu--horizontal li.is-active"
|
||||
);
|
||||
if (!els) return false;
|
||||
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft =
|
||||
els.offsetLeft;
|
||||
});
|
||||
};
|
||||
// 设置页面当前路由高亮
|
||||
const setCurrentRouterHighlight = (path: string) => {
|
||||
const currentPathSplit = path.split("/");
|
||||
if (store.state.themeConfig.layout === "classic") {
|
||||
state.defaultActive = `/${currentPathSplit[1]}`;
|
||||
} else {
|
||||
state.defaultActive = path;
|
||||
}
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initElMenuOffsetLeft();
|
||||
setCurrentRouterHighlight(route.path);
|
||||
});
|
||||
// 路由更新时
|
||||
onBeforeRouteUpdate((to) => {
|
||||
state.defaultActive = to.path;
|
||||
setCurrentRouterHighlight(to.path);
|
||||
proxy.mittBus.emit("onMenuClick");
|
||||
});
|
||||
return {
|
||||
menuList,
|
||||
onElMenuHorizontalScroll,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-menu-horizontal-warp {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-right: 30px;
|
||||
.el-menu.el-menu--horizontal {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -19,7 +19,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
export default defineComponent({
|
||||
name: "navMenuSubItem",
|
||||
props: {
|
||||
@ -31,7 +30,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const route = useRoute();
|
||||
// 获取父级菜单数据
|
||||
const chil = computed(() => {
|
||||
return props.chil;
|
||||
});
|
||||
|
@ -49,12 +49,15 @@ export default defineComponent({
|
||||
const state = reactive({
|
||||
defaultActive: route.path,
|
||||
});
|
||||
// 获取父级菜单数据
|
||||
const menuList = computed(() => {
|
||||
return props.menuList;
|
||||
});
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return store.state.themeConfig;
|
||||
});
|
||||
// 路由更新时
|
||||
onBeforeRouteUpdate((to) => {
|
||||
state.defaultActive = to.path;
|
||||
proxy.mittBus.emit("onMenuClick");
|
||||
|
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view v-slot="{ Component, route }">
|
||||
<div class="h100">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition :name="setTransitionName" mode="out-in">
|
||||
<keep-alive :include="getCaches">
|
||||
<component :is="Component" :key="route.path" />
|
||||
<component :is="Component" :key="refreshRouterViewKey" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
@ -18,18 +18,28 @@ import {
|
||||
reactive,
|
||||
getCurrentInstance,
|
||||
watch,
|
||||
onBeforeMount,
|
||||
onUnmounted,
|
||||
nextTick,
|
||||
} from "vue";
|
||||
import { useRouter, RouteRecordRaw } from "vue-router";
|
||||
import {
|
||||
useRoute,
|
||||
useRouter,
|
||||
RouteRecordRaw,
|
||||
onBeforeRouteUpdate,
|
||||
} from "vue-router";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
export default defineComponent({
|
||||
name: "layoutParentView",
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const { proxy } = getCurrentInstance();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const store = useStore();
|
||||
const state = reactive({
|
||||
transitionName: "slide-right",
|
||||
headerHeight: "84px",
|
||||
refreshRouterViewKey: route.path,
|
||||
});
|
||||
// 设置主界面切换动画
|
||||
const setTransitionName = computed(() => {
|
||||
@ -57,6 +67,24 @@ export default defineComponent({
|
||||
proxy.$refs.layoutScrollbarRef.update();
|
||||
}
|
||||
});
|
||||
// 路由更新时
|
||||
onBeforeRouteUpdate((to) => {
|
||||
state.refreshRouterViewKey = to.path;
|
||||
});
|
||||
// 页面加载时
|
||||
onBeforeMount(() => {
|
||||
proxy.mittBus.on("onTagsViewRefreshRouterView", (path: string) => {
|
||||
if (route.path !== path) return false;
|
||||
state.refreshRouterViewKey = Math.random();
|
||||
nextTick(() => {
|
||||
state.refreshRouterViewKey = path;
|
||||
});
|
||||
});
|
||||
});
|
||||
// 页面卸载时
|
||||
onUnmounted(() => {
|
||||
proxy.mittBus.off("onTagsViewRefreshRouterView");
|
||||
});
|
||||
return {
|
||||
getThemeConfig,
|
||||
getCaches,
|
||||
|
@ -6,13 +6,19 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive } from "vue";
|
||||
import { toRefs, reactive, onActivated, onMounted } from "vue";
|
||||
export default {
|
||||
name: "menu13",
|
||||
setup() {
|
||||
const state = reactive({
|
||||
val: "",
|
||||
});
|
||||
onMounted(() => {
|
||||
console.log(2222);
|
||||
});
|
||||
onActivated(() => {
|
||||
console.log(1111);
|
||||
});
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user