Skip to content

Commit

Permalink
feat(projects): add logout
Browse files Browse the repository at this point in the history
  • Loading branch information
honghuangdc committed Oct 19, 2023
1 parent 7677af5 commit 486dec4
Show file tree
Hide file tree
Showing 12 changed files with 207 additions and 34 deletions.
15 changes: 14 additions & 1 deletion build/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import VueDevtools from 'vite-plugin-vue-devtools';
import ElegantVueRouter from '@elegant-router/vue/vite';
import type { RouteKey } from '@elegant-router/types';
import progress from 'vite-plugin-progress';
import { setupUnocss } from './unocss';
import { setupUnplugin } from './unplugin';
Expand All @@ -21,7 +22,19 @@ export function setupVitePlugins(viteEnv: Env.ImportMeta) {
base: 'src/layouts/base-layout/index.vue',
blank: 'src/layouts/blank-layout/index.vue'
},
layoutLazyImport: () => false
routePathTransformer(routeName, routePath) {
const key = routeName as RouteKey;

if (key === 'login') {
const modules: UnionKey.LoginModule[] = ['pwd-login', 'code-login', 'register', 'reset-pwd', 'bind-wechat'];

const moduleReg = modules.join('|');

return `/login/:module(${moduleReg})?`;
}

return routePath;
}
}),
setupUnocss(viteEnv),
...setupUnplugin(viteEnv),
Expand Down
72 changes: 72 additions & 0 deletions src/hooks/common/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { useRouter } from 'vue-router';
import type { RouteLocationRaw } from 'vue-router';
import type { RouteKey } from '@elegant-router/types';
import { router as globalRouter } from '@/router';

/**
* router push
* @description jump to the specified route, it can replace function router.push
* @param inSetup
*/
export function useRouterPush(inSetup = true) {
const router = inSetup ? useRouter() : globalRouter;
const route = globalRouter.currentRoute;

const routerPush = router.push;

const routerBack = router.back;

interface RouterPushOptions {
query?: Record<string, string>;
params?: Record<string, string>;
}

async function routerPushByKey(key: RouteKey, options?: RouterPushOptions) {
const { query, params } = options || {};

const routeLocation: RouteLocationRaw = {
name: key
};

if (query) {
routeLocation.query = query;
}

if (params) {
routeLocation.params = params;
}

return routerPush(routeLocation);
}

/**
* navigate to login page
* @param loginModule the login module
* @param redirectUrl the redirect url, if not specified, it will be the current route fullPath
*/
async function toLogin(loginModule?: UnionKey.LoginModule, redirectUrl?: string) {
const module = loginModule || 'pwd-login';

const options: RouterPushOptions = {
params: {
module
}
};

const redirect = redirectUrl || route.value.fullPath;

options.query = {
redirect
};

return routerPushByKey('login', options);
}

return {
route,
routerPush,
routerBack,
routerPushByKey,
toLogin
};
}
22 changes: 20 additions & 2 deletions src/layouts/modules/global-header/components/user-avatar.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
<script setup lang="ts">
import { Modal } from 'ant-design-vue';
import { useRouterPush } from '@/hooks/common/router';
import { $t } from '@/locales';
import { useAuthStore } from '@/store/modules/auth';
defineOptions({
name: 'UserAvatar'
});
const { resetStore } = useAuthStore();
const { routerPushByKey } = useRouterPush();
function logout() {
Modal.confirm({
title: $t('common.tip'),
content: $t('common.logoutConfirm'),
okText: $t('common.confirm'),
cancelText: $t('common.cancel'),
onOk: () => {
resetStore();
}
});
}
</script>

