Complete main UI #37
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Icon from '@ant-design/icons'
|
import Icon from '@ant-design/icons'
|
||||||
import { getLoginStatus, getNickName, logout } from '@/utils/auth'
|
|
||||||
import { getRedirectUrl } from '@/utils/common'
|
|
||||||
import { notification } from 'antd'
|
import { notification } from 'antd'
|
||||||
import { COLOR_ERROR } from '@/constants/common.constants.ts'
|
import { getLoginStatus, getNickname, logout } from '@/utils/auth'
|
||||||
|
import { getRedirectUrl } from '@/utils/common'
|
||||||
|
import { COLOR_ERROR } from '@/constants/common.constants'
|
||||||
|
|
||||||
const SidebarFooter: React.FC = () => {
|
const SidebarFooter: React.FC = () => {
|
||||||
const matches = useMatches()
|
const matches = useMatches()
|
||||||
@@ -11,7 +11,7 @@ const SidebarFooter: React.FC = () => {
|
|||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [exiting, setExiting] = useState(false)
|
const [exiting, setExiting] = useState(false)
|
||||||
const [nickName, setNickName] = useState('')
|
const [nickname, setNickname] = useState('')
|
||||||
|
|
||||||
const handleClickAvatar = () => {
|
const handleClickAvatar = () => {
|
||||||
if (getLoginStatus()) {
|
if (getLoginStatus()) {
|
||||||
@@ -42,8 +42,8 @@ const SidebarFooter: React.FC = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (getLoginStatus()) {
|
if (getLoginStatus()) {
|
||||||
void getNickName().then((nickName) => {
|
void getNickname().then((nickname) => {
|
||||||
setNickName(nickName)
|
setNickname(nickname)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [loginStatus])
|
}, [loginStatus])
|
||||||
@@ -60,7 +60,7 @@ const SidebarFooter: React.FC = () => {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
</span>
|
</span>
|
||||||
<span hidden={!getLoginStatus()} className={'text'}>
|
<span hidden={!getLoginStatus()} className={'text'}>
|
||||||
{nickName}
|
{nickname}
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
hidden={!getLoginStatus()}
|
hidden={!getLoginStatus()}
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ export const URL_API_LOGIN = '/login'
|
|||||||
export const URL_API_TOKEN = '/token'
|
export const URL_API_TOKEN = '/token'
|
||||||
export const URL_API_LOGOUT = '/logout'
|
export const URL_API_LOGOUT = '/logout'
|
||||||
export const URL_API_USER_INFO = '/system/user/info'
|
export const URL_API_USER_INFO = '/system/user/info'
|
||||||
|
export const URL_API_USER_LIST = '/system/user'
|
||||||
|
|||||||
30
src/global.d.ts
vendored
30
src/global.d.ts
vendored
@@ -75,10 +75,26 @@ type UserWithPowerInfoVo = {
|
|||||||
operations: OperationVo[]
|
operations: OperationVo[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserWithRoleInfoVo = {
|
||||||
|
id: string
|
||||||
|
username: string
|
||||||
|
locking: boolean
|
||||||
|
expiration: Date
|
||||||
|
credentialsExpiration: Date
|
||||||
|
enable: number
|
||||||
|
lastLoginTime: Date
|
||||||
|
lastLoginIp: string
|
||||||
|
createTime: Date
|
||||||
|
updateTime: Date
|
||||||
|
userInfo: UserInfoVo
|
||||||
|
roles: RoleVo[]
|
||||||
|
groups: GroupVo[]
|
||||||
|
}
|
||||||
|
|
||||||
type UserInfoVo = {
|
type UserInfoVo = {
|
||||||
id: string
|
id: string
|
||||||
userId: string
|
userId: string
|
||||||
nickName: string
|
nickname: string
|
||||||
avatar: string
|
avatar: string
|
||||||
email: string
|
email: string
|
||||||
}
|
}
|
||||||
@@ -113,6 +129,18 @@ type OperationVo = {
|
|||||||
elementId: number
|
elementId: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RoleVo = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
enable: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
type GroupVo = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
enable: boolean
|
||||||
|
}
|
||||||
|
|
||||||
type LoginForm = {
|
type LoginForm = {
|
||||||
username: string
|
username: string
|
||||||
password: string
|
password: string
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import zh_CN from 'antd/locale/zh_CN'
|
|||||||
import '@/assets/css/base.scss'
|
import '@/assets/css/base.scss'
|
||||||
import '@/assets/css/common.scss'
|
import '@/assets/css/common.scss'
|
||||||
import App from './App'
|
import App from './App'
|
||||||
import { COLOR_MAIN } from '@/constants/common.constants.ts'
|
import { COLOR_MAIN } from '@/constants/common.constants'
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const Login: React.FC = () => {
|
|||||||
description: (
|
description: (
|
||||||
<>
|
<>
|
||||||
<span>
|
<span>
|
||||||
你好 <strong>{user.userInfo.nickName}</strong>
|
你好 <strong>{user.userInfo.nickname}</strong>
|
||||||
</span>
|
</span>
|
||||||
<br />
|
<br />
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import Sidebar from '@/components/common/sidebar'
|
|||||||
import SidebarItemList from '@/components/common/sidebar/SidebarItemList'
|
import SidebarItemList from '@/components/common/sidebar/SidebarItemList'
|
||||||
import SidebarItem from '@/components/common/sidebar/SidebarItem'
|
import SidebarItem from '@/components/common/sidebar/SidebarItem'
|
||||||
import SidebarSeparate from '@/components/common/sidebar/SidebarSeparate'
|
import SidebarSeparate from '@/components/common/sidebar/SidebarSeparate'
|
||||||
|
import LoadingMask from '@/components/common/LoadingMask'
|
||||||
|
|
||||||
const ToolsFramework: React.FC = () => {
|
const ToolsFramework: React.FC = () => {
|
||||||
const sidebarScrollRef = useRef<SidebarScrollElement>(null)
|
const sidebarScrollRef = useRef<SidebarScrollElement>(null)
|
||||||
@@ -63,7 +64,15 @@ const ToolsFramework: React.FC = () => {
|
|||||||
</Sidebar>
|
</Sidebar>
|
||||||
</div>
|
</div>
|
||||||
<div className={'right-panel'}>
|
<div className={'right-panel'}>
|
||||||
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<>
|
||||||
|
<LoadingMask />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
</FitFullScreen>
|
</FitFullScreen>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import FitFullScreen from '@/components/common/FitFullScreen'
|
|||||||
import Sidebar from '@/components/common/sidebar'
|
import Sidebar from '@/components/common/sidebar'
|
||||||
import SidebarItemList from '@/components/common/sidebar/SidebarItemList'
|
import SidebarItemList from '@/components/common/sidebar/SidebarItemList'
|
||||||
import SidebarItem from '@/components/common/sidebar/SidebarItem'
|
import SidebarItem from '@/components/common/sidebar/SidebarItem'
|
||||||
import { hasPathPermission } from '@/utils/auth.ts'
|
import { hasPathPermission } from '@/utils/auth'
|
||||||
|
import LoadingMask from '@/components/common/LoadingMask'
|
||||||
|
|
||||||
const ToolsFramework: React.FC = () => {
|
const ToolsFramework: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
@@ -42,7 +43,15 @@ const ToolsFramework: React.FC = () => {
|
|||||||
</Sidebar>
|
</Sidebar>
|
||||||
</div>
|
</div>
|
||||||
<div className={'right-panel'}>
|
<div className={'right-panel'}>
|
||||||
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<>
|
||||||
|
<LoadingMask />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
</FitFullScreen>
|
</FitFullScreen>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,7 +1,50 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { r_getUserList } from '@/services/user'
|
||||||
|
import { COLOR_BACKGROUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants'
|
||||||
|
import { ColumnsType } from 'antd/es/table/interface'
|
||||||
|
|
||||||
const User: React.FC = () => {
|
const User: React.FC = () => {
|
||||||
return <></>
|
const [userList, setUserList] = useState<UserWithRoleInfoVo[]>([])
|
||||||
|
|
||||||
|
const tableColumns: ColumnsType<UserWithRoleInfoVo> = [
|
||||||
|
{
|
||||||
|
dataIndex: 'id',
|
||||||
|
title: 'ID'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataIndex: ['userInfo', 'avatar'],
|
||||||
|
title: '头像',
|
||||||
|
render: (value) => (
|
||||||
|
<AntdAvatar
|
||||||
|
src={<img src={`data:image/png;base64,${value}`} alt={'avatar'} />}
|
||||||
|
style={{ background: COLOR_BACKGROUND }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataIndex: 'username',
|
||||||
|
title: '用户名'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataIndex: ['userInfo', 'nickname'],
|
||||||
|
title: '昵称'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
r_getUserList().then((res) => {
|
||||||
|
const data = res.data
|
||||||
|
if (data.code === DATABASE_SELECT_SUCCESS) {
|
||||||
|
data.data && setUserList(data.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AntdTable dataSource={userList} columns={tableColumns} rowKey={'id'} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default User
|
export default User
|
||||||
|
|||||||
10
src/services/auth.tsx
Normal file
10
src/services/auth.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import request from '@/services'
|
||||||
|
import { URL_API_LOGIN, URL_API_LOGOUT } from '@/constants/urls.constants'
|
||||||
|
|
||||||
|
export const r_login = (username: string, password: string) =>
|
||||||
|
request.post<TokenVo>(URL_API_LOGIN, {
|
||||||
|
username,
|
||||||
|
password
|
||||||
|
})
|
||||||
|
|
||||||
|
export const r_logout = () => request.post(URL_API_LOGOUT)
|
||||||
6
src/services/user.tsx
Normal file
6
src/services/user.tsx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import request from '@/services'
|
||||||
|
import { URL_API_USER_INFO, URL_API_USER_LIST } from '@/constants/urls.constants'
|
||||||
|
|
||||||
|
export const r_getInfo = () => request.get<UserWithPowerInfoVo>(URL_API_USER_INFO)
|
||||||
|
|
||||||
|
export const r_getUserList = () => request.get<UserWithRoleInfoVo[]>(URL_API_USER_LIST)
|
||||||
@@ -1,23 +1,20 @@
|
|||||||
import { getCaptcha, getLocalStorage, removeToken, setLocalStorage } from './common'
|
import { getCaptcha, getLocalStorage, removeToken, setLocalStorage } from './common'
|
||||||
import request from '@/services'
|
import { r_login, r_logout } from '@/services/auth'
|
||||||
|
import { r_getInfo } from '@/services/user'
|
||||||
import {
|
import {
|
||||||
STORAGE_TOKEN_KEY,
|
STORAGE_TOKEN_KEY,
|
||||||
STORAGE_USER_INFO_KEY,
|
STORAGE_USER_INFO_KEY,
|
||||||
DATABASE_SELECT_SUCCESS
|
DATABASE_SELECT_SUCCESS
|
||||||
} from '@/constants/common.constants'
|
} from '@/constants/common.constants'
|
||||||
import { URL_API_LOGIN, URL_API_LOGOUT, URL_API_USER_INFO } from '@/constants/urls.constants'
|
|
||||||
|
|
||||||
let captcha: Captcha
|
let captcha: Captcha
|
||||||
|
|
||||||
export const login = async (username: string, password: string) => {
|
export const login = async (username: string, password: string) => {
|
||||||
return await request.post<TokenVo>(URL_API_LOGIN, {
|
return await r_login(username, password)
|
||||||
username,
|
|
||||||
password
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const logout = async () => {
|
export const logout = async () => {
|
||||||
return request.post(URL_API_LOGOUT).finally(() => {
|
return r_logout().finally(() => {
|
||||||
removeToken()
|
removeToken()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -40,7 +37,7 @@ export const getUserInfo = async (): Promise<UserWithPowerInfoVo> => {
|
|||||||
export const requestUserInfo = async () => {
|
export const requestUserInfo = async () => {
|
||||||
let user: UserWithPowerInfoVo | null
|
let user: UserWithPowerInfoVo | null
|
||||||
|
|
||||||
await request.get<UserWithPowerInfoVo>(URL_API_USER_INFO).then((value) => {
|
await r_getInfo().then((value) => {
|
||||||
const response = value.data
|
const response = value.data
|
||||||
if (response.code === DATABASE_SELECT_SUCCESS) {
|
if (response.code === DATABASE_SELECT_SUCCESS) {
|
||||||
user = response.data
|
user = response.data
|
||||||
@@ -56,10 +53,10 @@ export const requestUserInfo = async () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getNickName = async () => {
|
export const getNickname = async () => {
|
||||||
const user = await getUserInfo()
|
const user = await getUserInfo()
|
||||||
|
|
||||||
return user.userInfo.nickName
|
return user.userInfo.nickname
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUsername = async () => {
|
export const getUsername = async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user