mirror of
				https://github.com/soybeanjs/soybean-admin.git
				synced 2025-11-04 15:53:43 +08:00 
			
		
		
		
	feat(projects): add auth example
This commit is contained in:
		
							
								
								
									
										5
									
								
								.env
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								.env
									
									
									
									
									
								
							@@ -12,7 +12,7 @@ VITE_ICON_PREFIX=icon
 | 
			
		||||
VITE_ICON_LOCAL_PREFIX=icon-local
 | 
			
		||||
 | 
			
		||||
# auth route mode: static | dynamic
 | 
			
		||||
VITE_AUTH_ROUTE_MODE=static
 | 
			
		||||
VITE_AUTH_ROUTE_MODE=dynamic
 | 
			
		||||
 | 
			
		||||
# static auth route home
 | 
			
		||||
VITE_ROUTE_HOME=home
 | 
			
		||||
@@ -37,3 +37,6 @@ VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
 | 
			
		||||
 | 
			
		||||
# token expired codes of backend service, when the code is received, it will refresh the token and resend the request
 | 
			
		||||
VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998
 | 
			
		||||
 | 
			
		||||
# when the route mode is static, the defined super role
 | 
			
		||||
VITE_STATIC_SUPER_ROLE=R_SUPER
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { computed } from 'vue';
 | 
			
		||||
import { $t } from '@/locales';
 | 
			
		||||
import { useRouterPush } from '@/hooks/common/router';
 | 
			
		||||
 | 
			
		||||
defineOptions({ name: 'ExceptionBase' });
 | 
			
		||||
 | 
			
		||||
