feat: support merchant team roles and permissions
This commit is contained in:
@@ -36,6 +36,8 @@ interface SidebarChild {
|
||||
label: string
|
||||
path?: string
|
||||
disabled?: boolean
|
||||
permission?: string
|
||||
feature?: string
|
||||
}
|
||||
|
||||
interface SidebarSection {
|
||||
@@ -112,38 +114,38 @@ const merchantSections: SidebarSection[] = [
|
||||
key: 'products',
|
||||
label: '商品管理',
|
||||
icon: <AppstoreOutlined />,
|
||||
children: [{ key: 'merchant-products', label: '商品列表', path: '/merchant-products' }],
|
||||
children: [{ key: 'merchant-products', label: '商品列表', path: '/merchant-products', permission: 'products:manage', feature: 'products' }],
|
||||
},
|
||||
{
|
||||
key: 'orders',
|
||||
label: '订单管理',
|
||||
icon: <OrderedListOutlined />,
|
||||
children: [{ key: 'fulfillment-orders', label: '发货订单', path: '/merchant-orders' }],
|
||||
children: [{ key: 'fulfillment-orders', label: '发货订单', path: '/merchant-orders', permission: 'orders:manage', feature: 'orders' }],
|
||||
},
|
||||
{
|
||||
key: 'funds',
|
||||
label: '积分管理',
|
||||
icon: <WalletOutlined />,
|
||||
children: [
|
||||
{ key: 'merchant-wallet', label: '积分明细', path: '/merchant-wallet' },
|
||||
{ key: 'merchant-recharge', label: '积分充值', path: '/merchant-recharge' },
|
||||
{ key: 'merchant-alert-settings', label: '余额告警', path: '/merchant-alert-settings' },
|
||||
{ key: 'merchant-wallet', label: '积分明细', path: '/merchant-wallet', permission: 'wallet:ledger', feature: 'wallet' },
|
||||
{ key: 'merchant-recharge', label: '积分充值', path: '/merchant-recharge', permission: 'wallet:view', feature: 'wallet' },
|
||||
{ key: 'merchant-alert-settings', label: '余额告警', path: '/merchant-alert-settings', permission: 'recharge:manage', feature: 'wallet' },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'staff',
|
||||
label: '员工管理',
|
||||
icon: <TeamOutlined />,
|
||||
children: [{ key: 'merchant-members', label: '成员管理', path: '/merchant-members' }],
|
||||
children: [{ key: 'merchant-members', label: '成员管理', path: '/merchant-members', permission: 'members:manage' }],
|
||||
},
|
||||
{
|
||||
key: 'open-api',
|
||||
label: '开放 API',
|
||||
icon: <ApiOutlined />,
|
||||
children: [
|
||||
{ key: 'api-keys', label: 'API 密钥', path: '/merchant-api-keys' },
|
||||
{ key: 'api-callbacks', label: '回调订阅', path: '/merchant-callbacks' },
|
||||
{ key: 'api-docs', label: '对接文档', path: '/open-api' },
|
||||
{ key: 'api-keys', label: 'API 密钥', path: '/merchant-api-keys', permission: 'api:manage', feature: 'api' },
|
||||
{ key: 'api-callbacks', label: '回调订阅', path: '/merchant-callbacks', permission: 'callbacks:manage', feature: 'callbacks' },
|
||||
{ key: 'api-docs', label: '对接文档', path: '/open-api', permission: 'api:manage', feature: 'api' },
|
||||
],
|
||||
},
|
||||
]
|
||||
@@ -204,12 +206,23 @@ export default function MainLayout() {
|
||||
const [collapsed, setCollapsed] = useState<boolean>(() => {
|
||||
return localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === 'true'
|
||||
})
|
||||
const { user, logout, isAdmin } = useAuth()
|
||||
const { user, logout, isAdmin, merchant, merchantPermissions } = useAuth()
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const isDocsPage = location.pathname.startsWith('/open-api')
|
||||
|
||||
const sections = useMemo(() => (isAdmin ? adminSections : merchantSections), [isAdmin])
|
||||
const sections = useMemo(() => {
|
||||
if (isAdmin) return adminSections
|
||||
const features = new Set((merchant?.features || '').split(/[\s,]+/).filter(Boolean))
|
||||
return merchantSections.flatMap((section) => {
|
||||
if (!section.children) return [section]
|
||||
const children = section.children.filter((child) => (
|
||||
(!child.permission || merchantPermissions.includes(child.permission))
|
||||
&& (!child.feature || features.has(child.feature))
|
||||
))
|
||||
return children.length > 0 ? [{ ...section, children }] : []
|
||||
})
|
||||
}, [isAdmin, merchant?.features, merchantPermissions])
|
||||
const selectedKey = getSelectedKey(location.pathname, location.search)
|
||||
const [openKeys, setOpenKeys] = useState<string[]>(() => loadStoredOpenKeys(sections, selectedKey))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user