From 8b5880fab5de8c05cd4fa8d755039a04b6c0cc8d Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Sat, 14 Oct 2023 23:00:52 +0800 Subject: [PATCH 1/3] Add login to ToolsFramework --- src/AuthRoute.tsx | 5 +- src/assets/css/constants.scss | 3 ++ src/assets/css/pages/tools-framework.scss | 66 +++++++++++++++++++++-- src/assets/svg/exit.svg | 1 + src/pages/ToolsFramework.tsx | 58 ++++++++++++++++++-- src/router/tools.tsx | 5 ++ src/services/index.tsx | 4 +- src/utils/auth.ts | 7 +-- src/utils/common.ts | 4 ++ 9 files changed, 136 insertions(+), 17 deletions(-) create mode 100644 src/assets/svg/exit.svg diff --git a/src/AuthRoute.tsx b/src/AuthRoute.tsx index 7335e5e..35b6a77 100644 --- a/src/AuthRoute.tsx +++ b/src/AuthRoute.tsx @@ -1,5 +1,6 @@ import { getLoginStatus } from '@/utils/auth.ts' import { PRODUCTION_NAME } from '@/constants/Common.constants.ts' +import { getRedirectUrl } from '@/utils/common.ts' const AuthRoute = () => { const matches = useMatches() @@ -16,9 +17,7 @@ const AuthRoute = () => { if (matches.some(({ handle }) => (handle as RouteHandle)?.auth) && !isLogin) { return ( ) } diff --git a/src/assets/css/constants.scss b/src/assets/css/constants.scss index 18e8338..3e6e1b5 100644 --- a/src/assets/css/constants.scss +++ b/src/assets/css/constants.scss @@ -1,6 +1,9 @@ $origin-color: white; $main-color: #4E47BB; $secondary-color: #BAB8E5; +$error-color: #ff4d4f; +$error-secondary-color: #ff7875; +$blue-color: #1677ff; $active-color: #EBECFFD; $background-color: #F5F5F5; $font-main-color: #4D4D4D; diff --git a/src/assets/css/pages/tools-framework.scss b/src/assets/css/pages/tools-framework.scss index b95691f..4ae1958 100644 --- a/src/assets/css/pages/tools-framework.scss +++ b/src/assets/css/pages/tools-framework.scss @@ -13,7 +13,6 @@ body { user-select: none; transition: all .3s; white-space: nowrap; - overflow: hidden; .title { display: flex; @@ -21,6 +20,7 @@ body { font-weight: bold; padding: 10px 14px; color: constants.$main-color; + overflow: hidden; .icon-box { display: flex; @@ -153,12 +153,10 @@ body { animation: 0.3s ease; @include mixins.unique-keyframes { 0% { - display: block; transform: translateX(-10px); opacity: 0; } 100% { - display: block; transform: translateX(0); opacity: 1; } @@ -188,7 +186,7 @@ body { padding: 8px 14px; color: constants.$main-color; - .icon-box { + .icon-user { display: flex; justify-content: center; align-items: center; @@ -205,10 +203,27 @@ body { .text { flex: 1; - padding-left: 8px; + padding-left: 10px; font-size: 1.4em; color: constants.$font-main-color; user-select: text; + + a{ + color: constants.$main-color; + text-decoration: underline; + } + } + + .icon-exit { + font-size: constants.$SIZE_ICON_XS; + color: constants.$error-color; + padding: 6px 10px; + cursor: pointer; + + &:hover { + border-radius: 8px; + background-color: constants.$background-color; + } } } @@ -234,9 +249,50 @@ body { } .footer { + position: relative; .text { display: none; } + + .submenu-exit { + display: none; + position: absolute; + padding-left: 6px; + left: 100%; + + .content { + padding: 8px; + border-radius: 8px; + background-color: constants.$origin-color; + + .icon-exit { + padding: 4px 8px; + &:hover { + border-radius: 8px; + background-color: constants.$background-color; + } + } + } + + &.hide { + display: none!important; + } + } + + &:hover .submenu-exit { + display: block; + animation: 0.3s ease; + @include mixins.unique-keyframes { + 0% { + transform: translateX(-10px); + opacity: 0; + } + 100% { + transform: translateX(0); + opacity: 1; + } + } + } } } } diff --git a/src/assets/svg/exit.svg b/src/assets/svg/exit.svg new file mode 100644 index 0000000..12a1804 --- /dev/null +++ b/src/assets/svg/exit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/pages/ToolsFramework.tsx b/src/pages/ToolsFramework.tsx index c29b28f..20f62a9 100644 --- a/src/pages/ToolsFramework.tsx +++ b/src/pages/ToolsFramework.tsx @@ -4,9 +4,15 @@ import '@/assets/css/pages/tools-framework.scss' import Icon from '@ant-design/icons' import { toolsJsonObjects } from '@/router/tools.tsx' import HideScrollbar, { HideScrollbarElement } from '@/components/common/HideScrollbar.tsx' -import { getLocalStorage, setLocalStorage } from '@/utils/common.ts' +import { getLocalStorage, getRedirectUrl, setLocalStorage } from '@/utils/common.ts' +import { getLoginStatus, logout } from '@/utils/auth.ts' +import { NavLink, Outlet } from 'react-router-dom' const ToolsFramework: React.FC = () => { + const matches = useMatches() + const lastMatch = matches.reduce((_, second) => second) + const location = useLocation() + const navigate = useNavigate() const hideScrollbarRef = useRef(null) const [submenuTop, setSubmenuTop] = useState(0) const [submenuLeft, setSubmenuLeft] = useState(0) @@ -37,6 +43,21 @@ const ToolsFramework: React.FC = () => { } } + const handleClickAvatar = () => { + if (getLoginStatus()) { + navigate(`${lastMatch.pathname}${location.search}`) + } else { + navigate(getRedirectUrl('/login', `${lastMatch.pathname}${location.search}`)) + } + } + + const handleLogout = () => { + logout() + setTimeout(() => { + window.location.reload() + }, 1500) + } + return ( <> @@ -183,13 +204,42 @@ const ToolsFramework: React.FC = () => {
- + - 未登录 + + +
-
+
+ +
) diff --git a/src/router/tools.tsx b/src/router/tools.tsx index a3a4fcd..997809a 100644 --- a/src/router/tools.tsx +++ b/src/router/tools.tsx @@ -309,4 +309,9 @@ const tools: RouteObject[] = toolsJsonObjects.map((value) => ({ })) })) +tools.push({ + path: '*', + element: +}) + export default tools diff --git a/src/services/index.tsx b/src/services/index.tsx index d89ba76..2117765 100644 --- a/src/services/index.tsx +++ b/src/services/index.tsx @@ -42,7 +42,7 @@ service.interceptors.request.use( ) { await axios .get(import.meta.env.VITE_API_TOKEN_URL, { - headers: { token } + headers: { Authorization: `Bearer ${token}` } }) .then((value: AxiosResponse<_Response>) => { const response = value.data @@ -53,7 +53,7 @@ service.interceptors.request.use( } token = getToken() - config.headers.set('token', token) + config.headers.set('Authorization', `Bearer ${token}`) } return config }, diff --git a/src/utils/auth.ts b/src/utils/auth.ts index 097e112..22a7817 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -1,4 +1,4 @@ -import { clearLocalStorage, getCaptcha, getLocalStorage, setLocalStorage } from './common' +import { getCaptcha, getLocalStorage, removeLocalStorage, setLocalStorage } from './common' import { SYSTEM_OK, TOKEN_NAME } from '@/constants/Common.constants' import request from '@/services' @@ -12,8 +12,9 @@ export async function login(username: string, password: string) { } export function logout(): void { - void request.get('/logout').finally(() => { - clearLocalStorage() + void request.post('/logout').finally(() => { + removeLocalStorage('userInfo') + removeLocalStorage(TOKEN_NAME) }) } diff --git a/src/utils/common.ts b/src/utils/common.ts index 7d0f9ce..18bc410 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -134,3 +134,7 @@ function randomFloat(start: number, end: number): number { function randomColor(start: number, end: number): string { return `rgb(${randomInt(start, end)},${randomInt(start, end)},${randomInt(start, end)})` } + +export const getRedirectUrl = (path: string, redirectUrl: string): string => { + return `${path}?redirect=${encodeURIComponent(redirectUrl)}` +} -- 2.49.1 From 7f709ac34158c50f304f12005937e2a6f47a6c90 Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Sat, 14 Oct 2023 23:20:25 +0800 Subject: [PATCH 2/3] Recode old code --- build/resolvers/antd.ts | 4 ++-- src/services/index.tsx | 2 +- src/utils/auth.ts | 16 ++++++++-------- src/utils/common.ts | 32 ++++++++++++++++---------------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/build/resolvers/antd.ts b/build/resolvers/antd.ts index 469af1b..3d18000 100644 --- a/build/resolvers/antd.ts +++ b/build/resolvers/antd.ts @@ -1,4 +1,4 @@ -export function kebabCase(key: string): string { +export const kebabCase = (key: string) => { const result: string = key.replace(/([A-Z])/g, ' $1').trim() return result.split(' ').join('-').toLowerCase() } @@ -395,7 +395,7 @@ const isAntd = (compName: string): boolean => { return antdNames.has(compName) } -export function AntDesignResolver(options: AntDesignResolverOptions = {}): ComponentResolver { +export const AntDesignResolver = (options: AntDesignResolverOptions = {}): ComponentResolver => { return { type: 'component', resolve: (name: string) => { diff --git a/src/services/index.tsx b/src/services/index.tsx index 2117765..3d3a308 100644 --- a/src/services/index.tsx +++ b/src/services/index.tsx @@ -74,7 +74,7 @@ service.interceptors.response.use( 登录已过期 ) - setTimeout(function () { + setTimeout(() => { location.reload() }, 1500) throw response?.data diff --git a/src/utils/auth.ts b/src/utils/auth.ts index 22a7817..a923968 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -4,25 +4,25 @@ import request from '@/services' let captcha: Captcha -export async function login(username: string, password: string) { +export const login = async (username: string, password: string) => { return await request.post('/login', { username, password }) } -export function logout(): void { +export const logout = () => { void request.post('/logout').finally(() => { removeLocalStorage('userInfo') removeLocalStorage(TOKEN_NAME) }) } -export function getLoginStatus(): boolean { +export const getLoginStatus = () => { return getLocalStorage(TOKEN_NAME) !== null } -export async function getUser(): Promise { +export const getUser = async (): Promise => { if (getLocalStorage('userInfo') !== null) { return new Promise((resolve) => { resolve(JSON.parse(getLocalStorage('userInfo') as string) as User) @@ -31,7 +31,7 @@ export async function getUser(): Promise { return requestUser() } -export async function requestUser(): Promise { +export const requestUser = async () => { let user: User | null await request.get('/user/info').then((value) => { @@ -50,17 +50,17 @@ export async function requestUser(): Promise { }) } -export async function getUsername(): Promise { +export const getUsername = async () => { const user = await getUser() return user.username } -export function getCaptchaSrc(): string { +export const getCaptchaSrc = () => { captcha = getCaptcha(300, 150, 4) return captcha.base64Src } -export function verifyCaptcha(value: string): boolean { +export const verifyCaptcha = (value: string) => { return captcha.value.toLowerCase() === value.replace(/\s*/g, '').toLowerCase() } diff --git a/src/utils/common.ts b/src/utils/common.ts index 18bc410..04d1244 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -1,6 +1,6 @@ import { TOKEN_NAME } from '@/constants/Common.constants' -export function getQueryVariable(variable: string): string | null { +export const getQueryVariable = (variable: string) => { const query = window.location.search.substring(1) const vars = query.split('&') for (const value of vars) { @@ -12,12 +12,12 @@ export function getQueryVariable(variable: string): string | null { return null } -export function setCookie( +export const setCookie = ( name: string, value: string, daysToLive: number | null, path: string | null -): void { +) => { let cookie = `${name}=${encodeURIComponent(value)}` if (typeof daysToLive === 'number') { @@ -31,15 +31,15 @@ export function setCookie( document.cookie = cookie } -export function setLocalStorage(name: string, value: string): void { +export const setLocalStorage = (name: string, value: string) => { localStorage.setItem(name, value) } -export function setToken(token: string): void { +export const setToken = (token: string) => { setLocalStorage(TOKEN_NAME, token) } -export function getCookie(name: string): string | null { +export const getCookie = (name: string) => { const cookieArr = document.cookie.split(';') for (const cookie of cookieArr) { @@ -52,31 +52,31 @@ export function getCookie(name: string): string | null { return null } -export function getLocalStorage(name: string): string | null { +export const getLocalStorage = (name: string) => { return localStorage.getItem(name) } -export function getToken(): string | null { +export const getToken = () => { return getLocalStorage(TOKEN_NAME) } -export function removeCookie(name: string): void { +export const removeCookie = (name: string) => { document.cookie = `${name}=; max-age=0` } -export function removeLocalStorage(name: string): void { +export const removeLocalStorage = (name: string) => { localStorage.removeItem(name) } -export function removeToken(): void { +export const removeToken = () => { removeLocalStorage(TOKEN_NAME) } -export function clearLocalStorage(): void { +export const clearLocalStorage = () => { localStorage.clear() } -export function getCaptcha(width: number, high: number, num: number): Captcha { +export const getCaptcha = (width: number, high: number, num: number) => { const CHARTS = '23456789ABCDEFGHJKLMNPRSTUVWXYZabcdefghijklmnpqrstuvwxyz'.split('') const canvas = document.createElement('canvas') @@ -116,7 +116,7 @@ export function getCaptcha(width: number, high: number, num: number): Captcha { } } -function randomInt(start: number, end: number): number { +const randomInt = (start: number, end: number) => { if (start > end) { const t = start start = end @@ -127,11 +127,11 @@ function randomInt(start: number, end: number): number { return start + Math.floor(Math.random() * (end - start)) } -function randomFloat(start: number, end: number): number { +const randomFloat = (start: number, end: number) => { return start + Math.random() * (end - start) } -function randomColor(start: number, end: number): string { +const randomColor = (start: number, end: number) => { return `rgb(${randomInt(start, end)},${randomInt(start, end)},${randomInt(start, end)})` } -- 2.49.1 From 6e31eb6e9d10f42adb039d2d943d366d659e3d12 Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Sat, 14 Oct 2023 23:20:48 +0800 Subject: [PATCH 3/3] Optimize stylesheet in ToolsFramework --- src/assets/css/pages/tools-framework.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/css/pages/tools-framework.scss b/src/assets/css/pages/tools-framework.scss index 4ae1958..f9e08cf 100644 --- a/src/assets/css/pages/tools-framework.scss +++ b/src/assets/css/pages/tools-framework.scss @@ -192,8 +192,8 @@ body { align-items: center; margin-left: 4px; padding: 10px; - width: 32px; - height: 32px; + width: 36px; + height: 36px; font-size: constants.$SIZE_ICON_XS; border: 2px constants.$font-secondary-color solid; color: constants.$font-secondary-color; -- 2.49.1