2025-05-06 06:45:49 +00:00
|
|
|
import type { CommonProps } from '@/@types/common'
|
|
|
|
|
import type { NavigationTree } from '@/@types/navigation'
|
|
|
|
|
import type { Direction } from '@/@types/theme'
|
|
|
|
|
import { PermissionCheck } from '@/components/shared'
|
|
|
|
|
import Dropdown from '@/components/ui/Dropdown'
|
|
|
|
|
import Menu from '@/components/ui/Menu'
|
|
|
|
|
import { Link } from 'react-router-dom'
|
|
|
|
|
import VerticalMenuIcon from './VerticalMenuIcon'
|
|
|
|
|
|
|
|
|
|
interface DefaultItemProps extends CommonProps {
|
|
|
|
|
nav: NavigationTree
|
|
|
|
|
onLinkClick?: (link: { key: string; title: string; path: string }) => void
|
|
|
|
|
userAuthority: string[]
|
|
|
|
|
icon?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface CollapsedItemProps extends DefaultItemProps {
|
|
|
|
|
direction: Direction
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface VerticalCollapsedMenuItemProps extends CollapsedItemProps {
|
|
|
|
|
sideCollapsed?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { MenuItem, MenuCollapse } = Menu
|
|
|
|
|
|
|
|
|
|
const DefaultItem = ({ nav, onLinkClick }: DefaultItemProps) => {
|
|
|
|
|
return (
|
|
|
|
|
<PermissionCheck permissions={nav.authority}>
|
|
|
|
|
<MenuCollapse
|
|
|
|
|
key={nav.key}
|
|
|
|
|
label={
|
|
|
|
|
<>
|
|
|
|
|
<VerticalMenuIcon icon={nav.icon} />
|
2025-08-12 09:39:09 +00:00
|
|
|
<span>{nav.title}</span>
|
2025-05-06 06:45:49 +00:00
|
|
|
</>
|
|
|
|
|
}
|
|
|
|
|
eventKey={nav.key}
|
|
|
|
|
expanded={false}
|
|
|
|
|
>
|
|
|
|
|
{nav.subMenu.map((subNav) => (
|
|
|
|
|
<PermissionCheck key={subNav.key} permissions={subNav.authority}>
|
|
|
|
|
<MenuItem icon={subNav.icon} eventKey={subNav.key}>
|
|
|
|
|
<VerticalMenuIcon icon={subNav.icon} />
|
|
|
|
|
{subNav.path ? (
|
|
|
|
|
<Link
|
|
|
|
|
className="h-full w-full flex items-center"
|
|
|
|
|
to={subNav.path}
|
|
|
|
|
onClick={() =>
|
|
|
|
|
onLinkClick?.({
|
|
|
|
|
key: subNav.key,
|
|
|
|
|
title: subNav.title,
|
|
|
|
|
path: subNav.path,
|
|
|
|
|
})
|
|
|
|
|
}
|
2025-08-12 09:39:09 +00:00
|
|
|
target={subNav.isExternalLink ? '_blank' : ''}
|
2025-05-06 06:45:49 +00:00
|
|
|
>
|
2025-08-13 14:58:33 +00:00
|
|
|
<span>{subNav.title}</span>
|
2025-05-06 06:45:49 +00:00
|
|
|
</Link>
|
|
|
|
|
) : (
|
2025-08-13 14:58:33 +00:00
|
|
|
<span>{subNav.title}</span>
|
2025-05-06 06:45:49 +00:00
|
|
|
)}
|
|
|
|
|
</MenuItem>
|
|
|
|
|
</PermissionCheck>
|
|
|
|
|
))}
|
|
|
|
|
</MenuCollapse>
|
|
|
|
|
</PermissionCheck>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const CollapsedItem = ({ nav, onLinkClick, direction }: CollapsedItemProps) => {
|
|
|
|
|
const menuItem = (
|
|
|
|
|
<MenuItem key={nav.key} icon={nav.icon} eventKey={nav.key}>
|
|
|
|
|
<VerticalMenuIcon icon={nav.icon} />
|
|
|
|
|
</MenuItem>
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<PermissionCheck permissions={nav.authority}>
|
|
|
|
|
<Dropdown
|
|
|
|
|
trigger="hover"
|
|
|
|
|
renderTitle={menuItem}
|
|
|
|
|
placement={direction === 'rtl' ? 'middle-end-top' : 'middle-start-top'}
|
|
|
|
|
>
|
|
|
|
|
{nav.subMenu.map((subNav) => (
|
|
|
|
|
<PermissionCheck key={subNav.key} permissions={subNav.authority}>
|
|
|
|
|
<Dropdown.Item eventKey={subNav.key}>
|
|
|
|
|
{subNav.path ? (
|
|
|
|
|
<Link
|
|
|
|
|
className="h-full w-full flex items-center"
|
|
|
|
|
to={subNav.path}
|
|
|
|
|
onClick={() =>
|
|
|
|
|
onLinkClick?.({
|
|
|
|
|
key: subNav.key,
|
|
|
|
|
title: subNav.title,
|
|
|
|
|
path: subNav.path,
|
|
|
|
|
})
|
|
|
|
|
}
|
2025-08-12 09:39:09 +00:00
|
|
|
target={subNav.isExternalLink ? '_blank' : ''}
|
2025-05-06 06:45:49 +00:00
|
|
|
>
|
2025-08-12 09:39:09 +00:00
|
|
|
<span>{subNav.title}</span>
|
2025-05-06 06:45:49 +00:00
|
|
|
</Link>
|
|
|
|
|
) : (
|
2025-08-12 09:39:09 +00:00
|
|
|
<span>{subNav.title}</span>
|
2025-05-06 06:45:49 +00:00
|
|
|
)}
|
|
|
|
|
</Dropdown.Item>
|
|
|
|
|
</PermissionCheck>
|
|
|
|
|
))}
|
|
|
|
|
</Dropdown>
|
|
|
|
|
</PermissionCheck>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const VerticalCollapsedMenuItem = ({ sideCollapsed, ...rest }: VerticalCollapsedMenuItemProps) => {
|
|
|
|
|
return sideCollapsed ? <CollapsedItem {...rest} /> : <DefaultItem {...rest} />
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default VerticalCollapsedMenuItem
|