diff --git a/package-lock.json b/package-lock.json
index c67c05d..159998f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
"localforage": "^1.10.0",
"lodash": "^4.17.21",
"match-sorter": "^6.3.1",
+ "moment": "^2.29.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "^6.15.0",
@@ -4885,6 +4886,14 @@
"ufo": "^1.3.0"
}
},
+ "node_modules/moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
diff --git a/package.json b/package.json
index 288a28a..932e59b 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"localforage": "^1.10.0",
"lodash": "^4.17.21",
"match-sorter": "^6.3.1",
+ "moment": "^2.29.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "^6.15.0",
diff --git a/src/assets/css/constants.scss b/src/assets/css/constants.scss
index 3e6e1b5..50786e0 100644
--- a/src/assets/css/constants.scss
+++ b/src/assets/css/constants.scss
@@ -1,10 +1,11 @@
$origin-color: white;
-$main-color: #4E47BB;
+$production-color: #4E47BB;
+$main-color: $production-color;
$secondary-color: #BAB8E5;
-$error-color: #ff4d4f;
-$error-secondary-color: #ff7875;
-$blue-color: #1677ff;
-$active-color: #EBECFFD;
+$error-color: #FF4D4F;
+$error-secondary-color: #FF7875;
+$blue-color: #1677FF;
+$active-color: #EBECFD;
$background-color: #F5F5F5;
$font-main-color: #4D4D4D;
$font-secondary-color: #9E9E9E;
diff --git a/src/components/common/sidebar/SidebarFooter.tsx b/src/components/common/sidebar/SidebarFooter.tsx
index 55e1d24..c3b7666 100644
--- a/src/components/common/sidebar/SidebarFooter.tsx
+++ b/src/components/common/sidebar/SidebarFooter.tsx
@@ -1,7 +1,9 @@
import React from 'react'
import Icon from '@ant-design/icons'
-import { getLoginStatus, logout } from '@/utils/auth'
+import { getLoginStatus, getUsername, logout } from '@/utils/auth'
import { getRedirectUrl } from '@/utils/common'
+import { notification } from 'antd'
+import { COLOR_ERROR } from '@/constants/common.constants.ts'
const SidebarFooter: React.FC = () => {
const matches = useMatches()
@@ -9,6 +11,8 @@ const SidebarFooter: React.FC = () => {
const location = useLocation()
const navigate = useNavigate()
const [exiting, setExiting] = useState(false)
+ const [username, setUsername] = useState('')
+
const handleClickAvatar = () => {
if (getLoginStatus()) {
navigate('/user')
@@ -24,12 +28,26 @@ const SidebarFooter: React.FC = () => {
setExiting(true)
void logout().finally(() => {
+ notification.info({
+ message: '已退出登录',
+ icon:
+ })
setTimeout(() => {
window.location.reload()
}, 1500)
})
}
+ const loginStatus = getLoginStatus()
+
+ useEffect(() => {
+ if (getLoginStatus()) {
+ void getUsername().then((username) => {
+ setUsername(username)
+ })
+ }
+ }, [loginStatus])
+
return (
@@ -42,7 +60,7 @@ const SidebarFooter: React.FC = () => {
- 已登录
+ {username}
{
const [messageApi, contextHolder] = message.useMessage()
@@ -31,6 +33,27 @@ const Login: React.FC = () => {
} else {
navigate('/')
}
+ void getUserInfo().then((user) => {
+ notification.success({
+ message: '欢迎回来',
+ description: (
+ <>
+
+ 你好 {user.username}
+
+
+
+ 上次登录:
+ {moment(user.lastLoginTime).format(
+ 'yyyy-MM-DD HH:mm:ssZ'
+ )}
+ 【{user.lastLoginIp}】
+
+ >
+ ),
+ placement: 'topRight'
+ })
+ })
}, 1500)
break
case SYSTEM_USERNAME_NOT_FOUND:
diff --git a/src/services/index.tsx b/src/services/index.tsx
index d509f81..50b4063 100644
--- a/src/services/index.tsx
+++ b/src/services/index.tsx
@@ -44,7 +44,7 @@ service.interceptors.request.use(
.get(import.meta.env.VITE_API_TOKEN_URL, {
headers: { Authorization: `Bearer ${token}` }
})
- .then((value: AxiosResponse<_Response>) => {
+ .then((value: AxiosResponse<_Response>) => {
const response = value.data
if (response.code === SYSTEM_TOKEN_RENEW_SUCCESS) {
setToken(response.data?.token ?? '')
diff --git a/src/utils/auth.ts b/src/utils/auth.ts
index f58a9ac..fd583ea 100644
--- a/src/utils/auth.ts
+++ b/src/utils/auth.ts
@@ -1,12 +1,16 @@
import { getCaptcha, getLocalStorage, removeToken, setLocalStorage } from './common'
-import { SYSTEM_OK, STORAGE_TOKEN_KEY, STORAGE_USER_INFO_KEY } from '@/constants/common.constants'
+import {
+ STORAGE_TOKEN_KEY,
+ STORAGE_USER_INFO_KEY,
+ DATABASE_SELECT_SUCCESS
+} from '@/constants/common.constants'
import request from '@/services'
-import { URL_API_LOGIN, URL_API_LOGOUT } from '@/constants/urls.constants'
+import { URL_API_LOGIN, URL_API_LOGOUT, URL_API_USER_INFO } from '@/constants/urls.constants'
let captcha: Captcha
export const login = async (username: string, password: string) => {
- return await request.post(URL_API_LOGIN, {
+ return await request.post(URL_API_LOGIN, {
username,
password
})
@@ -22,27 +26,27 @@ export const getLoginStatus = () => {
return getLocalStorage(STORAGE_TOKEN_KEY) !== null
}
-export const getUser = async (): Promise => {
+export const getUserInfo = async (): Promise => {
if (getLocalStorage(STORAGE_USER_INFO_KEY) !== null) {
return new Promise((resolve) => {
- resolve(JSON.parse(getLocalStorage(STORAGE_USER_INFO_KEY) as string) as User)
+ resolve(JSON.parse(getLocalStorage(STORAGE_USER_INFO_KEY) as string) as UserVo)
})
}
- return requestUser()
+ return requestUserInfo()
}
-export const requestUser = async () => {
- let user: User | null
+export const requestUserInfo = async () => {
+ let user: UserVo | null
- await request.get('/user/info').then((value) => {
+ await request.get(URL_API_USER_INFO).then((value) => {
const response = value.data
- if (response.code === SYSTEM_OK) {
+ if (response.code === DATABASE_SELECT_SUCCESS) {
user = response.data
setLocalStorage(STORAGE_USER_INFO_KEY, JSON.stringify(user))
}
})
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, reject) => {
if (user) {
resolve(user)
}
@@ -51,7 +55,7 @@ export const requestUser = async () => {
}
export const getUsername = async () => {
- const user = await getUser()
+ const user = await getUserInfo()
return user.username
}