优化页签功能&支持全屏按钮操作
This commit is contained in:
@@ -17,6 +17,8 @@ const { proxy } = getCurrentInstance()
|
|||||||
|
|
||||||
const scrollWrapper = computed(() => proxy.$refs.scrollContainer.$refs.wrapRef)
|
const scrollWrapper = computed(() => proxy.$refs.scrollContainer.$refs.wrapRef)
|
||||||
|
|
||||||
|
const emits = defineEmits(['scroll', 'updateArrows'])
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
scrollWrapper.value.addEventListener('scroll', emitScroll, true)
|
scrollWrapper.value.addEventListener('scroll', emitScroll, true)
|
||||||
})
|
})
|
||||||
@@ -25,15 +27,46 @@ onBeforeUnmount(() => {
|
|||||||
scrollWrapper.value.removeEventListener('scroll', emitScroll)
|
scrollWrapper.value.removeEventListener('scroll', emitScroll)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const emitScroll = () => {
|
||||||
|
emits('scroll')
|
||||||
|
emits('updateArrows')
|
||||||
|
}
|
||||||
|
|
||||||
|
function smoothScrollTo(target) {
|
||||||
|
const $scrollWrapper = scrollWrapper.value
|
||||||
|
const start = $scrollWrapper.scrollLeft
|
||||||
|
const distance = target - start
|
||||||
|
const duration = 300
|
||||||
|
let startTime = null
|
||||||
|
|
||||||
|
// easeInOutQuad »º¶¯º¯Êý
|
||||||
|
function ease(t, b, c, d) {
|
||||||
|
t /= d / 2
|
||||||
|
if (t < 1) return c / 2 * t * t + b
|
||||||
|
t--
|
||||||
|
return -c / 2 * (t * (t - 2) - 1) + b
|
||||||
|
}
|
||||||
|
|
||||||
|
function step(timestamp) {
|
||||||
|
if (!startTime) startTime = timestamp
|
||||||
|
const elapsed = timestamp - startTime
|
||||||
|
$scrollWrapper.scrollLeft = ease(elapsed, start, distance, duration)
|
||||||
|
if (elapsed < duration) {
|
||||||
|
requestAnimationFrame(step)
|
||||||
|
} else {
|
||||||
|
$scrollWrapper.scrollLeft = target
|
||||||
|
emits('updateArrows')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(step)
|
||||||
|
}
|
||||||
|
|
||||||
function handleScroll(e) {
|
function handleScroll(e) {
|
||||||
const eventDelta = e.wheelDelta || -e.deltaY * 40
|
const eventDelta = e.wheelDelta || -e.deltaY * 40
|
||||||
const $scrollWrapper = scrollWrapper.value
|
const $scrollWrapper = scrollWrapper.value
|
||||||
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
||||||
}
|
emits('updateArrows')
|
||||||
|
|
||||||
const emits = defineEmits()
|
|
||||||
const emitScroll = () => {
|
|
||||||
emits('scroll')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const tagsViewStore = useTagsViewStore()
|
const tagsViewStore = useTagsViewStore()
|
||||||
@@ -47,16 +80,15 @@ function moveToTarget(currentTag) {
|
|||||||
let firstTag = null
|
let firstTag = null
|
||||||
let lastTag = null
|
let lastTag = null
|
||||||
|
|
||||||
// find first tag and last tag
|
|
||||||
if (visitedViews.value.length > 0) {
|
if (visitedViews.value.length > 0) {
|
||||||
firstTag = visitedViews.value[0]
|
firstTag = visitedViews.value[0]
|
||||||
lastTag = visitedViews.value[visitedViews.value.length - 1]
|
lastTag = visitedViews.value[visitedViews.value.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstTag === currentTag) {
|
if (firstTag === currentTag) {
|
||||||
$scrollWrapper.scrollLeft = 0
|
smoothScrollTo(0)
|
||||||
} else if (lastTag === currentTag) {
|
} else if (lastTag === currentTag) {
|
||||||
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
|
smoothScrollTo($scrollWrapper.scrollWidth - $containerWidth)
|
||||||
} else {
|
} else {
|
||||||
const tagListDom = document.getElementsByClassName('tags-view-item')
|
const tagListDom = document.getElementsByClassName('tags-view-item')
|
||||||
const currentIndex = visitedViews.value.findIndex(item => item === currentTag)
|
const currentIndex = visitedViews.value.findIndex(item => item === currentTag)
|
||||||
@@ -72,22 +104,38 @@ function moveToTarget(currentTag) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the tag's offsetLeft after of nextTag
|
|
||||||
const afterNextTagOffsetLeft = nextTag.offsetLeft + nextTag.offsetWidth + tagAndTagSpacing.value
|
const afterNextTagOffsetLeft = nextTag.offsetLeft + nextTag.offsetWidth + tagAndTagSpacing.value
|
||||||
|
|
||||||
// the tag's offsetLeft before of prevTag
|
|
||||||
const beforePrevTagOffsetLeft = prevTag.offsetLeft - tagAndTagSpacing.value
|
const beforePrevTagOffsetLeft = prevTag.offsetLeft - tagAndTagSpacing.value
|
||||||
if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
|
if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
|
||||||
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
|
smoothScrollTo(afterNextTagOffsetLeft - $containerWidth)
|
||||||
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
|
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
|
||||||
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
|
smoothScrollTo(beforePrevTagOffsetLeft)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scrollToStart() {
|
||||||
|
smoothScrollTo(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollToEnd() {
|
||||||
|
const $scrollWrapper = scrollWrapper.value
|
||||||
|
smoothScrollTo($scrollWrapper.scrollWidth - $scrollWrapper.clientWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getScrollState() {
|
||||||
|
const $scrollWrapper = scrollWrapper.value
|
||||||
|
return {
|
||||||
|
canLeft: $scrollWrapper.scrollLeft > 0,
|
||||||
|
canRight: $scrollWrapper.scrollLeft < $scrollWrapper.scrollWidth - $scrollWrapper.clientWidth - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
moveToTarget,
|
moveToTarget,
|
||||||
|
scrollToStart,
|
||||||
|
scrollToEnd,
|
||||||
|
getScrollState
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -97,11 +145,16 @@ defineExpose({
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
:deep(.el-scrollbar__bar) {
|
:deep(.el-scrollbar__bar) {
|
||||||
bottom: 0px;
|
display: none;
|
||||||
}
|
}
|
||||||
:deep(.el-scrollbar__wrap) {
|
:deep(.el-scrollbar__wrap) {
|
||||||
height: 39px;
|
height: 34px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="tags-view-container" class="tags-view-container">
|
<div id="tags-view-container" class="tags-view-container">
|
||||||
<scroll-pane ref="scrollPaneRef" class="tags-view-wrapper" @scroll="handleScroll">
|
<!-- 左切换箭头 -->
|
||||||
|
<span class="tags-nav-btn tags-nav-btn--left" :class="{ disabled: !canScrollLeft }" @click="scrollLeft">
|
||||||
|
<el-icon><arrow-left /></el-icon>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- 标签滚动区 -->
|
||||||
|
<scroll-pane ref="scrollPaneRef" class="tags-view-wrapper" @scroll="handleScroll" @update-arrows="updateArrowState">
|
||||||
<router-link
|
<router-link
|
||||||
v-for="tag in visitedViews"
|
v-for="tag in visitedViews"
|
||||||
:key="tag.path"
|
:key="tag.path"
|
||||||
@@ -19,6 +25,50 @@
|
|||||||
</span>
|
</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</scroll-pane>
|
</scroll-pane>
|
||||||
|
|
||||||
|
<!-- 右切换箭头 -->
|
||||||
|
<span class="tags-nav-btn tags-nav-btn--right" :class="{ disabled: !canScrollRight }" @click="scrollRight">
|
||||||
|
<el-icon><arrow-right /></el-icon>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- 下拉操作菜单 -->
|
||||||
|
<el-dropdown class="tags-action-dropdown" trigger="click" placement="bottom-end" @command="handleDropdownCommand">
|
||||||
|
<span class="tags-action-btn">
|
||||||
|
<el-icon><arrow-down /></el-icon>
|
||||||
|
</span>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu class="tags-dropdown-menu">
|
||||||
|
<el-dropdown-item command="refresh">
|
||||||
|
<refresh-right style="width: 1em; height: 1em;" /> 刷新页面
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item v-if="!isAffix(selectedDropdownTag)" command="close">
|
||||||
|
<close style="width: 1em; height: 1em;" /> 关闭当前
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="closeOthers">
|
||||||
|
<circle-close style="width: 1em; height: 1em;" /> 关闭其他
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="closeLeft" :disabled="isFirstView()">
|
||||||
|
<back style="width: 1em; height: 1em;" /> 关闭左侧
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="closeRight" :disabled="isLastView()">
|
||||||
|
<right style="width: 1em; height: 1em;" /> 关闭右侧
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="closeAll" divided>
|
||||||
|
<circle-close style="width: 1em; height: 1em;" /> 全部关闭
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
|
||||||
|
<!-- 全屏按钮 -->
|
||||||
|
<span class="tags-action-btn tags-fullscreen-btn" :title="isFullscreen ? '退出全屏' : '全屏'" @click="toggleFullscreen">
|
||||||
|
<el-icon>
|
||||||
|
<full-screen v-if="!isFullscreen" />
|
||||||
|
<aim v-else />
|
||||||
|
</el-icon>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- 右键上下文菜单 -->
|
||||||
<ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
|
<ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
|
||||||
<li @click="refreshSelectedTag(selectedTag)">
|
<li @click="refreshSelectedTag(selectedTag)">
|
||||||
<refresh-right style="width: 1em; height: 1em;" /> 刷新页面
|
<refresh-right style="width: 1em; height: 1em;" /> 刷新页面
|
||||||
@@ -55,6 +105,9 @@ const left = ref(0)
|
|||||||
const selectedTag = ref({})
|
const selectedTag = ref({})
|
||||||
const affixTags = ref([])
|
const affixTags = ref([])
|
||||||
const scrollPaneRef = ref(null)
|
const scrollPaneRef = ref(null)
|
||||||
|
const canScrollLeft = ref(false)
|
||||||
|
const canScrollRight = ref(false)
|
||||||
|
const isFullscreen = ref(false)
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance()
|
const { proxy } = getCurrentInstance()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -65,6 +118,9 @@ const routes = computed(() => usePermissionStore().routes)
|
|||||||
const theme = computed(() => useSettingsStore().theme)
|
const theme = computed(() => useSettingsStore().theme)
|
||||||
const tagsIcon = computed(() => useSettingsStore().tagsIcon)
|
const tagsIcon = computed(() => useSettingsStore().tagsIcon)
|
||||||
|
|
||||||
|
// 下拉菜单针对当前激活的 tag
|
||||||
|
const selectedDropdownTag = computed(() => visitedViews.value.find(v => isActive(v)) || {})
|
||||||
|
|
||||||
watch(route, () => {
|
watch(route, () => {
|
||||||
addTags()
|
addTags()
|
||||||
moveToCurrentTag()
|
moveToCurrentTag()
|
||||||
@@ -78,9 +134,20 @@ watch(visible, (value) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(visitedViews, () => {
|
||||||
|
nextTick(() => updateArrowState())
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initTags()
|
initTags()
|
||||||
addTags()
|
addTags()
|
||||||
|
window.addEventListener('resize', updateArrowState)
|
||||||
|
document.addEventListener('fullscreenchange', onFullscreenChange)
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('resize', updateArrowState)
|
||||||
|
document.removeEventListener('fullscreenchange', onFullscreenChange)
|
||||||
})
|
})
|
||||||
|
|
||||||
function isActive(r) {
|
function isActive(r) {
|
||||||
@@ -90,18 +157,19 @@ function isActive(r) {
|
|||||||
function activeStyle(tag) {
|
function activeStyle(tag) {
|
||||||
if (!isActive(tag)) return {}
|
if (!isActive(tag)) return {}
|
||||||
return {
|
return {
|
||||||
"background-color": theme.value,
|
'background-color': theme.value,
|
||||||
"border-color": theme.value
|
'border-color': theme.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAffix(tag) {
|
function isAffix(tag) {
|
||||||
return tag.meta && tag.meta.affix
|
return tag && tag.meta && tag.meta.affix
|
||||||
}
|
}
|
||||||
|
|
||||||
function isFirstView() {
|
function isFirstView() {
|
||||||
try {
|
try {
|
||||||
return selectedTag.value.fullPath === '/index' || selectedTag.value.fullPath === visitedViews.value[1].fullPath
|
const tag = selectedTag.value && selectedTag.value.fullPath ? selectedTag.value : selectedDropdownTag.value
|
||||||
|
return tag.fullPath === '/index' || tag.fullPath === visitedViews.value[1].fullPath
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -109,7 +177,8 @@ function isFirstView() {
|
|||||||
|
|
||||||
function isLastView() {
|
function isLastView() {
|
||||||
try {
|
try {
|
||||||
return selectedTag.value.fullPath === visitedViews.value[visitedViews.value.length - 1].fullPath
|
const tag = selectedTag.value && selectedTag.value.fullPath ? selectedTag.value : selectedDropdownTag.value
|
||||||
|
return tag.fullPath === visitedViews.value[visitedViews.value.length - 1].fullPath
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -141,7 +210,6 @@ function initTags() {
|
|||||||
const res = filterAffixTags(routes.value)
|
const res = filterAffixTags(routes.value)
|
||||||
affixTags.value = res
|
affixTags.value = res
|
||||||
for (const tag of res) {
|
for (const tag of res) {
|
||||||
// Must have tag name
|
|
||||||
if (tag.name) {
|
if (tag.name) {
|
||||||
useTagsViewStore().addVisitedView(tag)
|
useTagsViewStore().addVisitedView(tag)
|
||||||
}
|
}
|
||||||
@@ -160,7 +228,6 @@ function moveToCurrentTag() {
|
|||||||
for (const r of visitedViews.value) {
|
for (const r of visitedViews.value) {
|
||||||
if (r.path === route.path) {
|
if (r.path === route.path) {
|
||||||
scrollPaneRef.value.moveToTarget(r)
|
scrollPaneRef.value.moveToTarget(r)
|
||||||
// when query is different then update
|
|
||||||
if (r.fullPath !== route.fullPath) {
|
if (r.fullPath !== route.fullPath) {
|
||||||
useTagsViewStore().updateVisitedView(route)
|
useTagsViewStore().updateVisitedView(route)
|
||||||
}
|
}
|
||||||
@@ -169,6 +236,51 @@ function moveToCurrentTag() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scrollLeft() {
|
||||||
|
if (!canScrollLeft.value) return
|
||||||
|
scrollPaneRef.value.scrollToStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollRight() {
|
||||||
|
if (!canScrollRight.value) return
|
||||||
|
scrollPaneRef.value.scrollToEnd()
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateArrowState() {
|
||||||
|
nextTick(() => {
|
||||||
|
if (scrollPaneRef.value) {
|
||||||
|
const state = scrollPaneRef.value.getScrollState()
|
||||||
|
canScrollLeft.value = state.canLeft
|
||||||
|
canScrollRight.value = state.canRight
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleFullscreen() {
|
||||||
|
if (!document.fullscreenElement) {
|
||||||
|
document.documentElement.requestFullscreen()
|
||||||
|
} else {
|
||||||
|
document.exitFullscreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFullscreenChange() {
|
||||||
|
isFullscreen.value = !!document.fullscreenElement
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDropdownCommand(command) {
|
||||||
|
const tag = selectedDropdownTag.value
|
||||||
|
selectedTag.value = tag
|
||||||
|
switch (command) {
|
||||||
|
case 'refresh': refreshSelectedTag(tag); break
|
||||||
|
case 'close': closeSelectedTag(tag); break
|
||||||
|
case 'closeOthers': closeOthersTags(); break
|
||||||
|
case 'closeLeft': closeLeftTags(); break
|
||||||
|
case 'closeRight': closeRightTags(); break
|
||||||
|
case 'closeAll': closeAllTags(tag); break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function refreshSelectedTag(view) {
|
function refreshSelectedTag(view) {
|
||||||
proxy.$tab.refreshPage(view)
|
proxy.$tab.refreshPage(view)
|
||||||
if (route.meta.link) {
|
if (route.meta.link) {
|
||||||
@@ -221,10 +333,7 @@ function toLastView(visitedViews, view) {
|
|||||||
if (latestView) {
|
if (latestView) {
|
||||||
router.push(latestView.fullPath)
|
router.push(latestView.fullPath)
|
||||||
} else {
|
} else {
|
||||||
// now the default is to redirect to the home page if there is no tags-view,
|
if (view && view.name === 'Dashboard') {
|
||||||
// you can adjust it according to your needs.
|
|
||||||
if (view.name === 'Dashboard') {
|
|
||||||
// to reload home page
|
|
||||||
router.replace({ path: '/redirect' + view.fullPath })
|
router.replace({ path: '/redirect' + view.fullPath })
|
||||||
} else {
|
} else {
|
||||||
router.push('/')
|
router.push('/')
|
||||||
@@ -233,18 +342,7 @@ function toLastView(visitedViews, view) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openMenu(tag, e) {
|
function openMenu(tag, e) {
|
||||||
const menuMinWidth = 105
|
left.value = e.clientX
|
||||||
const offsetLeft = proxy.$el.getBoundingClientRect().left // container margin left
|
|
||||||
const offsetWidth = proxy.$el.offsetWidth // container width
|
|
||||||
const maxLeft = offsetWidth - menuMinWidth // left boundary
|
|
||||||
const l = e.clientX - offsetLeft + 15 // 15: margin right
|
|
||||||
|
|
||||||
if (l > maxLeft) {
|
|
||||||
left.value = maxLeft
|
|
||||||
} else {
|
|
||||||
left.value = l
|
|
||||||
}
|
|
||||||
|
|
||||||
top.value = e.clientY
|
top.value = e.clientY
|
||||||
visible.value = true
|
visible.value = true
|
||||||
selectedTag.value = tag
|
selectedTag.value = tag
|
||||||
@@ -256,6 +354,7 @@ function closeMenu() {
|
|||||||
|
|
||||||
function handleScroll() {
|
function handleScroll() {
|
||||||
closeMenu()
|
closeMenu()
|
||||||
|
updateArrowState()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -265,9 +364,49 @@ function handleScroll() {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
background: var(--tags-bg, #fff);
|
background: var(--tags-bg, #fff);
|
||||||
border-bottom: 1px solid var(--tags-item-border, #d8dce5);
|
border-bottom: 1px solid var(--tags-item-border, #d8dce5);
|
||||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
$btn-width: 28px;
|
||||||
|
$btn-color: #71717a;
|
||||||
|
$btn-hover-bg: #f0f2f5;
|
||||||
|
$btn-hover-color: #303133;
|
||||||
|
$btn-disabled-color: #c0c4cc;
|
||||||
|
$divider: 1px solid var(--tags-item-border, #d8dce5);
|
||||||
|
|
||||||
|
.tags-nav-btn {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: $btn-width;
|
||||||
|
height: 34px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: $btn-color;
|
||||||
|
font-size: 13px;
|
||||||
|
user-select: none;
|
||||||
|
transition: background 0.15s, color 0.15s;
|
||||||
|
|
||||||
|
&:hover:not(.disabled) {
|
||||||
|
background: $btn-hover-bg;
|
||||||
|
color: $btn-hover-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
color: $btn-disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--left { border-right: $divider; }
|
||||||
|
&--right { border-left: $divider; }
|
||||||
|
}
|
||||||
|
|
||||||
.tags-view-wrapper {
|
.tags-view-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
.tags-view-item {
|
.tags-view-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -280,15 +419,9 @@ function handleScroll() {
|
|||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
margin-top: 4px;
|
|
||||||
|
|
||||||
&:first-of-type {
|
&:first-of-type { margin-left: 6px; }
|
||||||
margin-left: 15px;
|
&:last-of-type { margin-right: 15px; }
|
||||||
}
|
|
||||||
|
|
||||||
&:last-of-type {
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background-color: #42b983;
|
background-color: #42b983;
|
||||||
@@ -313,11 +446,40 @@ function handleScroll() {
|
|||||||
content: none !important;
|
content: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tags-action-dropdown {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-action-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: $btn-width;
|
||||||
|
height: 34px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: $btn-color;
|
||||||
|
font-size: 13px;
|
||||||
|
border-left: $divider;
|
||||||
|
user-select: none;
|
||||||
|
transition: background 0.15s, color 0.15s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $btn-hover-bg;
|
||||||
|
color: $btn-hover-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-fullscreen-btn {
|
||||||
|
border-left: $divider;
|
||||||
|
}
|
||||||
|
|
||||||
.contextmenu {
|
.contextmenu {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: var(--el-bg-color-overlay, #fff);
|
background: var(--el-bg-color-overlay, #fff);
|
||||||
z-index: 3000;
|
z-index: 3000;
|
||||||
position: absolute;
|
position: fixed;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@@ -341,7 +503,6 @@ function handleScroll() {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
//reset element css of el-icon-close
|
|
||||||
.tags-view-wrapper {
|
.tags-view-wrapper {
|
||||||
.tags-view-item {
|
.tags-view-item {
|
||||||
.el-icon-close {
|
.el-icon-close {
|
||||||
|
|||||||
Reference in New Issue
Block a user