ray-template/src/hooks/template/useSiderBar.ts
2024-01-28 15:40:04 +08:00

325 lines
7.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
*
* @author Ray <https://github.com/XiaoDaiGua-Ray>
*
* @date 2023-11-03
*
* @workspace ray-template
*
* @remark 今天也是元气满满撸代码的一天
*/
import { useMenuGetters, useMenuActions } from '@/store'
import { useVueRouter, useAppRoot } from '@/hooks'
import { pick } from '@/utils'
import type { MenuTagOptions, Key, AppMenuOption } from '@/types'
export type CloseMenuTag = Key | MenuTagOptions
/**
*
* @param target 标签页对象、索引、key
* @param fc 触发函数
*
* 该方法用于统一获取目标标签页方法
*/
const normalMenuTagOption = (target: CloseMenuTag, fc: string) => {
const { getMenuTagOptions } = useMenuGetters()
if (typeof target === 'number') {
// 判断是否为 NaN
if (isNaN(target)) {
console.warn(`${fc}: The ${target} is NaN, expect number.`)
return
}
// 判断是否超出当前标签页列表最大长度或者是否为负数
if (target > getMenuTagOptions.value.length || target < -1) {
console.warn(
`${fc}: The incoming index ${target} did not match the corresponding item.`,
)
return
}
return {
option: getMenuTagOptions.value[target],
index: target,
}
} else if (typeof target === 'string') {
// 查找符合条件的 key
const index = getMenuTagOptions.value.findIndex(
(curr) => curr.fullPath === target,
)
return index > -1
? {
option: getMenuTagOptions.value[index],
index,
}
: console.warn(
`${fc}: The incoming key ${target} did not match the corresponding item.`,
)
} else {
const { fullPath } = target
const index = getMenuTagOptions.value.findIndex(
(curr) => curr.fullPath === fullPath,
)
if (index === -1) {
console.warn(
`${fc}: The incoming menuTag option ${target.fullPath} did not match the corresponding item.`,
)
return
}
return {
option: target,
index,
}
}
}
export function useSiderBar() {
const { getMenuTagOptions, getMenuKey } = useMenuGetters()
const {
changeMenuModelValue,
spliceMenTagOptions,
setMenuTagOptions,
resolveOption,
} = useMenuActions()
/**
*
* @remark 获取当前激活标签页索引位置
*/
const getCurrentTagIndex = () => {
return getMenuTagOptions.value.findIndex(
(curr) => curr.fullPath === getMenuKey.value,
)
}
/**
*
* @param target 当前关闭项
*
* 传递参数类型情况:
* - number: 关闭当前项索引
* - string: 关闭当前项 key其实 key 也是一个具体的页面 url 地址
* - AppMenuOption: 关闭当前项
*
* @remark 校验指定标签右侧是否有可关闭的标签
*/
const checkCloseRight = (target: CloseMenuTag) => {
const normal = normalMenuTagOption(target, 'checkCloseRight')
if (normal) {
const { index } = normal
const length = getMenuTagOptions.value.length - 1
return !(index >= length)
}
return false
}
/**
*
* @param target 当前关闭项
*
* 传递参数类型情况:
* - number: 关闭当前项索引
* - string: 关闭当前项 key其实 key 也是一个具体的页面 url 地址
* - AppMenuOption: 关闭当前项
*
* @remark 校验指定标签左侧是否有可关闭的标签
*/
const checkCloseLeft = (target: CloseMenuTag) => {
const normal = normalMenuTagOption(target, 'checkCloseRight')
if (normal) {
const { index } = normal
const length = getMenuTagOptions.value.length - 1
if (index === 0) {
return false
}
if (index > 0 && length > 0) {
return true
}
return false
}
return false
}
/**
*
* @param target 当前关闭项
*
* 传递参数类型情况:
* - number: 关闭当前项索引
* - string: 关闭当前项 key其实 key 也是一个具体的页面 url 地址
* - AppMenuOption: 关闭当前项
*/
const close = (target: CloseMenuTag) => {
const normal = normalMenuTagOption(target, 'close')
if (getMenuTagOptions.value.length === 1) {
return
}
if (normal) {
const { index, option } = normal
spliceMenTagOptions(index)
if (option.fullPath === getMenuKey.value) {
const tag = getMenuTagOptions.value[index - 1]
if (tag) {
changeMenuModelValue(tag.fullPath, tag)
}
}
}
}
/**
*
* 关闭所有标签并且导航至 root path
*/
const closeAll = () => {
spliceMenTagOptions(0, getMenuTagOptions.value.length)
const { getRootPath } = useAppRoot()
const {
router: { getRoutes },
} = useVueRouter()
const findMenuOption = getRoutes().find(
(curr) => curr.path === getRootPath.value,
)
if (findMenuOption) {
const pickOption = pick(findMenuOption, [
'children',
'meta',
'path',
'name',
'redirect',
]) as unknown as AppMenuOption
changeMenuModelValue(
pickOption.path,
resolveOption({
...pickOption,
fullPath: pickOption.path,
}),
)
}
}
/**
*
* @param target 目标标签页
*
* 关闭以当前项为索引的右侧标签
* 如果当前选择标签与 menuKey 不匹配并且包含了当前激活标签页,则会关闭当前标签右侧所有变迁并且跳转至该页面
*
* 传递参数类型情况:
* - number: 关闭当前项索引
* - string: 关闭当前项 key其实 key 也是一个具体的页面 url 地址
* - AppMenuOption: 关闭当前项
*/
const closeRight = (target: CloseMenuTag) => {
const normal = normalMenuTagOption(target, 'closeRight')
if (normal) {
const { option, index } = normal
const spliceLength = getMenuTagOptions.value.length - index // 待删除长度
const currentIndex = getCurrentTagIndex()
spliceMenTagOptions(index + 1, spliceLength)
if (index <= currentIndex) {
if (getMenuKey.value !== option.fullPath) {
changeMenuModelValue(option.fullPath, option)
}
}
}
}
/**
*
* @param target 目标标签页
*
* 关闭以当前项左侧所有标签
* 如果当前选择标签与 menuKey 不匹配并且包含了当前激活标签页,则会关闭当前标签左侧所有变迁并且跳转至该页面
*
* 传递参数类型情况:
* - number: 关闭当前项索引
* - string: 关闭当前项 key其实 key 也是一个具体的页面 url 地址
* - AppMenuOption: 关闭当前项
*/
const closeLeft = (target: CloseMenuTag) => {
const normal = normalMenuTagOption(target, 'closeLeft')
if (normal) {
const { option, index } = normal
const currentIndex = getCurrentTagIndex()
spliceMenTagOptions(0, index)
if (currentIndex <= index) {
if (getMenuKey.value !== option.fullPath) {
changeMenuModelValue(option.fullPath, option)
}
}
}
}
/**
*
* @param target 目标标签页
*
* 会关闭除了当前索引的所有菜单项
*
* 传递参数类型情况:
* - number: 关闭当前项索引
* - string: 关闭当前项 key其实 key 也是一个具体的页面 url 地址
* - AppMenuOption: 关闭当前项
*/
const closeOther = (target: CloseMenuTag) => {
const normal = normalMenuTagOption(target, 'closeOther')
if (normal) {
const { option } = normal
if (getMenuKey.value !== option.fullPath) {
spliceMenTagOptions(0, getMenuTagOptions.value.length)
changeMenuModelValue(option.fullPath, option)
} else {
setMenuTagOptions(option, false)
}
}
}
return {
close,
closeAll,
closeRight,
closeLeft,
closeOther,
getCurrentTagIndex,
checkCloseRight,
checkCloseLeft,
}
}
export type UseSiderBarReturnType = ReturnType<typeof useSiderBar>