diff --git a/e2e/pages/system-permission.spec.ts b/e2e/pages/system-permission.spec.ts index 1cbd085..11ab090 100644 --- a/e2e/pages/system-permission.spec.ts +++ b/e2e/pages/system-permission.spec.ts @@ -19,6 +19,12 @@ test.describe('系统管理 / 权限配置', () => { await page.getByRole('button', { name: '保 存' }).click(); await expect(page.getByText('菜单已保存')).toBeVisible(); await expect(page.getByRole('tree').getByText('用户中心')).toBeVisible(); + + await page.getByRole('tab', { name: '按钮权限' }).click(); + const buttonPanel = page.getByRole('tabpanel', { name: '按钮权限' }); + await expect(buttonPanel.getByRole('row').filter({ hasText: 'system:user:add' })).toContainText( + '系统管理 / 用户中心', + ); }); test('可新增同级菜单', async ({ page }) => { @@ -42,4 +48,15 @@ test.describe('系统管理 / 权限配置', () => { await expect(buttonPanel.getByText('system:user:import')).toBeVisible(); await expect(page.getByText('按钮权限已添加')).toBeVisible(); }); + + test('删除菜单时同步清理按钮权限', async ({ page }) => { + await page.getByRole('button', { name: '删除' }).first().click(); + await page.getByRole('button', { name: '确 定' }).click(); + await expect(page.getByText('菜单已删除')).toBeVisible(); + + await page.getByRole('tab', { name: '按钮权限' }).click(); + const buttonPanel = page.getByRole('tabpanel', { name: '按钮权限' }); + await expect(buttonPanel.getByText('system:user:add')).toHaveCount(0); + await expect(buttonPanel.getByText('system:user:edit')).toHaveCount(0); + }); }); diff --git a/e2e/pages/system-roles.spec.ts b/e2e/pages/system-roles.spec.ts index 5fadba5..876001c 100644 --- a/e2e/pages/system-roles.spec.ts +++ b/e2e/pages/system-roles.spec.ts @@ -40,6 +40,9 @@ test.describe('系统管理 / 角色管理', () => { await expect(page.getByText('配置权限 - 运营')).toBeVisible(); await expect(page.getByText('菜单权限')).toBeVisible(); await expect(page.getByText('按钮权限')).toBeVisible(); + await expect(page.getByRole('treeitem', { name: '用量明细' })).toHaveAttribute('aria-checked', 'false'); + await expect(page.getByRole('treeitem', { name: '模型列表' })).toHaveAttribute('aria-checked', 'true'); + await expect(page.getByRole('checkbox', { name: 'system:user:add' })).toBeChecked(); await page.getByRole('button', { name: '保 存' }).click(); await expect(page.getByText('权限已保存')).toBeVisible(); diff --git a/e2e/pages/system-users.spec.ts b/e2e/pages/system-users.spec.ts index 46970e6..0fe7176 100644 --- a/e2e/pages/system-users.spec.ts +++ b/e2e/pages/system-users.spec.ts @@ -51,9 +51,14 @@ test.describe('系统管理 / 用户管理', () => { await operatorRow.getByRole('button', { name: '编辑' }).click(); const dialog = page.getByRole('dialog', { name: '编辑用户' }); await dialog.getByLabel('昵称').fill('新运营'); + await dialog.getByLabel('备注').fill('负责日常运营'); await dialog.getByRole('button', { name: '保 存' }).click(); await expect(page.getByText('新运营', { exact: true })).toBeVisible(); + await operatorRow.getByRole('button', { name: '编辑' }).click(); + await expect(page.getByRole('dialog', { name: '编辑用户' }).getByLabel('备注')).toHaveValue('负责日常运营'); + await page.getByRole('dialog', { name: '编辑用户' }).getByRole('button', { name: '取 消' }).click(); + const viewerRow = page.getByRole('row').filter({ hasText: 'viewer' }); await viewerRow.getByRole('button', { name: '删除' }).click(); await page.getByRole('button', { name: '确 定' }).click(); diff --git a/src/pages/system/permission/index.tsx b/src/pages/system/permission/index.tsx index 8e875f4..c20429b 100644 --- a/src/pages/system/permission/index.tsx +++ b/src/pages/system/permission/index.tsx @@ -93,6 +93,11 @@ const removeNode = (nodes: MenuPermissionNode[], key: string): MenuPermissionNod .filter(node => node.key !== key) .map(node => (node.children ? { ...node, children: removeNode(node.children, key) } : node)); +const collectNodeKeys = (node: MenuPermissionNode): string[] => [ + node.key, + ...(node.children?.flatMap(collectNodeKeys) ?? []), +]; + const toTreeData = (nodes: MenuPermissionNode[]): DataNode[] => nodes.map(node => ({ key: node.key, @@ -212,8 +217,10 @@ export default function PermissionManagement() { const deleteMenu = () => { if (!selectedNode) return; + const removedKeys = new Set(collectNodeKeys(selectedNode)); const nextTree = removeNode(menuTree, selectedKey); setMenuTree(nextTree); + setButtons(current => current.filter(item => !removedKeys.has(item.menuKey))); const fallback = nextTree[0]?.key ?? nextTree[0]?.children?.[0]?.key; if (fallback) { setSelectedKey(fallback); @@ -228,10 +235,17 @@ export default function PermissionManagement() { const saveMenu = async () => { if (!selectedKey) return; const values = await menuForm.validateFields(); - setMenuTree(current => - updateNode(current, selectedKey, node => ({ - ...node, - ...values, + const nextTree = updateNode(menuTree, selectedKey, node => ({ + ...node, + ...values, + })); + const menuPaths = new Map(flattenMenus(nextTree).map(item => [item.key, item.label])); + + setMenuTree(nextTree); + setButtons(current => + current.map(item => ({ + ...item, + menuPath: menuPaths.get(item.menuKey) ?? item.menuPath, })), ); message.success('菜单已保存'); diff --git a/src/pages/system/role/index.tsx b/src/pages/system/role/index.tsx index 345b0f5..9a220a0 100644 --- a/src/pages/system/role/index.tsx +++ b/src/pages/system/role/index.tsx @@ -287,6 +287,7 @@ export default function RoleManagement() { + nodes.map(node => ({ + key: node.key, + title: node.title, + children: node.children ? toRoleMenuTree(node.children) : undefined, + })); -export const buttonPermissionOptions = [ - { label: 'user:create', value: 'user:create' }, - { label: 'user:edit', value: 'user:edit' }, - { label: 'user:delete', value: 'user:delete' }, - { label: 'llm:create', value: 'llm:create' }, -]; +export const menuPermissionTree = toRoleMenuTree(initialMenuTree); + +export const buttonPermissionOptions = initialButtonPermissions.map(item => ({ + label: item.code, + value: item.code, +})); export const initialRoles: RoleItem[] = [ { @@ -56,20 +45,8 @@ export const initialRoles: RoleItem[] = [ enabled: true, description: '拥有系统全部权限', updatedAt: '2026-07-20 10:00', - menuKeys: [ - 'dashboard', - 'llm', - 'llm-models', - 'llm-providers', - 'llm-usage', - 'llm-usage-details', - 'llm-quota', - 'system', - 'system-user', - 'system-role', - 'system-permission', - ], - buttonKeys: ['user:create', 'user:edit', 'user:delete', 'llm:create'], + menuKeys: ['1', '2', '2-1', '2-2', '2-3', '2-4', '2-5', '3', '3-1', '3-2', '3-3'], + buttonKeys: initialButtonPermissions.map(item => item.code), }, { id: 'role-2', @@ -79,18 +56,8 @@ export const initialRoles: RoleItem[] = [ enabled: true, description: '负责模型与用户日常运营', updatedAt: '2026-07-22 15:30', - menuKeys: [ - 'dashboard', - 'llm', - 'llm-models', - 'llm-providers', - 'llm-usage', - 'llm-quota', - 'system', - 'system-user', - 'system-role', - ], - buttonKeys: ['user:create', 'user:edit', 'llm:create'], + menuKeys: ['1', '2', '2-1', '2-2', '2-3', '2-5', '3', '3-1', '3-2'], + buttonKeys: ['system:user:add', 'system:user:edit', 'llm:models:add'], }, { id: 'role-3', @@ -100,7 +67,7 @@ export const initialRoles: RoleItem[] = [ enabled: true, description: '仅可查看数据,不可修改', updatedAt: '2026-07-18 09:12', - menuKeys: ['dashboard', 'llm', 'llm-models', 'llm-usage'], + menuKeys: ['1', '2', '2-1', '2-3'], buttonKeys: [], }, ]; diff --git a/src/pages/system/user/index.tsx b/src/pages/system/user/index.tsx index 1417a86..7e47ba4 100644 --- a/src/pages/system/user/index.tsx +++ b/src/pages/system/user/index.tsx @@ -118,6 +118,7 @@ export default function UserManagement() { phone: values.phone, roles: values.roles, enabled: values.enabled, + remark: values.remark, } : user, ), @@ -134,6 +135,7 @@ export default function UserManagement() { phone: values.phone, roles: values.roles, enabled: values.enabled, + remark: values.remark, lastLoginAt: '从未登录', createdAt: '2026-07-26', }, diff --git a/src/pages/system/user/mock.ts b/src/pages/system/user/mock.ts index 693c4c4..c5901d9 100644 --- a/src/pages/system/user/mock.ts +++ b/src/pages/system/user/mock.ts @@ -10,6 +10,7 @@ export interface UserItem { enabled: boolean; lastLoginAt: string; createdAt: string; + remark?: string; } export const roleOptions: UserRole[] = ['超级管理员', '运营', '只读']; @@ -25,6 +26,7 @@ export const initialUsers: UserItem[] = [ enabled: true, lastLoginAt: '2026-07-25 22:10', createdAt: '2025-01-01', + remark: '系统内置管理员', }, { id: 'user-2', @@ -36,6 +38,7 @@ export const initialUsers: UserItem[] = [ enabled: true, lastLoginAt: '2026-07-24 18:32', createdAt: '2025-02-15', + remark: '', }, { id: 'user-3', @@ -47,6 +50,7 @@ export const initialUsers: UserItem[] = [ enabled: false, lastLoginAt: '2026-07-20 09:15', createdAt: '2025-03-10', + remark: '', }, { id: 'user-4', @@ -58,5 +62,6 @@ export const initialUsers: UserItem[] = [ enabled: true, lastLoginAt: '2026-07-25 16:08', createdAt: '2025-05-21', + remark: '', }, ];