feat(projects): add auth example
This commit is contained in:
parent
41e8bc44f8
commit
c11d56da29
5
.env
5
.env
@ -12,7 +12,7 @@ VITE_ICON_PREFIX=icon
|
|||||||
VITE_ICON_LOCAL_PREFIX=icon-local
|
VITE_ICON_LOCAL_PREFIX=icon-local
|
||||||
|
|
||||||
# auth route mode: static | dynamic
|
# auth route mode: static | dynamic
|
||||||
VITE_AUTH_ROUTE_MODE=static
|
VITE_AUTH_ROUTE_MODE=dynamic
|
||||||
|
|
||||||
# static auth route home
|
# static auth route home
|
||||||
VITE_ROUTE_HOME=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
|
# 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
|
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>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
|
|
||||||
defineOptions({ name: 'ExceptionBase' });
|
defineOptions({ name: 'ExceptionBase' });
|
||||||
|
|
||||||
@ -19,6 +20,8 @@ interface Props {
|
|||||||
|
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const { routerPushByKey } = useRouterPush();
|
||||||
|
|
||||||
const iconMap: Record<ExceptionType, string> = {
|
const iconMap: Record<ExceptionType, string> = {
|
||||||
'403': 'no-permission',
|
'403': 'no-permission',
|
||||||
'404': 'not-found',
|
'404': 'not-found',
|
||||||
@ -33,9 +36,7 @@ const icon = computed(() => iconMap[props.type]);
|
|||||||
<div class="flex text-400px text-primary">
|
<div class="flex text-400px text-primary">
|
||||||
<SvgIcon :local-icon="icon" />
|
<SvgIcon :local-icon="icon" />
|
||||||
</div>
|
</div>
|
||||||
<RouterLink to="/">
|
<NButton type="primary" @click="routerPushByKey('root')">{{ $t('common.backToHome') }}</NButton>
|
||||||
<NButton type="primary">{{ $t('common.backToHome') }}</NButton>
|
|
||||||
</RouterLink>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</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_two': 'Two',
|
||||||
'function_hide-child_three': 'Three',
|
'function_hide-child_three': 'Three',
|
||||||
function_request: 'Request',
|
function_request: 'Request',
|
||||||
|
'function_toggle-auth': 'Toggle Auth',
|
||||||
|
'function_super-page': 'Super Admin Visible',
|
||||||
manage: 'System Manage',
|
manage: 'System Manage',
|
||||||
manage_user: 'User Manage',
|
manage_user: 'User Manage',
|
||||||
'manage_user-detail': 'User Detail',
|
'manage_user-detail': 'User Detail',
|
||||||
@ -187,9 +189,9 @@ const local: App.I18n.Schema = {
|
|||||||
register: 'Register',
|
register: 'Register',
|
||||||
otherAccountLogin: 'Other Account Login',
|
otherAccountLogin: 'Other Account Login',
|
||||||
otherLoginMode: 'Other Login Mode',
|
otherLoginMode: 'Other Login Mode',
|
||||||
superAdmin: 'Super Administrator',
|
superAdmin: 'Super Admin',
|
||||||
admin: 'Administrator',
|
admin: 'Admin',
|
||||||
user: 'Ordinary User'
|
user: 'User'
|
||||||
},
|
},
|
||||||
codeLogin: {
|
codeLogin: {
|
||||||
title: 'Verification Code Login',
|
title: 'Verification Code Login',
|
||||||
@ -275,6 +277,13 @@ const local: App.I18n.Schema = {
|
|||||||
multiTab: {
|
multiTab: {
|
||||||
routeParam: 'Route Param',
|
routeParam: 'Route Param',
|
||||||
backTab: 'Back function_tab'
|
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: {
|
manage: {
|
||||||
|
@ -148,6 +148,8 @@ const local: App.I18n.Schema = {
|
|||||||
'function_hide-child_two': '菜单二',
|
'function_hide-child_two': '菜单二',
|
||||||
'function_hide-child_three': '菜单三',
|
'function_hide-child_three': '菜单三',
|
||||||
function_request: '请求',
|
function_request: '请求',
|
||||||
|
'function_toggle-auth': '切换权限',
|
||||||
|
'function_super-page': '超级管理员可见',
|
||||||
manage: '系统管理',
|
manage: '系统管理',
|
||||||
manage_user: '用户管理',
|
manage_user: '用户管理',
|
||||||
'manage_user-detail': '用户详情',
|
'manage_user-detail': '用户详情',
|
||||||
@ -275,6 +277,13 @@ const local: App.I18n.Schema = {
|
|||||||
multiTab: {
|
multiTab: {
|
||||||
routeParam: '路由参数',
|
routeParam: '路由参数',
|
||||||
backTab: '返回 function_tab'
|
backTab: '返回 function_tab'
|
||||||
|
},
|
||||||
|
toggleAuth: {
|
||||||
|
toggleAccount: '切换账号',
|
||||||
|
authHook: '权限钩子函数 `hasAuth`',
|
||||||
|
superAdminVisible: '超级管理员可见',
|
||||||
|
adminVisible: '管理员可见',
|
||||||
|
adminOrUserVisible: '管理员和用户可见'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
manage: {
|
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_hide-child_two": () => import("@/views/function/hide-child/two/index.vue"),
|
||||||
"function_multi-tab": () => import("@/views/function/multi-tab/index.vue"),
|
"function_multi-tab": () => import("@/views/function/multi-tab/index.vue"),
|
||||||
function_request: () => import("@/views/function/request/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_tab: () => import("@/views/function/tab/index.vue"),
|
||||||
|
"function_toggle-auth": () => import("@/views/function/toggle-auth/index.vue"),
|
||||||
home: () => import("@/views/home/index.vue"),
|
home: () => import("@/views/home/index.vue"),
|
||||||
manage_menu: () => import("@/views/manage/menu/index.vue"),
|
manage_menu: () => import("@/views/manage/menu/index.vue"),
|
||||||
manage_role: () => import("@/views/manage/role/index.vue"),
|
manage_role: () => import("@/views/manage/role/index.vue"),
|
||||||
|
@ -64,7 +64,8 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
meta: {
|
meta: {
|
||||||
title: 'function_hide-child',
|
title: 'function_hide-child',
|
||||||
i18nKey: 'route.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',
|
redirect: '/function/hide-child/one',
|
||||||
children: [
|
children: [
|
||||||
@ -124,7 +125,19 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
meta: {
|
meta: {
|
||||||
title: 'function_request',
|
title: 'function_request',
|
||||||
i18nKey: 'route.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: {
|
meta: {
|
||||||
title: 'function_tab',
|
title: 'function_tab',
|
||||||
i18nKey: 'route.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_hide-child_two": "/function/hide-child/two",
|
||||||
"function_multi-tab": "/function/multi-tab",
|
"function_multi-tab": "/function/multi-tab",
|
||||||
"function_request": "/function/request",
|
"function_request": "/function/request",
|
||||||
|
"function_super-page": "/function/super-page",
|
||||||
"function_tab": "/function/tab",
|
"function_tab": "/function/tab",
|
||||||
|
"function_toggle-auth": "/function/toggle-auth",
|
||||||
"home": "/home",
|
"home": "/home",
|
||||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
|
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
|
||||||
"manage": "/manage",
|
"manage": "/manage",
|
||||||
|
@ -27,13 +27,10 @@ export function createPermissionGuard(router: Router) {
|
|||||||
|
|
||||||
// check whether the user has permission to access the route
|
// check whether the user has permission to access the route
|
||||||
// 1. if the route's "roles" is empty, then it is allowed to access
|
// 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
|
// 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 =
|
const hasPermission =
|
||||||
!routeRoles.length ||
|
!routeRoles.length || authStore.isStaticSuper || authStore.userInfo.roles.some(role => routeRoles.includes(role));
|
||||||
authStore.userInfo.roles.includes(SUPER_ADMIN) ||
|
|
||||||
authStore.userInfo.roles.some(role => routeRoles.includes(role));
|
|
||||||
|
|
||||||
const strategicPatterns: CommonType.StrategicPattern[] = [
|
const strategicPatterns: CommonType.StrategicPattern[] = [
|
||||||
// 1. if it is login route when logged in, change to the root page
|
// 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());
|
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 */
|
/** Is login */
|
||||||
const isLogin = computed(() => Boolean(token.value));
|
const isLogin = computed(() => Boolean(token.value));
|
||||||
|
|
||||||
@ -41,8 +48,9 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
*
|
*
|
||||||
* @param userName User name
|
* @param userName User name
|
||||||
* @param password Password
|
* @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();
|
startLoading();
|
||||||
|
|
||||||
const { data: loginToken, error } = await fetchLogin(userName, password);
|
const { data: loginToken, error } = await fetchLogin(userName, password);
|
||||||
@ -53,7 +61,9 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
if (pass) {
|
if (pass) {
|
||||||
await routeStore.initAuthRoute();
|
await routeStore.initAuthRoute();
|
||||||
|
|
||||||
await redirectFromLogin();
|
if (redirect) {
|
||||||
|
await redirectFromLogin();
|
||||||
|
}
|
||||||
|
|
||||||
if (routeStore.isInitAuthRoute) {
|
if (routeStore.isInitAuthRoute) {
|
||||||
window.$notification?.success({
|
window.$notification?.success({
|
||||||
@ -94,6 +104,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
userInfo,
|
userInfo,
|
||||||
|
isStaticSuper,
|
||||||
isLogin,
|
isLogin,
|
||||||
loginLoading,
|
loginLoading,
|
||||||
resetStore,
|
resetStore,
|
||||||
|
@ -10,10 +10,16 @@ export function getUserInfo() {
|
|||||||
const emptyInfo: Api.Auth.UserInfo = {
|
const emptyInfo: Api.Auth.UserInfo = {
|
||||||
userId: '',
|
userId: '',
|
||||||
userName: '',
|
userName: '',
|
||||||
roles: []
|
roles: [],
|
||||||
|
buttons: []
|
||||||
};
|
};
|
||||||
const userInfo = localStg.get('userInfo') || emptyInfo;
|
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;
|
return userInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +194,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
|||||||
|
|
||||||
const vueRoutes = getAuthVueRoutes(sortRoutes);
|
const vueRoutes = getAuthVueRoutes(sortRoutes);
|
||||||
|
|
||||||
|
resetVueRoutes();
|
||||||
|
|
||||||
addRoutesToVueRouter(vueRoutes);
|
addRoutesToVueRouter(vueRoutes);
|
||||||
|
|
||||||
getGlobalMenus(sortRoutes);
|
getGlobalMenus(sortRoutes);
|
||||||
|
@ -10,6 +10,7 @@ import { useSvgIcon } from '@/hooks/common/icon';
|
|||||||
* @param roles Roles
|
* @param roles Roles
|
||||||
*/
|
*/
|
||||||
export function filterAuthRoutesByRoles(routes: ElegantConstRoute[], roles: string[]) {
|
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';
|
const SUPER_ROLE = 'R_SUPER';
|
||||||
|
|
||||||
// if the user is super admin, then it is allowed to access all routes
|
// 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) || [];
|
const routeRoles = (route.meta && route.meta.roles) || [];
|
||||||
|
|
||||||
// if the route's "roles" is empty, then it is allowed to access
|
// if the route's "roles" is empty, then it is allowed to access
|
||||||
if (!routeRoles.length) {
|
const isEmptyRoles = !routeRoles.length;
|
||||||
return [route];
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the user's role is included in the route's "roles", then it is allowed to access
|
// 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));
|
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));
|
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;
|
userId: string;
|
||||||
userName: string;
|
userName: string;
|
||||||
roles: 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;
|
routeParam: string;
|
||||||
backTab: string;
|
backTab: string;
|
||||||
};
|
};
|
||||||
|
toggleAuth: {
|
||||||
|
toggleAccount: string;
|
||||||
|
authHook: string;
|
||||||
|
superAdminVisible: string;
|
||||||
|
adminVisible: string;
|
||||||
|
adminOrUserVisible: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
manage: {
|
manage: {
|
||||||
common: {
|
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_hide-child_two": "/function/hide-child/two";
|
||||||
"function_multi-tab": "/function/multi-tab";
|
"function_multi-tab": "/function/multi-tab";
|
||||||
"function_request": "/function/request";
|
"function_request": "/function/request";
|
||||||
|
"function_super-page": "/function/super-page";
|
||||||
"function_tab": "/function/tab";
|
"function_tab": "/function/tab";
|
||||||
|
"function_toggle-auth": "/function/toggle-auth";
|
||||||
"home": "/home";
|
"home": "/home";
|
||||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
||||||
"manage": "/manage";
|
"manage": "/manage";
|
||||||
@ -119,7 +121,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_tab"
|
| "function_tab"
|
||||||
|
| "function_toggle-auth"
|
||||||
| "home"
|
| "home"
|
||||||
| "manage_menu"
|
| "manage_menu"
|
||||||
| "manage_role"
|
| "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
|
* use "," to separate multiple codes
|
||||||
*/
|
*/
|
||||||
readonly VITE_SERVICE_EXPIRED_TOKEN_CODES: string;
|
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
|
* other backend service base url
|
||||||
*
|
*
|
||||||
|
@ -38,6 +38,40 @@ async function handleSubmit() {
|
|||||||
await validate();
|
await validate();
|
||||||
await authStore.login(model.userName, model.password);
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -71,6 +105,12 @@ async function handleSubmit() {
|
|||||||
{{ $t(loginModuleRecord.register) }}
|
{{ $t(loginModuleRecord.register) }}
|
||||||
</NButton>
|
</NButton>
|
||||||
</div>
|
</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>
|
</NSpace>
|
||||||
</NForm>
|
</NForm>
|
||||||
</template>
|
</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>
|
Loading…
Reference in New Issue
Block a user