UNPKG

create-iking-admin

Version:

金合技术中台脚手架

423 lines (417 loc) 15.7 kB
import { cloneDeep } from 'lodash-es' import type { RouteLocationNormalized } from 'vue-router' import { userApi } from '@main/api/modules/user' import useSettingsStore from './settings' import useUserStore from './user' import useRouteStore from './route' import useKeepAliveStore from './keepAlive' import useIframeStore from './iframe' import type { Tabbar } from '#/global' const useTabbarStore = defineStore( // 唯一ID 'tabbar', () => { const settingsStore = useSettingsStore() const userStore = useUserStore() const routeStore = useRouteStore() const keepAliveStore = useKeepAliveStore() const iframeStore = useIframeStore() const list = ref<Tabbar.recordRaw[]>([]) const leaveIndex = ref(-1) // 初始化常驻标签页 function initPermanentTab() { const tabs: Tabbar.recordRaw[] = [] routeStore.flatSystemRoutes.forEach((items) => { items.children && items.children.forEach((route) => { if (route.meta?.permanent && route.meta?.breadcrumbNeste) { const fullPath = route.meta.breadcrumbNeste.at(-1)?.path as string const tabId = settingsStore.settings.tabbar.mergeTabsBy === 'activeMenu' ? (route.meta.activeMenu || fullPath) : fullPath tabs.push({ tabId, fullPath, routeName: route.name, activeMenu: route.meta.activeMenu, title: typeof route.meta.title === 'function' ? route.meta.title() : route.meta.title, i18n: route.meta.i18n, iframe: route.meta.iframe, icon: route.meta?.icon ?? route.meta?.breadcrumbNeste?.findLast(item => item.icon)?.icon, activeIcon: route.meta?.activeIcon ?? route.meta?.breadcrumbNeste?.findLast(item => item.activeIcon)?.activeIcon, name: route.name ? [route.name as string] : [], customTitleList: [], isPin: false, isPermanent: true, }) } }) }) routeStore.flatRoutes.forEach((items) => { if (settingsStore.settings.app.routeBaseOn !== 'filesystem') { items.children && items.children.forEach((route) => { if (route.meta?.permanent && route.meta?.breadcrumbNeste) { const fullPath = route.meta.breadcrumbNeste.at(-1)?.path as string const tabId = settingsStore.settings.tabbar.mergeTabsBy === 'activeMenu' ? (route.meta.activeMenu || fullPath) : fullPath tabs.push({ tabId, fullPath, routeName: route.name, activeMenu: route.meta.activeMenu, title: typeof route.meta.title === 'function' ? route.meta.title() : route.meta.title, i18n: route.meta.i18n, iframe: route.meta.iframe, icon: route.meta?.icon ?? route.meta?.breadcrumbNeste?.findLast(item => item.icon)?.icon, activeIcon: route.meta?.activeIcon ?? route.meta?.breadcrumbNeste?.findLast(item => item.activeIcon)?.activeIcon, name: route.name ? [route.name as string] : [], customTitleList: [], isPin: false, isPermanent: true, }) } }) } else { if (items.meta?.permanent) { const tabId = settingsStore.settings.tabbar.mergeTabsBy === 'activeMenu' ? (items.meta.activeMenu || items.path) : items.path tabs.push({ tabId, fullPath: items.path, routeName: items.name, activeMenu: items.meta.activeMenu, title: typeof items.meta.title === 'function' ? items.meta.title() : items.meta.title, i18n: items.meta.i18n, iframe: items.meta.iframe, icon: items.meta?.icon ?? items.meta?.breadcrumbNeste?.findLast(item => item.icon)?.icon, activeIcon: items.meta?.activeIcon ?? items.meta?.breadcrumbNeste?.findLast(item => item.activeIcon)?.activeIcon, name: items.name ? [items.name as string] : [], customTitleList: [], isPin: false, isPermanent: true, }) } } }) // 常驻的标签页添加到标签栏开头 tabs.length && list.value.unshift(...tabs) } // 添加标签页 async function add(route: RouteLocationNormalized) { const names: string[] = [] route.matched.forEach((v, i) => { if (i > 0) { v.components?.default.name && names.push(v.components.default.name) } }) const meta = route.matched.at(-1)?.meta const tabId = settingsStore.settings.tabbar.mergeTabsBy === 'activeMenu' ? (meta?.activeMenu ?? route.fullPath) : route.fullPath if (route.name !== 'reload') { // 记录查找到的标签页 const findTab = list.value.find((item) => { if (settingsStore.settings.tabbar.mergeTabsBy === 'routeName' && item.routeName) { return item.routeName === route.name } else { return item.tabId === tabId } }) // 新增标签页 if (!findTab) { const listItem = { tabId, fullPath: route.fullPath, routeName: route.name, activeMenu: meta?.activeMenu, title: typeof meta?.title === 'function' ? meta.title() : meta?.title, i18n: meta?.i18n, iframe: meta?.iframe, icon: meta?.icon ?? meta?.breadcrumbNeste?.findLast(item => item.icon)?.icon, activeIcon: meta?.activeIcon ?? meta?.breadcrumbNeste?.findLast(item => item.activeIcon)?.activeIcon, name: names, customTitleList: [], isPin: false, isPermanent: false, } if (leaveIndex.value >= 0) { list.value.splice(leaveIndex.value + 1, 0, listItem) leaveIndex.value = -1 } else { list.value.push(listItem) } } // 更新标签页 else { if (settingsStore.settings.tabbar.mergeTabsBy !== '') { findTab.tabId = tabId findTab.fullPath = route.fullPath findTab.routeName = route.name findTab.activeMenu = meta?.activeMenu findTab.title = typeof meta?.title === 'function' ? meta.title() : meta?.title findTab.i18n = meta?.i18n findTab.iframe = meta?.iframe findTab.icon = meta?.icon ?? meta?.breadcrumbNeste?.findLast(item => item.icon)?.icon findTab.activeIcon = meta?.activeIcon ?? meta?.breadcrumbNeste?.findLast(item => item.activeIcon)?.activeIcon } } } updateStorage() } // 删除指定标签页 function remove(tabId: Tabbar.recordRaw['tabId']) { const keepName: string[] = [] const removeName: string[] = [] const removeIframe: string[] = [] list.value.forEach((v) => { if (v.tabId === tabId) { !v.iframe ? removeName.push(...v.name) : removeIframe.push(v.tabId) } else { keepName.push(...v.name) } }) const name: string[] = [] removeName.forEach((v) => { if (!keepName.includes(v)) { name.push(v) } }) // 如果是手动点击关闭 tab 标签页,则删除页面缓存 keepAliveStore.remove(name) iframeStore.close(removeIframe) list.value = list.value.filter((item) => { return item.tabId !== tabId }) updateStorage() } // 删除两侧非常驻和非固定标签页 function removeOtherSide(tabId: Tabbar.recordRaw['tabId']) { const keepName: string[] = [] const removeName: string[] = [] const removeIframe: string[] = [] list.value.forEach((v) => { if (v.tabId !== tabId && !v.isPermanent && !v.isPin) { !v.iframe ? removeName.push(...v.name) : removeIframe.push(v.tabId) } else { keepName.push(...v.name) } }) const name: string[] = [] removeName.forEach((v) => { if (!keepName.includes(v)) { name.push(v) } }) keepAliveStore.remove(name) iframeStore.close(removeIframe) list.value = list.value.filter((item) => { return item.tabId === tabId || item.isPermanent || item.isPin }) updateStorage() } // 删除左侧非常驻和非固定标签页 function removeLeftSide(tabId: Tabbar.recordRaw['tabId']) { // 查找指定路由对应在标签页列表里的下标 const index = list.value.findIndex(item => item.tabId === tabId) const keepName: string[] = [] const removeName: string[] = [] const removeIframe: string[] = [] list.value.forEach((v, i) => { if (i < index && !v.isPermanent && !v.isPin) { !v.iframe ? removeName.push(...v.name) : removeIframe.push(v.tabId) } else { keepName.push(...v.name) } }) const name: string[] = [] removeName.forEach((v) => { if (!keepName.includes(v)) { name.push(v) } }) keepAliveStore.remove(name) iframeStore.close(removeIframe) list.value = list.value.filter((item, i) => { return i >= index || item.isPermanent || item.isPin }) updateStorage() } // 删除右侧非常驻和非固定标签页 function removeRightSide(tabId: Tabbar.recordRaw['tabId']) { // 查找指定路由对应在标签页列表里的下标 const index = list.value.findIndex(item => item.tabId === tabId) const keepName: string[] = [] const removeName: string[] = [] const removeIframe: string[] = [] list.value.forEach((v, i) => { if (i > index && !v.isPermanent && !v.isPin) { !v.iframe ? removeName.push(...v.name) : removeIframe.push(v.tabId) } else { keepName.push(...v.name) } }) const name: string[] = [] removeName.forEach((v) => { if (!keepName.includes(v)) { name.push(v) } }) keepAliveStore.remove(name) iframeStore.close(removeIframe) list.value = list.value.filter((item, i) => { return i <= index || item.isPermanent || item.isPin }) updateStorage() } // 固定标签页(移动到最后一个常驻或固定标签页后面,如果没有则移动至第一个) function pin(tabId: Tabbar.recordRaw['tabId']) { const index = list.value.findIndex(item => item.tabId === tabId) let toIndex = -1 list.value.forEach((item, index) => { if (item.isPermanent || item.isPin) { toIndex = index } }) if (index > toIndex) { list.value.splice(toIndex + 1, 0, list.value[index]) list.value.splice(index + 1, 1) } // 修改状态 list.value.forEach((item) => { if (item.tabId === tabId) { item.isPin = true } }) updateStorage() } // 取消固定标签页(移动到最后一个常驻或固定标签页后面) function unPin(tabId: Tabbar.recordRaw['tabId']) { const index = list.value.findIndex(item => item.tabId === tabId) let toIndex = -1 list.value.forEach((item, index) => { if (item.isPermanent || item.isPin) { toIndex = index } }) list.value.splice(toIndex + 1, 0, list.value[index]) list.value.splice(index, 1) // 修改状态 list.value.forEach((item) => { if (item.tabId === tabId) { item.isPin = false } }) updateStorage() } // 清空所有标签页,登出的时候需要清空 function clean() { list.value = [] } // 拖拽排序 function sort(newIndex: number, oldIndex: number) { list.value.splice(newIndex, 0, list.value.splice(oldIndex, 1)[0]) updateStorage() } // 设置标签页自定义标题 function setCustomTitle({ tabId, title }: { tabId: Tabbar.recordRaw['tabId'] title: string }) { list.value.forEach((item) => { if (item.tabId === tabId) { const findItem = item.customTitleList.find(v => v.fullPath === item.fullPath) if (findItem) { findItem.title = title } else { item.customTitleList.push({ fullPath: item.fullPath, title, }) } } }) updateStorage() } // 重置标签页自定义标题 function resetCustomTitle(tabId: Tabbar.recordRaw['tabId']) { list.value.forEach((item) => { if (item.tabId === tabId) { const index = item.customTitleList.findIndex(v => v.fullPath === item.fullPath) if (index > -1) { item.customTitleList.splice(index, 1) } } }) updateStorage() } // 更新 ikStore 数据 async function updateStorage() { if (settingsStore.settings.tabbar.storageTo === 'local') { const pinData = ikStore.local.has('tabbarPinData') ? JSON.parse(ikStore.local.getItem('tabbarPinData') as string) : {} pinData[userStore.account] = cloneDeep(list.value.filter((item) => { return item.isPin })).map((item) => { // 不存储自定义标题 item.customTitleList = [] return item }) ikStore.local.setItem('tabbarPinData', JSON.stringify(pinData)) } else if (settingsStore.settings.tabbar.storageTo === 'server') { await apiUser.tabbarEdit(JSON.stringify(cloneDeep(list.value.filter((item) => { return item.isPin })).map((item) => { // 不存储自定义标题 item.customTitleList = [] return item }))) } if (settingsStore.settings.tabbar.enableMemory) { // 将非固定和非常驻标签页记录到 sessionStorage const unpinData = ikStore.session.has('tabbarTempData') ? JSON.parse(ikStore.session.getItem('tabbarTempData') as string) : {} unpinData[userStore.account] = cloneDeep(list.value.filter((item) => { return !item.isPin && !item.isPermanent })).map((item) => { // 不存储自定义标题 item.customTitleList = [] return item }) ikStore.session.setItem('tabbarTempData', JSON.stringify(unpinData)) } } // 根据 ikStore 数据复原当前帐号的标签页 async function recoveryStorage() { if (settingsStore.settings.tabbar.storageTo === 'local') { if (ikStore.local.has('tabbarPinData')) { list.value.push(...(JSON.parse(ikStore.local.getItem('tabbarPinData') as string)[userStore.account] || [])) } } else if (settingsStore.settings.tabbar.storageTo === 'server') { const res = await apiUser.tabbar() list.value.push(...(JSON.parse(res.data.tabbar || '[]'))) } if (settingsStore.settings.tabbar.enableMemory && ikStore.session.has('tabbarTempData')) { list.value.push(...(JSON.parse(ikStore.session.getItem('tabbarTempData') as string)[userStore.account] || [])) } } return { list, leaveIndex, initPermanentTab, add, remove, removeOtherSide, removeLeftSide, removeRightSide, pin, unPin, clean, sort, setCustomTitle, resetCustomTitle, recoveryStorage, } }, ) export default useTabbarStore