Skip to content

Commit

Permalink
feat(user): add user login expiration example
Browse files Browse the repository at this point in the history
  • Loading branch information
anncwb committed May 25, 2021
1 parent d5b7689 commit 5465f05
Show file tree
Hide file tree
Showing 16 changed files with 149 additions and 30 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- 新增 `JsonPreview`Json 数据查看组件
- 表格的数据列(column)和操作列(actionColumn)的字段可以根据权限和业务来控制是否显示
- 新增权限控制表格示例(AuthColumn.vue)
- 新增用户登录过期示例

### ⚡ Performance Improvements

Expand Down
10 changes: 9 additions & 1 deletion mock/demo/account.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess } from '../_util';
import { resultSuccess, resultError } from '../_util';

const userInfo = {
name: 'Vben',
Expand Down Expand Up @@ -51,4 +51,12 @@ export default [
return resultSuccess(userInfo);
},
},
{
url: '/basic-api/user/sessionTimeout',
method: 'post',
statusCode: 401,
response: () => {
return resultError();
},
},
] as MockMethod[];
3 changes: 3 additions & 0 deletions src/api/demo/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { GetAccountInfoModel } from './model/accountModel';

enum Api {
ACCOUNT_INFO = '/account/getAccountInfo',
SESSION_TIMEOUT = '/user/sessionTimeout',
}

// Get personal center-basic settings

export const accountInfoApi = () => defHttp.get<GetAccountInfoModel>({ url: Api.ACCOUNT_INFO });

