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> <template>
<el-descriptions <el-descriptions
class="margin-top" class="margin-top"
@ -75,17 +86,6 @@
</el-descriptions> </el-descriptions>
</template> </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> <style scoped>
.el-tag--mini { .el-tag--mini {
margin-right: 10px !important; 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> <template>
<div class="navbar"> <div class="navbar">
<Hamburger <Hamburger
@ -13,7 +69,7 @@
<screenfull v-show="!deviceDetection()" /> <screenfull v-show="!deviceDetection()" />
<!-- 国际化 --> <!-- 国际化 -->
<el-dropdown trigger="click"> <el-dropdown trigger="click">
<iconinternationality /> <globalization />
<template #dropdown> <template #dropdown>
<el-dropdown-menu class="translation"> <el-dropdown-menu class="translation">
<el-dropdown-item <el-dropdown-item
@ -60,99 +116,6 @@
</div> </div>
</template> </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> <style lang="scss" scoped>
.navbar { .navbar {
width: 100%; width: 100%;
@ -190,7 +153,7 @@ export default defineComponent({
} }
} }
.iconinternationality { .globalization {
height: 48px; height: 48px;
width: 40px; width: 40px;
padding: 11px; padding: 11px;

View File

@ -1,81 +1,6 @@
<template> <script setup lang="ts">
<div class="horizontal-header">
<div class="horizontal-header-left" @click="backHome">
<i class="fa fa-optin-monster"></i>
<h4>{{ settings.title }}</h4>
</div>
<el-menu
ref="menu"
:default-active="activeMenu"
unique-opened
router
class="horizontal-header-menu"
mode="horizontal"
@select="menuSelect"
>
<sidebar-item
v-for="route in routeStore.wholeRoutes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
<div class="horizontal-header-right">
<!-- 全屏 -->
<screenfull v-show="!deviceDetection()" />
<!-- 国际化 -->
<el-dropdown trigger="click">
<iconinternationality />
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="{
background: locale === 'zh' ? '#1b2a47' : '',
color: locale === 'zh' ? '#f4f4f5' : '#000'
}"
@click="translationCh"
>简体中文</el-dropdown-item
>
<el-dropdown-item
:style="{
background: locale === 'en' ? '#1b2a47' : '',
color: locale === 'en' ? '#f4f4f5' : '#000'
}"
@click="translationEn"
>English</el-dropdown-item
>
</el-dropdown-menu>
</template>
</el-dropdown>
<!-- 退出登陆 -->
<el-dropdown trigger="click">
<span class="el-dropdown-link">
<img
src="https://avatars.githubusercontent.com/u/44761321?s=400&u=30907819abd29bb3779bc247910873e7c7f7c12f&v=4"
/>
<p>{{ usename }}</p>
</span>
<template #dropdown>
<el-dropdown-menu class="logout">
<el-dropdown-item icon="el-icon-switch-button" @click="logout">{{
$t("message.hsLoginOut")
}}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<i
class="el-icon-setting"
:title="$t('message.hssystemSet')"
@click="onPanel"
></i>
</div>
</div>
</template>
<script lang="ts">
import { import {
computed, computed,
defineComponent,
unref, unref,
watch, watch,
nextTick, nextTick,
@ -92,54 +17,12 @@ import screenfull from "../screenfull/index.vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import { storageSession } from "/@/utils/storage"; import { storageSession } from "/@/utils/storage";
import { deviceDetection } from "/@/utils/deviceDetection"; import { deviceDetection } from "/@/utils/deviceDetection";
import globalization from "/@/assets/svg/globalization.svg";
import { usePermissionStoreHook } from "/@/store/modules/permission"; 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 = const instance =
getCurrentInstance().appContext.config.globalProperties.$storage; getCurrentInstance().appContext.config.globalProperties.$storage;
const menuRef = templateRef<ElRef | null>("menu", null); const menuRef = templateRef<ElRef | null>("menu", null);
const routeStore = usePermissionStoreHook(); const routeStore = usePermissionStoreHook();
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
@ -224,25 +107,82 @@ export default defineComponent({
handleResize(); handleResize();
}); });
}); });
return {
locale,
usename,
settings,
routeStore,
activeMenu,
logout,
onPanel,
backHome,
menuSelect,
translationCh,
translationEn,
deviceDetection
};
}
});
</script> </script>
<template>
<div class="horizontal-header">
<div class="horizontal-header-left" @click="backHome">
<i class="fa fa-optin-monster"></i>
<h4>{{ settings.title }}</h4>
</div>
<el-menu
ref="menu"
:default-active="activeMenu"
unique-opened
router
class="horizontal-header-menu"
mode="horizontal"
@select="menuSelect"
>
<sidebar-item
v-for="route in routeStore.wholeRoutes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
<div class="horizontal-header-right">
<!-- 全屏 -->
<screenfull v-show="!deviceDetection()" />
<!-- 国际化 -->
<el-dropdown trigger="click">
<globalization />
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="{
background: locale === 'zh' ? '#1b2a47' : '',
color: locale === 'zh' ? '#f4f4f5' : '#000'
}"
@click="translationCh"
>简体中文</el-dropdown-item
>
<el-dropdown-item
:style="{
background: locale === 'en' ? '#1b2a47' : '',
color: locale === 'en' ? '#f4f4f5' : '#000'
}"
@click="translationEn"
>English</el-dropdown-item
>
</el-dropdown-menu>
</template>
</el-dropdown>
<!-- 退出登陆 -->
<el-dropdown trigger="click">
<span class="el-dropdown-link">
<img
src="https://avatars.githubusercontent.com/u/44761321?s=400&u=30907819abd29bb3779bc247910873e7c7f7c12f&v=4"
/>
<p>{{ usename }}</p>
</span>
<template #dropdown>
<el-dropdown-menu class="logout">
<el-dropdown-item icon="el-icon-switch-button" @click="logout">{{
$t("message.hsLoginOut")
}}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<i
class="el-icon-setting"
:title="$t('message.hssystemSet')"
@click="onPanel"
></i>
</div>
</div>
</template>
<style lang="scss" scoped> <style lang="scss" scoped>
.translation { .translation {
.el-dropdown-menu__item { .el-dropdown-menu__item {

View File

@ -1,52 +1,22 @@
<template> <script setup lang="ts">
<div :class="['sidebar-container', showLogo ? 'has-logo' : '']">
<Logo v-if="showLogo === '1'" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
unique-opened
router
:collapse-transition="false"
mode="vertical"
@select="menuSelect"
>
<sidebar-item
v-for="route in routeStore.wholeRoutes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
</el-scrollbar>
</div>
</template>
<script lang="ts">
import Logo from "./logo.vue"; import Logo from "./logo.vue";
import { emitter } from "/@/utils/mitt"; import { emitter } from "/@/utils/mitt";
import SidebarItem from "./sidebarItem.vue"; import SidebarItem from "./sidebarItem.vue";
import { algorithm } from "/@/utils/algorithm"; import { algorithm } from "/@/utils/algorithm";
import { storageLocal } from "/@/utils/storage"; import { storageLocal } from "/@/utils/storage";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import { computed, ref, onBeforeMount } from "vue";
import { useAppStoreHook } from "/@/store/modules/app"; import { useAppStoreHook } from "/@/store/modules/app";
import { computed, defineComponent, ref, onBeforeMount } from "vue";
import { usePermissionStoreHook } from "/@/store/modules/permission"; 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 route = useRoute();
const pureApp = useAppStoreHook();
const router = useRouter().options.routes;
const routeStore = usePermissionStoreHook();
const showLogo = ref(storageLocal.getItem("logoVal") || "1"); const showLogo = ref(storageLocal.getItem("logoVal") || "1");
const isCollapse = computed(() => {
return !pureApp.getSidebarStatus;
});
const activeMenu = computed(() => { const activeMenu = computed(() => {
const { meta, path } = route; const { meta, path } = route;
if (meta.activeMenu) { if (meta.activeMenu) {
@ -84,14 +54,28 @@ export default defineComponent({
showLogo.value = key; showLogo.value = key;
}); });
}); });
return {
activeMenu,
isCollapse: computed(() => !pureApp.getSidebarStatus),
menuSelect,
showLogo,
routeStore
};
}
});
</script> </script>
<template>
<div :class="['sidebar-container', showLogo ? 'has-logo' : '']">
<Logo v-if="showLogo === '1'" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
unique-opened
router
:collapse-transition="false"
mode="vertical"
@select="menuSelect"
>
<sidebar-item
v-for="route in routeStore.wholeRoutes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
</el-scrollbar>
</div>
</template>

View File

@ -1,93 +1,14 @@
<template>
<div ref="containerDom" class="tags-view" v-if="!showTags">
<el-scrollbar wrap-class="scrollbar-wrapper" class="scroll-container">
<div
v-for="(item, index) in dynamicTagList"
:key="index"
:ref="'dynamic' + index"
:class="[
'scroll-item is-closable',
$route.path === item.path ? 'is-active' : '',
$route.path === item.path && showModel === 'card' ? 'card-active' : ''
]"
@contextmenu.prevent="openMenu(item, $event)"
@mouseenter.prevent="onMouseenter(item, index)"
@mouseleave.prevent="onMouseleave(item, index)"
>
<router-link :to="item.path" @click="tagOnClick(item)">{{
$t(item.meta.title)
}}</router-link>
<span
v-if="
($route.path === item.path && index !== 0) ||
(index === activeIndex && index !== 0)
"
class="el-icon-close"
@click="deleteMenu(item)"
></span>
<div
:ref="'schedule' + index"
v-if="showModel !== 'card'"
:class="[$route.path === item.path ? 'schedule-active' : '']"
></div>
</div>
</el-scrollbar>
<!-- 右键菜单按钮 -->
<transition name="el-zoom-in-top">
<ul
v-show="visible"
:key="Math.random()"
:style="{ left: buttonLeft + 'px', top: buttonTop + 'px' }"
class="contextmenu"
>
<div
v-for="(item, key) in tagsViews"
:key="key"
style="display: flex; align-items: center"
>
<li v-if="item.show" @click="selectTag(key, item)">
<component :is="item.icon" :key="key" />
{{ item.text }}
</li>
</div>
</ul>
</transition>
<!-- 右侧功能按钮 -->
<ul class="right-button">
<li>
<i
:title="$t('message.hsrefreshRoute')"
class="el-icon-refresh-right rotate"
@click="onFresh"
></i>
</li>
<li>
<el-dropdown trigger="click" placement="bottom-end">
<i class="el-icon-arrow-down"></i>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="(item, key) in tagsViews"
:key="key"
:divided="item.divided"
:disabled="item.disabled"
@click="onClickDrop(key, item)"
>
<component :is="item.icon" :key="key" />
{{ item.text }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</li>
<li>
<slot></slot>
</li>
</ul>
</div>
</template>
<script lang="ts"> <script lang="ts">
export default {
computed: {
dynamicTagList() {
return this.$storage.routesInStorage;
}
}
};
</script>
<script setup lang="ts">
import { import {
ref, ref,
watch, watch,
@ -96,20 +17,29 @@ import {
nextTick, nextTick,
getCurrentInstance getCurrentInstance
} from "vue"; } from "vue";
import { useRoute, useRouter } from "vue-router"; import { RouteConfigs } from "../../types";
import { storageLocal } from "/@/utils/storage";
import { emitter } from "/@/utils/mitt"; import { emitter } from "/@/utils/mitt";
import { toggleClass, removeClass, hasClass } from "/@/utils/operate";
import { templateRef } from "@vueuse/core"; import { templateRef } from "@vueuse/core";
import closeOther from "/@/assets/svg/close_other.svg"; import { storageLocal } from "/@/utils/storage";
import closeLeft from "/@/assets/svg/close_left.svg"; import { useRoute, useRouter } from "vue-router";
import closeRight from "/@/assets/svg/close_right.svg"; import { toggleClass, removeClass, hasClass } from "/@/utils/operate";
import close from "/@/assets/svg/close.svg"; import close from "/@/assets/svg/close.svg";
import refresh from "/@/assets/svg/refresh.svg"; import refresh from "/@/assets/svg/refresh.svg";
import closeAll from "/@/assets/svg/close_all.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"; let refreshButton = "refresh-button";
let routerArrays: Array<object> = [ 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", path: "/welcome",
parentPath: "/", parentPath: "/",
@ -121,69 +51,44 @@ let routerArrays: Array<object> = [
} }
} }
]; ];
const tagsViews = ref<ForDataType<undefined>>([
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", icon: refresh,
text: "重新加载", text: "重新加载",
divided: false, divided: false,
disabled: false, disabled: false,
show: true show: true
}, },
{ {
icon: "close", icon: close,
text: "关闭当前标签页", text: "关闭当前标签页",
divided: false, divided: false,
disabled: routerArrays.length > 1 ? false : true, disabled: routerArrays.length > 1 ? false : true,
show: true show: true
}, },
{ {
icon: "closeLeft", icon: closeLeft,
text: "关闭左侧标签页", text: "关闭左侧标签页",
divided: true, divided: true,
disabled: routerArrays.length > 1 ? false : true, disabled: routerArrays.length > 1 ? false : true,
show: true show: true
}, },
{ {
icon: "closeRight", icon: closeRight,
text: "关闭右侧标签页", text: "关闭右侧标签页",
divided: false, divided: false,
disabled: routerArrays.length > 1 ? false : true, disabled: routerArrays.length > 1 ? false : true,
show: true show: true
}, },
{ {
icon: "closeOther", icon: closeOther,
text: "关闭其他标签页", text: "关闭其他标签页",
divided: true, divided: true,
disabled: routerArrays.length > 2 ? false : true, disabled: routerArrays.length > 2 ? false : true,
show: true show: true
}, },
{ {
icon: "closeAll", icon: closeAll,
text: "关闭全部标签页", text: "关闭全部标签页",
divided: false, divided: false,
disabled: routerArrays.length > 1 ? false : true, disabled: routerArrays.length > 1 ? false : true,
@ -248,13 +153,9 @@ export default {
return item.path === obj.path; return item.path === obj.path;
}); });
const spliceRoute = ( const spliceRoute = (start?: number, end?: number, other?: boolean): void => {
start?: number,
end?: number,
other?: boolean
): void => {
if (other) { if (other) {
st.routesInStorage = routerArrays = [ st.routesInStorage = [
{ {
path: "/welcome", path: "/welcome",
parentPath: "/", parentPath: "/",
@ -267,6 +168,7 @@ export default {
}, },
obj obj
]; ];
routerArrays = st.routesInStorage;
} else { } else {
routerArrays.splice(start, end); routerArrays.splice(start, end);
st.routesInStorage = routerArrays; st.routesInStorage = routerArrays;
@ -300,7 +202,7 @@ export default {
deleteDynamicTag(item, item.path, tag); deleteDynamicTag(item, item.path, tag);
} }
function onClickDrop(key, item, selectRoute) { function onClickDrop(key, item, selectRoute?: RouteConfigs) {
if (item && item.disabled) return; if (item && item.disabled) return;
// //
switch (key) { switch (key) {
@ -471,8 +373,7 @@ export default {
function onMouseenter(item, index) { function onMouseenter(item, index) {
if (index) activeIndex.value = index; if (index) activeIndex.value = index;
if (unref(showModel) === "smart") { if (unref(showModel) === "smart") {
if (hasClass(instance.refs["schedule" + index], "schedule-active")) if (hasClass(instance.refs["schedule" + index], "schedule-active")) return;
return;
toggleClass(true, "schedule-in", instance.refs["schedule" + index]); toggleClass(true, "schedule-in", instance.refs["schedule" + index]);
toggleClass(false, "schedule-out", instance.refs["schedule" + index]); toggleClass(false, "schedule-out", instance.refs["schedule" + index]);
} else { } else {
@ -486,8 +387,7 @@ export default {
function onMouseleave(item, index) { function onMouseleave(item, index) {
activeIndex.value = -1; activeIndex.value = -1;
if (unref(showModel) === "smart") { if (unref(showModel) === "smart") {
if (hasClass(instance.refs["schedule" + index], "schedule-active")) if (hasClass(instance.refs["schedule" + index], "schedule-active")) return;
return;
toggleClass(false, "schedule-in", instance.refs["schedule" + index]); toggleClass(false, "schedule-in", instance.refs["schedule" + index]);
toggleClass(true, "schedule-out", instance.refs["schedule" + index]); toggleClass(true, "schedule-out", instance.refs["schedule" + index]);
} else { } else {
@ -535,31 +435,97 @@ export default {
}); });
}); });
}); });
return {
deleteMenu,
showTags,
onFresh,
tagsViews,
onClickDrop,
visible,
buttonLeft,
buttonTop,
openMenu,
closeMenu,
selectTag,
currentSelect,
onMouseenter,
onMouseleave,
tagOnClick,
activeIndex,
showModel,
showMenuModel
};
}
};
</script> </script>
<template>
<div ref="containerDom" class="tags-view" v-if="!showTags">
<el-scrollbar wrap-class="scrollbar-wrapper" class="scroll-container">
<div
v-for="(item, index) in dynamicTagList"
:key="index"
:ref="'dynamic' + index"
:class="[
'scroll-item is-closable',
$route.path === item.path ? 'is-active' : '',
$route.path === item.path && showModel === 'card' ? 'card-active' : ''
]"
@contextmenu.prevent="openMenu(item, $event)"
@mouseenter.prevent="onMouseenter(item, index)"
@mouseleave.prevent="onMouseleave(item, index)"
>
<router-link :to="item.path" @click="tagOnClick(item)">{{
$t(item.meta.title)
}}</router-link>
<span
v-if="
($route.path === item.path && index !== 0) ||
(index === activeIndex && index !== 0)
"
class="el-icon-close"
@click="deleteMenu(item)"
></span>
<div
:ref="'schedule' + index"
v-if="showModel !== 'card'"
:class="[$route.path === item.path ? 'schedule-active' : '']"
></div>
</div>
</el-scrollbar>
<!-- 右键菜单按钮 -->
<transition name="el-zoom-in-top">
<ul
v-show="visible"
:key="Math.random()"
:style="{ left: buttonLeft + 'px', top: buttonTop + 'px' }"
class="contextmenu"
>
<div
v-for="(item, key) in tagsViews"
:key="key"
style="display: flex; align-items: center"
>
<li v-if="item.show" @click="selectTag(key, item)">
<component :is="item.icon" :key="key" />
{{ item.text }}
</li>
</div>
</ul>
</transition>
<!-- 右侧功能按钮 -->
<ul class="right-button">
<li>
<i
:title="$t('message.hsrefreshRoute')"
class="el-icon-refresh-right rotate"
@click="onFresh"
></i>
</li>
<li>
<el-dropdown trigger="click" placement="bottom-end">
<i class="el-icon-arrow-down"></i>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="(item, key) in tagsViews"
:key="key"
:divided="item.divided"
:disabled="item.disabled"
@click="onClickDrop(key, item)"
>
<component :is="item.icon" :key="key" />
{{ item.text }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</li>
<li>
<slot></slot>
</li>
</ul>
</div>
</template>
<style lang="scss" scoped> <style lang="scss" scoped>
@keyframes scheduleInWidth { @keyframes scheduleInWidth {
from { from {

View File

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