@@ -19,6 +20,8 @@ interface Props {
 | 
			
		||||
 | 
			
		||||
const props = defineProps<Props>();
 | 
			
		||||
 | 
			
		||||
const { routerPushByKey } = useRouterPush();
 | 
			
		||||
 | 
			
		||||
const iconMap: Record<ExceptionType, string> = {
 | 
			
		||||
  '403': 'no-permission',
 | 
			
		||||
  '404': 'not-found',
 | 
			
		||||
@@ -33,9 +36,7 @@ const icon = computed(() => iconMap[props.type]);
 | 
			
		||||
    <div class="flex text-400px text-primary">
 | 
			
		||||
      <SvgIcon :local-icon="icon" />
 | 
			
		||||
    </div>
 | 
			
		||||
    <RouterLink to="/">
 | 
			
		||||
      <NButton type="primary">{{ $t('common.backToHome') }}</NButton>
 | 
			
		||||
    </RouterLink>
 | 
			
		||||
    <NButton type="primary" @click="routerPushByKey('root')">{{ $t('common.backToHome') }}</NButton>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								src/hooks/business/auth.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/hooks/business/auth.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
import { useAuthStore } from '@/store/modules/auth';
 | 
			
		||||
 | 
			
		||||
export function useAuth() {
 | 
			
		||||
  const authStore = useAuthStore();
 | 
			
		||||
 | 
			
		||||
  function hasAuth(codes: string | string[]) {
 | 
			
		||||
    if (!authStore.isLogin) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof codes === 'string') {
 | 
			
		||||
      return authStore.userInfo.buttons.includes(codes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return codes.some(code => authStore.userInfo.buttons.includes(code));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    hasAuth
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@@ -148,6 +148,8 @@ const local: App.I18n.Schema = {
 | 
			
		||||
    'function_hide-child_two': 'Two',
 | 
			
		||||
    'function_hide-child_three': 'Three',
 | 
			
		||||
    function_request: 'Request',
 | 
			
		||||
    'function_toggle-auth': 'Toggle Auth',
 | 
			
		||||
    'function_super-page': 'Super Admin Visible',
 | 
			
		||||
    manage: 'System Manage',
 | 
			
		||||
    manage_user: 'User Manage',
 | 
			
		||||
    'manage_user-detail': 'User Detail',
 | 
			
		||||
@@ -187,9 +189,9 @@ const local: App.I18n.Schema = {
 | 
			
		||||
        register: 'Register',
 | 
			
		||||
        otherAccountLogin: 'Other Account Login',
 | 
			
		||||
        otherLoginMode: 'Other Login Mode',
 | 
			
		||||
        superAdmin: 'Super Administrator',
 | 
			
		||||
        admin: 'Administrator',
 | 
			
		||||
        user: 'Ordinary User'
 | 
			
		||||
        superAdmin: 'Super Admin',
 | 
			
		||||
        admin: 'Admin',
 | 
			
		||||
        user: 'User'
 | 
			
		||||
      },
 | 
			
		||||
      codeLogin: {
 | 
			
		||||
        title: 'Verification Code Login',
 | 
			
		||||
@@ -275,6 +277,13 @@ const local: App.I18n.Schema = {
 | 
			
		||||
      multiTab: {
 | 
			
		||||
        routeParam: 'Route Param',
 | 
			
		||||
        backTab: 'Back function_tab'
 | 
			
		||||
      },
 | 
			
		||||
      toggleAuth: {
 | 
			
		||||
        toggleAccount: 'Toggle Account',
 | 
			
		||||
        authHook: 'Auth Hook Function `hasAuth`',
 | 
			
		||||
        superAdminVisible: 'Super Admin Visible',
 | 
			
		||||
        adminVisible: 'Admin Visible',
 | 
			
		||||
        adminOrUserVisible: 'Admin and User Visible'
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    manage: {
 | 
			
		||||
 
 | 
			
		||||
@@ -148,6 +148,8 @@ const local: App.I18n.Schema = {
 | 
			
		||||
    'function_hide-child_two': '菜单二',
 | 
			
		||||
    'function_hide-child_three': '菜单三',
 | 
			
		||||
    function_request: '请求',
 | 
			
		||||
    'function_toggle-auth': '切换权限',
 | 
			
		||||
    'function_super-page': '超级管理员可见',
 | 
			
		||||
    manage: '系统管理',
 | 
			
		||||
    manage_user: '用户管理',
 | 
			
		||||
    'manage_user-detail': '用户详情',
 | 
			
		||||
@@ -275,6 +277,13 @@ const local: App.I18n.Schema = {
 | 
			
		||||
      multiTab: {
 | 
			
		||||
        routeParam: '路由参数',
 | 
			
		||||
        backTab: '返回 function_tab'
 | 
			
		||||
      },
 | 
			
		||||
      toggleAuth: {
 | 
			
		||||
        toggleAccount: '切换账号',
 | 
			
		||||
        authHook: '权限钩子函数 `hasAuth`',
 | 
			
		||||
        superAdminVisible: '超级管理员可见',
 | 
			
		||||
        adminVisible: '管理员可见',
 | 
			
		||||
        adminOrUserVisible: '管理员和用户可见'
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    manage: {
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,9 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
 | 
			
		||||
  "function_hide-child_two": () => import("@/views/function/hide-child/two/index.vue"),
 | 
			
		||||
  "function_multi-tab": () => import("@/views/function/multi-tab/index.vue"),
 | 
			
		||||
  function_request: () => import("@/views/function/request/index.vue"),
 | 
			
		||||
  "function_super-page": () => import("@/views/function/super-page/index.vue"),
 | 
			
		||||
  function_tab: () => import("@/views/function/tab/index.vue"),
 | 
			
		||||
  "function_toggle-auth": () => import("@/views/function/toggle-auth/index.vue"),
 | 
			
		||||
  home: () => import("@/views/home/index.vue"),
 | 
			
		||||
  manage_menu: () => import("@/views/manage/menu/index.vue"),
 | 
			
		||||
  manage_role: () => import("@/views/manage/role/index.vue"),
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,8 @@ export const generatedRoutes: GeneratedRoute[] = [
 | 
			
		||||
        meta: {
 | 
			
		||||
          title: 'function_hide-child',
 | 
			
		||||
          i18nKey: 'route.function_hide-child',
 | 
			
		||||
          icon: 'material-symbols:filter-list-off'
 | 
			
		||||
          icon: 'material-symbols:filter-list-off',
 | 
			
		||||
          order: 2
 | 
			
		||||
        },
 | 
			
		||||
        redirect: '/function/hide-child/one',
 | 
			
		||||
        children: [
 | 
			
		||||
@@ -124,7 +125,19 @@ export const generatedRoutes: GeneratedRoute[] = [
 | 
			
		||||
        meta: {
 | 
			
		||||
          title: 'function_request',
 | 
			
		||||
          i18nKey: 'route.function_request',
 | 
			
		||||
          icon: 'carbon:network-overlay'
 | 
			
		||||
          icon: 'carbon:network-overlay',
 | 
			
		||||
          order: 3
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        name: 'function_super-page',
 | 
			
		||||
        path: '/function/super-page',
 | 
			
		||||
        component: 'view.function_super-page',
 | 
			
		||||
        meta: {
 | 
			
		||||
          title: 'function_super-page',
 | 
			
		||||
          i18nKey: 'route.function_super-page',
 | 
			
		||||
          icon: 'ic:round-supervisor-account',
 | 
			
		||||
          order: 5
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
@@ -134,7 +147,20 @@ export const generatedRoutes: GeneratedRoute[] = [
 | 
			
		||||
        meta: {
 | 
			
		||||
          title: 'function_tab',
 | 
			
		||||
          i18nKey: 'route.function_tab',
 | 
			
		||||
          icon: 'ic:round-tab'
 | 
			
		||||
          icon: 'ic:round-tab',
 | 
			
		||||
          order: 1
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        name: 'function_toggle-auth',
 | 
			
		||||
        path: '/function/toggle-auth',
 | 
			
		||||
        component: 'view.function_toggle-auth',
 | 
			
		||||
        meta: {
 | 
			
		||||
          title: 'function_toggle-auth',
 | 
			
		||||
          i18nKey: 'route.function_toggle-auth',
 | 
			
		||||
          icon: 'ic:round-construction',
 | 
			
		||||
          order: 4,
 | 
			
		||||
          roles: ['R_SUPER']
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
 
 | 
			
		||||
@@ -158,7 +158,9 @@ const routeMap: RouteMap = {
 | 
			
		||||
  "function_hide-child_two": "/function/hide-child/two",
 | 
			
		||||
  "function_multi-tab": "/function/multi-tab",
 | 
			
		||||
  "function_request": "/function/request",
 | 
			
		||||
  "function_super-page": "/function/super-page",
 | 
			
		||||
  "function_tab": "/function/tab",
 | 
			
		||||
  "function_toggle-auth": "/function/toggle-auth",
 | 
			
		||||
  "home": "/home",
 | 
			
		||||
  "login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
 | 
			
		||||
  "manage": "/manage",
 | 
			
		||||
 
 | 
			
		||||
@@ -27,13 +27,10 @@ export function createPermissionGuard(router: Router) {
 | 
			
		||||
 | 
			
		||||
    // check whether the user has permission to access the route
 | 
			
		||||
    // 1. if the route's "roles" is empty, then it is allowed to access
 | 
			
		||||
    // 2. if the user is super admin, then it is allowed to access
 | 
			
		||||
    // 2. if the user is super admin in static route, then it is allowed to access
 | 
			
		||||
    // 3. if the user's role is included in the route's "roles", then it is allowed to access
 | 
			
		||||
    const SUPER_ADMIN = 'R_SUPER';
 | 
			
		||||
    const hasPermission =
 | 
			
		||||
      !routeRoles.length ||
 | 
			
		||||
      authStore.userInfo.roles.includes(SUPER_ADMIN) ||
 | 
			
		||||
      authStore.userInfo.roles.some(role => routeRoles.includes(role));
 | 
			
		||||
      !routeRoles.length || authStore.isStaticSuper || authStore.userInfo.roles.some(role => routeRoles.includes(role));
 | 
			
		||||
 | 
			
		||||
    const strategicPatterns: CommonType.StrategicPattern[] = [
 | 
			
		||||
      // 1. if it is login route when logged in, change to the root page
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,13 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
 | 
			
		||||
 | 
			
		||||
  const userInfo: Api.Auth.UserInfo = reactive(getUserInfo());
 | 
			
		||||
 | 
			
		||||
  /** is super role in static route */
 | 
			
		||||
  const isStaticSuper = computed(() => {
 | 
			
		||||
    const { VITE_AUTH_ROUTE_MODE, VITE_STATIC_SUPER_ROLE } = import.meta.env;
 | 
			
		||||
 | 
			
		||||
    return VITE_AUTH_ROUTE_MODE === 'static' && userInfo.roles.includes(VITE_STATIC_SUPER_ROLE);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  /** Is login */
 | 
			
		||||
  const isLogin = computed(() => Boolean(token.value));
 | 
			
		||||
 | 
			
		||||
@@ -41,8 +48,9 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
 | 
			
		||||
   *
 | 
			
		||||
   * @param userName User name
 | 
			
		||||
   * @param password Password
 | 
			
		||||
   * @param [redirect=true] Whether to redirect after login. Default is `true`
 | 
			
		||||
   */
 | 
			
		||||
  async function login(userName: string, password: string) {
 | 
			
		||||
  async function login(userName: string, password: string, redirect = true) {
 | 
			
		||||
    startLoading();
 | 
			
		||||
 | 
			
		||||
    const { data: loginToken, error } = await fetchLogin(userName, password);
 | 
			
		||||
@@ -53,7 +61,9 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
 | 
			
		||||
      if (pass) {
 | 
			
		||||
        await routeStore.initAuthRoute();
 | 
			
		||||
 | 
			
		||||
        if (redirect) {
 | 
			
		||||
          await redirectFromLogin();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (routeStore.isInitAuthRoute) {
 | 
			
		||||
          window.$notification?.success({
 | 
			
		||||
@@ -94,6 +104,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
 | 
			
		||||
  return {
 | 
			
		||||
    token,
 | 
			
		||||
    userInfo,
 | 
			
		||||
    isStaticSuper,
 | 
			
		||||
    isLogin,
 | 
			
		||||
    loginLoading,
 | 
			
		||||
    resetStore,
 | 
			
		||||
 
 | 
			
		||||
@@ -10,10 +10,16 @@ export function getUserInfo() {
 | 
			
		||||
  const emptyInfo: Api.Auth.UserInfo = {
 | 
			
		||||
    userId: '',
 | 
			
		||||
    userName: '',
 | 
			
		||||
    roles: []
 | 
			
		||||
    roles: [],
 | 
			
		||||
    buttons: []
 | 
			
		||||
  };
 | 
			
		||||
  const userInfo = localStg.get('userInfo') || emptyInfo;
 | 
			
		||||
 | 
			
		||||
  // fix new property: buttons, this will be removed in the next version `1.1.0`
 | 
			
		||||
  if (!userInfo.buttons) {
 | 
			
		||||
    userInfo.buttons = [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return userInfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -194,6 +194,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
 | 
			
		||||
 | 
			
		||||
    const vueRoutes = getAuthVueRoutes(sortRoutes);
 | 
			
		||||
 | 
			
		||||
    resetVueRoutes();
 | 
			
		||||
 | 
			
		||||
    addRoutesToVueRouter(vueRoutes);
 | 
			
		||||
 | 
			
		||||
    getGlobalMenus(sortRoutes);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ import { useSvgIcon } from '@/hooks/common/icon';
 | 
			
		||||
 * @param roles Roles
 | 
			
		||||
 */
 | 
			
		||||
export function filterAuthRoutesByRoles(routes: ElegantConstRoute[], roles: string[]) {
 | 
			
		||||
  // in static mode of auth route, the super admin role is defined in front-end
 | 
			
		||||
  const SUPER_ROLE = 'R_SUPER';
 | 
			
		||||
 | 
			
		||||
  // if the user is super admin, then it is allowed to access all routes
 | 
			
		||||
@@ -30,9 +31,7 @@ function filterAuthRouteByRoles(route: ElegantConstRoute, roles: string[]) {
 | 
			
		||||
  const routeRoles = (route.meta && route.meta.roles) || [];
 | 
			
		||||
 | 
			
		||||
  // if the route's "roles" is empty, then it is allowed to access
 | 
			
		||||
  if (!routeRoles.length) {
 | 
			
		||||
    return [route];
 | 
			
		||||
  }
 | 
			
		||||
  const isEmptyRoles = !routeRoles.length;
 | 
			
		||||
 | 
			
		||||
  // if the user's role is included in the route's "roles", then it is allowed to access
 | 
			
		||||
  const hasPermission = routeRoles.some(role => roles.includes(role));
 | 
			
		||||
@@ -43,7 +42,7 @@ function filterAuthRouteByRoles(route: ElegantConstRoute, roles: string[]) {
 | 
			
		||||
    filterRoute.children = filterRoute.children.flatMap(item => filterAuthRouteByRoles(item, roles));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return hasPermission ? [filterRoute] : [];
 | 
			
		||||
  return hasPermission || isEmptyRoles ? [filterRoute] : [];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								src/typings/api.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/typings/api.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -60,6 +60,7 @@ declare namespace Api {
 | 
			
		||||
      userId: string;
 | 
			
		||||
      userName: string;
 | 
			
		||||
      roles: string[];
 | 
			
		||||
      buttons: string[];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								src/typings/app.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								src/typings/app.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -458,6 +458,13 @@ declare namespace App {
 | 
			
		||||
            routeParam: string;
 | 
			
		||||
            backTab: string;
 | 
			
		||||
          };
 | 
			
		||||
          toggleAuth: {
 | 
			
		||||
            toggleAccount: string;
 | 
			
		||||
            authHook: string;
 | 
			
		||||
            superAdminVisible: string;
 | 
			
		||||
            adminVisible: string;
 | 
			
		||||
            adminOrUserVisible: string;
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
        manage: {
 | 
			
		||||
          common: {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								src/typings/elegant-router.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								src/typings/elegant-router.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -32,7 +32,9 @@ declare module "@elegant-router/types" {
 | 
			
		||||
    "function_hide-child_two": "/function/hide-child/two";
 | 
			
		||||
    "function_multi-tab": "/function/multi-tab";
 | 
			
		||||
    "function_request": "/function/request";
 | 
			
		||||
    "function_super-page": "/function/super-page";
 | 
			
		||||
    "function_tab": "/function/tab";
 | 
			
		||||
    "function_toggle-auth": "/function/toggle-auth";
 | 
			
		||||
    "home": "/home";
 | 
			
		||||
    "login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
 | 
			
		||||
    "manage": "/manage";
 | 
			
		||||
@@ -119,7 +121,9 @@ declare module "@elegant-router/types" {
 | 
			
		||||
    | "function_hide-child_two"
 | 
			
		||||
    | "function_multi-tab"
 | 
			
		||||
    | "function_request"
 | 
			
		||||
    | "function_super-page"
 | 
			
		||||
    | "function_tab"
 | 
			
		||||
    | "function_toggle-auth"
 | 
			
		||||
    | "home"
 | 
			
		||||
    | "manage_menu"
 | 
			
		||||
    | "manage_role"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								src/typings/env.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/typings/env.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -57,6 +57,8 @@ declare namespace Env {
 | 
			
		||||
     * use "," to separate multiple codes
 | 
			
		||||
     */
 | 
			
		||||
    readonly VITE_SERVICE_EXPIRED_TOKEN_CODES: string;
 | 
			
		||||
    /** when the route mode is static, the defined super role */
 | 
			
		||||
    readonly VITE_STATIC_SUPER_ROLE: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * other backend service base url
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,40 @@ async function handleSubmit() {
 | 
			
		||||
  await validate();
 | 
			
		||||
  await authStore.login(model.userName, model.password);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type AccountKey = 'super' | 'admin' | 'user';
 | 
			
		||||
 | 
			
		||||
interface Account {
 | 
			
		||||
  key: AccountKey;
 | 
			
		||||
  label: string;
 | 
			
		||||
  userName: string;
 | 
			
		||||
  password: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const accounts = computed<Account[]>(() => [
 | 
			
		||||
  {
 | 
			
		||||
    key: 'super',
 | 
			
		||||
    label: $t('page.login.pwdLogin.superAdmin'),
 | 
			
		||||
    userName: 'Super',
 | 
			
		||||
    password: '123456'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    key: 'admin',
 | 
			
		||||
    label: $t('page.login.pwdLogin.admin'),
 | 
			
		||||
    userName: 'Admin',
 | 
			
		||||
    password: '123456'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    key: 'user',
 | 
			
		||||
    label: $t('page.login.pwdLogin.user'),
 | 
			
		||||
    userName: 'User',
 | 
			
		||||
    password: '123456'
 | 
			
		||||
  }
 | 
			
		||||
]);
 | 
			
		||||
 | 
			
		||||
async function handleAccountLogin(account: Account) {
 | 
			
		||||
  await authStore.login(account.userName, account.password);
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
@@ -71,6 +105,12 @@ async function handleSubmit() {
 | 
			
		||||
          {{ $t(loginModuleRecord.register) }}
 | 
			
		||||
        </NButton>
 | 
			
		||||
      </div>
 | 
			
		||||
      <NDivider class="text-14px text-#666 !m-0">{{ $t('page.login.pwdLogin.otherAccountLogin') }}</NDivider>
 | 
			
		||||
      <div class="flex-center gap-12px">
 | 
			
		||||
        <NButton v-for="item in accounts" :key="item.key" type="primary" @click="handleAccountLogin(item)">
 | 
			
		||||
          {{ item.label }}
 | 
			
		||||
        </NButton>
 | 
			
		||||
      </div>
 | 
			
		||||
    </NSpace>
 | 
			
		||||
  </NForm>
 | 
			
		||||
</template>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								src/views/function/super-page/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/views/function/super-page/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
<script setup lang="ts"></script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <LookForward />
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped></style>
 | 
			
		||||
							
								
								
									
										98
									
								
								src/views/function/toggle-auth/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/views/function/toggle-auth/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { computed, ref } from 'vue';
 | 
			
		||||
import { useLoading } from '@sa/hooks';
 | 
			
		||||
import { $t } from '@/locales';
 | 
			
		||||
import { useAppStore } from '@/store/modules/app';
 | 
			
		||||
import { useAuthStore } from '@/store/modules/auth';
 | 
			
		||||
import { useAuth } from '@/hooks/business/auth';
 | 
			
		||||
 | 
			
		||||
const appStore = useAppStore();
 | 
			
		||||
const authStore = useAuthStore();
 | 
			
		||||
const { hasAuth } = useAuth();
 | 
			
		||||
const { loading, startLoading, endLoading } = useLoading();
 | 
			
		||||
 | 
			
		||||
type AccountKey = 'super' | 'admin' | 'user';
 | 
			
		||||
 | 
			
		||||
interface Account {
 | 
			
		||||
  key: AccountKey;
 | 
			
		||||
  label: string;
 | 
			
		||||
  userName: string;
 | 
			
		||||
  password: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const accounts = computed<Account[]>(() => [
 | 
			
		||||
  {
 | 
			
		||||
    key: 'super',
 | 
			
		||||
    label: $t('page.login.pwdLogin.superAdmin'),
 | 
			
		||||
    userName: 'Super',
 | 
			
		||||
    password: '123456'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    key: 'admin',
 | 
			
		||||
    label: $t('page.login.pwdLogin.admin'),
 | 
			
		||||
    userName: 'Admin',
 | 
			
		||||
    password: '123456'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    key: 'user',
 | 
			
		||||
    label: $t('page.login.pwdLogin.user'),
 | 
			
		||||
    userName: 'User',
 | 
			
		||||
    password: '123456'
 | 
			
		||||
  }
 | 
			
		||||
]);
 | 
			
		||||
 | 
			
		||||
const loginAccount = ref<AccountKey>('super');
 | 
			
		||||
 | 
			
		||||
async function handleToggleAccount(account: Account) {
 | 
			
		||||
  loginAccount.value = account.key;
 | 
			
		||||
 | 
			
		||||
  startLoading();
 | 
			
		||||
  await authStore.login(account.userName, account.password, false);
 | 
			
		||||
  endLoading();
 | 
			
		||||
  appStore.reloadPage();
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <NSpace vertical :size="16">
 | 
			
		||||
    <NCard :title="$t('route.function_toggle-auth')" :bordered="false" size="small" segmented class="card-wrapper">
 | 
			
		||||
      <NDescriptions bordered :column="1">
 | 
			
		||||
        <NDescriptionsItem :label="$t('page.manage.user.userRole')">
 | 
			
		||||
          <NSpace>
 | 
			
		||||
            <NTag v-for="role in authStore.userInfo.roles" :key="role">{{ role }}</NTag>
 | 
			
		||||
          </NSpace>
 | 
			
		||||
        </NDescriptionsItem>
 | 
			
		||||
        <NDescriptionsItem ions-item :label="$t('page.function.toggleAuth.toggleAccount')">
 | 
			
		||||
          <NSpace>
 | 
			
		||||
            <NButton
 | 
			
		||||
              v-for="account in accounts"
 | 
			
		||||
              :key="account.key"
 | 
			
		||||
              :loading="loading && loginAccount === account.key"
 | 
			
		||||
              :disabled="loading && loginAccount !== account.key"
 | 
			
		||||
              @click="handleToggleAccount(account)"
 | 
			
		||||
            >
 | 
			
		||||
              {{ account.label }}
 | 
			
		||||
            </NButton>
 | 
			
		||||
          </NSpace>
 | 
			
		||||
        </NDescriptionsItem>
 | 
			
		||||
      </NDescriptions>
 | 
			
		||||
    </NCard>
 | 
			
		||||
    <NCard
 | 
			
		||||
      :title="$t('page.function.toggleAuth.authHook')"
 | 
			
		||||
      :bordered="false"
 | 
			
		||||
      size="small"
 | 
			
		||||
      segmented
 | 
			
		||||
      class="card-wrapper"
 | 
			
		||||
    >
 | 
			
		||||
      <NSpace>
 | 
			
		||||
        <NButton v-if="hasAuth('B_CODE1')">{{ $t('page.function.toggleAuth.superAdminVisible') }}</NButton>
 | 
			
		||||
        <NButton v-if="hasAuth('B_CODE2')">{{ $t('page.function.toggleAuth.adminVisible') }}</NButton>
 | 
			
		||||
        <NButton v-if="hasAuth('B_CODE3')">
 | 
			
		||||
          {{ $t('page.function.toggleAuth.adminOrUserVisible') }}
 | 
			
		||||
        </NButton>
 | 
			
		||||
      </NSpace>
 | 
			
		||||
    </NCard>
 | 
			
		||||
  </NSpace>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped></style>
 | 
			
		||||
		Reference in New Issue
	
	Block a user