feat: support merchant team roles and permissions

This commit is contained in:
yml2213
2026-08-13 11:41:34 +08:00
parent 6c98fa557e
commit a4791decb0
21 changed files with 969 additions and 201 deletions
+24 -11
View File
@@ -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))