From 0b79b6557567a56cbeb653a5869b5f927285b4e2 Mon Sep 17 00:00:00 2001 From: xiaoxian521 <1923740402@qq.com> Date: Fri, 19 Nov 2021 15:13:28 +0800 Subject: [PATCH] refactor: tag --- src/assets/svg/arrow-left.svg | 1 + src/assets/svg/arrow-right.svg | 1 + src/layout/components/tag/index.scss | 303 ++++++++++++++++++ src/layout/components/tag/index.vue | 405 ++++++------------------- src/layout/theme/auroraGreen-vars.scss | 3 +- src/layout/theme/default-vars.scss | 27 +- src/layout/theme/dusk-vars.scss | 3 +- src/layout/theme/light-vars.scss | 2 +- src/layout/theme/mingQing-vars.scss | 3 +- src/layout/theme/pink-vars.scss | 3 +- src/layout/theme/saucePurple-vars.scss | 3 +- src/layout/theme/volcano-vars.scss | 3 +- src/layout/theme/yellow-vars.scss | 3 +- src/layout/types.ts | 6 + src/style/element-plus.scss | 6 - src/style/index.scss | 4 +- src/style/sidebar.scss | 28 +- src/style/transition.scss | 2 - vite.config.ts | 9 - 19 files changed, 439 insertions(+), 376 deletions(-) create mode 100644 src/assets/svg/arrow-left.svg create mode 100644 src/assets/svg/arrow-right.svg create mode 100644 src/layout/components/tag/index.scss diff --git a/src/assets/svg/arrow-left.svg b/src/assets/svg/arrow-left.svg new file mode 100644 index 000000000..b7fa5b5f2 --- /dev/null +++ b/src/assets/svg/arrow-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg/arrow-right.svg b/src/assets/svg/arrow-right.svg new file mode 100644 index 000000000..2dd67a0ba --- /dev/null +++ b/src/assets/svg/arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/layout/components/tag/index.scss b/src/layout/components/tag/index.scss new file mode 100644 index 000000000..3e2100496 --- /dev/null +++ b/src/layout/components/tag/index.scss @@ -0,0 +1,303 @@ +@keyframes scheduleInWidth { + from { + width: 0; + } + + to { + width: 100%; + } +} + +@keyframes scheduleOutWidth { + from { + width: 100%; + } + + to { + width: 0; + } +} + +@-webkit-keyframes rotate { + from { + -webkit-transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + } +} + +@-moz-keyframes rotate { + from { + -moz-transform: rotate(0deg); + } + + to { + -moz-transform: rotate(360deg); + } +} + +@-o-keyframes rotate { + from { + -o-transform: rotate(0deg); + } + + to { + -o-transform: rotate(360deg); + } +} + +@keyframes rotate { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +.tags-view { + width: 100%; + font-size: 14px; + display: flex; + align-items: center; + box-shadow: 0 0 1px #888; + + .scroll-item { + border-radius: 3px 3px 0 0; + padding: 2px 6px; + display: inline-block; + position: relative; + margin-right: 4px; + height: 28px; + line-height: 25px; + transition: all 0.4s; + + .el-icon-close { + font-size: 10px; + color: #1890ff; + cursor: pointer; + + &:hover { + border-radius: 50%; + color: #fff; + background: #b4bccc; + font-size: 14px; + } + } + + &.is-closable:not(:first-child) { + &:hover { + padding-right: 8px; + } + } + } + + a { + text-decoration: none; + color: #666; + padding: 0 4px 0 4px; + } + + .scroll-container { + flex: 1; + overflow: hidden; + padding: 5px 0; + white-space: nowrap; + position: relative; + + .tab { + position: relative; + float: left; + list-style: none; + overflow: visible; + white-space: nowrap; + transition: transform 0.5s ease-in-out; + + .scroll-item { + &:nth-child(1) { + margin-left: 5px; + } + } + } + + .scrollbar-wrapper { + position: absolute; + height: 40px; + overflow-x: hidden !important; + } + } + + .right-button { + display: flex; + align-items: center; + font-size: 16px; + + li { + width: 40px; + height: 38px; + line-height: 38px; + text-align: center; + border-right: 1px solid #ccc; + cursor: pointer; + } + } + + /* 右键菜单 */ + .contextmenu { + margin: 0; + background: #fff; + position: absolute; + list-style-type: none; + padding: 5px 0; + border-radius: 4px; + color: #000000d9; + font-weight: normal; + font-size: 13px; + white-space: nowrap; + outline: 0; + box-shadow: 0 2px 8px rgb(0 0 0 / 15%); + + li { + width: 100%; + margin: 0; + padding: 7px 12px; + cursor: pointer; + display: flex; + align-items: center; + + &:hover { + background: #eee; + } + + svg { + display: block; + margin-right: 0.5em; + } + } + } +} + +.el-dropdown-menu { + padding: 0; + + li { + width: 100%; + margin: 0; + padding: 0 12px; + cursor: pointer; + display: flex; + align-items: center; + + svg { + display: block; + margin-right: 0.5em; + } + } +} + +.el-dropdown-menu__item:not(.is-disabled):hover { + color: #606266; + background: #f0f0f0; +} + +:deep(.el-dropdown-menu__item) i { + margin-right: 10px; +} + +.el-dropdown-menu__item--divided::before { + margin: 0; +} + +.el-dropdown-menu__item.is-disabled { + cursor: not-allowed; +} + +.is-active { + background-color: #eaf4fe; + position: relative; + color: #fff; + + a { + color: #1890ff; + } +} + +.icon-left { + &:hover { + cursor: w-resize; + } +} + +.icon-right { + &:hover { + cursor: e-resize; + } +} + +/* 卡片模式 */ +.card-active { + border: 1px solid #1890ff; +} + +/* 卡片模式下鼠标移入显示蓝色边框 */ +.card-in { + border: 1px solid #1890ff; + color: #1890ff; + + a { + color: #1890ff; + } +} + +/* 卡片模式下鼠标移出隐藏蓝色边框 */ +.card-out { + border: none; + color: #666; + + a { + color: #666; + } +} + +/* 灵动模式 */ +.schedule-active { + width: 100%; + height: 2px; + position: absolute; + left: 0; + bottom: 0; + background: #1890ff; +} + +/* 灵动模式下鼠标移入显示蓝色进度条 */ +.schedule-in { + width: 100%; + height: 2px; + position: absolute; + left: 0; + bottom: 0; + background: #1890ff; + animation: scheduleInWidth 400ms ease-in; +} + +/* 灵动模式下鼠标移出隐藏蓝色进度条 */ +.schedule-out { + width: 0; + height: 2px; + position: absolute; + left: 0; + bottom: 0; + background: #1890ff; + animation: scheduleOutWidth 400ms ease-in; +} + +/* 刷新按钮动画效果 */ +.refresh-button { + -webkit-animation: rotate 600ms linear infinite; + -moz-animation: rotate 600ms linear infinite; + -o-animation: rotate 600ms linear infinite; + animation: rotate 600ms linear infinite; +} diff --git a/src/layout/components/tag/index.vue b/src/layout/components/tag/index.vue index 161cabd3c..99935ee61 100644 --- a/src/layout/components/tag/index.vue +++ b/src/layout/components/tag/index.vue @@ -24,33 +24,63 @@ import { getCurrentInstance, ComputedRef } from "vue"; -import { RouteConfigs, relativeStorageType, tagsViewsType } from "../../types"; -import { emitter } from "/@/utils/mitt"; -import { templateRef } from "@vueuse/core"; -import { handleAliveRoute, delAliveRoutes } from "/@/router"; -import { storageLocal } from "/@/utils/storage"; -import { useRoute, useRouter } from "vue-router"; -import { usePermissionStoreHook } from "/@/store/modules/permission"; -import { toggleClass, removeClass, hasClass } from "/@/utils/operate"; -import { transformI18n } from "/@/utils/i18n"; 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 arrowLeft from "/@/assets/svg/arrow-left.svg"; +import arrowRight from "/@/assets/svg/arrow-right.svg"; import closeOther from "/@/assets/svg/close_other.svg"; import closeRight from "/@/assets/svg/close_right.svg"; -let refreshButton = "refresh-button"; -const instance = getCurrentInstance(); +import { emitter } from "/@/utils/mitt"; +import { templateRef } from "@vueuse/core"; +import { transformI18n } from "/@/utils/i18n"; +import { storageLocal } from "/@/utils/storage"; +import { useRoute, useRouter } from "vue-router"; +import { handleAliveRoute, delAliveRoutes } from "/@/router"; +import { usePermissionStoreHook } from "/@/store/modules/permission"; +import { toggleClass, removeClass, hasClass } from "/@/utils/operate"; +import { + RouteConfigs, + relativeStorageType, + tagsViewsType, + scrollbarDomType +} from "../../types"; -// 响应式storage -let relativeStorage: relativeStorageType; const route = useRoute(); const router = useRouter(); +const translateX = ref(0); +const activeIndex = ref(-1); +let refreshButton = "refresh-button"; +const instance = getCurrentInstance(); +let relativeStorage: relativeStorageType; const showTags = ref(storageLocal.getItem("tagsVal") || false); +const tabDom = templateRef("tabDom", null); const containerDom = templateRef("containerDom", null); -const activeIndex = ref(-1); +const scrollbarDom = templateRef("scrollbarDom", null); + +const handleScroll = (offset: number): void => { + const scrollbarDomWidth = scrollbarDom.value?.wrap + ? scrollbarDom.value?.wrap.offsetWidth + : 0; + const tabDomWidth = tabDom.value ? tabDom.value.offsetWidth : 0; + if (offset > 0) { + translateX.value = Math.min(0, translateX.value + offset); + } else { + if (scrollbarDomWidth < tabDomWidth) { + if (translateX.value >= -(tabDomWidth - scrollbarDomWidth)) { + translateX.value = Math.max( + translateX.value + offset, + scrollbarDomWidth - tabDomWidth + ); + } + } else { + translateX.value = 0; + } + } +}; const tagsViews = ref>([ { @@ -469,40 +499,55 @@ onBeforeMount(() => { diff --git a/src/layout/theme/auroraGreen-vars.scss b/src/layout/theme/auroraGreen-vars.scss index e6365faf5..2fcea09b9 100644 --- a/src/layout/theme/auroraGreen-vars.scss +++ b/src/layout/theme/auroraGreen-vars.scss @@ -1,5 +1,4 @@ -// 极光绿 - +/* 极光绿 */ $subMenuActiveText: #fff; $menuBg: #0b1e15; $menuHover: #60ac80; diff --git a/src/layout/theme/default-vars.scss b/src/layout/theme/default-vars.scss index b9d8b91fe..8b2fd4ae5 100644 --- a/src/layout/theme/default-vars.scss +++ b/src/layout/theme/default-vars.scss @@ -1,24 +1,29 @@ /** -*此scss变量文件作为multipleScopeVars去编译时,会自动移除!default以达到变量提升 -*同时此scss变量文件作为默认主题变量文件,被其他.scss通过 @import 时,必需 !default + * 暗雅(默认) + * 此scss变量文件作为multipleScopeVars去编译时,会自动移除!default以达到变量提升 + * 同时此scss变量文件作为默认主题变量文件,被其他.scss通过 @import 时,必需 !default */ -// 暗雅(默认) - -// 菜单选中后字体样式 +/* 菜单选中后字体样式 */ $subMenuActiveText: #fff !default; -//菜单背景 + +/* 菜单背景 */ $menuBg: #001529 !default; -// 鼠标覆盖到菜单时的背景 + +/* 鼠标覆盖到菜单时的背景 */ $menuHover: #4091f7 !default; -// 子菜单背景 + +/* 子菜单背景 */ $subMenuBg: #0f0303 !default; -// 有无子集的激活菜单背景 + +/* 有无子集的激活菜单背景 */ $subMenuActiveBg: #4091f7 !default; $navTextColor: #fff !default; $menuText: rgba(254, 254, 254, 0.65) !default; -// logo背景颜色 + +/* logo背景颜色 */ $sidebarLogo: #002140 !default; -// 鼠标覆盖到菜单时的字体颜色 + +/* 鼠标覆盖到菜单时的字体颜色 */ $menuTitleHover: #fff !default; $menuActiveBefore: #4091f7 !default; diff --git a/src/layout/theme/dusk-vars.scss b/src/layout/theme/dusk-vars.scss index 6e38b947b..bb34fee9e 100644 --- a/src/layout/theme/dusk-vars.scss +++ b/src/layout/theme/dusk-vars.scss @@ -1,5 +1,4 @@ -// 薄暮 - +/* 薄暮 */ $subMenuActiveText: #fff; $menuBg: #2a0608; $menuHover: #e13c39; diff --git a/src/layout/theme/light-vars.scss b/src/layout/theme/light-vars.scss index 2e07500a4..f83a0841b 100644 --- a/src/layout/theme/light-vars.scss +++ b/src/layout/theme/light-vars.scss @@ -1,4 +1,4 @@ -// 明亮 +/* 明亮 */ $subMenuActiveText: #409eff; $menuBg: #fff; $menuHover: #e0ebf6; diff --git a/src/layout/theme/mingQing-vars.scss b/src/layout/theme/mingQing-vars.scss index 5749c90cf..8b8b0afe9 100644 --- a/src/layout/theme/mingQing-vars.scss +++ b/src/layout/theme/mingQing-vars.scss @@ -1,5 +1,4 @@ -// 明青 - +/* 明青 */ $subMenuActiveText: #fff; $menuBg: #032121; $menuHover: #59bfc1; diff --git a/src/layout/theme/pink-vars.scss b/src/layout/theme/pink-vars.scss index 30d4a4243..6a0403cc4 100644 --- a/src/layout/theme/pink-vars.scss +++ b/src/layout/theme/pink-vars.scss @@ -1,5 +1,4 @@ -// 粉红 - +/* 粉红 */ $subMenuActiveText: #fff; $menuBg: #28081a; $menuHover: #d84493; diff --git a/src/layout/theme/saucePurple-vars.scss b/src/layout/theme/saucePurple-vars.scss index 6d248a92b..9bb55d15c 100644 --- a/src/layout/theme/saucePurple-vars.scss +++ b/src/layout/theme/saucePurple-vars.scss @@ -1,5 +1,4 @@ -// 酱紫 - +/* 酱紫 */ $subMenuActiveText: #fff; $menuBg: #130824; $menuHover: #693ac9; diff --git a/src/layout/theme/volcano-vars.scss b/src/layout/theme/volcano-vars.scss index 5974ee692..aea4d33d5 100644 --- a/src/layout/theme/volcano-vars.scss +++ b/src/layout/theme/volcano-vars.scss @@ -1,5 +1,4 @@ -// 火山 - +/* 火山 */ $subMenuActiveText: #fff; $menuBg: #2b0e05; $menuHover: #e85f33; diff --git a/src/layout/theme/yellow-vars.scss b/src/layout/theme/yellow-vars.scss index 1410057a0..a0fe225cd 100644 --- a/src/layout/theme/yellow-vars.scss +++ b/src/layout/theme/yellow-vars.scss @@ -1,5 +1,4 @@ -// 黄色 - +/* 橘黄 */ $subMenuActiveText: #d25f00; $menuBg: #2b2503; $menuHover: #f6da4d; diff --git a/src/layout/types.ts b/src/layout/types.ts index 82ac8144a..1825d610d 100644 --- a/src/layout/types.ts +++ b/src/layout/types.ts @@ -73,3 +73,9 @@ export type themeColorsType = { rgb: string; themeColor: string; }; + +export interface scrollbarDomType extends HTMLElement { + wrap?: { + offsetWidth: number; + }; +} diff --git a/src/style/element-plus.scss b/src/style/element-plus.scss index 308d9b6ea..0b278893f 100644 --- a/src/style/element-plus.scss +++ b/src/style/element-plus.scss @@ -1,5 +1,3 @@ -// cover some element-plus styles - .el-breadcrumb__inner, .el-breadcrumb__inner a { font-weight: 400 !important; @@ -15,7 +13,6 @@ display: none; } -// refine element ui upload .upload-container { .el-upload { width: 100%; @@ -27,17 +24,14 @@ } } -// dropdown .el-dropdown-menu { padding: 2px 0 2px 0 !important; } -// to fix el-date-picker css style .el-range-separator { box-sizing: content-box; } -// el-tooltip的权重 .is-dark { z-index: 99999 !important; } diff --git a/src/style/index.scss b/src/style/index.scss index 25430701b..1eeeb9ec9 100644 --- a/src/style/index.scss +++ b/src/style/index.scss @@ -70,7 +70,7 @@ ul { display: none !important; } -// 灰色模式 +/* 灰色模式 */ .html-grey { filter: grayscale(100%); -webkit-filter: grayscale(100%); @@ -79,7 +79,7 @@ ul { -o-filter: grayscale(100%); } -// 色弱模式 +/* 色弱模式 */ .html-weakness { filter: invert(80%); -webkit-filter: invert(80%); diff --git a/src/style/sidebar.scss b/src/style/sidebar.scss index b82d9d796..d6f85a54b 100644 --- a/src/style/sidebar.scss +++ b/src/style/sidebar.scss @@ -1,8 +1,7 @@ @import "../layout/theme/default-vars.scss"; @mixin merge-style( - // vertical模式下主体内容距离网页文档左侧的距离 - $sideBarWidth + /* vertical模式下主体内容距离网页文档左侧的距离 */ $sideBarWidth ) { $menuActiveText: #7a80b4; @@ -126,7 +125,6 @@ } } - // menu hover .submenu-title-noDropdown, .el-sub-menu__title { &:hover { @@ -155,12 +153,12 @@ background-color: $subMenuBg !important; } - // 无子集的激活菜单背景 + /* 无子集的激活菜单背景 */ .is-active.submenu-title-noDropdown.outer-most { background: $subMenuActiveBg; } - // 有子集的激活菜单背景 + /* 有子集的激活菜单背景 */ .is-active.nest-menu { background: $subMenuActiveBg !important; } @@ -319,7 +317,7 @@ } } - // vertical菜单折叠 + /* vertical菜单折叠 */ .el-menu--vertical { .el-menu--popup { background-color: $subMenuBg !important; @@ -355,7 +353,7 @@ } } - // 子菜单中还有子菜单 + /* 子菜单中还有子菜单 */ .el-menu .el-sub-menu__title { font-size: 12px; min-width: $sideBarWidth !important; @@ -396,7 +394,7 @@ } } - // horizontal菜单 + /* horizontal菜单 */ .el-menu--horizontal { & > .el-sub-menu .el-sub-menu__icon-arrow { position: static !important; @@ -425,13 +423,13 @@ } } - // 无子菜单时激活border-bottom + /* 无子菜单时激活border-bottom */ .router-link-exact-active > .submenu-title-noDropdown { height: 60px; border-bottom: 2px solid var(--el-menu-active-color); } - // 子菜单中还有子菜单 + /* 子菜单中还有子菜单 */ .el-menu .el-sub-menu__title { font-size: 12px; min-width: $sideBarWidth !important; @@ -464,7 +462,7 @@ } } - // 有子集的激活菜单背景 + /* 有子集的激活菜单背景 */ .is-active.nest-menu { background: $subMenuActiveBg !important; } @@ -484,7 +482,7 @@ min-width: $sideBarWidth !important; } - // 有子菜单 + /* 有子菜单 */ .el-menu--collapse .is-active.outer-most.el-sub-menu > .el-sub-menu__title::before { @@ -502,7 +500,7 @@ transform: translateY(0); } - // 无子菜单 + /* 无子菜单 */ .el-menu--collapse .is-active.submenu-title-noDropdown.outer-most::before { position: absolute; top: 0; @@ -530,7 +528,7 @@ top: 50%; } - // 手机端 + /* 手机端 */ .mobile { .fixed-header { width: 100% !important; @@ -604,7 +602,7 @@ body[layout="vertical"] { } } - // 菜单折叠 + /* 菜单折叠 */ .el-menu--collapse { margin-left: -5px; diff --git a/src/style/transition.scss b/src/style/transition.scss index b529f82c4..017c1d95e 100644 --- a/src/style/transition.scss +++ b/src/style/transition.scss @@ -1,5 +1,3 @@ -// global transition css - /* fade */ .fade-enter-active, .fade-leave-active { diff --git a/vite.config.ts b/vite.config.ts index 5a46c87ec..933462d4e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -60,47 +60,38 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => { scss: { multipleScopeVars: [ { - // 暗雅(默认) scopeName: "layout-theme-default", path: pathResolve("src/layout/theme/default-vars.scss") }, { - // 明亮 scopeName: "layout-theme-light", path: pathResolve("src/layout/theme/light-vars.scss") }, { - // 薄暮 scopeName: "layout-theme-dusk", path: pathResolve("src/layout/theme/dusk-vars.scss") }, { - // 火山 scopeName: "layout-theme-volcano", path: pathResolve("src/layout/theme/volcano-vars.scss") }, { - // 黄色 scopeName: "layout-theme-yellow", path: pathResolve("src/layout/theme/yellow-vars.scss") }, { - // 明青 scopeName: "layout-theme-mingQing", path: pathResolve("src/layout/theme/mingQing-vars.scss") }, { - // 极光绿 scopeName: "layout-theme-auroraGreen", path: pathResolve("src/layout/theme/auroraGreen-vars.scss") }, { - // 粉红 scopeName: "layout-theme-pink", path: pathResolve("src/layout/theme/pink-vars.scss") }, { - // 酱紫 scopeName: "layout-theme-saucePurple", path: pathResolve("src/layout/theme/saucePurple-vars.scss") }