瀏覽代碼

style: 完善角色管理

kailong321200875 1 年之前
父節點
當前提交
c4576bd57b
共有 4 個文件被更改,包括 498 次插入66 次删除
  1. 33 34
      mock/menu/index.ts
  2. 409 4
      mock/role/index.ts
  3. 21 21
      src/views/Authorization/Menu/components/Write.vue
  4. 35 7
      src/views/Authorization/Role/components/Write.vue

+ 33 - 34
mock/menu/index.ts

@@ -1,7 +1,6 @@
 import config from '@/config/axios/config'
 import { MockMethod } from 'vite-plugin-mock'
 import Mock from 'mockjs'
-import { toAnyString } from '@/utils'
 
 const { code } = config
 
@@ -25,7 +24,7 @@ export default [
                 redirect: '/dashboard/analysis',
                 name: 'Dashboard',
                 status: Mock.Random.integer(0, 1),
-                id: toAnyString(),
+                id: 1,
                 meta: {
                   title: '首页',
                   icon: 'ant-design:dashboard-filled',
@@ -37,7 +36,7 @@ export default [
                     component: 'views/Dashboard/Analysis',
                     name: 'Analysis',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 2,
                     meta: {
                       title: '分析页',
                       noCache: true
@@ -48,7 +47,7 @@ export default [
                     component: 'views/Dashboard/Workplace',
                     name: 'Workplace',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 3,
                     meta: {
                       title: '工作台',
                       noCache: true
@@ -65,13 +64,13 @@ export default [
                 },
                 name: 'ExternalLink',
                 status: Mock.Random.integer(0, 1),
-                id: toAnyString(),
+                id: 4,
                 children: [
                   {
                     path: 'https://element-plus-admin-doc.cn/',
                     name: 'DocumentLink',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 5,
                     meta: {
                       title: '文档'
                     }
@@ -84,7 +83,7 @@ export default [
                 redirect: '/level/menu1/menu1-1/menu1-1-1',
                 name: 'Level',
                 status: Mock.Random.integer(0, 1),
-                id: toAnyString(),
+                id: 6,
                 meta: {
                   title: '菜单',
                   icon: 'carbon:skill-level-advanced'
@@ -95,7 +94,7 @@ export default [
                     name: 'Menu1',
                     component: '##',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 7,
                     redirect: '/level/menu1/menu1-1/menu1-1-1',
                     meta: {
                       title: '菜单1'
@@ -106,7 +105,7 @@ export default [
                         name: 'Menu11',
                         component: '##',
                         status: Mock.Random.integer(0, 1),
-                        id: toAnyString(),
+                        id: 8,
                         redirect: '/level/menu1/menu1-1/menu1-1-1',
                         meta: {
                           title: '菜单1-1',
@@ -118,10 +117,10 @@ export default [
                             name: 'Menu111',
                             component: 'views/Level/Menu111',
                             status: Mock.Random.integer(0, 1),
-                            id: toAnyString(),
+                            id: 9,
+                            permission: ['edit', 'add', 'delete'],
                             meta: {
-                              title: '菜单1-1-1',
-                              permission: ['edit', 'add']
+                              title: '菜单1-1-1'
                             }
                           }
                         ]
@@ -131,10 +130,10 @@ export default [
                         name: 'Menu12',
                         component: 'views/Level/Menu12',
                         status: Mock.Random.integer(0, 1),
-                        id: toAnyString(),
+                        id: 10,
+                        permission: ['edit', 'add', 'delete'],
                         meta: {
-                          title: '菜单1-2',
-                          permission: ['edit', 'add']
+                          title: '菜单1-2'
                         }
                       }
                     ]
@@ -144,10 +143,10 @@ export default [
                     name: 'Menu2Demo',
                     component: 'views/Level/Menu2',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 11,
+                    permission: ['edit', 'add', 'delete'],
                     meta: {
-                      title: '菜单2',
-                      permission: ['edit', 'add']
+                      title: '菜单2'
                     }
                   }
                 ]
@@ -158,7 +157,7 @@ export default [
                 redirect: '/example/example-dialog',
                 name: 'Example',
                 status: Mock.Random.integer(0, 1),
-                id: toAnyString(),
+                id: 12,
                 meta: {
                   title: '综合示例',
                   icon: 'ep:management',
@@ -170,11 +169,11 @@ export default [
                     component: 'views/Example/Dialog/ExampleDialog',
                     name: 'ExampleDialog',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 13,
+                    permission: ['edit', 'add', 'delete'],
                     meta: {
                       title: '综合示例-弹窗',
-                      currentPermission: ['edit', 'add'],
-                      permission: ['edit', 'add', 'delete']
+                      permission: ['edit', 'add']
                     }
                   },
                   {
@@ -182,11 +181,11 @@ export default [
                     component: 'views/Example/Page/ExamplePage',
                     name: 'ExamplePage',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 14,
+                    permission: ['edit', 'add', 'delete'],
                     meta: {
                       title: '综合示例-页面',
-                      currentPermission: ['edit', 'add'],
-                      permission: ['edit', 'add', 'delete']
+                      permission: ['edit', 'add']
                     }
                   },
                   {
@@ -194,7 +193,8 @@ export default [
                     component: 'views/Example/Page/ExampleAdd',
                     name: 'ExampleAdd',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 15,
+                    permission: ['edit', 'add', 'delete'],
                     meta: {
                       title: '综合示例-新增',
                       noTagsView: true,
@@ -202,8 +202,7 @@ export default [
                       hidden: true,
                       showMainRoute: true,
                       activeMenu: '/example/example-page',
-                      currentPermission: ['delete', 'add'],
-                      permission: ['edit', 'add', 'delete']
+                      permission: ['delete', 'add']
                     }
                   },
                   {
@@ -211,7 +210,8 @@ export default [
                     component: 'views/Example/Page/ExampleEdit',
                     name: 'ExampleEdit',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 16,
+                    permission: ['edit', 'add', 'delete'],
                     meta: {
                       title: '综合示例-编辑',
                       noTagsView: true,
@@ -219,8 +219,7 @@ export default [
                       hidden: true,
                       showMainRoute: true,
                       activeMenu: '/example/example-page',
-                      currentPermission: ['delete', 'add'],
-                      permission: ['edit', 'add', 'delete']
+                      permission: ['delete', 'add']
                     }
                   },
                   {
@@ -228,7 +227,8 @@ export default [
                     component: 'views/Example/Page/ExampleDetail',
                     name: 'ExampleDetail',
                     status: Mock.Random.integer(0, 1),
-                    id: toAnyString(),
+                    id: 17,
+                    permission: ['edit', 'add', 'delete'],
                     meta: {
                       title: '综合示例-详情',
                       noTagsView: true,
@@ -236,8 +236,7 @@ export default [
                       hidden: true,
                       showMainRoute: true,
                       activeMenu: '/example/example-page',
-                      currentPermission: ['delete', 'edit'],
-                      permission: ['edit', 'add', 'delete']
+                      permission: ['delete', 'edit']
                     }
                   }
                 ]

+ 409 - 4
mock/role/index.ts

@@ -531,9 +531,413 @@ const testList: string[] = [
 
 const List: any[] = []
 
-const roleNames = ['超级管理员', '管理员', '普通用户', '游客', '测试用户']
+const roleNames = ['超级管理员', '管理员', '普通用户', '游客']
+const menus = [
+  [
+    {
+      path: '/dashboard',
+      component: '#',
+      redirect: '/dashboard/analysis',
+      name: 'Dashboard',
+      status: Mock.Random.integer(0, 1),
+      id: 1,
+      meta: {
+        title: '首页',
+        icon: 'ant-design:dashboard-filled',
+        alwaysShow: true
+      },
+      children: [
+        {
+          path: 'analysis',
+          component: 'views/Dashboard/Analysis',
+          name: 'Analysis',
+          status: Mock.Random.integer(0, 1),
+          id: 2,
+          meta: {
+            title: '分析页',
+            noCache: true
+          }
+        },
+        {
+          path: 'workplace',
+          component: 'views/Dashboard/Workplace',
+          name: 'Workplace',
+          status: Mock.Random.integer(0, 1),
+          id: 3,
+          meta: {
+            title: '工作台',
+            noCache: true
+          }
+        }
+      ]
+    },
+    {
+      path: '/external-link',
+      component: '#',
+      meta: {
+        title: '文档',
+        icon: 'clarity:document-solid'
+      },
+      name: 'ExternalLink',
+      status: Mock.Random.integer(0, 1),
+      id: 4,
+      children: [
+        {
+          path: 'https://element-plus-admin-doc.cn/',
+          name: 'DocumentLink',
+          status: Mock.Random.integer(0, 1),
+          id: 5,
+          meta: {
+            title: '文档'
+          }
+        }
+      ]
+    },
+    {
+      path: '/level',
+      component: '#',
+      redirect: '/level/menu1/menu1-1/menu1-1-1',
+      name: 'Level',
+      status: Mock.Random.integer(0, 1),
+      id: 6,
+      meta: {
+        title: '菜单',
+        icon: 'carbon:skill-level-advanced'
+      },
+      children: [
+        {
+          path: 'menu1',
+          name: 'Menu1',
+          component: '##',
+          status: Mock.Random.integer(0, 1),
+          id: 7,
+          redirect: '/level/menu1/menu1-1/menu1-1-1',
+          meta: {
+            title: '菜单1'
+          },
+          children: [
+            {
+              path: 'menu1-1',
+              name: 'Menu11',
+              component: '##',
+              status: Mock.Random.integer(0, 1),
+              id: 8,
+              redirect: '/level/menu1/menu1-1/menu1-1-1',
+              meta: {
+                title: '菜单1-1',
+                alwaysShow: true
+              },
+              children: [
+                {
+                  path: 'menu1-1-1',
+                  name: 'Menu111',
+                  component: 'views/Level/Menu111',
+                  status: Mock.Random.integer(0, 1),
+                  id: 9,
+                  permission: ['edit', 'add', 'delete'],
+                  meta: {
+                    title: '菜单1-1-1',
+                    permission: ['edit', 'add', 'delete']
+                  }
+                }
+              ]
+            },
+            {
+              path: 'menu1-2',
+              name: 'Menu12',
+              component: 'views/Level/Menu12',
+              status: Mock.Random.integer(0, 1),
+              id: 10,
+              permission: ['edit', 'add', 'delete'],
+              meta: {
+                title: '菜单1-2',
+                permission: ['edit', 'add', 'delete']
+              }
+            }
+          ]
+        },
+        {
+          path: 'menu2',
+          name: 'Menu2Demo',
+          component: 'views/Level/Menu2',
+          status: Mock.Random.integer(0, 1),
+          id: 11,
+          permission: ['edit', 'add', 'delete'],
+          meta: {
+            title: '菜单2',
+            permission: ['edit', 'add', 'delete']
+          }
+        }
+      ]
+    },
+    {
+      path: '/example',
+      component: '#',
+      redirect: '/example/example-dialog',
+      name: 'Example',
+      status: Mock.Random.integer(0, 1),
+      id: 12,
+      meta: {
+        title: '综合示例',
+        icon: 'ep:management',
+        alwaysShow: true
+      },
+      children: [
+        {
+          path: 'example-dialog',
+          component: 'views/Example/Dialog/ExampleDialog',
+          name: 'ExampleDialog',
+          status: Mock.Random.integer(0, 1),
+          id: 13,
+          permission: ['edit', 'add', 'delete'],
+          meta: {
+            title: '综合示例-弹窗',
+            permission: ['edit', 'add', 'delete']
+          }
+        },
+        {
+          path: 'example-page',
+          component: 'views/Example/Page/ExamplePage',
+          name: 'ExamplePage',
+          status: Mock.Random.integer(0, 1),
+          id: 14,
+          permission: ['edit', 'add', 'delete'],
+          meta: {
+            title: '综合示例-页面',
+            permission: ['edit', 'add', 'delete']
+          }
+        },
+        {
+          path: 'example-add',
+          component: 'views/Example/Page/ExampleAdd',
+          name: 'ExampleAdd',
+          status: Mock.Random.integer(0, 1),
+          id: 15,
+          permission: ['edit', 'add', 'delete'],
+          meta: {
+            title: '综合示例-新增',
+            noTagsView: true,
+            noCache: true,
+            hidden: true,
+            showMainRoute: true,
+            activeMenu: '/example/example-page',
+            permission: ['edit', 'add', 'delete']
+          }
+        },
+        {
+          path: 'example-edit',
+          component: 'views/Example/Page/ExampleEdit',
+          name: 'ExampleEdit',
+          status: Mock.Random.integer(0, 1),
+          id: 16,
+          permission: ['edit', 'add', 'delete'],
+          meta: {
+            title: '综合示例-编辑',
+            noTagsView: true,
+            noCache: true,
+            hidden: true,
+            showMainRoute: true,
+            activeMenu: '/example/example-page',
+            permission: ['edit', 'add', 'delete']
+          }
+        },
+        {
+          path: 'example-detail',
+          component: 'views/Example/Page/ExampleDetail',
+          name: 'ExampleDetail',
+          status: Mock.Random.integer(0, 1),
+          id: 17,
+          permission: ['edit', 'add', 'delete'],
+          meta: {
+            title: '综合示例-详情',
+            noTagsView: true,
+            noCache: true,
+            hidden: true,
+            showMainRoute: true,
+            activeMenu: '/example/example-page',
+            permission: ['edit', 'add', 'delete']
+          }
+        }
+      ]
+    }
+  ],
+  [
+    {
+      path: '/dashboard',
+      component: '#',
+      redirect: '/dashboard/analysis',
+      name: 'Dashboard',
+      status: Mock.Random.integer(0, 1),
+      id: 1,
+      meta: {
+        title: '首页',
+        icon: 'ant-design:dashboard-filled',
+        alwaysShow: true
+      },
+      children: [
+        {
+          path: 'analysis',
+          component: 'views/Dashboard/Analysis',
+          name: 'Analysis',
+          status: Mock.Random.integer(0, 1),
+          id: 2,
+          meta: {
+            title: '分析页',
+            noCache: true
+          }
+        },
+        {
+          path: 'workplace',
+          component: 'views/Dashboard/Workplace',
+          name: 'Workplace',
+          status: Mock.Random.integer(0, 1),
+          id: 3,
+          meta: {
+            title: '工作台',
+            noCache: true
+          }
+        }
+      ]
+    }
+  ],
+  [
+    {
+      path: '/external-link',
+      component: '#',
+      meta: {
+        title: '文档',
+        icon: 'clarity:document-solid'
+      },
+      name: 'ExternalLink',
+      status: Mock.Random.integer(0, 1),
+      id: 4,
+      children: [
+        {
+          path: 'https://element-plus-admin-doc.cn/',
+          name: 'DocumentLink',
+          status: Mock.Random.integer(0, 1),
+          id: 5,
+          meta: {
+            title: '文档'
+          }
+        }
+      ]
+    },
+    {
+      path: '/level',
+      component: '#',
+      redirect: '/level/menu1/menu1-1/menu1-1-1',
+      name: 'Level',
+      status: Mock.Random.integer(0, 1),
+      id: 6,
+      meta: {
+        title: '菜单',
+        icon: 'carbon:skill-level-advanced'
+      },
+      children: [
+        {
+          path: 'menu1',
+          name: 'Menu1',
+          component: '##',
+          status: Mock.Random.integer(0, 1),
+          id: 7,
+          redirect: '/level/menu1/menu1-1/menu1-1-1',
+          meta: {
+            title: '菜单1'
+          },
+          children: [
+            {
+              path: 'menu1-1',
+              name: 'Menu11',
+              component: '##',
+              status: Mock.Random.integer(0, 1),
+              id: 8,
+              redirect: '/level/menu1/menu1-1/menu1-1-1',
+              meta: {
+                title: '菜单1-1',
+                alwaysShow: true
+              },
+              children: [
+                {
+                  path: 'menu1-1-1',
+                  name: 'Menu111',
+                  component: 'views/Level/Menu111',
+                  status: Mock.Random.integer(0, 1),
+                  id: 9,
+                  permission: ['edit', 'add', 'delete'],
+                  meta: {
+                    title: '菜单1-1-1',
+                    permission: ['edit', 'add', 'delete']
+                  }
+                }
+              ]
+            },
+            {
+              path: 'menu1-2',
+              name: 'Menu12',
+              component: 'views/Level/Menu12',
+              status: Mock.Random.integer(0, 1),
+              id: 10,
+              permission: ['edit', 'add', 'delete'],
+              meta: {
+                title: '菜单1-2',
+                permission: ['edit', 'add', 'delete']
+              }
+            }
+          ]
+        },
+        {
+          path: 'menu2',
+          name: 'Menu2Demo',
+          component: 'views/Level/Menu2',
+          status: Mock.Random.integer(0, 1),
+          id: 11,
+          permission: ['edit', 'add', 'delete'],
+          meta: {
+            title: '菜单2',
+            permission: ['edit', 'add', 'delete']
+          }
+        }
+      ]
+    }
+  ],
+  [
+    {
+      path: '/example',
+      component: '#',
+      redirect: '/example/example-dialog',
+      name: 'Example',
+      status: Mock.Random.integer(0, 1),
+      id: 12,
+      meta: {
+        title: '综合示例',
+        icon: 'ep:management',
+        alwaysShow: true
+      },
+      children: [
+        {
+          path: 'example-detail',
+          component: 'views/Example/Page/ExampleDetail',
+          name: 'ExampleDetail',
+          status: Mock.Random.integer(0, 1),
+          id: 17,
+          permission: ['edit', 'add', 'delete'],
+          meta: {
+            title: '综合示例-详情',
+            noTagsView: true,
+            noCache: true,
+            hidden: true,
+            showMainRoute: true,
+            activeMenu: '/example/example-page',
+            permission: ['edit', 'add', 'delete']
+          }
+        }
+      ]
+    }
+  ]
+]
 
-for (let i = 0; i < 5; i++) {
+for (let i = 0; i < 4; i++) {
   List.push(
     Mock.mock({
       id: toAnyString(),
@@ -542,7 +946,8 @@ for (let i = 0; i < 5; i++) {
       role: '@first',
       status: Mock.Random.integer(0, 1),
       createTime: '@datetime',
-      remark: '@cword(10, 15)'
+      remark: '@cword(10, 15)',
+      menu: menus[i]
     })
   )
 }
@@ -573,7 +978,7 @@ export default [
           code: code,
           data: {
             list: List,
-            total: 5
+            total: 4
           }
         }
       }

+ 21 - 21
src/views/Authorization/Menu/components/Write.vue

@@ -64,27 +64,27 @@ const formSchema = reactive<FormSchema[]>([
     label: t('menu.activeMenu'),
     component: 'Input'
   },
-  // {
-  //   field: 'meta.permission',
-  //   label: t('menu.permission'),
-  //   component: 'CheckboxGroup',
-  //   componentProps: {
-  //     options: [
-  //       {
-  //         label: 'add',
-  //         value: 'add'
-  //       },
-  //       {
-  //         label: 'edit',
-  //         value: 'edit'
-  //       },
-  //       {
-  //         label: 'delete',
-  //         value: 'delete'
-  //       }
-  //     ]
-  //   }
-  // },
+  {
+    field: 'permission',
+    label: t('menu.permission'),
+    component: 'CheckboxGroup',
+    componentProps: {
+      options: [
+        {
+          label: 'add',
+          value: 'add'
+        },
+        {
+          label: 'edit',
+          value: 'edit'
+        },
+        {
+          label: 'delete',
+          value: 'delete'
+        }
+      ]
+    }
+  },
   {
     field: 'meta.hidden',
     label: t('menu.hidden'),

+ 35 - 7
src/views/Authorization/Role/components/Write.vue

@@ -1,12 +1,13 @@
 <script setup lang="tsx">
 import { Form, FormSchema } from '@/components/Form'
 import { useForm } from '@/hooks/web/useForm'
-import { PropType, reactive, watch, ref, unref } from 'vue'
+import { PropType, reactive, watch, ref, unref, nextTick } from 'vue'
 import { useValidator } from '@/hooks/web/useValidator'
 import { useI18n } from '@/hooks/web/useI18n'
 import { ElTree, ElCheckboxGroup, ElCheckbox } from 'element-plus'
 import { getMenuListApi } from '@/api/menu'
-import { filter } from '@/utils/tree'
+import { filter, eachTree } from '@/utils/tree'
+import { findIndex } from '@/utils'
 
 const { t } = useI18n()
 
@@ -57,8 +58,7 @@ const formSchema = ref<FormSchema[]>([
     },
     formItemProps: {
       slots: {
-        default: (formData: any) => {
-          console.log(formData)
+        default: () => {
           return (
             <>
               <div class="flex w-full">
@@ -68,6 +68,7 @@ const formSchema = ref<FormSchema[]>([
                     show-checkbox
                     node-key="id"
                     highlight-current
+                    expand-on-click-node={false}
                     data={treeData.value}
                     onNode-click={nodeClick}
                   >
@@ -79,9 +80,9 @@ const formSchema = ref<FormSchema[]>([
                   </ElTree>
                 </div>
                 <div class="flex-1">
-                  {unref(currentTreeData) && unref(currentTreeData)?.meta?.permission ? (
-                    <ElCheckboxGroup v-model={unref(currentTreeData).meta.currentPermission}>
-                      {unref(currentTreeData)?.meta?.permission.map((v: string) => {
+                  {unref(currentTreeData) && unref(currentTreeData)?.permission ? (
+                    <ElCheckboxGroup v-model={unref(currentTreeData).meta.permission}>
+                      {unref(currentTreeData)?.permission.map((v: string) => {
                         return <ElCheckbox label={v} />
                       })}
                     </ElCheckboxGroup>
@@ -115,6 +116,32 @@ const getMenuList = async () => {
   const res = await getMenuListApi()
   if (res) {
     treeData.value = res.data.list
+    if (!props.currentRow) return
+    await nextTick()
+    const checked: any[] = []
+    eachTree(props.currentRow.menu, (v) => {
+      checked.push({
+        id: v.id,
+        permission: v.meta?.permission || []
+      })
+    })
+    eachTree(treeData.value, (v) => {
+      const index = findIndex(checked, (item) => {
+        return item.id === v.id
+      })
+      if (index > -1) {
+        const meta = { ...(v.meta || {}) }
+        meta.permission = checked[index].permission
+        v.meta = meta
+      }
+    })
+    for (const item of checked) {
+      unref(treeRef)?.setChecked(item.id, true, false)
+    }
+    // unref(treeRef)?.setCheckedKeys(
+    //   checked.map((v) => v.id),
+    //   false
+    // )
   }
 }
 getMenuList()
@@ -134,6 +161,7 @@ const submit = async () => {
       return checkedKeys.includes(item.id)
     })
     formData.menu = data || []
+    console.log(formData)
     return formData
   }
 }