import { defineComponent, watch, getCurrentInstance } from 'vue' import { useRoute } from 'vue-router' import { ElTabs, ElTabPane, ElTooltip } from 'element-plus' import { getRouteTitle, getMenuTitle, getRouteCache, isCacheView, matchMenuByRouteName, getRouteIcon, getMenuIcon, getFullPathWithoutHash } from '../helper' import { useOpenedView, useCacheView } from './hooks' import { useCipConfig } from '../../hooks/use-cip-config' import CipMainIcon from '../cip-main-icon' import './index.less' import { isEmpty, getUsingConfig } from '@cip/utils/util' import { isSubApp } from '../../cip-subapp-container/micro-app/util' export default defineComponent({ name: 'CipTabs', props: { menu: Array, // 菜单配置 cache: Array, // 缓存fullPath列表 menuTitleMap: Object, // 自定义fullPath对应的视图title homeView: Object, // 首页视图配置 withTabs: { type: Boolean, default: undefined } }, emits: ['update:cache'], setup (props, { emit }) { const cipConfig = useCipConfig() const route = useRoute() const instance = getCurrentInstance() // 已打开的view(包含未缓存及已缓存的视图) const { openedViewList, activeView, addOpenedView, updateOpenedView, removeOpenedView, findViewByOpenedViewList, setActiveView } = useOpenedView(props.homeView) const updateCache = (cache) => { emit('update:cache', cache) } const { cacheViewList, addCacheView, removeCacheView } = useCacheView(updateCache) // menu 配置的优先级高于 route const getViewConfig = (map, menu, view) => { let viewTitle = getRouteTitle(view) // 获取路由信息中的title let isCache = getRouteCache(view) // 获取路由信息中的cache let icon = getRouteIcon(view) const customTitle = map[view.fullPath] const menuMatch = matchMenuByRouteName(menu, view.name) if (menuMatch) { const innerIcon = getMenuIcon(menuMatch) // 开启递归查找 倒着查找 if (!isEmpty(innerIcon)) icon = innerIcon const currentMenu = menuMatch.pop() if (!isEmpty(getMenuTitle(currentMenu))) viewTitle = getUsingConfig(currentMenu.tagTitle, getMenuTitle(currentMenu))// 匹配到菜单项后获取菜单项的title if (!isEmpty(isCacheView(currentMenu))) isCache = isCacheView(currentMenu) } const title = [viewTitle, customTitle].filter(v => !!v).join('-') return { title, isCache, icon } } const handlerPathChange = (path) => { const { matched, ...currentView } = route currentView.fullPath = path // 重写fullPath const primaryKey = cipConfig.withQuery === false ? 'path' : 'fullPath' const index = openedViewList.value.findIndex(openedView => openedView[primaryKey] === currentView[primaryKey]) if (index === -1 || index === 0) { const { title, isCache, icon } = getViewConfig(props.menuTitleMap, props.menu, currentView) title && (currentView.title = title) icon && (currentView.icon = icon) currentView.isCache = isCache if (index === -1) addOpenedView(currentView) if (index === 0) updateOpenedView(index, currentView) if (isCache) { addCacheView(currentView.fullPath) emit('update:cache', cacheViewList.value) } } else { if (primaryKey === 'path') { openedViewList.value[index].fullPath = currentView.fullPath } setActiveView(openedViewList.value[index]) } } watch(() => getFullPathWithoutHash(route.fullPath), (val) => { if (isSubApp(route.name)) { console.log('子应用不缓存') } else { handlerPathChange(val) } }, { immediate: true }) // 打开view 缓存 tab名称 // 控制tab名称及缓存 watch(() => props.menu, (val) => { // menu变化是对整个openedViewList进行viewName计算 openedViewList.value.forEach((openedView) => { const { title, isCache, icon } = getViewConfig(props.menuTitleMap, val, openedView) title && (openedView.title = title) icon && (openedView.icon = icon) if (openedView.isCache !== isCache) { // 存在变化的openedView openedView.isCache = isCache isCache ? addCacheView(openedView.fullPath) : removeCacheView(openedView.fullPath) } }) }, { immediate: true }) // 控制tab名称 watch(() => props.menuTitleMap, (val) => { Object.keys(val).forEach(fullPath => { const matchRoute = openedViewList.value.find(view => view.fullPath === fullPath) if (matchRoute) { const { title, icon } = getViewConfig(val, props.menu, matchRoute) matchRoute.title = title matchRoute.icon = icon } }) }, { deep: true, immediate: true }) // 前往Tab视图 const toTab = (fullPath) => { const view = findViewByOpenedViewList(fullPath) setActiveView(view) } // 删除当前Tab视图 const removeTab = (fullPath) => { const view = findViewByOpenedViewList(fullPath) removeCacheView(fullPath) removeOpenedView(view) } instance.ctx.removeTab = removeTab instance.ctx.handlerPathChange = handlerPathChange return () => { // 隐藏模式时只有功能,没有dom if (!props.withTabs) return null return
toTab(paneName)} onTabRemove={(paneName) => { removeTab(paneName) }}> {openedViewList.value.map(openedView => ( 1} // closable={openedView.fullPath !== props.homeView?.fullPath} onClick={() => toTab(openedView)} onClose={() => removeOpenedView(openedView)} > {{ label: () => <> {openedView.icon && } {openedView.title || openedView.name} }} ))}
} } })