123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- <template>
- <right-click-menu
- :mouse-position="mousePosition"
- :config="opt"/>
- <div class="route_navigation_main"
- ref="tagRef">
- <div v-for="(item,index) in menuList"
- :class="index === currentIndex ? 'active_text item' : 'item'"
- :key="index"
- @contextmenu.prevent="contextmenuItem(item,index,$event)"
- @click="handleRouterPush(item)">
- {{ item?.title }}
- <el-icon @click.stop.prevent="closeRouter(index,item.path)">
- <Close/>
- </el-icon>
- </div>
- <div class="active_box" :style="selectedStyle"/>
- </div>
- </template>
- <script setup lang="ts">
- import {ref} from "vue";
- import tabsHook from "@/layout/HeaderV2/tabs-hook";
- import RightClickMenu from "@/components/menu-item/RightClickMenu";
- import router from '@/router'
- import XEUtils from "xe-utils";
- import {stringIsBlank} from "@/utils/blank-utils";
- const tagRef = ref<HTMLElement | null>(null)
- const opt = [
- {
- name: '关闭', click: (data, index) => {
- closeRouter(index, data.path)
- }
- },
- {
- name: '关闭其他选项卡', click: (data, index) => {
- router.push(data.path)
- setLabel([data])
- }
- },
- {
- name: '关闭所有选项卡', click: (data, index) => {
- menuList.value = []
- menuKey.value = []
- backToTheHomepage()
- }
- },
- {
- name: '关闭左侧选项卡', click: (data, index) => {
- if (index === 0) return
- if (index > currentIndex.value) {
- router.push(data.path)
- }
- let temp = []
- for (let i = index; i < menuList.value.length; i++) {
- temp.push(menuList.value[i])
- }
- setLabel(temp)
- }
- },
- {
- name: '关闭右侧选项卡', click: (data, index) => {
- if (index + 1 === menuList.value.length) return
- if (index < currentIndex.value) {
- router.push(data.path)
- }
- let temp = []
- for (let i = 0; i < index + 1; i++) {
- temp.push(menuList.value[i])
- }
- setLabel(temp)
- }
- }
- ]
- const mousePosition = ref()
- const contextmenuItem = async (item, index, event) => {
- mousePosition.value = {
- event,
- data: item,
- index
- }
- }
- const menuList = ref(tabsHook.getItem())
- const menuKey = ref(tabsHook.getItemKey())
- const currentPath = ref('')
- const currentIndex = ref(-1)
- const closeRouter = (index, path) => {
- menuList.value.splice(index, 1)
- menuKey.value.splice(index, 1)
- if (menuList.value.length === 0) {
- let data = {
- path: '/dashboard',
- title: '首页',
- }
- menuList.value.push(data)
- menuKey.value.push(JSON.stringify(data))
- router.push('/dashboard')
- } else {
- if (router.currentRoute.value.path === path || router.currentRoute.value.meta.activeMenu === path) {
- let temp = index === menuList.value.length ? menuList.value.length - 1 : index
- router.push(menuList.value[temp]?.path)
- }
- }
- }
- // 设置标签
- const setLabel = (data) => {
- menuList.value = data
- menuKey.value.value = []
- for (let i = 0, len = menuList.value.length; i < len; i++) {
- menuKey.value.value.push(JSON.stringify(menuList.value[i]))
- }
- }
- // 回到首页
- const backToTheHomepage = () => {
- router.push('/dashboard')
- }
- // 设置滚动条位置
- const handleScrolling = async (str) => {
- currentIndex.value = menuList.value.findIndex((item) => {
- return item.name === str.name
- })
- if (currentIndex.value === -1) return
- let itemData = tagRef.value!.querySelectorAll('.item')
- let scroll = 0;
- for (let i = 0; i < currentIndex.value; i++) {
- let item = itemData[i]
- scroll += item.scrollWidth
- }
- selectedStyle.value = {
- width: itemData[currentIndex.value].clientWidth + 'px',
- transform: `translateX(${scroll}px)`
- }
- tagRef.value!.scrollTo({top: 0, left: scroll, behavior: 'smooth'})
- }
- const selectedStyle = ref({})
- function handleRouterPush(item) {
- router.push({
- name: item.name,
- query: item.query
- })
- }
- watch(() => menuList.value, () => {
- tabsHook.setItem(menuList.value)
- routingChanges(false)
- }, {deep: true})
- const createLabels = (str, data) => {
- if (menuKey.value.indexOf(str) > -1) return
- menuList.value.push(data)
- tabsHook.setItem(menuList.value)
- menuKey.value.push(str)
- }
- const routingChanges = (createTabs = true) => {
- const currentRoute = router.currentRoute.value
- currentPath.value = currentRoute.path
- const data = {
- path: currentRoute.path,
- title: currentRoute.meta.title,
- name: currentRoute.name,
- query: currentRoute.query
- }
- const routerInfoToStr = JSON.stringify(data)
- nextTick(() => {
- handleScrolling(data)
- })
- if (XEUtils.get(currentRoute, 'meta.hideTabs', true)) {
- return;
- }
- if (stringIsBlank(currentRoute.name)) {
- return;
- }
- if (createTabs) {
- createLabels(routerInfoToStr, data)
- }
- }
- watch(() => router.currentRoute.value, () => {
- routingChanges()
- }, {immediate: true})
- </script>
- <style scoped lang="scss">
- $item-height: 40px;
- .route_navigation_main {
- flex: 1;
- display: flex;
- height: 100%;
- width: 100%;
- position: relative;
- overflow-x: auto;
- overflow-y: hidden;
- margin-right: 16px;
- }
- .active_text {
- color: var(--xc-header-active-text-color);
- opacity: 1 !important;
- }
- .active_box {
- position: absolute;
- height: $item-height;
- border-radius: 4px;
- background-color: var(--xc-header-active-bg-color);
- box-shadow: var(--el-box-shadow-light);
- transition: all .2s;
- -webkit-transition: all .2s;
- }
- .route_navigation_main::-webkit-scrollbar {
- height: 4px;
- background-color: #eaeaea;
- }
- .route_navigation_main:hover ::-webkit-scrollbar-track-piece {
- /*鼠标移动上去再显示滚动条*/
- background-color: #fff;
- /* 滚动条的背景颜色 */
- border-radius: 6px;
- /* 滚动条的圆角宽度 */
- }
- .route_navigation_main:hover::-webkit-scrollbar-thumb { /*滚动条里面小方块*/
- border-radius: 10px;
- -webkit-box-shadow: inset 0 0 5px rgba(28, 28, 28, 0.2);
- background: #919191;
- }
- .route_navigation_main::-webkit-scrollbar-track {
- background: white;
- }
- .item {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 0 20px;
- cursor: pointer;
- z-index: 1;
- height: $item-height;
- user-select: none;
- transition: all .2s;
- white-space: nowrap;
- -webkit-transition: all .2s;
- opacity: .7;
- &:hover {
- opacity: 1;
- }
- i {
- padding: 2px;
- font-size: 12px;
- margin-left: 5px;
- color: rgb(0, 0, 0);
- &:hover {
- background-color: #0a84fd;
- color: white;
- border-radius: 50%;
- }
- }
- }
- </style>
|