create-iking-admin
Version:
金合技术中台脚手架
423 lines (417 loc) • 15.7 kB
text/typescript
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