export function createMenuSearchState() {
|
return {
|
name: '',
|
route: ''
|
}
|
}
|
|
export function normalizeMenuNumber(value, fallback = 0) {
|
if (value === '' || value === null || value === undefined) {
|
return fallback
|
}
|
const normalized = Number(value)
|
return Number.isNaN(normalized) ? fallback : normalized
|
}
|
|
export function normalizeMenuTitleKey(row = {}) {
|
const titleKey = row.meta?.title || row.name || ''
|
return titleKey && !String(titleKey).includes('.') ? `menu.${titleKey}` : titleKey
|
}
|
|
export function defaultMenuTitleFormatter(title = '') {
|
if (!title) {
|
return ''
|
}
|
return String(title).split('.').pop() || String(title)
|
}
|
|
export function getMenuDisplayTitle(row = {}, titleFormatter = defaultMenuTitleFormatter) {
|
return titleFormatter(normalizeMenuTitleKey(row))
|
}
|
|
export function getMenuDisplayIcon(row = {}) {
|
return row.meta?.icon || row.icon || ''
|
}
|
|
export function hasNestedMenus(row = {}) {
|
return Array.isArray(row.children) && row.children.some((child) => !child.meta?.isAuthButton)
|
}
|
|
export function getMenuTypeTag(row = {}) {
|
if (row.meta?.isAuthButton || Number(row.type) === 1) return 'danger'
|
if (hasNestedMenus(row)) return 'info'
|
return 'primary'
|
}
|
|
export function getMenuTypeText(row = {}) {
|
if (row.meta?.isAuthButton || Number(row.type) === 1) return '按钮'
|
if (hasNestedMenus(row)) return '目录'
|
return '菜单'
|
}
|
|
export function getMenuStatusMeta(status) {
|
return normalizeMenuNumber(status, 1) === 1
|
? { text: '启用', type: 'success' }
|
: { text: '禁用', type: 'danger' }
|
}
|
|
export function normalizeMenuTreeOptions(nodes = [], titleFormatter = defaultMenuTitleFormatter) {
|
if (!Array.isArray(nodes)) {
|
return []
|
}
|
|
return nodes.map((node) => ({
|
label: getMenuDisplayTitle(node, titleFormatter),
|
value: normalizeMenuNumber(node.id, 0),
|
children: normalizeMenuTreeOptions(node.children, titleFormatter)
|
}))
|
}
|
|
export function buildMenuTreeOptions(tree = [], titleFormatter = defaultMenuTitleFormatter) {
|
return [
|
{
|
label: '顶级菜单',
|
value: 0,
|
children: normalizeMenuTreeOptions(tree, titleFormatter)
|
}
|
]
|
}
|
|
export function buildMenuSubmitPayload(formData = {}) {
|
return {
|
...(formData.id ? { id: normalizeMenuNumber(formData.id, 0) } : {}),
|
parentId: normalizeMenuNumber(formData.parentId, 0),
|
name: String(formData.name || '').trim(),
|
route: String(formData.route || '').trim(),
|
component: String(formData.component || '').trim(),
|
authority: String(formData.authority || '').trim(),
|
icon: String(formData.icon || '').trim(),
|
sort: normalizeMenuNumber(formData.sort, 0),
|
status: normalizeMenuNumber(formData.status, 1),
|
memo: String(formData.memo || '').trim(),
|
type: formData.menuType === 'button' ? 1 : 0
|
}
|
}
|
|
export function cloneMenuTree(source) {
|
if (source === null || typeof source !== 'object') return source
|
if (source instanceof Date) return new Date(source)
|
if (Array.isArray(source)) return source.map((item) => cloneMenuTree(item))
|
const cloned = {}
|
for (const key in source) {
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
cloned[key] = cloneMenuTree(source[key])
|
}
|
}
|
return cloned
|
}
|
|
export function expandMenuAuthChildren(items = []) {
|
return items.map((item) => {
|
const clonedItem = cloneMenuTree(item)
|
if (clonedItem.children?.length) {
|
clonedItem.children = expandMenuAuthChildren(clonedItem.children)
|
}
|
if (item.meta?.authList?.length) {
|
const authChildren = item.meta.authList.map((auth) => ({
|
...cloneMenuTree(auth),
|
route: auth.route || '',
|
component: auth.component || '',
|
meta: {
|
title: auth.title,
|
authMark: auth.authMark,
|
isAuthButton: true,
|
parentPath: item.path,
|
icon: auth.icon,
|
sort: auth.sort,
|
isEnable: normalizeMenuNumber(auth.status, 1) === 1
|
}
|
}))
|
clonedItem.children = clonedItem.children?.length
|
? [...clonedItem.children, ...authChildren]
|
: authChildren
|
}
|
return clonedItem
|
})
|
}
|
|
export function filterMenuTree(items = [], filters = {}, titleFormatter = defaultMenuTitleFormatter) {
|
const results = []
|
const searchName = String(filters.name || '').toLowerCase().trim()
|
const searchRoute = String(filters.route || '').toLowerCase().trim()
|
|
for (const item of items) {
|
const menuTitle = getMenuDisplayTitle(item, titleFormatter).toLowerCase()
|
const menuRoute = String(item.route || item.path || item.authority || '').toLowerCase()
|
const nameMatch = !searchName || menuTitle.includes(searchName)
|
const routeMatch = !searchRoute || menuRoute.includes(searchRoute)
|
|
if (item.children?.length) {
|
const matchedChildren = filterMenuTree(item.children, filters, titleFormatter)
|
if (matchedChildren.length > 0) {
|
const clonedItem = cloneMenuTree(item)
|
clonedItem.children = matchedChildren
|
results.push(clonedItem)
|
continue
|
}
|
}
|
|
if (nameMatch && routeMatch) {
|
results.push(cloneMenuTree(item))
|
}
|
}
|
return results
|
}
|