From cab3b1ee96e0afc251a281231d048884c32dbc0e Mon Sep 17 00:00:00 2001 From: landaiqing <3517283258@qq.com> Date: Wed, 14 Aug 2024 20:04:57 +0800 Subject: [PATCH] :sparkles: add automatic login --- components.d.ts | 1 + src/api/user/index.ts | 17 +++++++---- .../Nprogress}/nprogress.ts | 0 src/locales/language/en.ts | 4 +++ src/locales/language/zh.ts | 3 +- src/router/modules/landing.ts | 11 +++++++ src/router/modules/login.ts | 18 ++++++++++++ src/router/modules/qrlogin.ts | 11 ------- src/router/modules/resetpass.ts | 11 ------- src/router/modules/test.ts | 2 +- src/router/modules/testI18n.ts | 2 +- src/router/router.ts | 16 +++++----- src/store/index.ts | 12 +++++++- src/store/modules/userSessionStore.ts | 27 +++++++++++++++++ src/types/user.d.ts | 1 - src/utils/alova/service.ts | 29 +++++++------------ src/views/Landing/LandingPage.vue | 17 +++++++++++ src/views/Login/LoginPage.vue | 17 +++++++++-- 18 files changed, 136 insertions(+), 63 deletions(-) rename src/{utils/nprogress => components/Nprogress}/nprogress.ts (100%) create mode 100644 src/router/modules/landing.ts delete mode 100644 src/router/modules/qrlogin.ts delete mode 100644 src/router/modules/resetpass.ts create mode 100644 src/store/modules/userSessionStore.ts create mode 100644 src/views/Landing/LandingPage.vue diff --git a/components.d.ts b/components.d.ts index e8fbc45..f3c8183 100644 --- a/components.d.ts +++ b/components.d.ts @@ -29,6 +29,7 @@ declare module 'vue' { BoxDog: typeof import('./src/components/BoxDog/BoxDog.vue')['default'] DynamicTitle: typeof import('./src/components/DynamicTitle/DynamicTitle.vue')['default'] ForgetPage: typeof import('./src/views/Forget/ForgetPage.vue')['default'] + LandingPage: typeof import('./src/views/Landing/LandingPage.vue')['default'] LockOutlined: typeof import('@ant-design/icons-vue')['LockOutlined'] LoginFooter: typeof import('./src/views/Login/LoginFooter.vue')['default'] LoginPage: typeof import('./src/views/Login/LoginPage.vue')['default'] diff --git a/src/api/user/index.ts b/src/api/user/index.ts index ffda278..6576347 100644 --- a/src/api/user/index.ts +++ b/src/api/user/index.ts @@ -5,11 +5,17 @@ import {PhoneLogin} from "@/types/user"; * 获取用户信息 */ export const getUserInfo = () => { - return service.Get('/api/auth/user/List', { + return service.Get('/api/auth/user/list', { meta: { ignoreToken: false }, - cacheFor: 1000 * 60 + cacheFor: { + // 设置缓存模式为持久化模式 + mode: 'restore', + // 缓存时间 + expire: 1000 * 10, + tag: 'v1' + } }); }; @@ -18,10 +24,9 @@ export const getUserInfo = () => { * @param refreshToken */ export const refreshToken = (refreshToken: string) => { - return service.Get('/api/auth/token/refresh', { - params: { - refresh_token: refreshToken - }, + return service.Post('/api/token/refresh', { + refresh_token: refreshToken + }, { meta: { authRole: 'refreshToken', ignoreToken: false diff --git a/src/utils/nprogress/nprogress.ts b/src/components/Nprogress/nprogress.ts similarity index 100% rename from src/utils/nprogress/nprogress.ts rename to src/components/Nprogress/nprogress.ts diff --git a/src/locales/language/en.ts b/src/locales/language/en.ts index 1cd828a..4465885 100644 --- a/src/locales/language/en.ts +++ b/src/locales/language/en.ts @@ -38,6 +38,7 @@ export default { sendCaptchaError: "captcha sending failed, please try again later", loginSuccess: "login success!", loginError: "login failed!", + }, error: { networkError: 'Network error, please try again later', @@ -55,5 +56,8 @@ export default { other: 'connect error', authTokenError: "auth token error, please try again later", authTokenExpired: "auth token expired, please login again", + loginExpired: "login expired, please try again", + pleaseLogin: "please login first", + } }; diff --git a/src/locales/language/zh.ts b/src/locales/language/zh.ts index 775c88d..19bd91b 100644 --- a/src/locales/language/zh.ts +++ b/src/locales/language/zh.ts @@ -57,6 +57,7 @@ export default { other: '连接出错', authTokenError: "认证失败,请重新登录!", authTokenExpired: "认证过期,请重新登录!", - + loginExpired: "登录已过期!,请重新登录!", + pleaseLogin: "请先登录!", } }; diff --git a/src/router/modules/landing.ts b/src/router/modules/landing.ts new file mode 100644 index 0000000..230e7bf --- /dev/null +++ b/src/router/modules/landing.ts @@ -0,0 +1,11 @@ +export default [ + { + path: '/', + name: 'index', + component: () => import('@/views/Landing/LandingPage.vue'), + meta: { + requiresAuth: false, + title: '首页' + } + } +]; diff --git a/src/router/modules/login.ts b/src/router/modules/login.ts index a760cf9..6e051f0 100644 --- a/src/router/modules/login.ts +++ b/src/router/modules/login.ts @@ -7,5 +7,23 @@ export default [ requiresAuth: false, title: '登录页' } + }, + { + path: '/qrlogin', + name: 'qrlogin', + component: () => import('@/views/QRLogin/QRLogin.vue'), + meta: { + requiresAuth: false, + title: '扫码登录' + } + }, + { + path: '/resetpass', + name: 'resetpass', + component: () => import('@/views/Forget/ForgetPage.vue'), + meta: { + requiresAuth: false, + title: '重置密码' + } } ]; diff --git a/src/router/modules/qrlogin.ts b/src/router/modules/qrlogin.ts deleted file mode 100644 index 286771a..0000000 --- a/src/router/modules/qrlogin.ts +++ /dev/null @@ -1,11 +0,0 @@ -export default [ - { - path: '/qrlogin', - name: 'qrlogin', - component: () => import('@/views/QRLogin/QRLogin.vue'), - meta: { - requiresAuth: false, - title: '扫码登录' - } - } -]; diff --git a/src/router/modules/resetpass.ts b/src/router/modules/resetpass.ts deleted file mode 100644 index 1170257..0000000 --- a/src/router/modules/resetpass.ts +++ /dev/null @@ -1,11 +0,0 @@ -export default [ - { - path: '/resetpass', - name: 'resetpass', - component: () => import('@/views/Forget/ForgetPage.vue'), - meta: { - requiresAuth: false, - title: '重置密码' - } - } -]; diff --git a/src/router/modules/test.ts b/src/router/modules/test.ts index 94bdef0..d75fd65 100644 --- a/src/router/modules/test.ts +++ b/src/router/modules/test.ts @@ -4,7 +4,7 @@ export default [ name: 'test', component: () => import('@/views/TestTheme.vue'), meta: { - requiresAuth: false, + requiresAuth: true, title: '测试' } } diff --git a/src/router/modules/testI18n.ts b/src/router/modules/testI18n.ts index 3d3cf07..f9a4b5a 100644 --- a/src/router/modules/testI18n.ts +++ b/src/router/modules/testI18n.ts @@ -4,7 +4,7 @@ export default [ name: 'test2', component: () => import('@/views/TestI18n.vue'), meta: { - requiresAuth: false, + requiresAuth: true, title: '测试' } } diff --git a/src/router/router.ts b/src/router/router.ts index 8c8d4f9..7770dce 100644 --- a/src/router/router.ts +++ b/src/router/router.ts @@ -6,17 +6,15 @@ import test from "@/router/modules/test.ts"; import test2 from "@/router/modules/testI18n.ts"; import useStore from "@/store"; import {message} from "ant-design-vue"; -import {close, start} from '@/utils/nprogress/nprogress.ts'; -import qrlogin from "@/router/modules/qrlogin.ts"; -import resetpass from "@/router/modules/resetpass.ts"; +import {close, start} from '@/components/Nprogress/nprogress.ts'; import notFound from "@/router/modules/notFound.ts"; +import landing from "@/router/modules/landing.ts"; const routes: Array = [ ...login, - ...qrlogin, - ...resetpass, ...notFound, + ...landing, ...test, ...test2, { @@ -35,14 +33,14 @@ router.beforeEach((to, from, next) => { start(); if (to.meta.requiresAuth) { const user = useStore().user; - const token: string | undefined = user.getUser()?.token; - const userId: string | undefined = user.getUser()?.userId; - if (token !== undefined && userId !== undefined) { + const token: string | undefined = user.user.refreshToken; + const userId: string | undefined = user.user.userId; + if (token !== "" && userId !== "") { next(); } else { message.warn('请先登录').then(); next({ - path: '/', + path: '/login', query: {redirect: to.fullPath} }); } diff --git a/src/store/index.ts b/src/store/index.ts index 1cb6f3e..3e91832 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,10 +1,20 @@ import {useAuthStore} from '@/store/modules/userStore.ts'; import {useThemeStore} from "@/store/modules/themeStore.ts"; import {langStore} from "@/store/modules/langStore.ts"; +import {useAuthSessionStore} from "@/store/modules/userSessionStore.ts"; export default function useStore() { + // 是否自动登录 默认自动化登录 + function isAutoLogin() { + const result: string | null = localStorage.getItem('auto_login'); + if (result) { + return result === 'true'; + } + return true; + } + return { - user: useAuthStore(), + user: isAutoLogin() ? useAuthStore() : useAuthSessionStore(), // 自动登录时使用 useAuthStore,否则使用 useAuthSessionStore theme: useThemeStore(), lang: langStore() }; diff --git a/src/store/modules/userSessionStore.ts b/src/store/modules/userSessionStore.ts new file mode 100644 index 0000000..036dcd6 --- /dev/null +++ b/src/store/modules/userSessionStore.ts @@ -0,0 +1,27 @@ +import {defineStore} from 'pinia'; +import {reactive} from 'vue'; + + +export const useAuthSessionStore = defineStore( + 'user', + () => { + const user: any = reactive({ + accessToken: '', + userId: '', + refreshToken: '', + expiresAt: 0, + }); + + return { + user, + }; + }, + { + // 开启数据持久化 + persist: { + key: 'user', + storage: sessionStorage, + paths: ['user'], + } + } +); diff --git a/src/types/user.d.ts b/src/types/user.d.ts index ae2e55d..501d1db 100644 --- a/src/types/user.d.ts +++ b/src/types/user.d.ts @@ -1,4 +1,3 @@ - export interface AccountLogin { account?: string password?: string; diff --git a/src/utils/alova/service.ts b/src/utils/alova/service.ts index c720c10..b6d72fc 100644 --- a/src/utils/alova/service.ts +++ b/src/utils/alova/service.ts @@ -22,25 +22,18 @@ const {onAuthRequired, onResponseRefreshToken} = createServerTokenAuthentication // 当token过期时触发,在此函数中触发刷新token handler: async () => { - try { - const user = useStore().user; - const res: any = await refreshToken(user.user?.refreshToken || ''); - if (res.code === 0 && res.data) { - const {uid, access_token, refresh_token, expires_at} = res.data; - user.user.userId = uid; - user.user.accessToken = access_token; - user.user.refreshToken = refresh_token; - user.user.expiresAt = expires_at; - } - // else { - // message.error(res.message); - // await router.push('/login'); - // } - } catch (error) { - // token刷新失败,跳转回登录页 - message.error(i18n.global.t('error.authTokenError')).then(); + // 刷新token + const user = useStore().user; + const res: any = await refreshToken(user.user?.refreshToken || ''); + if (res.code === 0 && res.data) { + const {access_token, refresh_token, uid} = res.data; + user.user.accessToken = access_token; + user.user.refreshToken = refresh_token; + user.user.uid = uid; + } else { + message.error(i18n.global.t('error.loginExpired')); + localStorage.removeItem('user'); await router.push('/login'); - throw error; } } } diff --git a/src/views/Landing/LandingPage.vue b/src/views/Landing/LandingPage.vue new file mode 100644 index 0000000..c72c369 --- /dev/null +++ b/src/views/Landing/LandingPage.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/views/Login/LoginPage.vue b/src/views/Login/LoginPage.vue index 09fbec7..5f3d7c4 100644 --- a/src/views/Login/LoginPage.vue +++ b/src/views/Login/LoginPage.vue @@ -54,7 +54,10 @@ - {{ t("login.autoLogin") }} + {{ t("login.autoLogin") }} + @@ -100,7 +103,10 @@ - {{ t("login.autoLogin") }} + {{ t("login.autoLogin") }} + {{ t("login.forgotPassword") }} @@ -162,6 +168,7 @@ const phoneLoginFormRef = ref(); const showRotateCaptcha = ref(false); const captchaData = reactive({angle: 0, image: "", thumb: "", key: ""}); const captchaErrorCount = ref(0); +const autoLoginChecked = ref(localStorage.getItem('auto_login') === 'true'); const rotateEvent = { confirm: (angle: number) => { checkCaptcha(angle); @@ -209,7 +216,7 @@ const rules: Record = { captcha: [ { required: true, message: t('login.captchaValidate'), trigger: 'change' - } + }, ] }; @@ -379,6 +386,10 @@ async function sendMessageByPhone(): Promise { return false; } } + +async function autoLoginChang(checkedValue: boolean) { + return localStorage.setItem('auto_login', String(checkedValue)); +}