<template>
Expand All @@ -16,14 +34,14 @@ defineOptions({
</AButton>
<template #overlay>
<AMenu>
<AMenuItem>
<AMenuItem @click="routerPushByKey('user-center')">
<div class="flex-y-center">
<SvgIcon icon="ph:user-circle" class="text-icon" />
<span class="pl-8px">{{ $t('common.userCenter') }}</span>
</div>
</AMenuItem>
<AMenuDivider />
<AMenuItem>
<AMenuItem @click="logout">
<div class="flex-y-center">
<SvgIcon icon="ph:sign-out" class="text-icon" />
<span class="pl-8px">{{ $t('common.logout') }}</span>
Expand Down
4 changes: 3 additions & 1 deletion src/locales/lang/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const local: App.I18n.Schema = {
title: 'SoybeanAdmin'
},
common: {
tip: 'Tip',
add: 'Add',
addSuccess: 'Add Success',
edit: 'Edit',
Expand All @@ -17,7 +18,8 @@ const local: App.I18n.Schema = {
backToHome: 'Back to home',
lookForward: 'Coming soon',
userCenter: 'User Center',
logout: 'Logout'
logout: 'Logout',
logoutConfirm: 'Are you sure you want to log out?'
}
};

Expand Down
4 changes: 3 additions & 1 deletion src/locales/lang/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const local: App.I18n.Schema = {
title: 'Soybean 管理系统'
},
common: {
tip: '提示',
add: '添加',
addSuccess: '添加成功',
edit: '修改',
Expand All @@ -17,7 +18,8 @@ const local: App.I18n.Schema = {
backToHome: '返回首页',
lookForward: '敬请期待',
userCenter: '个人中心',
logout: '退出登录'
logout: '退出登录',
logoutConfirm: '确认退出登录吗?'
}
};

Expand Down
14 changes: 9 additions & 5 deletions src/router/elegant/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,14 @@ export const autoRoutes: ElegantRoute[] = [
path: '',
component: 'view.home',
meta: {
title: 'home'
title: 'home',
requiresAuth: true
}
}
]
},
{
path: '/login',
path: '/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?',
component: 'layout.blank',
children: [
{
Expand All @@ -82,7 +83,8 @@ export const autoRoutes: ElegantRoute[] = [
name: 'multi-menu_first'
},
meta: {
title: 'multi-menu'
title: 'multi-menu',
requiresAuth: true
},
children: [
{
Expand Down Expand Up @@ -141,7 +143,8 @@ export const autoRoutes: ElegantRoute[] = [
name: 'user_list'
},
meta: {
title: 'user'
title: 'user',
requiresAuth: true
},
children: [
{
Expand Down Expand Up @@ -171,7 +174,8 @@ export const autoRoutes: ElegantRoute[] = [
path: '',
component: 'view.user-center',
meta: {
title: 'user-center'
title: 'user-center',
requiresAuth: true
}
}
]
Expand Down
38 changes: 38 additions & 0 deletions src/store/modules/auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ref } from 'vue';
import { defineStore } from 'pinia';
import { useLoading } from '@sa/hooks';
import { SetupStoreId } from '@/enum';
import { useRouterPush } from '@/hooks/common/router';
import { localStg } from '@/utils/storage';

export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
const { route, toLogin } = useRouterPush(false);
const { loading: loginLoading, startLoading, endLoading } = useLoading();

const token = ref(localStg.get('token') || '');

async function resetStore() {
const auth = useAuthStore();

localStg.remove('token');

auth.$reset();

if (route.value.meta.requiresAuth) {
toLogin();
}
}

async function login() {
startLoading();

endLoading();
}

return {
token,
loginLoading,
resetStore,
login
};
});
2 changes: 1 addition & 1 deletion src/store/modules/route/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
import { SetupStoreId } from '@/enum';

export const routeStore = defineStore(SetupStoreId.Route, () => {
export const useRouteStore = defineStore(SetupStoreId.Route, () => {
//
});
2 changes: 2 additions & 0 deletions src/typings/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ declare namespace App {
title: string;
};
common: {
tip: string;
add: string;
addSuccess: string;
edit: string;
Expand All @@ -92,6 +93,7 @@ declare namespace App {
lookForward: string;
userCenter: string;
logout: string;
logoutConfirm: string;
};
};

Expand Down
2 changes: 1 addition & 1 deletion src/typings/elegant-router.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ declare module "@elegant-router/types" {
"404": "/404";
"500": "/500";
"home": "/home";
"login": "/login";
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
"multi-menu": "/multi-menu";
"multi-menu_first": "/multi-menu/first";
"multi-menu_first_child": "/multi-menu/first/child";
Expand Down
20 changes: 20 additions & 0 deletions src/typings/router.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'vue-router';

declare module 'vue-router' {
interface RouteMeta {
/**
* title of the route
* @description it can be used in document title
*/
title: string;
/**
* i18n key of the route
* @description it's used in i18n, if it is set, the title will be ignored
*/
i18nKey?: App.I18n.I18nKey;
/**
* whether to require authentication
*/
requiresAuth?: boolean;
}
}
46 changes: 24 additions & 22 deletions src/typings/union-key.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,49 @@
* the union key namespace
*/
declare namespace UnionKey {
/** http请求头的content-type类型 */
/**
* the content-type of http request header
*/
type ContentType = 'application/json' | 'application/x-www-form-urlencoded' | 'multipart/form-data';

/**
* 登录模块
* - pwd-login: 账密登录
* - code-login: 手机验证码登录
* - register: 注册
* - reset-pwd: 重置密码
* - bind-wechat: 微信绑定
* the login module
* - pwd-login: password login
* - code-login: phone code login
* - register: register
* - reset-pwd: reset password
* - bind-wechat: bind wechat
*/
type LoginModule = 'pwd-login' | 'code-login' | 'register' | 'reset-pwd' | 'bind-wechat';

/**
* 布局模式
* - vertical: 左侧菜单模式
* - horizontal: 顶部菜单模式
* - vertical-mix: 左侧菜单混合模式
* - horizontal-mix: 顶部菜单混合模式
* the layout mode
* - vertical: the vertical menu in left
* - horizontal: the horizontal menu in top
* - vertical-mix: two vertical mixed menus in left
* - horizontal-mix: the vertical menu in left and horizontal menu in top
*/
type ThemeLayoutMode = 'vertical' | 'horizontal' | 'vertical-mix' | 'horizontal-mix';

/**
* 内容溢出时的出现滚动条的方式
* - wrapper 布局组件最外层的元素出现滚动条
* - content 主体内容组件出现滚动条
* the scroll mode when content overflow
* - wrapper the wrapper component's root element overflow
* - content the content component overflow
*/
type ThemeScrollMode = import('@sa/materials').LayoutScrollMode;

/**
* 多页签风格
* - chrome: 谷歌风格
* - button: 按钮风格
* tab mode
* - chrome: chrome style
* - button: button style
*/
type ThemeTabMode = import('@sa/materials').PageTabMode;

/**
* 水平模式的菜单位置
* - flex-start: 居左
* - center: 居中
* - flex-end: 居右
* the menu position in horizontal mode
* - flex-start: left position
* - center: center position
* - flex-end: right position
*/
type ThemeHorizontalMenuPosition = 'flex-start' | 'center' | 'flex-end';

Expand Down

0 comments on commit 486dec4

Please sign in to comment.