feat: add persistence of tabs

This commit is contained in:
xiaoxian521 2021-04-21 05:08:39 +08:00
parent 762833e545
commit 62ad9e6f40
5 changed files with 114 additions and 47 deletions

View File

@ -20,12 +20,7 @@
</app-link>
</template>
<el-submenu
v-else
ref="subMenu"
:index="resolvePath(item.path)"
popper-append-to-body
>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template #title>
<i :class="item.meta.icon"></i>
<span>{{ $t(item.meta.title) }}</span>
@ -53,16 +48,16 @@ export default defineComponent({
props: {
item: {
type: Object as PropType<RouteRecordRaw>,
required: true,
required: true
},
isNest: {
type: Boolean,
default: false,
default: false
},
basePath: {
type: String,
default: "",
},
default: ""
}
},
setup(props) {
const onlyOneChild = ref<RouteRecordRaw>({} as any);
@ -71,7 +66,7 @@ export default defineComponent({
children: RouteRecordRaw[] = [],
parent: RouteRecordRaw
) {
const showingChildren = children.filter((item) => {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false;
} else {
@ -96,6 +91,6 @@ export default defineComponent({
};
return { hasOneShowingChild, resolvePath, onlyOneChild };
},
}
});
</script>

View File

@ -22,12 +22,13 @@
</template>
<script lang="ts">
import { computed, defineComponent } from "vue";
import { computed, defineComponent, unref, nextTick } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useStore } from "vuex";
import SidebarItem from "./SidebarItem.vue";
import { algorithm } from "../../../utils/algorithm";
import { useDynamicRoutesHook } from "../tag/tagsHook";
import { emitter } from "/@/utils/mitt";
export default defineComponent({
name: "sidebar",
@ -55,15 +56,27 @@ export default defineComponent({
if (parentPathIndex > 0) {
parentPath = indexPath.slice(0, parentPathIndex);
}
dynamicRouteTags(indexPath, parentPath);
//
function findCurrentRoute(routes) {
return routes.map((item, key) => {
if (item.path === indexPath) {
dynamicRouteTags(indexPath, parentPath, item);
} else {
if (item.children) findCurrentRoute(item.children);
}
});
return;
}
findCurrentRoute(algorithm.increaseIndexes(router));
emitter.emit("changLayoutRoute", indexPath);
};
return {
routes: computed(() => algorithm.increaseIndexes(router)),
activeMenu,
isCollapse: computed(() => !store.getters.sidebar.opened),
menuSelect,
menuSelect
};
},
}
});
</script>

View File

@ -42,11 +42,11 @@
<script>
import { useDynamicRoutesHook } from "./tagsHook"
import { useRoute, useRouter } from "vue-router"
import { ref, watchEffect, onBeforeMount, unref } from "vue"
import { ref, watchEffect, onBeforeMount, unref, nextTick } from "vue"
import { storageLocal } from "/@/utils/storage"
import { emitter } from "/@/utils/mitt"
import { toggleClass, removeClass } from "/@/utils/operate"
import { nextTick } from 'vue'
import { homeRoute } from "./type"
let refreshDiv = "refresh-div"
export default {
@ -73,20 +73,25 @@ export default {
icon: "el-icon-more",
text: "关闭其他标签页",
divided: true,
disabled: false
disabled: unref(routesLength) > 2 ? false : true
},
{
icon: "el-icon-minus",
text: "关闭全部标签页",
divided: false,
disabled: false
disabled: unref(routesLength) > 1 ? false : true
},
])
function deleteMenu(item) {
let tagslen = storageLocal.getItem("routesInStorage").length - 1
if (tagslen === 1) {
tagsViews.value[1].disabled = true
let tagslen = storageLocal.getItem("routesInStorage").length
if (tagslen === 2) {
Array.from([1, 2, 3]).forEach(v => {
tagsViews.value[v].disabled = true
})
}
if (tagslen === 3) {
tagsViews.value[2].disabled = true
}
deleteDynamicTag(item, route.path)
}
@ -115,6 +120,7 @@ export default {
function onClickDrop(key, item) {
if (item.disabled) return
//
switch (key) {
case 0:
//
@ -122,25 +128,22 @@ export default {
break
case 1:
//
deleteMenu({ meta: route.meta, path: route.path })
deleteMenu({ path: route.path, meta: route.meta })
break
case 2:
//
dRoutes.value = [homeRoute, { path: route.path, meta: route.meta }]
storageLocal.setItem("routesInStorage", dRoutes.value)
tagsViews.value[2].disabled = true
break
case 3:
//
dRoutes.value = [{
path: "/welcome",
meta: {
title: "home",
icon: "el-icon-s-home",
showLink: true,
savedPosition: false,
},
}]
dRoutes.value = [homeRoute]
storageLocal.setItem("routesInStorage", dRoutes.value)
router.push("/welcome")
tagsViews.value[1].disabled = true
Array.from([1, 2, 3]).forEach(v => {
tagsViews.value[v].disabled = true
})
break
}
}
@ -150,6 +153,20 @@ export default {
if (unref(showTags) === key) return
showTags.value = key
})
emitter.on("changLayoutRoute", (indexPath) => {
let currentLen = storageLocal.getItem("routesInStorage").length
if (currentLen === 1) {
Array.from([1, 3]).forEach(v => {
tagsViews.value[v].disabled = false
})
}
if (currentLen >= 2) {
Array.from([1, 2, 3]).forEach(v => {
tagsViews.value[v].disabled = false
})
}
})
})
return {

View File

@ -1,6 +1,7 @@
import { reactive, toRefs, nextTick, computed } from "vue";
import { reactive, toRefs, unref, nextTick, computed } from "vue";
import { storageLocal } from "/@/utils/storage";
import { useRouter } from "vue-router";
import { homeRoute } from "./type";
interface InterDynamic {
dRoutes: object[];
@ -24,21 +25,57 @@ let dynamic: InterDynamic = reactive({
export function useDynamicRoutesHook() {
const router = useRouter();
const routesLength = computed(() => {
return storageLocal.getItem("routesInStorage")
? storageLocal.getItem("routesInStorage").length
: 0;
});
// 返回当前路由组成的数组
const routesStorageLists = computed(() => {
return storageLocal.getItem("routesInStorage")
? storageLocal.getItem("routesInStorage")
: [];
});
/**
* @param value string menu对应的路由path
* @param parentPath string
*/
const dynamicRouteTags = (value: string, parentPath: string): void => {
const dynamicRouteTags = (
value: string,
parentPath: string,
route: any
): void => {
nextTick(() => {
if (unref(routesStorageLists).length > 2) {
dynamic.dRoutes = unref(routesStorageLists);
return;
}
});
const hasValue = dynamic.dRoutes.some((item: any) => {
return item.path === value;
});
if (route) {
let ramStorage = storageLocal.getItem("routesInStorage");
nextTick(() => {
let currentIndex = ramStorage.findIndex((v) => v.path === route.path);
if (currentIndex !== -1) return;
ramStorage.push({ path: route.path, meta: route.meta });
storageLocal.setItem("routesInStorage", ramStorage);
});
}
function concatPath(arr: object[], value: string, parentPath: string) {
if (!hasValue) {
arr.forEach((arrItem: any) => {
let pathConcat = parentPath + "/" + arrItem.path;
if (arrItem.path === value || pathConcat === value) {
dynamic.dRoutes.push({ path: value, meta: arrItem.meta });
unref(routesLength) === 0
? storageLocal.setItem("routesInStorage", dynamic.dRoutes)
: [];
} else {
if (arrItem.children && arrItem.children.length > 0) {
concatPath(arrItem.children, value, parentPath);
@ -48,12 +85,6 @@ export function useDynamicRoutesHook() {
}
}
concatPath(router.options.routes, value, parentPath);
// if (storageLocal.getItem("routesInStorage") && storageLocal.getItem("routesInStorage").length > 2) {
// let lens = storageLocal.getItem("routesInStorage").length
// let itemss = storageLocal.getItem("routesInStorage")[lens - 1]
// dynamic.dRoutes.push({ path: itemss.path, meta: itemss.meta })
// }
storageLocal.setItem("routesInStorage", dynamic.dRoutes);
};
/**
* @param value any tag路由
@ -76,16 +107,12 @@ export function useDynamicRoutesHook() {
});
}
};
const routesLength = computed(() => {
return storageLocal.getItem("routesInStorage")
? storageLocal.getItem("routesInStorage").length
: 0;
});
return {
...toRefs(dynamic),
dynamicRouteTags,
deleteDynamicTag,
routesLength,
routesStorageLists,
};
}

View File

@ -0,0 +1,15 @@
interface RouteModel {
readonly path: string;
readonly meta: object;
}
// 固定首页路由
export const homeRoute: RouteModel = {
path: "/welcome",
meta: {
title: "home",
icon: "el-icon-s-home",
showLink: true,
savedPosition: false,
},
};