perf: layout (#50)

This commit is contained in:
啝裳 2021-10-03 13:09:12 +08:00 committed by GitHub
parent 77b7abcbc3
commit 6b16a04229
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 705 additions and 861 deletions

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="globalization" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 512 512"><path d="M478.33 433.6l-90-218a22 22 0 0 0-40.67 0l-90 218a22 22 0 1 0 40.67 16.79L316.66 406h102.67l18.33 44.39A22 22 0 0 0 458 464a22 22 0 0 0 20.32-30.4zM334.83 362L368 281.65L401.17 362z" fill="currentColor"></path><path d="M267.84 342.92a22 22 0 0 0-4.89-30.7c-.2-.15-15-11.13-36.49-34.73c39.65-53.68 62.11-114.75 71.27-143.49H330a22 22 0 0 0 0-44H214V70a22 22 0 0 0-44 0v20H54a22 22 0 0 0 0 44h197.25c-9.52 26.95-27.05 69.5-53.79 108.36c-31.41-41.68-43.08-68.65-43.17-68.87a22 22 0 0 0-40.58 17c.58 1.38 14.55 34.23 52.86 83.93c.92 1.19 1.83 2.35 2.74 3.51c-39.24 44.35-77.74 71.86-93.85 80.74a22 22 0 1 0 21.07 38.63c2.16-1.18 48.6-26.89 101.63-85.59c22.52 24.08 38 35.44 38.93 36.1a22 22 0 0 0 30.75-4.9z" fill="currentColor"></path></svg>

After

Width:  |  Height:  |  Size: 965 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconinternationality" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 512 512"><path d="M478.33 433.6l-90-218a22 22 0 0 0-40.67 0l-90 218a22 22 0 1 0 40.67 16.79L316.66 406h102.67l18.33 44.39A22 22 0 0 0 458 464a22 22 0 0 0 20.32-30.4zM334.83 362L368 281.65L401.17 362z" fill="currentColor"></path><path d="M267.84 342.92a22 22 0 0 0-4.89-30.7c-.2-.15-15-11.13-36.49-34.73c39.65-53.68 62.11-114.75 71.27-143.49H330a22 22 0 0 0 0-44H214V70a22 22 0 0 0-44 0v20H54a22 22 0 0 0 0 44h197.25c-9.52 26.95-27.05 69.5-53.79 108.36c-31.41-41.68-43.08-68.65-43.17-68.87a22 22 0 0 0-40.58 17c.58 1.38 14.55 34.23 52.86 83.93c.92 1.19 1.83 2.35 2.74 3.51c-39.24 44.35-77.74 71.86-93.85 80.74a22 22 0 1 0 21.07 38.63c2.16-1.18 48.6-26.89 101.63-85.59c22.52 24.08 38 35.44 38.93 36.1a22 22 0 0 0 30.75-4.9z" fill="currentColor"></path></svg>

Before

Width:  |  Height:  |  Size: 972 B

View File

@ -1,10 +0,0 @@
import { App } from "vue";
import reBreadCrumb from "./src/index.vue";
export const ReBreadCrumb = Object.assign(reBreadCrumb, {
install(app: App) {
app.component(reBreadCrumb.name, reBreadCrumb);
}
});
export default ReBreadCrumb;

View File

@ -1,3 +1,14 @@
<script setup lang="ts">
import { ref } from "vue";
const lists = ref<ForDataType<undefined>>([
{ type: "", label: "善良" },
{ type: "success", label: "好学" },
{ type: "info", label: "幽默" },
{ type: "danger", label: "旅游" },
{ type: "warning", label: "追剧" }
]);
</script>
<template>
<el-descriptions
class="margin-top"
@ -75,17 +86,6 @@
</el-descriptions>
</template>
<script setup lang="ts">
import { ref } from "vue";
const lists = ref<ForDataType<undefined>>([
{ type: "", label: "善良" },
{ type: "success", label: "好学" },
{ type: "info", label: "幽默" },
{ type: "danger", label: "旅游" },
{ type: "warning", label: "追剧" }
]);
</script>
<style scoped>
.el-tag--mini {
margin-right: 10px !important;

View File

@ -1,10 +0,0 @@
import { App } from "vue";
import reHamBurger from "./src/index.vue";
export const ReHamBurger = Object.assign(reHamBurger, {
install(app: App) {
app.component(reHamBurger.name, reHamBurger);
}
});
export default ReHamBurger;

View File

@ -1,3 +1,59 @@
<script setup lang="ts">
import { useI18n } from "vue-i18n";
import { emitter } from "/@/utils/mitt";
import Hamburger from "./sidebar/hamBurger.vue";
import { useRouter, useRoute } from "vue-router";
import { storageSession } from "/@/utils/storage";
import Breadcrumb from "./sidebar/breadCrumb.vue";
import { useAppStoreHook } from "/@/store/modules/app";
import { unref, watch, getCurrentInstance } from "vue";
import { deviceDetection } from "/@/utils/deviceDetection";
import screenfull from "../components/screenfull/index.vue";
import globalization from "/@/assets/svg/globalization.svg";
const instance =
getCurrentInstance().appContext.config.globalProperties.$storage;
const pureApp = useAppStoreHook();
const router = useRouter();
const route = useRoute();
let usename = storageSession.getItem("info")?.username;
const { locale, t } = useI18n();
watch(
() => locale.value,
() => {
//@ts-ignore
document.title = t(unref(route.meta.title)); // title
}
);
// 退
const logout = (): void => {
storageSession.removeItem("info");
router.push("/login");
};
function onPanel() {
emitter.emit("openPanel");
}
function toggleSideBar() {
pureApp.toggleSideBar();
}
//
function translationCh() {
instance.locale = { locale: "zh" };
locale.value = "zh";
}
// English
function translationEn() {
instance.locale = { locale: "en" };
locale.value = "en";
}
</script>
<template>
<div class="navbar">
<Hamburger
@ -13,7 +69,7 @@
<screenfull v-show="!deviceDetection()" />
<!-- 国际化 -->
<el-dropdown trigger="click">
<iconinternationality />
<globalization />
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
@ -60,99 +116,6 @@
</div>
</template>
<script lang="ts">
import { defineComponent, unref, watch, getCurrentInstance } from "vue";
import Breadcrumb from "/@/components/ReBreadCrumb";
import Hamburger from "/@/components/ReHamBurger";
import screenfull from "../components/screenfull/index.vue";
import { useRouter, useRoute } from "vue-router";
import { useAppStoreHook } from "/@/store/modules/app";
import { storageSession } from "/@/utils/storage";
import favicon from "/favicon.ico";
import { emitter } from "/@/utils/mitt";
import { deviceDetection } from "/@/utils/deviceDetection";
import { useI18n } from "vue-i18n";
import iconinternationality from "/@/assets/svg/iconinternationality.svg";
export default defineComponent({
name: "Navbar",
components: {
Breadcrumb,
Hamburger,
screenfull,
iconinternationality
},
// @ts-ignore
computed: {
// eslint-disable-next-line vue/return-in-computed-property
currentLocale() {
switch (this.$storage.locale?.locale) {
case "zh":
return true;
case "en":
return false;
}
}
},
setup() {
const instance =
getCurrentInstance().appContext.config.globalProperties.$storage;
const pureApp = useAppStoreHook();
const router = useRouter();
const route = useRoute();
let usename = storageSession.getItem("info")?.username;
const { locale, t } = useI18n();
watch(
() => locale.value,
() => {
//@ts-ignore
document.title = t(unref(route.meta.title)); // title
}
);
// 退
const logout = (): void => {
storageSession.removeItem("info");
router.push("/login");
};
function onPanel() {
emitter.emit("openPanel");
}
function toggleSideBar() {
pureApp.toggleSideBar();
}
//
function translationCh() {
instance.locale = { locale: "zh" };
locale.value = "zh";
}
// English
function translationEn() {
instance.locale = { locale: "en" };
locale.value = "en";
}
return {
locale,
usename,
pureApp,
favicon,
logout,
onPanel,
translationCh,
translationEn,
toggleSideBar,
deviceDetection
};
}
});
</script>
<style lang="scss" scoped>
.navbar {
width: 100%;
@ -190,7 +153,7 @@ export default defineComponent({
}
}
.iconinternationality {
.globalization {
height: 48px;
width: 40px;
padding: 11px;

View File

@ -1,3 +1,114 @@
<script setup lang="ts">
import {
computed,
unref,
watch,
nextTick,
onMounted,
getCurrentInstance
} from "vue";
import { useI18n } from "vue-i18n";
import settings from "/@/settings";
import { emitter } from "/@/utils/mitt";
import { templateRef } from "@vueuse/core";
import SidebarItem from "./sidebarItem.vue";
import { algorithm } from "/@/utils/algorithm";
import screenfull from "../screenfull/index.vue";
import { useRoute, useRouter } from "vue-router";
import { storageSession } from "/@/utils/storage";
import { deviceDetection } from "/@/utils/deviceDetection";
import globalization from "/@/assets/svg/globalization.svg";
import { usePermissionStoreHook } from "/@/store/modules/permission";
const instance =
getCurrentInstance().appContext.config.globalProperties.$storage;
const menuRef = templateRef<ElRef | null>("menu", null);
const routeStore = usePermissionStoreHook();
const route = useRoute();
const router = useRouter();
const routers = useRouter().options.routes;
let usename = storageSession.getItem("info")?.username;
const { locale, t } = useI18n();
watch(
() => locale.value,
() => {
//@ts-ignore
// title
document.title = t(unref(route.meta.title));
}
);
// 退
const logout = (): void => {
storageSession.removeItem("info");
router.push("/login");
};
function onPanel() {
emitter.emit("openPanel");
}
const activeMenu = computed(() => {
const { meta, path } = route;
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
});
const menuSelect = (indexPath: string): void => {
let parentPath = "";
let parentPathIndex = indexPath.lastIndexOf("/");
if (parentPathIndex > 0) {
parentPath = indexPath.slice(0, parentPathIndex);
}
//
function findCurrentRoute(routes) {
return routes.map(item => {
if (item.path === indexPath) {
//
emitter.emit("changLayoutRoute", {
indexPath,
parentPath
});
} else {
if (item.children) findCurrentRoute(item.children);
}
});
}
findCurrentRoute(algorithm.increaseIndexes(routers));
};
function backHome() {
router.push("/welcome");
}
function handleResize() {
menuRef.value.handleResize();
}
//
function translationCh() {
instance.locale = { locale: "zh" };
locale.value = "zh";
handleResize();
}
// English
function translationEn() {
instance.locale = { locale: "en" };
locale.value = "en";
handleResize();
}
onMounted(() => {
nextTick(() => {
handleResize();
});
});
</script>
<template>
<div class="horizontal-header">
<div class="horizontal-header-left" @click="backHome">
@ -25,7 +136,7 @@
<screenfull v-show="!deviceDetection()" />
<!-- 国际化 -->
<el-dropdown trigger="click">
<iconinternationality />
<globalization />
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
@ -72,177 +183,6 @@
</div>
</template>
<script lang="ts">
import {
computed,
defineComponent,
unref,
watch,
nextTick,
onMounted,
getCurrentInstance
} from "vue";
import { useI18n } from "vue-i18n";
import settings from "/@/settings";
import { emitter } from "/@/utils/mitt";
import { templateRef } from "@vueuse/core";
import SidebarItem from "./sidebarItem.vue";
import { algorithm } from "/@/utils/algorithm";
import screenfull from "../screenfull/index.vue";
import { useRoute, useRouter } from "vue-router";
import { storageSession } from "/@/utils/storage";
import { deviceDetection } from "/@/utils/deviceDetection";
import { usePermissionStoreHook } from "/@/store/modules/permission";
import iconinternationality from "/@/assets/svg/iconinternationality.svg";
let routerArrays: Array<object> = [
{
path: "/welcome",
parentPath: "/",
meta: {
title: "message.hshome",
icon: "el-icon-s-home",
showLink: true,
savedPosition: false
}
}
];
export default defineComponent({
name: "sidebar",
components: { SidebarItem, screenfull, iconinternationality },
// @ts-ignore
computed: {
// eslint-disable-next-line vue/return-in-computed-property
currentLocale() {
if (
!this.$storage.routesInStorage ||
this.$storage.routesInStorage.length === 0
) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
this.$storage.routesInStorage = routerArrays;
}
if (!this.$storage.locale) {
// eslint-disable-next-line
this.$storage.locale = { locale: "zh" };
useI18n().locale.value = "zh";
}
switch (this.$storage.locale?.locale) {
case "zh":
return true;
case "en":
return false;
}
}
},
setup() {
const instance =
getCurrentInstance().appContext.config.globalProperties.$storage;
const menuRef = templateRef<ElRef | null>("menu", null);
const routeStore = usePermissionStoreHook();
const route = useRoute();
const router = useRouter();
const routers = useRouter().options.routes;
let usename = storageSession.getItem("info")?.username;
const { locale, t } = useI18n();
watch(
() => locale.value,
() => {
//@ts-ignore
// title
document.title = t(unref(route.meta.title));
}
);
// 退
const logout = (): void => {
storageSession.removeItem("info");
router.push("/login");
};
function onPanel() {
emitter.emit("openPanel");
}
const activeMenu = computed(() => {
const { meta, path } = route;
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
});
const menuSelect = (indexPath: string): void => {
let parentPath = "";
let parentPathIndex = indexPath.lastIndexOf("/");
if (parentPathIndex > 0) {
parentPath = indexPath.slice(0, parentPathIndex);
}
//
function findCurrentRoute(routes) {
return routes.map(item => {
if (item.path === indexPath) {
//
emitter.emit("changLayoutRoute", {
indexPath,
parentPath
});
} else {
if (item.children) findCurrentRoute(item.children);
}
});
}
findCurrentRoute(algorithm.increaseIndexes(routers));
};
function backHome() {
router.push("/welcome");
}
function handleResize() {
menuRef.value.handleResize();
}
//
function translationCh() {
instance.locale = { locale: "zh" };
locale.value = "zh";
handleResize();
}
// English
function translationEn() {
instance.locale = { locale: "en" };
locale.value = "en";
handleResize();
}
onMounted(() => {
nextTick(() => {
handleResize();
});
});
return {
locale,
usename,
settings,
routeStore,
activeMenu,
logout,
onPanel,
backHome,
menuSelect,
translationCh,
translationEn,
deviceDetection
};
}
});
</script>
<style lang="scss" scoped>
.translation {
.el-dropdown-menu__item {

View File

@ -1,3 +1,61 @@
<script setup lang="ts">
import Logo from "./logo.vue";
import { emitter } from "/@/utils/mitt";
import SidebarItem from "./sidebarItem.vue";
import { algorithm } from "/@/utils/algorithm";
import { storageLocal } from "/@/utils/storage";
import { useRoute, useRouter } from "vue-router";
import { computed, ref, onBeforeMount } from "vue";
import { useAppStoreHook } from "/@/store/modules/app";
import { usePermissionStoreHook } from "/@/store/modules/permission";
const route = useRoute();
const pureApp = useAppStoreHook();
const router = useRouter().options.routes;
const routeStore = usePermissionStoreHook();
const showLogo = ref(storageLocal.getItem("logoVal") || "1");
const isCollapse = computed(() => {
return !pureApp.getSidebarStatus;
});
const activeMenu = computed(() => {
const { meta, path } = route;
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
});
const menuSelect = (indexPath: string): void => {
let parentPath = "";
let parentPathIndex = indexPath.lastIndexOf("/");
if (parentPathIndex > 0) {
parentPath = indexPath.slice(0, parentPathIndex);
}
//
// eslint-disable-next-line no-inner-declarations
function findCurrentRoute(routes) {
return routes.map(item => {
if (item.path === indexPath) {
//
emitter.emit("changLayoutRoute", {
indexPath,
parentPath
});
} else {
if (item.children) findCurrentRoute(item.children);
}
});
}
findCurrentRoute(algorithm.increaseIndexes(router));
};
onBeforeMount(() => {
emitter.on("logoChange", key => {
showLogo.value = key;
});
});
</script>
<template>
<div :class="['sidebar-container', showLogo ? 'has-logo' : '']">
<Logo v-if="showLogo === '1'" :collapse="isCollapse" />
@ -21,77 +79,3 @@
</el-scrollbar>
</div>
</template>
<script lang="ts">
import Logo from "./logo.vue";
import { emitter } from "/@/utils/mitt";
import SidebarItem from "./sidebarItem.vue";
import { algorithm } from "/@/utils/algorithm";
import { storageLocal } from "/@/utils/storage";
import { useRoute, useRouter } from "vue-router";
import { useAppStoreHook } from "/@/store/modules/app";
import { computed, defineComponent, ref, onBeforeMount } from "vue";
import { usePermissionStoreHook } from "/@/store/modules/permission";
export default defineComponent({
name: "sidebar",
components: { SidebarItem, Logo },
setup() {
const routeStore = usePermissionStoreHook();
const router = useRouter().options.routes;
const pureApp = useAppStoreHook();
const route = useRoute();
const showLogo = ref(storageLocal.getItem("logoVal") || "1");
const activeMenu = computed(() => {
const { meta, path } = route;
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
});
const menuSelect = (indexPath: string): void => {
let parentPath = "";
let parentPathIndex = indexPath.lastIndexOf("/");
if (parentPathIndex > 0) {
parentPath = indexPath.slice(0, parentPathIndex);
}
//
// eslint-disable-next-line no-inner-declarations
function findCurrentRoute(routes) {
return routes.map(item => {
if (item.path === indexPath) {
//
emitter.emit("changLayoutRoute", {
indexPath,
parentPath
});
} else {
if (item.children) findCurrentRoute(item.children);
}
});
}
findCurrentRoute(algorithm.increaseIndexes(router));
};
onBeforeMount(() => {
emitter.on("logoChange", key => {
showLogo.value = key;
});
});
return {
activeMenu,
isCollapse: computed(() => !pureApp.getSidebarStatus),
menuSelect,
showLogo,
routeStore
};
}
});
</script>

View File

@ -1,3 +1,442 @@
<script lang="ts">
export default {
computed: {
dynamicTagList() {
return this.$storage.routesInStorage;
}
}
};
</script>
<script setup lang="ts">
import {
ref,
watch,
onBeforeMount,
unref,
nextTick,
getCurrentInstance
} from "vue";
import { RouteConfigs } from "../../types";
import { emitter } from "/@/utils/mitt";
import { templateRef } from "@vueuse/core";
import { storageLocal } from "/@/utils/storage";
import { useRoute, useRouter } from "vue-router";
import { toggleClass, removeClass, hasClass } from "/@/utils/operate";
import close from "/@/assets/svg/close.svg";
import refresh from "/@/assets/svg/refresh.svg";
import closeAll from "/@/assets/svg/close_all.svg";
import closeLeft from "/@/assets/svg/close_left.svg";
import closeOther from "/@/assets/svg/close_other.svg";
import closeRight from "/@/assets/svg/close_right.svg";
let refreshButton = "refresh-button";
const instance = getCurrentInstance();
let st: any;
const route = useRoute();
const router = useRouter();
const showTags = ref(storageLocal.getItem("tagsVal") || false);
const containerDom = templateRef<HTMLElement | null>("containerDom", null);
const activeIndex = ref(-1);
let routerArrays: Array<RouteConfigs> = [
{
path: "/welcome",
parentPath: "/",
meta: {
title: "message.hshome",
icon: "el-icon-s-home",
showLink: true,
savedPosition: false
}
}
];
const tagsViews = ref<ForDataType<undefined>>([
{
icon: refresh,
text: "重新加载",
divided: false,
disabled: false,
show: true
},
{
icon: close,
text: "关闭当前标签页",
divided: false,
disabled: routerArrays.length > 1 ? false : true,
show: true
},
{
icon: closeLeft,
text: "关闭左侧标签页",
divided: true,
disabled: routerArrays.length > 1 ? false : true,
show: true
},
{
icon: closeRight,
text: "关闭右侧标签页",
divided: false,
disabled: routerArrays.length > 1 ? false : true,
show: true
},
{
icon: closeOther,
text: "关闭其他标签页",
divided: true,
disabled: routerArrays.length > 2 ? false : true,
show: true
},
{
icon: closeAll,
text: "关闭全部标签页",
divided: false,
disabled: routerArrays.length > 1 ? false : true,
show: true
}
]);
//
const showModel = ref(storageLocal.getItem("showModel") || "smart");
if (!showModel.value) {
storageLocal.setItem("showModel", "card");
}
let visible = ref(false);
let buttonLeft = ref(0);
let buttonTop = ref(0);
//
let currentSelect = ref({});
function dynamicRouteTag(value: string, parentPath: string): void {
const hasValue = st.routesInStorage.some((item: any) => {
return item.path === value;
});
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) {
routerArrays.push({
path: value,
parentPath: `/${parentPath.split("/")[1]}`,
meta: arrItem.meta
});
st.routesInStorage = routerArrays;
} else {
if (arrItem.children && arrItem.children.length > 0) {
concatPath(arrItem.children, value, parentPath);
}
}
});
}
}
concatPath(router.options.routes, value, parentPath);
}
//
function onFresh() {
toggleClass(true, refreshButton, document.querySelector(".rotate"));
const { fullPath } = unref(route);
router.replace({
path: "/redirect" + fullPath
});
setTimeout(() => {
removeClass(document.querySelector(".rotate"), refreshButton);
}, 600);
}
function deleteDynamicTag(obj: any, current: any, tag?: string) {
let valueIndex: number = routerArrays.findIndex((item: any) => {
return item.path === obj.path;
});
const spliceRoute = (start?: number, end?: number, other?: boolean): void => {
if (other) {
st.routesInStorage = [
{
path: "/welcome",
parentPath: "/",
meta: {
title: "message.hshome",
icon: "el-icon-s-home",
showLink: true,
savedPosition: false
}
},
obj
];
routerArrays = st.routesInStorage;
} else {
routerArrays.splice(start, end);
st.routesInStorage = routerArrays;
}
router.push(obj.path);
};
if (tag === "other") {
spliceRoute(1, 1, true);
} else if (tag === "left") {
spliceRoute(1, valueIndex - 1);
} else if (tag === "right") {
spliceRoute(valueIndex + 1, routerArrays.length);
} else {
//
spliceRoute(valueIndex, 1);
}
if (current === obj.path) {
// tagtag
let newRoute: any = routerArrays.slice(-1);
nextTick(() => {
router.push({
path: newRoute[0].path
});
});
}
}
function deleteMenu(item, tag?: string) {
deleteDynamicTag(item, item.path, tag);
}
function onClickDrop(key, item, selectRoute?: RouteConfigs) {
if (item && item.disabled) return;
//
switch (key) {
case 0:
//
onFresh();
break;
case 1:
//
selectRoute
? deleteMenu({ path: selectRoute.path, meta: selectRoute.meta })
: deleteMenu({ path: route.path, meta: route.meta });
break;
case 2:
//
selectRoute
? deleteMenu(
{
path: selectRoute.path,
meta: selectRoute.meta
},
"left"
)
: deleteMenu({ path: route.path, meta: route.meta }, "left");
break;
case 3:
//
selectRoute
? deleteMenu(
{
path: selectRoute.path,
meta: selectRoute.meta
},
"right"
)
: deleteMenu({ path: route.path, meta: route.meta }, "right");
break;
case 4:
//
selectRoute
? deleteMenu(
{
path: selectRoute.path,
meta: selectRoute.meta
},
"other"
)
: deleteMenu({ path: route.path, meta: route.meta }, "other");
break;
case 5:
//
routerArrays.splice(1, routerArrays.length);
st.routesInStorage = routerArrays;
router.push("/welcome");
break;
}
setTimeout(() => {
showMenuModel(route.fullPath);
});
}
//
function selectTag(key, item) {
onClickDrop(key, item, currentSelect.value);
}
function closeMenu() {
visible.value = false;
}
function showMenus(value: Boolean) {
Array.of(1, 2, 3, 4, 5).forEach(v => {
tagsViews.value[v].show = value;
});
}
function disabledMenus(value: Boolean) {
Array.of(1, 2, 3, 4, 5).forEach(v => {
tagsViews.value[v].disabled = value;
});
}
//
function showMenuModel(currentPath: string, refresh = false) {
let allRoute = unref(st.routesInStorage);
let routeLength = unref(st.routesInStorage).length;
// currentIndex1
let currentIndex = allRoute.findIndex(v => v.path === currentPath);
// currentIndexrouteLength-1
showMenus(true);
if (refresh) {
tagsViews.value[0].show = true;
}
if (currentIndex === 1 && routeLength !== 2) {
//
tagsViews.value[2].show = false;
Array.of(1, 3, 4, 5).forEach(v => {
tagsViews.value[v].disabled = false;
});
tagsViews.value[2].disabled = true;
} else if (currentIndex === 1 && routeLength === 2) {
disabledMenus(false);
//
Array.of(2, 3, 4).forEach(v => {
tagsViews.value[v].show = false;
tagsViews.value[v].disabled = true;
});
} else if (routeLength - 1 === currentIndex && currentIndex !== 0) {
//
tagsViews.value[3].show = false;
Array.of(1, 2, 4, 5).forEach(v => {
tagsViews.value[v].disabled = false;
});
tagsViews.value[3].disabled = true;
} else if (currentIndex === 0) {
//
disabledMenus(true);
} else {
disabledMenus(false);
}
}
function openMenu(tag, e) {
closeMenu();
if (tag.path === "/welcome") {
//
showMenus(false);
tagsViews.value[0].show = true;
} else if (route.path !== tag.path) {
//
tagsViews.value[0].show = false;
showMenuModel(tag.path);
// eslint-disable-next-line no-dupe-else-if
} else if (st.routesInStorage.length === 2 && route.path !== tag.path) {
showMenus(true);
//
tagsViews.value[4].show = false;
} else if (route.path === tag.path) {
//
showMenuModel(tag.path, true);
}
currentSelect.value = tag;
const menuMinWidth = 105;
const offsetLeft = unref(containerDom).getBoundingClientRect().left;
const offsetWidth = unref(containerDom).offsetWidth;
const maxLeft = offsetWidth - menuMinWidth;
const left = e.clientX - offsetLeft + 5;
if (left > maxLeft) {
buttonLeft.value = maxLeft;
} else {
buttonLeft.value = left;
}
buttonTop.value = e.clientY + 10;
setTimeout(() => {
visible.value = true;
}, 10);
}
// tags
function tagOnClick(item) {
showMenuModel(item.path);
}
//
function onMouseenter(item, index) {
if (index) activeIndex.value = index;
if (unref(showModel) === "smart") {
if (hasClass(instance.refs["schedule" + index], "schedule-active")) return;
toggleClass(true, "schedule-in", instance.refs["schedule" + index]);
toggleClass(false, "schedule-out", instance.refs["schedule" + index]);
} else {
if (hasClass(instance.refs["dynamic" + index], "card-active")) return;
toggleClass(true, "card-in", instance.refs["dynamic" + index]);
toggleClass(false, "card-out", instance.refs["dynamic" + index]);
}
}
//
function onMouseleave(item, index) {
activeIndex.value = -1;
if (unref(showModel) === "smart") {
if (hasClass(instance.refs["schedule" + index], "schedule-active")) return;
toggleClass(false, "schedule-in", instance.refs["schedule" + index]);
toggleClass(true, "schedule-out", instance.refs["schedule" + index]);
} else {
if (hasClass(instance.refs["dynamic" + index], "card-active")) return;
toggleClass(false, "card-in", instance.refs["dynamic" + index]);
toggleClass(true, "card-out", instance.refs["dynamic" + index]);
}
}
watch(
() => visible.value,
val => {
if (val) {
document.body.addEventListener("click", closeMenu);
} else {
document.body.removeEventListener("click", closeMenu);
}
}
);
onBeforeMount(() => {
if (!instance) return;
st = instance.appContext.app.config.globalProperties.$storage;
routerArrays = st.routesInStorage ?? routerArrays;
//
showMenuModel(route.fullPath);
//
emitter.on("tagViewsChange", key => {
if (unref(showTags) === key) return;
showTags.value = key;
});
//
emitter.on("tagViewsShowModel", key => {
showModel.value = key;
});
//
emitter.on("changLayoutRoute", ({ indexPath, parentPath }) => {
dynamicRouteTag(indexPath, parentPath);
setTimeout(() => {
showMenuModel(indexPath);
});
});
});
</script>
<template>
<div ref="containerDom" class="tags-view" v-if="!showTags">
<el-scrollbar wrap-class="scrollbar-wrapper" class="scroll-container">
@ -87,479 +526,6 @@
</div>
</template>
<script lang="ts">
import {
ref,
watch,
onBeforeMount,
unref,
nextTick,
getCurrentInstance
} from "vue";
import { useRoute, useRouter } from "vue-router";
import { storageLocal } from "/@/utils/storage";
import { emitter } from "/@/utils/mitt";
import { toggleClass, removeClass, hasClass } from "/@/utils/operate";
import { templateRef } from "@vueuse/core";
import closeOther from "/@/assets/svg/close_other.svg";
import closeLeft from "/@/assets/svg/close_left.svg";
import closeRight from "/@/assets/svg/close_right.svg";
import close from "/@/assets/svg/close.svg";
import refresh from "/@/assets/svg/refresh.svg";
import closeAll from "/@/assets/svg/close_all.svg";
let refreshButton = "refresh-button";
let routerArrays: Array<object> = [
{
path: "/welcome",
parentPath: "/",
meta: {
title: "message.hshome",
icon: "el-icon-s-home",
showLink: true,
savedPosition: false
}
}
];
export default {
name: "tag",
components: {
closeOther,
closeLeft,
closeRight,
close,
refresh,
closeAll
},
// @ts-ignore
computed: {
dynamicTagList() {
return this.$storage.routesInStorage;
}
},
setup() {
const instance = getCurrentInstance();
let st: any;
const route = useRoute();
const router = useRouter();
const showTags = ref(storageLocal.getItem("tagsVal") || false);
const containerDom = templateRef<HTMLElement | null>("containerDom", null);
const activeIndex = ref(-1);
const tagsViews = ref([
{
icon: "refresh",
text: "重新加载",
divided: false,
disabled: false,
show: true
},
{
icon: "close",
text: "关闭当前标签页",
divided: false,
disabled: routerArrays.length > 1 ? false : true,
show: true
},
{
icon: "closeLeft",
text: "关闭左侧标签页",
divided: true,
disabled: routerArrays.length > 1 ? false : true,
show: true
},
{
icon: "closeRight",
text: "关闭右侧标签页",
divided: false,
disabled: routerArrays.length > 1 ? false : true,
show: true
},
{
icon: "closeOther",
text: "关闭其他标签页",
divided: true,
disabled: routerArrays.length > 2 ? false : true,
show: true
},
{
icon: "closeAll",
text: "关闭全部标签页",
divided: false,
disabled: routerArrays.length > 1 ? false : true,
show: true
}
]);
//
const showModel = ref(storageLocal.getItem("showModel") || "smart");
if (!showModel.value) {
storageLocal.setItem("showModel", "card");
}
let visible = ref(false);
let buttonLeft = ref(0);
let buttonTop = ref(0);
//
let currentSelect = ref({});
function dynamicRouteTag(value: string, parentPath: string): void {
const hasValue = st.routesInStorage.some((item: any) => {
return item.path === value;
});
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) {
routerArrays.push({
path: value,
parentPath: `/${parentPath.split("/")[1]}`,
meta: arrItem.meta
});
st.routesInStorage = routerArrays;
} else {
if (arrItem.children && arrItem.children.length > 0) {
concatPath(arrItem.children, value, parentPath);
}
}
});
}
}
concatPath(router.options.routes, value, parentPath);
}
//
function onFresh() {
toggleClass(true, refreshButton, document.querySelector(".rotate"));
const { fullPath } = unref(route);
router.replace({
path: "/redirect" + fullPath
});
setTimeout(() => {
removeClass(document.querySelector(".rotate"), refreshButton);
}, 600);
}
function deleteDynamicTag(obj: any, current: any, tag?: string) {
let valueIndex: number = routerArrays.findIndex((item: any) => {
return item.path === obj.path;
});
const spliceRoute = (
start?: number,
end?: number,
other?: boolean
): void => {
if (other) {
st.routesInStorage = routerArrays = [
{
path: "/welcome",
parentPath: "/",
meta: {
title: "message.hshome",
icon: "el-icon-s-home",
showLink: true,
savedPosition: false
}
},
obj
];
} else {
routerArrays.splice(start, end);
st.routesInStorage = routerArrays;
}
router.push(obj.path);
};
if (tag === "other") {
spliceRoute(1, 1, true);
} else if (tag === "left") {
spliceRoute(1, valueIndex - 1);
} else if (tag === "right") {
spliceRoute(valueIndex + 1, routerArrays.length);
} else {
//
spliceRoute(valueIndex, 1);
}
if (current === obj.path) {
// tagtag
let newRoute: any = routerArrays.slice(-1);
nextTick(() => {
router.push({
path: newRoute[0].path
});
});
}
}
function deleteMenu(item, tag?: string) {
deleteDynamicTag(item, item.path, tag);
}
function onClickDrop(key, item, selectRoute) {
if (item && item.disabled) return;
//
switch (key) {
case 0:
//
onFresh();
break;
case 1:
//
selectRoute
? deleteMenu({ path: selectRoute.path, meta: selectRoute.meta })
: deleteMenu({ path: route.path, meta: route.meta });
break;
case 2:
//
selectRoute
? deleteMenu(
{
path: selectRoute.path,
meta: selectRoute.meta
},
"left"
)
: deleteMenu({ path: route.path, meta: route.meta }, "left");
break;
case 3:
//
selectRoute
? deleteMenu(
{
path: selectRoute.path,
meta: selectRoute.meta
},
"right"
)
: deleteMenu({ path: route.path, meta: route.meta }, "right");
break;
case 4:
//
selectRoute
? deleteMenu(
{
path: selectRoute.path,
meta: selectRoute.meta
},
"other"
)
: deleteMenu({ path: route.path, meta: route.meta }, "other");
break;
case 5:
//
routerArrays.splice(1, routerArrays.length);
st.routesInStorage = routerArrays;
router.push("/welcome");
break;
}
setTimeout(() => {
showMenuModel(route.fullPath);
});
}
//
function selectTag(key, item) {
onClickDrop(key, item, currentSelect.value);
}
function closeMenu() {
visible.value = false;
}
function showMenus(value: Boolean) {
Array.of(1, 2, 3, 4, 5).forEach(v => {
tagsViews.value[v].show = value;
});
}
function disabledMenus(value: Boolean) {
Array.of(1, 2, 3, 4, 5).forEach(v => {
tagsViews.value[v].disabled = value;
});
}
//
function showMenuModel(currentPath: string, refresh = false) {
let allRoute = unref(st.routesInStorage);
let routeLength = unref(st.routesInStorage).length;
// currentIndex1
let currentIndex = allRoute.findIndex(v => v.path === currentPath);
// currentIndexrouteLength-1
showMenus(true);
if (refresh) {
tagsViews.value[0].show = true;
}
if (currentIndex === 1 && routeLength !== 2) {
//
tagsViews.value[2].show = false;
Array.of(1, 3, 4, 5).forEach(v => {
tagsViews.value[v].disabled = false;
});
tagsViews.value[2].disabled = true;
} else if (currentIndex === 1 && routeLength === 2) {
disabledMenus(false);
//
Array.of(2, 3, 4).forEach(v => {
tagsViews.value[v].show = false;
tagsViews.value[v].disabled = true;
});
} else if (routeLength - 1 === currentIndex && currentIndex !== 0) {
//
tagsViews.value[3].show = false;
Array.of(1, 2, 4, 5).forEach(v => {
tagsViews.value[v].disabled = false;
});
tagsViews.value[3].disabled = true;
} else if (currentIndex === 0) {
//
disabledMenus(true);
} else {
disabledMenus(false);
}
}
function openMenu(tag, e) {
closeMenu();
if (tag.path === "/welcome") {
//
showMenus(false);
tagsViews.value[0].show = true;
} else if (route.path !== tag.path) {
//
tagsViews.value[0].show = false;
showMenuModel(tag.path);
// eslint-disable-next-line no-dupe-else-if
} else if (st.routesInStorage.length === 2 && route.path !== tag.path) {
showMenus(true);
//
tagsViews.value[4].show = false;
} else if (route.path === tag.path) {
//
showMenuModel(tag.path, true);
}
currentSelect.value = tag;
const menuMinWidth = 105;
const offsetLeft = unref(containerDom).getBoundingClientRect().left;
const offsetWidth = unref(containerDom).offsetWidth;
const maxLeft = offsetWidth - menuMinWidth;
const left = e.clientX - offsetLeft + 5;
if (left > maxLeft) {
buttonLeft.value = maxLeft;
} else {
buttonLeft.value = left;
}
buttonTop.value = e.clientY + 10;
setTimeout(() => {
visible.value = true;
}, 10);
}
// tags
function tagOnClick(item) {
showMenuModel(item.path);
}
//
function onMouseenter(item, index) {
if (index) activeIndex.value = index;
if (unref(showModel) === "smart") {
if (hasClass(instance.refs["schedule" + index], "schedule-active"))
return;
toggleClass(true, "schedule-in", instance.refs["schedule" + index]);
toggleClass(false, "schedule-out", instance.refs["schedule" + index]);
} else {
if (hasClass(instance.refs["dynamic" + index], "card-active")) return;
toggleClass(true, "card-in", instance.refs["dynamic" + index]);
toggleClass(false, "card-out", instance.refs["dynamic" + index]);
}
}
//
function onMouseleave(item, index) {
activeIndex.value = -1;
if (unref(showModel) === "smart") {
if (hasClass(instance.refs["schedule" + index], "schedule-active"))
return;
toggleClass(false, "schedule-in", instance.refs["schedule" + index]);
toggleClass(true, "schedule-out", instance.refs["schedule" + index]);
} else {
if (hasClass(instance.refs["dynamic" + index], "card-active")) return;
toggleClass(false, "card-in", instance.refs["dynamic" + index]);
toggleClass(true, "card-out", instance.refs["dynamic" + index]);
}
}
watch(
() => visible.value,
val => {
if (val) {
document.body.addEventListener("click", closeMenu);
} else {
document.body.removeEventListener("click", closeMenu);
}
}
);
onBeforeMount(() => {
if (!instance) return;
st = instance.appContext.app.config.globalProperties.$storage;
routerArrays = st.routesInStorage ?? routerArrays;
//
showMenuModel(route.fullPath);
//
emitter.on("tagViewsChange", key => {
if (unref(showTags) === key) return;
showTags.value = key;
});
//
emitter.on("tagViewsShowModel", key => {
showModel.value = key;
});
//
emitter.on("changLayoutRoute", ({ indexPath, parentPath }) => {
dynamicRouteTag(indexPath, parentPath);
setTimeout(() => {
showMenuModel(indexPath);
});
});
});
return {
deleteMenu,
showTags,
onFresh,
tagsViews,
onClickDrop,
visible,
buttonLeft,
buttonTop,
openMenu,
closeMenu,
selectTag,
currentSelect,
onMouseenter,
onMouseleave,
tagOnClick,
activeIndex,
showModel,
showMenuModel
};
}
};
</script>
<style lang="scss" scoped>
@keyframes scheduleInWidth {
from {

View File

@ -1,16 +1,5 @@
<script lang="ts">
let routerArrays: Array<object> = [
{
path: "/welcome",
parentPath: "/",
meta: {
title: "message.hshome",
icon: "el-icon-s-home",
showLink: true,
savedPosition: false
}
}
];
import { routerArrays } from "./types";
export default {
computed: {
layout() {
@ -204,7 +193,6 @@ onBeforeMount(() => {
</style>
<style lang="scss" scoped>
$sideBarWidth: 210px;
@mixin clearfix {
&::after {
content: "";
@ -241,7 +229,7 @@ $sideBarWidth: 210px;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$sideBarWidth});
width: calc(100% - 210px);
transition: width 0.28s;
}

23
src/layout/types.ts Normal file
View File

@ -0,0 +1,23 @@
export type RouteConfigs = {
path?: string;
parentPath?: string;
meta?: {
title?: string;
icon?: string;
showLink?: boolean;
savedPosition?: boolean;
};
};
export const routerArrays: Array<RouteConfigs> = [
{
path: "/welcome",
parentPath: "/",
meta: {
title: "message.hshome",
icon: "el-icon-s-home",
showLink: true,
savedPosition: false
}
}
];

View File

@ -179,7 +179,7 @@
}
}
.iconinternationality {
.globalization {
height: 62px;
width: 40px;
padding: 11px;