-
Notifications
You must be signed in to change notification settings - Fork 722
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Akiraka
committed
Sep 5, 2024
1 parent
f70c9f4
commit d352198
Showing
4 changed files
with
312 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
<script setup> | ||
import { watch, ref, nextTick } from 'vue'; | ||
import { useRoute, useRouter } from 'vue-router'; | ||
import { useTagViewStore } from '@/store/tagView'; | ||
import { onMounted } from 'vue'; | ||
const store = useTagViewStore(); | ||
const route = useRoute(); | ||
const router = useRouter(); | ||
const tagListRef = ref(null); | ||
const tagMore = ref(false); | ||
const checkTagListWidth = async () => { | ||
await nextTick(); | ||
// 获取 tagList 宽度 | ||
const tagListWidth = tagListRef.value.offsetWidth; | ||
// 获取 tagList 子元素实际宽度 | ||
const tagItemWidth = tagListRef.value.children[0].scrollWidth; | ||
// 判断 tagList 宽度是否小于 tagItem 实际宽度 | ||
if (tagListWidth < tagItemWidth) { | ||
// 设置 tagMore 为 true | ||
tagMore.value = true; | ||
// 计算向右偏移宽度 | ||
const rightOffset = tagListRef.value.children[0].offsetWidth - tagListRef.value.clientWidth; | ||
tagListRef.value.children[0].style.right = rightOffset + 'px'; | ||
} else { | ||
tagMore.value = false; | ||
} | ||
} | ||
// Tag 标签上一页 | ||
const handleTagPrev = () => { | ||
let leftOffset = tagListRef.value.clientWidth - tagListRef.value.children[0].offsetWidth; | ||
if (leftOffset < 0) { | ||
leftOffset = 0; | ||
} | ||
tagListRef.value.children[0].style.right = leftOffset + 'px'; | ||
} | ||
// Tag 标签下一页 | ||
const handleTagNext = () => { | ||
// 计算向右偏移宽度 | ||
const rightOffset = tagListRef.value.children[0].offsetWidth - tagListRef.value.clientWidth; | ||
tagListRef.value.children[0].style.right = rightOffset + 'px'; | ||
} | ||
// Tag 关闭事件 | ||
const handleTagClose = (view, index) => { | ||
// 判断是否为当前选中 | ||
if (view.path === route.path) { | ||
// 判断是否为第一个 | ||
if (index !== 0 ) { | ||
router.push(store.visitedViews[index - 1].path); | ||
} else { | ||
router.push(store.visitedViews[index + 1].path) | ||
} | ||
} | ||
store.delVisitedViews(view); | ||
} | ||
const handleDelTag = (v) => { | ||
switch (v) { | ||
case 'left': | ||
store.delLeftVisitedViews(route); | ||
break; | ||
case 'right': | ||
store.delRightVisitedViews(route); | ||
break; | ||
case 'all': | ||
store.delAllVisitedViews(route); | ||
break; | ||
default: | ||
console.log('参数错误') | ||
} | ||
} | ||
// 监听 store 数据变化 | ||
watch(store.visitedViews, () => { | ||
// 重新计算 tagList 宽度 | ||
checkTagListWidth(); | ||
}) | ||
// 监听路由变化 | ||
watch(() => route.path, () => { | ||
store.addVisitedViews(route) | ||
}, { immediate: true }) | ||
onMounted(() => { | ||
checkTagListWidth() | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div class="tag-view-main"> | ||
<div | ||
class="tag-card" | ||
> | ||
<div class="tag-prev" v-if="tagMore" @click="handleTagPrev"> | ||
<icon-left :size="18"/> | ||
</div> | ||
|
||
<div class="tag-list" ref="tagListRef"> | ||
<transition-group name="tag-fade"> | ||
<a-tag | ||
v-for="(view, index) in store.visitedViews" | ||
:key="view.name" | ||
:checked="view.meta.title === route.meta.title" | ||
:color="view.meta.title === route.meta.title ? '#5d87ff' : ''" | ||
@close="handleTagClose(view, index)" | ||
:closable="store.visitedViews.length > 1" | ||
checkable | ||
:style="{ marginRight: '5px' }" | ||
> | ||
<router-link :to="view.path" class="tag-link"> | ||
{{ view.title }} | ||
</router-link> | ||
</a-tag> | ||
</transition-group> | ||
<!-- <a-tag | ||
v-for="name, index in tagListCount" | ||
:key="index" | ||
@close="() => tagListCount -= 1" | ||
closable> | ||
标题{{ name }} | ||
</a-tag> --> | ||
|
||
</div> | ||
|
||
<div class="tag-next" v-if="tagMore" @click="handleTagNext"> | ||
<icon-right :size="18"/> | ||
</div> | ||
</div> | ||
|
||
<!-- <div class="tag-close">--> | ||
<!-- <a-dropdown @select="handleDelTag">--> | ||
<!-- <a-button>--> | ||
<!-- <template #icon>--> | ||
<!-- <icon-down />--> | ||
<!-- </template>--> | ||
<!-- </a-button>--> | ||
<!-- <template #content>--> | ||
<!-- <a-doption value="left">关闭左侧</a-doption>--> | ||
<!-- <a-doption value="right">关闭右侧</a-doption>--> | ||
<!-- <a-doption value="all">关闭全部</a-doption>--> | ||
<!-- </template>--> | ||
<!-- </a-dropdown>--> | ||
<!-- </div>--> | ||
</div> | ||
</template> | ||
|
||
<style lang="scss" scoped> | ||
.tag-view-main { | ||
padding: 0 15px; | ||
display: flex; | ||
justify-content: space-between; | ||
max-width: 100%; | ||
min-width: 100%; | ||
background-color: var(--color-bg-2); | ||
.tag-card { | ||
display: flex; | ||
align-items: center; | ||
height: 36px; | ||
overflow: hidden; | ||
.tag-list { | ||
position: relative; | ||
overflow-x: hidden; | ||
transition: .3s ease-in-out; | ||
} | ||
.tag-prev, .tag-next{ | ||
width: 48px; | ||
cursor: pointer; | ||
text-align: center; | ||
} | ||
} | ||
} | ||
.tag-link { | ||
color: inherit; | ||
} | ||
.tag-link:hover { | ||
color: inherit; | ||
} | ||
.tag-fade-enter-active, | ||
.tag-fade-leave-active { | ||
transition: opacity 0.3s ease-in-out; | ||
} | ||
.tag-fade-enter-from, | ||
.tag-fade-leave-to { | ||
opacity: 0; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { defineStore } from 'pinia'; | ||
import { ref } from 'vue'; | ||
import { sessionStorage } from '@/utils/storage'; | ||
|
||
export const useTagViewStore = defineStore('tagView', () => { | ||
const visitedViews = ref(sessionStorage.getItem('tagList') || []); | ||
const cachedViews = ref([]); | ||
|
||
function addVisitedViews(view) { | ||
console.log(view.meta.title) | ||
|
||
// Akiraka 20240228 限制标签数量 | ||
if (visitedViews.value.length >= 20) { | ||
visitedViews.value.splice(0,1) | ||
} | ||
|
||
if (visitedViews.value.some(v => v.path === view.path || v.meta.title === view.meta.title)) return; | ||
|
||
visitedViews.value.push( | ||
Object.assign({}, view, { | ||
title: view.meta.title || 'no-name' | ||
}) | ||
) | ||
sessionStorage.setItem('tagList', visitedViews.value); | ||
} | ||
|
||
function delVisitedViews(view) { | ||
for (const [i, v] of visitedViews.value.entries()) { | ||
if (v.path === view.path) { | ||
visitedViews.value.splice(i, 1); | ||
break; | ||
} | ||
} | ||
sessionStorage.setItem('tagList', visitedViews.value); | ||
} | ||
|
||
function delAllVisitedViews(view) { | ||
visitedViews.value = visitedViews.value.filter(v => v.path === view.path); | ||
sessionStorage.setItem('tagList', visitedViews.value); | ||
} | ||
|
||
function delLeftVisitedViews(view) { | ||
for (const [i, v] of visitedViews.value.entries()) { | ||
if (v.path === view.path) { | ||
visitedViews.value = visitedViews.value.slice(i); | ||
break; | ||
} | ||
} | ||
sessionStorage.setItem('tagList', visitedViews.value); | ||
} | ||
function delRightVisitedViews(view) { | ||
for (const [i, v] of visitedViews.value.entries()) { | ||
if (v.path === view.path) { | ||
visitedViews.value = visitedViews.value.slice(0, i + 1); | ||
break; | ||
} | ||
} | ||
sessionStorage.setItem('tagList', visitedViews.value); | ||
} | ||
|
||
function addCachedViews(view) { | ||
if (cachedViews.value.includes(view.name)) return; | ||
if (!view.meta.noCache) cachedViews.value.push(view.name); | ||
} | ||
|
||
function delCachedViews(view) { | ||
visitedViews.value = visitedViews.value.filter(v => v !== view.name); | ||
} | ||
|
||
function delCachedVisitedViews() { | ||
cachedViews.value = []; | ||
} | ||
|
||
return { | ||
visitedViews, | ||
cachedViews, | ||
addVisitedViews, | ||
delVisitedViews, | ||
delAllVisitedViews, | ||
delLeftVisitedViews, | ||
delRightVisitedViews | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters