Browse Source

refactor: unify frontend and backend access control with shared page … (#43)

* refactor: unify frontend and backend access control with shared page components

* fix: role switch not show

* chore: update title
Li Kui 8 months ago
parent
commit
7801a90dcb

+ 26 - 37
apps/backend-mock/src/modules/menu/menu.controller.ts

@@ -50,30 +50,30 @@ export class MenuController {
     const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
       const roleWithMenus = {
         admin: {
-          component: '/demos/access/backend/admin-visible',
+          component: '/demos/access/admin-visible',
           meta: {
             icon: 'mdi:button-cursor',
             title: 'page.demos.access.adminVisible',
           },
-          name: 'AccessBackendAdminVisible',
+          name: 'AccessAdminVisible',
           path: 'admin-visible',
         },
         super: {
-          component: '/demos/access/backend/super-visible',
+          component: '/demos/access/super-visible',
           meta: {
             icon: 'mdi:button-cursor',
             title: 'page.demos.access.superVisible',
           },
-          name: 'AccessBackendSuperVisible',
+          name: 'AccessSuperVisible',
           path: 'super-visible',
         },
         user: {
-          component: '/demos/access/backend/user-visible',
+          component: '/demos/access/user-visible',
           meta: {
             icon: 'mdi:button-cursor',
             title: 'page.demos.access.userVisible',
           },
-          name: 'AccessBackendUserVisible',
+          name: 'AccessUserVisible',
           path: 'user-visible',
         },
       };
@@ -92,44 +92,33 @@ export class MenuController {
           redirect: '/demos/access',
           children: [
             {
-              meta: {
-                icon: 'mdi:shield-key-outline',
-                title: 'page.demos.access.title',
-              },
               name: 'Access',
               path: 'access',
-              redirect: '/demos/access/backend',
+              meta: {
+                icon: 'mdi:cloud-key-outline',
+                title: 'page.demos.access.backendControl',
+              },
+              redirect: '/demos/access/page-control',
               children: [
                 {
-                  name: 'AccessBackend',
-                  path: 'backend',
+                  name: 'AccessPageControl',
+                  path: 'page-control',
+                  component: '/demos/access/index',
+                  meta: {
+                    icon: 'mdi:page-previous-outline',
+                    title: 'page.demos.access.pageAccess',
+                  },
+                },
+                {
+                  name: 'AccessButtonControl',
+                  path: 'button-control',
+                  component: '/demos/access/button-control',
                   meta: {
-                    icon: 'mdi:cloud-key-outline',
-                    title: 'page.demos.access.backendControl',
+                    icon: 'mdi:button-cursor',
+                    title: 'page.demos.access.buttonControl',
                   },
-                  redirect: '/demos/access/backend/page-control',
-                  children: [
-                    {
-                      name: 'AccessBackendPageControl',
-                      path: 'page-control',
-                      component: '/demos/access/backend/index',
-                      meta: {
-                        icon: 'mdi:page-previous-outline',
-                        title: 'page.demos.access.pageAccess',
-                      },
-                    },
-                    {
-                      name: 'AccessBackendButtonControl',
-                      path: 'button-control',
-                      component: '/demos/access/backend/button-control',
-                      meta: {
-                        icon: 'mdi:button-cursor',
-                        title: 'page.demos.access.buttonControl',
-                      },
-                    },
-                    roleWithMenus[role],
-                  ],
                 },
+                roleWithMenus[role],
               ],
             },
           ],

+ 0 - 1
apps/web-antd/src/locales/langs/en-US.json

@@ -3,7 +3,6 @@
     "demos": {
       "title": "Demos",
       "access": {
-        "title": "Access Control",
         "frontendControl": "Frontend Control",
         "backendControl": "Backend Control",
         "pageAccess": "Page Access",

+ 0 - 1
apps/web-antd/src/locales/langs/zh-CN.json

@@ -3,7 +3,6 @@
     "demos": {
       "title": "演示",
       "access": {
-        "title": "访问控制",
         "frontendControl": "前端控制",
         "backendControl": "后端控制",
         "pageAccess": "页面访问",

+ 54 - 92
apps/web-antd/src/router/routes/modules/demos.ts

@@ -19,109 +19,71 @@ const routes: RouteRecordRaw[] = [
       {
         meta: {
           icon: 'mdi:shield-key-outline',
-          title: $t('page.demos.access.title'),
+          title: $t('page.demos.access.frontendControl'),
         },
         name: 'Access',
         path: 'access',
-        redirect: '/demos/access/frontend',
+        redirect: '/demos/access',
         children: [
           {
-            name: 'AccessFrontend',
-            path: 'frontend',
-            redirect: '/demos/access/frontend/page-control',
+            name: 'AccessPageControl',
+            path: 'page-control',
+            component: () => import('#/views/demos/access/index.vue'),
             meta: {
-              icon: 'mdi:table-key',
-              title: $t('page.demos.access.frontendControl'),
+              icon: 'mdi:page-previous-outline',
+              title: $t('page.demos.access.pageAccess'),
             },
-            children: [
-              {
-                name: 'AccessFrontendPageControl',
-                path: 'page-control',
-                component: () =>
-                  import('#/views/demos/access/frontend/index.vue'),
-                meta: {
-                  icon: 'mdi:page-previous-outline',
-                  title: $t('page.demos.access.pageAccess'),
-                },
-              },
-              {
-                name: 'AccessFrontendButtonControl',
-                path: 'button-control',
-                component: () =>
-                  import('#/views/demos/access/frontend/button-control.vue'),
-                meta: {
-                  icon: 'mdi:button-cursor',
-                  title: $t('page.demos.access.buttonControl'),
-                },
-              },
-              {
-                name: 'AccessFrontendMenuVisible403',
-                path: 'menu-visible-403',
-                component: () =>
-                  import('#/views/demos/access/frontend/menu-visible-403.vue'),
-                meta: {
-                  authority: ['no-body'],
-                  icon: 'mdi:button-cursor',
-                  menuVisibleWithForbidden: true,
-                  title: $t('page.demos.access.menuVisible403'),
-                },
-              },
-
-              {
-                name: 'AccessFrontendSuperVisible',
-                path: 'super-visible',
-                component: () =>
-                  import('#/views/demos/access/frontend/super-visible.vue'),
-                meta: {
-                  authority: ['super'],
-                  icon: 'mdi:button-cursor',
-                  title: $t('page.demos.access.superVisible'),
-                },
-              },
-              {
-                name: 'AccessFrontendAdminVisible',
-                path: 'admin-visible',
-                component: () =>
-                  import('#/views/demos/access/frontend/admin-visible.vue'),
-                meta: {
-                  authority: ['admin'],
-                  icon: 'mdi:button-cursor',
-                  title: $t('page.demos.access.adminVisible'),
-                },
-              },
-              {
-                name: 'AccessFrontendUserVisible',
-                path: 'user-visible',
-                component: () =>
-                  import('#/views/demos/access/frontend/user-visible.vue'),
-                meta: {
-                  authority: ['user'],
-                  icon: 'mdi:button-cursor',
-                  title: $t('page.demos.access.userVisible'),
-                },
-              },
-            ],
           },
           {
-            name: 'AccessBackend',
-            path: 'backend',
-            component: () => import('#/views/demos/access/backend/index.vue'),
+            name: 'AccessButtonControl',
+            path: 'button-control',
+            component: () => import('#/views/demos/access/button-control.vue'),
             meta: {
-              icon: 'mdi:cloud-key-outline',
-              title: $t('page.demos.access.backendControl'),
+              icon: 'mdi:button-cursor',
+              title: $t('page.demos.access.buttonControl'),
+            },
+          },
+          {
+            name: 'AccessMenuVisible403',
+            path: 'menu-visible-403',
+            component: () =>
+              import('#/views/demos/access/menu-visible-403.vue'),
+            meta: {
+              authority: ['no-body'],
+              icon: 'mdi:button-cursor',
+              menuVisibleWithForbidden: true,
+              title: $t('page.demos.access.menuVisible403'),
+            },
+          },
+          {
+            name: 'AccessSuperVisible',
+            path: 'super-visible',
+            component: () => import('#/views/demos/access/super-visible.vue'),
+            meta: {
+              authority: ['super'],
+              icon: 'mdi:button-cursor',
+              title: $t('page.demos.access.superVisible'),
+            },
+          },
+          {
+            name: 'AccessAdminVisible',
+            path: 'admin-visible',
+            component: () => import('#/views/demos/access/admin-visible.vue'),
+            meta: {
+              authority: ['admin'],
+              icon: 'mdi:button-cursor',
+              title: $t('page.demos.access.adminVisible'),
+            },
+          },
+          {
+            name: 'AccessUserVisible',
+            path: 'user-visible',
+            component: () => import('#/views/demos/access/user-visible.vue'),
+            meta: {
+              authority: ['user'],
+              icon: 'mdi:button-cursor',
+              title: $t('page.demos.access.userVisible'),
             },
-            children: [
-              {
-                name: 'AccessBackendPageControl',
-                path: 'page-control',
-                component: () =>
-                  import('#/views/demos/access/frontend/index.vue'),
-                meta: {
-                  icon: 'mdi:page-previous-outline',
-                  title: $t('page.demos.access.pageAccess'),
-                },
-              },
-            ],
           },
         ],
       },

+ 0 - 0
apps/web-antd/src/views/demos/access/backend/admin-visible.vue → apps/web-antd/src/views/demos/access/admin-visible.vue


+ 0 - 0
apps/web-antd/src/views/demos/access/backend/button-control.vue → apps/web-antd/src/views/demos/access/button-control.vue


+ 0 - 13
apps/web-antd/src/views/demos/access/frontend/admin-visible.vue

@@ -1,13 +0,0 @@
-<script lang="ts" setup>
-import { Fallback } from '@vben/universal-ui';
-
-defineOptions({ name: 'AccessFrontendAccessTest2' });
-</script>
-
-<template>
-  <Fallback
-    description="当前页面仅 Admin 角色可见"
-    status="comming-soon"
-    title="页面访问测试"
-  />
-</template>

+ 0 - 149
apps/web-antd/src/views/demos/access/frontend/button-control.vue

@@ -1,149 +0,0 @@
-<script lang="ts" setup>
-import type { LoginAndRegisterParams } from '@vben/universal-ui';
-
-import { useRouter } from 'vue-router';
-
-import { CodeAccess, RoleAccess, useAccess } from '@vben/access';
-
-import { Button } from 'ant-design-vue';
-
-import { useAccessStore, useAppStore } from '#/store';
-
-defineOptions({ name: 'AccessFrontendButtonControl' });
-
-const { accessMode, hasAuthByCodes, hasAuthByRoles } = useAccess();
-const accessStore = useAccessStore();
-const appStore = useAppStore();
-const router = useRouter();
-
-function roleButtonType(role: string) {
-  return accessStore.userRoles.includes(role) ? 'primary' : 'default';
-}
-
-async function changeAccount(role: string) {
-  if (accessStore.userRoles.includes(role)) {
-    return;
-  }
-  const accounts: Record<string, LoginAndRegisterParams> = {
-    admin: {
-      password: '123456',
-      username: 'admin',
-    },
-    super: {
-      password: '123456',
-      username: 'vben',
-    },
-    user: {
-      password: '123456',
-      username: 'jack',
-    },
-  };
-  const account = accounts[role];
-  await appStore.resetAppState();
-  await accessStore.authLogin(account, async () => {
-    router.go(0);
-  });
-}
-</script>
-
-<template>
-  <div class="p-5">
-    <div class="card-box p-5">
-      <h1 class="text-xl font-semibold">前端按钮访问权限演示</h1>
-      <div class="text-foreground/80 mt-2">
-        切换不同的账号,观察按钮显示变化
-      </div>
-    </div>
-
-    <template v-if="accessMode === 'frontend'">
-      <div class="card-box mt-5 p-5 font-semibold">
-        <div class="mb-3">
-          <span class="text-lg">当前账号:</span>
-          <span class="text-primary mx-4">
-            {{ accessStore.userRoles }}
-          </span>
-        </div>
-
-        <Button :type="roleButtonType('super')" @click="changeAccount('super')">
-          切换为 Super 账号
-        </Button>
-
-        <Button
-          :type="roleButtonType('admin')"
-          class="mx-4"
-          @click="changeAccount('admin')"
-        >
-          切换为 Admin 账号
-        </Button>
-        <Button :type="roleButtonType('user')" @click="changeAccount('user')">
-          切换为 User 账号
-        </Button>
-      </div>
-      <div class="card-box mt-5 p-5 font-semibold">
-        <div class="mb-3 text-lg">角色 - 组件形式控制</div>
-        <RoleAccess :value="['super']">
-          <Button class="mr-4"> Super 角色可见 </Button>
-        </RoleAccess>
-        <RoleAccess :value="['admin']">
-          <Button class="mr-4"> Admin 角色可见 </Button>
-        </RoleAccess>
-        <RoleAccess :value="['user']">
-          <Button class="mr-4"> User 角色可见 </Button>
-        </RoleAccess>
-        <RoleAccess :value="['super', 'admin']">
-          <Button class="mr-4"> Super & Admin 角色都可见 </Button>
-        </RoleAccess>
-      </div>
-
-      <div class="card-box mt-5 p-5 font-semibold">
-        <div class="mb-3 text-lg">角色 - 函数形式控制</div>
-        <Button v-if="hasAuthByRoles(['super'])" class="mr-4">
-          Super 角色可见
-        </Button>
-        <Button v-if="hasAuthByRoles(['admin'])" class="mr-4">
-          Admin 角色可见
-        </Button>
-        <Button v-if="hasAuthByRoles(['user'])" class="mr-4">
-          User 角色可见
-        </Button>
-        <Button v-if="hasAuthByRoles(['super', 'admin'])" class="mr-4">
-          Super & Admin 角色都可见
-        </Button>
-      </div>
-
-      <div class="card-box mt-5 p-5 font-semibold">
-        <div class="mb-3 text-lg">权限码 - 组件形式控制</div>
-        <CodeAccess :value="['AC_100100']">
-          <Button class="mr-4"> Super 账号可见 ["AC_1000001"] </Button>
-        </CodeAccess>
-        <CodeAccess :value="['AC_100030']">
-          <Button class="mr-4"> Admin 账号可见 ["AC_100010"] </Button>
-        </CodeAccess>
-        <CodeAccess :value="['AC_1000001']">
-          <Button class="mr-4"> User 账号可见 ["AC_1000001"] </Button>
-        </CodeAccess>
-        <CodeAccess :value="['AC_100100', 'AC_100010']">
-          <Button class="mr-4">
-            Super & Admin 账号可见 ["AC_100100","AC_1000001"]
-          </Button>
-        </CodeAccess>
-      </div>
-
-      <div class="card-box mt-5 p-5 font-semibold">
-        <div class="mb-3 text-lg">权限码 - 函数形式控制</div>
-        <Button v-if="hasAuthByCodes(['AC_100100'])" class="mr-4">
-          Super 账号可见 ["AC_1000001"]
-        </Button>
-        <Button v-if="hasAuthByCodes(['AC_100030'])" class="mr-4">
-          Admin 账号可见 ["AC_100010"]
-        </Button>
-        <Button v-if="hasAuthByCodes(['AC_1000001'])" class="mr-4">
-          User 账号可见 ["AC_1000001"]
-        </Button>
-        <Button v-if="hasAuthByCodes(['AC_100100', 'AC_1000001'])" class="mr-4">
-          Super & Admin 账号可见 ["AC_100100","AC_1000001"]
-        </Button>
-      </div>
-    </template>
-  </div>
-</template>

+ 0 - 84
apps/web-antd/src/views/demos/access/frontend/index.vue

@@ -1,84 +0,0 @@
-<script lang="ts" setup>
-import type { LoginAndRegisterParams } from '@vben/universal-ui';
-
-import { useRouter } from 'vue-router';
-
-import { useAccess } from '@vben/access';
-
-import { Button } from 'ant-design-vue';
-
-import { useAccessStore, useAppStore } from '#/store';
-
-defineOptions({ name: 'AccessBackend' });
-
-const { accessMode } = useAccess();
-const accessStore = useAccessStore();
-const appStore = useAppStore();
-const router = useRouter();
-
-function roleButtonType(role: string) {
-  return accessStore.userRoles.includes(role) ? 'primary' : 'default';
-}
-
-async function changeAccount(role: string) {
-  if (accessStore.userRoles.includes(role)) {
-    return;
-  }
-  const accounts: Record<string, LoginAndRegisterParams> = {
-    admin: {
-      password: '123456',
-      username: 'admin',
-    },
-    super: {
-      password: '123456',
-      username: 'vben',
-    },
-    user: {
-      password: '123456',
-      username: 'jack',
-    },
-  };
-  const account = accounts[role];
-  await appStore.resetAppState();
-  await accessStore.authLogin(account, async () => {
-    router.go(0);
-  });
-}
-</script>
-
-<template>
-  <div class="p-5">
-    <div class="card-box p-5">
-      <h1 class="text-xl font-semibold">前端页面访问权限演示</h1>
-      <div class="text-foreground/80 mt-2">
-        切换不同的账号,观察左侧菜单变化。
-      </div>
-    </div>
-
-    <template v-if="accessMode === 'frontend'">
-      <div class="card-box mt-5 p-5 font-semibold">
-        <div class="mb-3">
-          <span class="text-lg">当前账号:</span>
-          <span class="text-primary mx-4">
-            {{ accessStore.userRoles }}
-          </span>
-        </div>
-
-        <Button :type="roleButtonType('super')" @click="changeAccount('super')">
-          切换为 Super 账号
-        </Button>
-
-        <Button
-          :type="roleButtonType('admin')"
-          class="mx-4"
-          @click="changeAccount('admin')"
-        >
-          切换为 Admin 账号
-        </Button>
-        <Button :type="roleButtonType('user')" @click="changeAccount('user')">
-          切换为 User 账号
-        </Button>
-      </div>
-    </template>
-  </div>
-</template>

+ 0 - 13
apps/web-antd/src/views/demos/access/frontend/super-visible.vue

@@ -1,13 +0,0 @@
-<script lang="ts" setup>
-import { Fallback } from '@vben/universal-ui';
-
-defineOptions({ name: 'AccessFrontendAccessTest1' });
-</script>
-
-<template>
-  <Fallback
-    description="当前页面仅 Super 角色可见"
-    status="comming-soon"
-    title="页面访问测试"
-  />
-</template>

+ 0 - 13
apps/web-antd/src/views/demos/access/frontend/user-visible.vue

@@ -1,13 +0,0 @@
-<script lang="ts" setup>
-import { Fallback } from '@vben/universal-ui';
-
-defineOptions({ name: 'AccessFrontendAccessTest1' });
-</script>
-
-<template>
-  <Fallback
-    description="当前页面仅 User 角色可见"
-    status="comming-soon"
-    title="页面访问测试"
-  />
-</template>

+ 27 - 27
apps/web-antd/src/views/demos/access/backend/index.vue → apps/web-antd/src/views/demos/access/index.vue

@@ -9,7 +9,7 @@ import { Button } from 'ant-design-vue';
 
 import { useAccessStore, useAppStore } from '#/store';
 
-defineOptions({ name: 'AccessBackend' });
+defineOptions({ name: 'Access' });
 
 const accounts: Record<string, LoginAndRegisterParams> = {
   admin: {
@@ -41,7 +41,7 @@ async function changeAccount(role: string) {
   }
 
   const account = accounts[role];
-  await appStore.resetAppState();
+  appStore.resetAppState();
   await accessStore.authLogin(account, async () => {
     router.go(0);
   });
@@ -49,7 +49,7 @@ async function changeAccount(role: string) {
 
 async function handleToggleAccessMode() {
   await toggleAccessMode();
-  await appStore.resetAppState();
+  appStore.resetAppState();
   await accessStore.authLogin(accounts.super, async () => {
     router.go(0);
   });
@@ -59,7 +59,9 @@ async function handleToggleAccessMode() {
 <template>
   <div class="p-5">
     <div class="card-box p-5">
-      <h1 class="text-xl font-semibold">后端页面访问权限演示</h1>
+      <h1 class="text-xl font-semibold">
+        {{ accessMode === 'frontend' ? '前端' : '后端' }}页面访问权限演示
+      </h1>
       <div class="text-foreground/80 mt-2">
         切换不同的账号,观察左侧菜单变化。
       </div>
@@ -72,30 +74,28 @@ async function handleToggleAccessMode() {
         切换为{{ accessMode === 'frontend' ? '后端' : '前端' }}权限模式
       </Button>
     </div>
-    <template v-if="accessMode === 'backend'">
-      <div class="card-box mt-5 p-5 font-semibold">
-        <div class="mb-3">
-          <span class="text-lg">当前账号:</span>
-          <span class="text-primary mx-4">
-            {{ accessStore.userRoles }}
-          </span>
-        </div>
+    <div class="card-box mt-5 p-5 font-semibold">
+      <div class="mb-3">
+        <span class="text-lg">当前账号:</span>
+        <span class="text-primary mx-4">
+          {{ accessStore.userRoles }}
+        </span>
+      </div>
 
-        <Button :type="roleButtonType('super')" @click="changeAccount('super')">
-          切换为 Super 账号
-        </Button>
+      <Button :type="roleButtonType('super')" @click="changeAccount('super')">
+        切换为 Super 账号
+      </Button>
 
-        <Button
-          :type="roleButtonType('admin')"
-          class="mx-4"
-          @click="changeAccount('admin')"
-        >
-          切换为 Admin 账号
-        </Button>
-        <Button :type="roleButtonType('user')" @click="changeAccount('user')">
-          切换为 User 账号
-        </Button>
-      </div>
-    </template>
+      <Button
+        :type="roleButtonType('admin')"
+        class="mx-4"
+        @click="changeAccount('admin')"
+      >
+        切换为 Admin 账号
+      </Button>
+      <Button :type="roleButtonType('user')" @click="changeAccount('user')">
+        切换为 User 账号
+      </Button>
+    </div>
   </div>
 </template>

+ 0 - 0
apps/web-antd/src/views/demos/access/frontend/menu-visible-403.vue → apps/web-antd/src/views/demos/access/menu-visible-403.vue


+ 0 - 0
apps/web-antd/src/views/demos/access/backend/super-visible.vue → apps/web-antd/src/views/demos/access/super-visible.vue


+ 0 - 0
apps/web-antd/src/views/demos/access/backend/user-visible.vue → apps/web-antd/src/views/demos/access/user-visible.vue