123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- 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 '@cip/components/main/cip-main-tabs/hooks'
- import { useCipConfig } from '../../hooks/use-cip-config'
- import CipMainIcon from '../cip-main-icon'
- import './index.less'
- import { isEmpty } from '@cip/utils/util'
- export default defineComponent({
- name: 'CipTabs',
- props: {
- menu: Array, // 菜单配置
- cache: Array, // 缓存fullPath列表
- menuTitleMap: Object, // 自定义fullPath对应的视图title
- homeView: Object // 首页视图配置
- },
- 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 = 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) => {
- 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 () => (
- <div class={['cip-main-tabs']}>
- <ElTabs
- type="card"
- modelValue={activeView.value.fullPath}
- onTabClick={({ paneName }) => toTab(paneName)}
- onTabRemove={(paneName) => { removeTab(paneName) }}>
- {openedViewList.value.map(openedView => (
- <ElTabPane
- key={openedView.fullPath}
- name={openedView.fullPath}
- label={openedView.title || openedView.name}
- closable={openedView.fullPath !== props.homeView?.fullPath}
- onClick={() => toTab(openedView)}
- onClose={() => removeOpenedView(openedView)} >
- {{
- label: () => <>
- {openedView.icon && <CipMainIcon style={'margin-right: 4px'} name={openedView.icon}/>}
- <ElTooltip content={openedView.title || openedView.name} >
- <span class={'cip-main-tab__label'}>{openedView.title || openedView.name}</span>
- </ElTooltip>
- </>
- }}
- </ElTabPane>
- ))}
- </ElTabs>
- </div>
- )
- }
- })
|