From e31a20e92dcef284ec295cac223637b8a68aefcd Mon Sep 17 00:00:00 2001 From: Jimmy Liow Date: Fri, 7 Jun 2024 14:36:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=20useStorage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useStorage.js | 69 +++++++++++++++++++++++++++-------------- src/main.jsx | 2 ++ src/stores/Auth.js | 21 +++++++------ src/views/App.jsx | 10 +++--- src/views/Login.jsx | 22 +++++-------- src/views/Logout.jsx | 31 ++++++++++++++++++ 6 files changed, 104 insertions(+), 51 deletions(-) create mode 100644 src/views/Logout.jsx diff --git a/src/hooks/useStorage.js b/src/hooks/useStorage.js index 16da146..5252acf 100644 --- a/src/hooks/useStorage.js +++ b/src/hooks/useStorage.js @@ -1,22 +1,38 @@ +const persistObject = {} + +/** + * GH-INT:USER_ID -> userId = 456 + * GH-STR:LOGIN_TOKEN -> loginToken = 'E6779386E7D64DF0ADD0F97767E00D8B' + */ export function useStorage() { - const setSession = (key, value) => { - if (window.sessionStorage) { - const sessionStorage = window.sessionStorage - return sessionStorage.setItem(key, value) + const getStorage = () => { + if (import.meta.env.DEV && window.localStorage) { + return window.localStorage + } else if (window.sessionStorage) { + return window.sessionStorage } else { - console.error('browser not support sessionStorage.') + console.error('browser not support localStorage and sessionStorage.') + } + } + + const setProperty = (key, value) => { + const webStorage = getStorage() + const typeAndKey = key.split(':') + if (typeAndKey.length === 2) { + const propName = camelCasedWords(typeAndKey[1]) + persistObject[propName] = value + webStorage.setItem(key, value) } } + // USER_ID -> userId const camelCasedWords = (string) => { if (typeof string !== 'string' || string.length === 0) { return string; } return string.split('_').map((word, index) => { if (index === 0) { - return '' - } else if (index === 1) { return word.toLowerCase() } else { return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase() @@ -24,27 +40,34 @@ export function useStorage() { }).join('') } - const storageObject = {} + if (Object.keys(persistObject).length == 0) { - if (window.sessionStorage) { + const webStorage = getStorage() - const sessionStorage = window.sessionStorage + for (let i = 0; i < webStorage.length; i++) { + const key = webStorage.key(i) + const typeAndKey = key.split(':') - for (let i = 0; i < sessionStorage.length; i++) { - const key = sessionStorage.key(i) - const value = sessionStorage.getItem(key) - const propName = camelCasedWords(key) - storageObject[propName] = value + if (typeAndKey.length === 2) { + const value = webStorage.getItem(key) + const propName = camelCasedWords(typeAndKey[1]) + if (typeAndKey[0] === 'GH-INT') { + persistObject[propName] = parseInt(value, 10) + } else { + persistObject[propName] = value + } + } } + } - return { - ...storageObject, - setStorage: (key, value) => { - setSession(key, value) - } + return { + ...persistObject, + setStorage: (key, value) => { + setProperty(key, value) + }, + clearStorage: () => { + getStorage().clear() + Object.assign(persistObject, {}) } - } else { - console.error('browser not support sessionStorage.') - return {} } } diff --git a/src/main.jsx b/src/main.jsx index c29c9b4..4d2f463 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -11,6 +11,7 @@ import "@/assets/global.css"; import App from "@/views/App"; import Standlone from "@/views/Standlone"; import Login from "@/views/Login"; +import Logout from "@/views/Logout"; import Index from "@/views/index"; import ErrorPage from "@/views/error-page"; import ReservationNewest from "@/views/reservation/Newest"; @@ -66,6 +67,7 @@ const router = createBrowserRouter([ element: , children: [ { path: "/login", element: }, + { path: "/logout", element: }, ] } ]); diff --git a/src/stores/Auth.js b/src/stores/Auth.js index 525bb4a..6fb65de 100644 --- a/src/stores/Auth.js +++ b/src/stores/Auth.js @@ -1,15 +1,15 @@ import { makeAutoObservable, runInAction } from "mobx"; import { create } from 'zustand' -import { appendRequestParams, fetchJSON, postForm } from '@/utils/request'; -import { HT_HOST } from "@/config"; -import { isNotEmpty, prepareUrl } from '@/utils/commons'; -import { loadPageSpy } from '@/pageSpy'; +import { appendRequestParams, fetchJSON, postForm } from '@/utils/request' +import { HT_HOST } from "@/config" +import { isNotEmpty, prepareUrl } from '@/utils/commons' +import { loadPageSpy } from '@/pageSpy' import { useStorage } from '@/hooks/useStorage' -const KEY_LOGIN_TOKEN = 'KEY_LOGIN_TOKEN' -const KEY_TRAVEL_AGENCY_ID = 'KEY_TRAVEL_AGENCY_ID' -const KEY_USER_ID = 'KEY_USER_ID' +const KEY_LOGIN_TOKEN = 'GH-STR:LOGIN_TOKEN' +const KEY_TRAVEL_AGENCY_ID = 'GH-INT:TRAVEL_AGENCY_ID' +const KEY_USER_ID = 'GH-INT:USER_ID' const useAuthStore = create((set, get) => ({ @@ -97,11 +97,14 @@ const useAuthStore = create((set, get) => ({ }, logout: () => { - window.sessionStorage.clearSession() + const { clearStorage } = useStorage() + clearStorage() set(() => ({ loginUser: { + token: '', timeout: true - } + }, + loginStatus: 0 })) }, diff --git a/src/views/App.jsx b/src/views/App.jsx index 245de13..7c05be4 100644 --- a/src/views/App.jsx +++ b/src/views/App.jsx @@ -13,6 +13,7 @@ import 'dayjs/locale/zh-cn'; import { BUILD_VERSION, } from '@/config'; import useNoticeStore from '@/stores/Notice'; import useAuthStore from '@/stores/Auth' +import { useStorage } from '@/hooks/useStorage' const { Header, Content, Footer } = Layout; const { Title } = Typography; @@ -25,11 +26,12 @@ function App() { const loginUser = useAuthStore((state) => state.loginUser) + const { loginToken } = useStorage() + const noticeUnRead = useNoticeStore((state) => state.noticeUnRead); const href = useHref(); - const loginToken = loginUser.token; - const navigate = useNavigate(); - const location = useLocation(); + const navigate = useNavigate() + const location = useLocation() useEffect(() => { if (href !== '/login' && isEmpty(loginToken)) { @@ -151,7 +153,7 @@ function App() { { label: {t('ChangePassword')}, key: '0' }, { label: {t('Profile')}, key: '1' }, { type: 'divider' }, - { label: {t('Logout')}, key: '3' }, + { label: {t('Logout')}, key: '3' }, ], { type: 'divider' }, { label: <>v{BUILD_VERSION}, key: 'BUILD_VERSION' }, diff --git a/src/views/Login.jsx b/src/views/Login.jsx index d8e4f91..7918d1b 100644 --- a/src/views/Login.jsx +++ b/src/views/Login.jsx @@ -1,28 +1,20 @@ -import { useNavigate, useLocation } from 'react-router-dom'; -import { useEffect } from 'react'; -import { Button, Checkbox, Form, Input, Row, App } from 'antd'; -import { useTranslation } from 'react-i18next'; +import { useNavigate, useLocation } from 'react-router-dom' +import { useEffect } from 'react' +import { Button, Checkbox, Form, Input, Row, App } from 'antd' +import { useTranslation } from 'react-i18next' import useAuthStore from '@/stores/Auth' -import useNoticeStore from '@/stores/Notice'; +import useNoticeStore from '@/stores/Notice' function Login() { - const [validateUserPassword, loginStatus, logout] = + const [validateUserPassword, loginStatus] = useAuthStore((state) => [state.validateUserPassword, state.loginStatus]) const getBulletinUnReadCount = useNoticeStore((state) => state.getBulletinUnReadCount) const { t, i18n } = useTranslation() - const { notification } = App.useApp(); + const { notification } = App.useApp() const navigate = useNavigate() - const location = useLocation() const [form] = Form.useForm() - useEffect (() => { - if (location.search === '?out') { - logout(); - navigate('/login') - } - }, []) - useEffect (() => { if (loginStatus === 302) { navigate('/reservation/newest') diff --git a/src/views/Logout.jsx b/src/views/Logout.jsx new file mode 100644 index 0000000..2f695eb --- /dev/null +++ b/src/views/Logout.jsx @@ -0,0 +1,31 @@ +import { Flex, Result, Spin } from 'antd' +import { useEffect } from 'react' +import { useNavigate } from 'react-router-dom' +import useAuthStore from '@/stores/Auth' + +function Logout() { + + const navigate = useNavigate() + + const logout = useAuthStore(state => state.logout) + + useEffect(() => { + logout() + navigate('/login') + }, []) + + return ( + + + ]} + /> + + ) +} + +export default Logout