export const sessionTimeoutApi = () => defHttp.post<void>({ url: Api.SESSION_TIMEOUT });
17 changes: 10 additions & 7 deletions src/layouts/default/feature/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,29 @@
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
import { useDesign } from '/@/hooks/web/useDesign';
import { useUserStoreWidthOut } from '/@/store/modules/user';
import { SettingButtonPositionEnum } from '/@/enums/appEnum';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import SessionTimeoutLogin from '/@/views/sys/login/SessionTimeoutLogin.vue';
export default defineComponent({
name: 'LayoutFeatures',
components: {
BackTop,
LayoutLockPage: createAsyncComponent(() => import('/@/views/sys/lock/index.vue')),
SettingDrawer: createAsyncComponent(() => import('/@/layouts/default/setting/index.vue')),
SessionTimeoutLogin,
},
setup() {
const {
getUseOpenBackTop,
getShowSettingButton,
getSettingButtonPosition,
getFullContent,
} = useRootSetting();
const { getUseOpenBackTop, getShowSettingButton, getSettingButtonPosition, getFullContent } =
useRootSetting();
const userStore = useUserStoreWidthOut();
const { prefixCls } = useDesign('setting-drawer-fearure');
const { getShowHeader } = useHeaderSetting();
const getIsSessionTimeout = computed(() => userStore.getSessionTimeout);
const getIsFixedSettingDrawer = computed(() => {
if (!unref(getShowSettingButton)) {
return false;
Expand All @@ -44,6 +45,7 @@
getUseOpenBackTop,
getIsFixedSettingDrawer,
prefixCls,
getIsSessionTimeout,
};
},
});
Expand All @@ -53,6 +55,7 @@
<LayoutLockPage />
<BackTop v-if="getUseOpenBackTop" :target="getTarget" />
<SettingDrawer v-if="getIsFixedSettingDrawer" :class="prefixCls" />
<SessionTimeoutLogin v-if="getIsSessionTimeout" />
</template>

<style lang="less">
Expand Down
1 change: 1 addition & 0 deletions src/locales/lang/en/routes/demo/feat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export default {
feat: 'Page Function',
icon: 'Icon',
tabs: 'Tabs',
sessionTimeout: 'Session Timeout',
print: 'Print',
contextMenu: 'Context Menu',
download: 'Download',
Expand Down
1 change: 1 addition & 0 deletions src/locales/lang/zh_CN/routes/demo/feat.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export default {
feat: '功能',
icon: '图标',
sessionTimeout: '登录过期',
tabs: '标签页操作',
print: '打印',
contextMenu: '右键菜单',
Expand Down
6 changes: 0 additions & 6 deletions src/router/menus/modules/demo/comp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ const menu: MenuModule = {
menu: {
name: t('routes.demo.comp.comp'),
path: '/comp',
tag: {
dot: true,
},
children: [
{
path: 'basic',
Expand Down Expand Up @@ -191,9 +188,6 @@ const menu: MenuModule = {
{
name: t('routes.demo.editor.editor'),
path: 'editor',
tag: {
dot: true,
},
children: [
{
path: 'json',
Expand Down
11 changes: 10 additions & 1 deletion src/router/menus/modules/demo/feat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ const menu: MenuModule = {
menu: {
name: t('routes.demo.feat.feat'),
path: '/feat',

tag: {
dot: true,
},
children: [
{
path: 'icon',
Expand All @@ -16,6 +18,13 @@ const menu: MenuModule = {
path: 'ws',
name: t('routes.demo.feat.ws'),
},
{
name: t('routes.demo.feat.sessionTimeout'),
path: 'session-timeout',
tag: {
content: 'new',
},
},
{
path: 'tabs',
name: t('routes.demo.feat.tabs'),
Expand Down
7 changes: 0 additions & 7 deletions src/router/menus/modules/demo/flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,10 @@ const menu: MenuModule = {
menu: {
name: t('routes.demo.flow.name'),
path: '/flow',
tag: {
dot: true,
},

children: [
{
path: 'flowChart',
name: t('routes.demo.flow.flowChart'),
tag: {
content: 'new',
},
},
],
},
Expand Down
9 changes: 9 additions & 0 deletions src/router/routes/modules/demo/feat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const feat: AppRouteModule = {
icon: 'ion:git-compare-outline',
title: t('routes.demo.feat.feat'),
},

children: [
{
path: 'icon',
Expand All @@ -29,6 +30,14 @@ const feat: AppRouteModule = {
title: t('routes.demo.feat.ws'),
},
},
{
path: 'session-timeout',
name: 'SessionTimeout',
component: () => import('/@/views/demo/feat/session-timeout/index.vue'),
meta: {
title: t('routes.demo.feat.sessionTimeout'),
},
},
{
path: 'print',
name: 'Print',
Expand Down
16 changes: 14 additions & 2 deletions src/store/modules/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface UserState {
userInfo: Nullable<UserInfo>;
token?: string;
roleList: RoleEnum[];
sessionTimeout?: boolean;
}

export const useUserStore = defineStore({
Expand All @@ -36,6 +37,8 @@ export const useUserStore = defineStore({
token: undefined,
// roleList
roleList: [],
// Whether the login expired
sessionTimeout: false,
}),
getters: {
getUserInfo(): UserInfo {
Expand All @@ -47,9 +50,12 @@ export const useUserStore = defineStore({
getRoleList(): RoleEnum[] {
return this.roleList.length > 0 ? this.roleList : getAuthCache<RoleEnum[]>(ROLES_KEY);
},
getSessionTimeout(): boolean {
return !!this.sessionTimeout;
},
},
actions: {
setToken(info: string) {
setToken(info: string | undefined) {
this.token = info;
setAuthCache(TOKEN_KEY, info);
},
Expand All @@ -61,10 +67,14 @@ export const useUserStore = defineStore({
this.userInfo = info;
setAuthCache(USER_INFO_KEY, info);
},
setSessionTimeout(flag: boolean) {
this.sessionTimeout = flag;
},
resetState() {
this.userInfo = null;
this.token = '';
this.roleList = [];
this.sessionTimeout = false;
},
/**
* @description: login
Expand All @@ -85,7 +95,9 @@ export const useUserStore = defineStore({
// get user info
const userInfo = await this.getUserInfoAction({ userId });

goHome && (await router.replace(PageEnum.BASE_HOME));
const sessionTimeout = this.sessionTimeout;
sessionTimeout && this.setSessionTimeout(false);
!sessionTimeout && goHome && (await router.replace(PageEnum.BASE_HOME));
return userInfo;
} catch (error) {
return null;
Expand Down
9 changes: 6 additions & 3 deletions src/utils/http/axios/checkStatus.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import router from '/@/router';
import { PageEnum } from '/@/enums/pageEnum';
// import router from '/@/router';
// import { PageEnum } from '/@/enums/pageEnum';
import { useUserStoreWidthOut } from '/@/store/modules/user';

const { createMessage } = useMessage();

const error = createMessage.error!;
export function checkStatus(status: number, msg: string): void {
const { t } = useI18n();
const userStore = useUserStoreWidthOut();
switch (status) {
case 400:
error(`${msg}`);
Expand All @@ -17,7 +19,8 @@ export function checkStatus(status: number, msg: string): void {
// Return to the current page after successful login. This step needs to be operated on the login page.
case 401:
error(t('sys.api.errMsg401'));
router.push(PageEnum.BASE_LOGIN);
userStore.setToken(undefined);
userStore.setSessionTimeout(true);
break;
case 403:
error(t('sys.api.errMsg403'));
Expand Down
3 changes: 2 additions & 1 deletion src/utils/http/axios/helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { isObject, isString } from '/@/utils/is';

const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm';

export function createNow<T extends boolean>(
join: boolean,
restful: T
Expand All @@ -16,7 +18,6 @@ export function createNow(join: boolean, restful = false): string | object {
return { _t: now };
}

const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm';
/**
* @description: Format request parameter time
*/
Expand Down
25 changes: 25 additions & 0 deletions src/views/demo/feat/session-timeout/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<template>
<PageWrapper
title="登录过期示例"
content="用户登录过期示例,不再跳转登录页,直接生成页面覆盖当前页面,方便保持过期前的用户状态!"
>
<a-button type="primary" @click="test">点击触发用户登录过期</a-button>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { PageWrapper } from '/@/components/Page';
import { sessionTimeoutApi } from '/@/api/demo/account';
export default defineComponent({
name: 'TestSessionTimeout',
components: { PageWrapper },
setup() {
async function test() {
await sessionTimeoutApi();
}
return { test };
},
});
</script>
28 changes: 26 additions & 2 deletions src/views/sys/login/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
<AppLocalePicker
class="absolute top-4 right-4 enter-x text-white xl:text-gray-600"
:showText="false"
v-if="!sessionTimeout"
/>
<AppDarkModeToggle class="absolute top-3 right-7 enter-x" />
<AppDarkModeToggle class="absolute top-3 right-7 enter-x" v-if="!sessionTimeout" />

<span class="-enter-x xl:hidden">
<AppLogo :alwaysShowTitle="true" />
Expand All @@ -31,7 +32,25 @@
<div class="h-full xl:h-auto flex py-5 xl:py-0 xl:my-0 w-full xl:w-6/12">
<div
:class="`${prefixCls}-form`"
class="my-auto mx-auto xl:ml-20 xl:bg-transparent px-5 py-8 sm:px-8 xl:p-4 rounded-md shadow-md xl:shadow-none w-full sm:w-3/4 lg:w-2/4 xl:w-auto enter-x relative"
class="
my-auto
mx-auto
xl:ml-20
xl:bg-transparent
px-5
py-8
sm:px-8
xl:p-4
rounded-md
shadow-md
xl:shadow-none
w-full
sm:w-3/4
lg:w-2/4
xl:w-auto
enter-x
relative
"
>
<LoginForm />
<ForgetPasswordForm />
Expand Down Expand Up @@ -72,6 +91,11 @@
AppLocalePicker,
AppDarkModeToggle,
},
props: {
sessionTimeout: {
type: Boolean,
},
},
setup() {
const globSetting = useGlobSetting();
const { prefixCls } = useDesign('login');
Expand Down
Loading

0 comments on commit 5465f05

Please sign in to comment.