diff --git a/src/layout/components/TagsView/ScrollPane.vue b/src/layout/components/TagsView/ScrollPane.vue
index 2a7e6116..65399990 100644
--- a/src/layout/components/TagsView/ScrollPane.vue
+++ b/src/layout/components/TagsView/ScrollPane.vue
@@ -1,5 +1,5 @@
@@ -120,7 +119,7 @@ const showScreenfull = computed(() => {
-
+
@@ -143,7 +142,7 @@ const showScreenfull = computed(() => {
}
.el-scrollbar {
flex: 1;
- // 横向超出窗口长度时,显示滚动条
+ // 防止换行(超出宽度时,显示滚动条)
white-space: nowrap;
.scrollbar-content {
display: inline-block;
diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue
index a9d796d7..4a6bd261 100644
--- a/src/layout/components/TagsView/index.vue
+++ b/src/layout/components/TagsView/index.vue
@@ -13,26 +13,35 @@ const route = useRoute()
const tagsViewStore = useTagsViewStore()
const permissionStore = usePermissionStore()
+/** 标签页组件元素的引用数组 */
const tagRefs = ref[]>([])
+/** 右键菜单的状态 */
const visible = ref(false)
+/** 右键菜单的 top 位置 */
const top = ref(0)
+/** 右键菜单的 left 位置 */
const left = ref(0)
+/** 当前正在右键操作的标签页 */
const selectedTag = ref({})
+/** 固定的标签页 */
let affixTags: TagView[] = []
+/** 判断标签页是否激活 */
const isActive = (tag: TagView) => {
return tag.path === route.path
}
+/** 判断标签页是否固定 */
const isAffix = (tag: TagView) => {
return tag.meta?.affix
}
+/** 筛选出固定标签页 */
const filterAffixTags = (routes: RouteRecordRaw[], basePath = "/") => {
- let tags: TagView[] = []
+ const tags: TagView[] = []
routes.forEach((route) => {
- if (route.meta?.affix) {
+ if (isAffix(route)) {
const tagPath = path.resolve(basePath, route.path)
tags.push({
fullPath: tagPath,
@@ -43,24 +52,22 @@ const filterAffixTags = (routes: RouteRecordRaw[], basePath = "/") => {
}
if (route.children) {
const childTags = filterAffixTags(route.children, route.path)
- if (childTags.length >= 1) {
- tags = tags.concat(childTags)
- }
+ tags.push(...childTags)
}
})
return tags
}
+/** 初始化标签页 */
const initTags = () => {
affixTags = filterAffixTags(permissionStore.routes)
for (const tag of affixTags) {
// 必须含有 name 属性
- if (tag.name) {
- tagsViewStore.addVisitedView(tag)
- }
+ tag.name && tagsViewStore.addVisitedView(tag)
}
}
+/** 添加标签页 */
const addTags = () => {
if (route.name) {
tagsViewStore.addVisitedView(route)
@@ -68,40 +75,43 @@ const addTags = () => {
}
}
+/** 刷新当前正在右键操作的标签页 */
const refreshSelectedTag = (view: TagView) => {
tagsViewStore.delCachedView(view)
router.replace({ path: "/redirect" + view.path, query: view.query })
}
+/** 关闭当前正在右键操作的标签页 */
const closeSelectedTag = (view: TagView) => {
tagsViewStore.delVisitedView(view)
tagsViewStore.delCachedView(view)
- if (isActive(view)) {
- toLastView(tagsViewStore.visitedViews, view)
- }
+ isActive(view) && toLastView(tagsViewStore.visitedViews, view)
}
+/** 关闭其他标签页 */
const closeOthersTags = () => {
- if (selectedTag.value.fullPath !== route.path && selectedTag.value.fullPath !== undefined) {
- router.push(selectedTag.value.fullPath)
+ const fullPath = selectedTag.value.fullPath
+ if (fullPath !== route.path && fullPath !== undefined) {
+ router.push(fullPath)
}
tagsViewStore.delOthersVisitedViews(selectedTag.value)
tagsViewStore.delOthersCachedViews(selectedTag.value)
}
+/** 关闭所有标签页 */
const closeAllTags = (view: TagView) => {
tagsViewStore.delAllVisitedViews()
tagsViewStore.delAllCachedViews()
- if (affixTags.some((tag) => tag.path === route.path)) {
- return
- }
+ if (affixTags.some((tag) => tag.path === route.path)) return
toLastView(tagsViewStore.visitedViews, view)
}
+/** 跳转到最后一个标签页 */
const toLastView = (visitedViews: TagView[], view: TagView) => {
const latestView = visitedViews.slice(-1)[0]
- if (latestView !== undefined && latestView.fullPath !== undefined) {
- router.push(latestView.fullPath)
+ const fullPath = latestView?.fullPath
+ if (fullPath !== undefined) {
+ router.push(fullPath)
} else {
// 如果 TagsView 全部被关闭了,则默认重定向到主页
if (view.name === "Dashboard") {
@@ -113,26 +123,26 @@ const toLastView = (visitedViews: TagView[], view: TagView) => {
}
}
+/** 打开右键菜单面板 */
const openMenu = (tag: TagView, e: MouseEvent) => {
const menuMinWidth = 105
- // container margin left
+ // 当前组件距离浏览器左端的距离
const offsetLeft = instance!.proxy!.$el.getBoundingClientRect().left
- // container width
+ // 当前组件宽度
const offsetWidth = instance!.proxy!.$el.offsetWidth
- // left boundary
+ // 面板的最大左边距
const maxLeft = offsetWidth - menuMinWidth
- // 15: margin right
+ // 面板距离鼠标指针的距离
const left15 = e.clientX - offsetLeft + 15
- if (left15 > maxLeft) {
- left.value = maxLeft
- } else {
- left.value = left15
- }
+ left.value = left15 > maxLeft ? maxLeft : left15
top.value = e.clientY
+ // 显示面板
visible.value = true
+ // 更新当前正在右键操作的标签页
selectedTag.value = tag
}
+/** 关闭右键菜单面板 */
const closeMenu = () => {
visible.value = false
}
@@ -148,11 +158,7 @@ watch(
)
watch(visible, (value) => {
- if (value) {
- document.body.addEventListener("click", closeMenu)
- } else {
- document.body.removeEventListener("click", closeMenu)
- }
+ value ? document.body.addEventListener("click", closeMenu) : document.body.removeEventListener("click", closeMenu)
})
onMounted(() => {
@@ -168,10 +174,10 @@ onMounted(() => {
ref="tagRefs"
v-for="tag in tagsViewStore.visitedViews"
:key="tag.path"
- :class="isActive(tag) ? 'active' : ''"
- :to="{ path: tag.path, query: tag.query }"
+ :class="{ active: isActive(tag) }"
class="tags-view-item"
- @click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
+ :to="{ path: tag.path, query: tag.query }"
+ @click.middle="!isAffix(tag) && closeSelectedTag(tag)"
@contextmenu.prevent="openMenu(tag, $event)"
>
{{ tag.meta?.title }}
@@ -180,7 +186,7 @@ onMounted(() => {
-