Template
1
0
mirror of https://github.com/un-pany/v3-admin-vite.git synced 2025-04-22 03:49:19 +08:00

feat: upgrade tags view

This commit is contained in:
蔡开奕 2022-09-30 14:59:15 +08:00
parent e0aaa704a7
commit 249ad05925
2 changed files with 97 additions and 77 deletions

View File

@ -1,13 +1,9 @@
<script lang="ts" setup>
import { getCurrentInstance, onMounted, ref, watch } from "vue"
import { useRoute, useRouter } from "vue-router"
import type { RouteRecordRaw } from "vue-router"
import { useTagsViewStore } from "@/store/modules/tags-view"
import type { ITagView } from "@/store/modules/tags-view"
import { getCurrentInstance, ref, onMounted, watch } from "vue"
import { RouteRecordRaw, useRoute, useRouter } from "vue-router"
import { useTagsViewStore, ITagView } from "@/store/modules/tags-view"
import { usePermissionStore } from "@/store/modules/permission"
import ScrollPane from "./ScrollPane.vue"
import path from "path-browserify"
import { Close } from "@element-plus/icons-vue"
const instance = getCurrentInstance()
const router = useRouter()
@ -29,6 +25,26 @@ const isAffix = (tag: ITagView) => {
return tag.meta?.affix
}
// click tab
const clickTab = (pane: any) => {
// actively jump route if not currently active
if (!pane.active) {
for (const v of tagsViewStore.visitedViews) {
if (v.fullPath && v.path === pane.paneName) {
router.push(v.fullPath)
break
}
}
}
}
// remove tab
const removeTab = (pane: any) => {
closeSelectedTag({
path: pane
})
}
const filterAffixTags = (routes: RouteRecordRaw[], basePath = "/") => {
let tags: ITagView[] = []
routes.forEach((route) => {
@ -158,22 +174,25 @@ onMounted(() => {
<template>
<div class="tags-view-container">
<ScrollPane class="tags-view-wrapper">
<router-link
<el-tabs
class="tags-view-tabs"
:model-value="route.path"
type="card"
closable
@tab-remove="removeTab"
@tab-click="clickTab"
>
<el-tab-pane
v-for="tag in tagsViewStore.visitedViews"
:key="tag.path"
:class="isActive(tag) ? 'active' : ''"
:to="{ path: tag.path, query: tag.query }"
class="tags-view-item"
@click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
@contextmenu.prevent="openMenu(tag, $event)"
:name="tag.path"
>
{{ tag.meta?.title }}
<el-icon v-if="!isAffix(tag)" :size="12" @click.prevent.stop="closeSelectedTag(tag)">
<Close />
</el-icon>
</router-link>
</ScrollPane>
<template #label>
<div class="tags-view-item-link" @contextmenu.prevent="openMenu(tag, $event)">
{{ tag?.meta?.title }}
</div>
</template>
</el-tab-pane>
</el-tabs>
<ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
<li @click="refreshSelectedTag(selectedTag)">刷新</li>
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">关闭</li>
@ -185,53 +204,59 @@ onMounted(() => {
<style lang="scss" scoped>
.tags-view-container {
height: var(--v3-tagsview-height);
width: 100%;
background-color: #fff;
border-bottom: 1px solid #d8dce5;
box-shadow: 0 1px 3px 0 #00000010, 0 0 3px 0 #00000010;
.tags-view-wrapper {
.tags-view-item {
display: inline-block;
position: relative;
cursor: pointer;
height: 26px;
line-height: 26px;
border: 1px solid var(--v3-tagsview-tag-border-color);
color: var(--v3-tagsview-tag-text-color);
background-color: var(--v3-tagsview-tag-bg-color);
padding: 0 8px;
font-size: 12px;
margin-left: 5px;
margin-top: 4px;
&:first-of-type {
margin-left: 15px;
.tags-view-tabs {
height: var(--v3-tagsview-height);
margin: var(--v3-tagsview-margin);
user-select: none;
:deep(.el-tabs__header) {
margin-bottom: 0;
border: none;
.el-tabs__nav-next,
.el-tabs__nav-prev {
height: 30px;
display: flex;
align-items: center;
background-color: #ffffff;
border-radius: var(--v3-tagsview-border-radius);
color: #000000;
}
&:last-of-type {
margin-right: 15px;
}
&.active {
background-color: var(--v3-tagsview-tag-active-bg-color);
color: var(--v3-tagsview-tag-active-text-color);
border-color: var(--v3-tagsview-tag-active-border-color);
&::before {
content: "";
background-color: var(--v3-tagsview-tag-active-before-color);
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
position: relative;
margin-right: 2px;
}
}
.el-icon {
margin: 0 2px;
vertical-align: middle;
border-radius: 50%;
&:hover {
background-color: var(--v3-tagsview-tag-icon-hover-bg-color);
color: var(--v3-tagsview-tag-icon-hover-color);
.el-tabs__nav {
border: none;
.el-tabs__item {
display: inline-flex;
align-items: center;
border: none;
border-radius: var(--v3-tagsview-border-radius);
height: 30px;
line-height: 30px;
padding: 0 var(--v3-tagsview-gap);
background-color: #fff;
font-size: 12px;
margin-right: var(--v3-tagsview-gap);
&:first-of-type {
.is-icon-close {
display: none;
}
}
&:last-of-type {
margin-right: 0;
}
&:hover .is-icon-close,
&.is-active .is-icon-close,
.is-icon-close:hover {
width: 12px;
height: 12px;
}
.is-icon-close {
top: 0;
&:hover {
background-color: var(--v3-tagsview-tag-active-bg-color);
}
svg {
margin-top: 0;
}
}
}
}
}

View File

@ -4,7 +4,7 @@
/** 全局背景色 */
--v3-body-bg-color: #f0f2f5;
/** Header 区域 = NavigationBar 组件 + TagsView 组件 */
--v3-header-height: calc(var(--v3-navigationbar-height) + var(--v3-tagsview-height));
--v3-header-height: calc(var(--v3-navigationbar-height) + var(--v3-tagsview-height) + var(--v3-tagsview-margin));
/** NavigationBar 组件 */
--v3-navigationbar-height: 50px;
/** Sidebar 组件 */
@ -19,16 +19,11 @@
/** SidebarLogo 组件 */
--v3-sidebarlogo-bg-color: #0c202b;
/** TagsView 组件 */
--v3-tagsview-height: 34px;
--v3-tagsview-tag-text-color: #495060;
--v3-tagsview-tag-active-text-color: #ffffff;
--v3-tagsview-tag-bg-color: #ffffff;
--v3-tagsview-height: 30px;
--v3-tagsview-margin: 20px;
--v3-tagsview-gap: 10px;
--v3-tagsview-border-radius: 4px;
--v3-tagsview-tag-active-bg-color: #409eff;
--v3-tagsview-tag-border-color: #d8dce5;
--v3-tagsview-tag-active-border-color: #409eff;
--v3-tagsview-tag-active-before-color: #ffffff;
--v3-tagsview-tag-icon-hover-bg-color: #00000030;
--v3-tagsview-tag-icon-hover-color: #ffffff;
/** RightPanel 组件 */
--v3-rightpanel-button-bg-color: #152d3d;
}