Complete main UI #37

Merged
FatttSnake merged 192 commits from FatttSnake into dev 2024-02-23 16:31:17 +08:00
10 changed files with 113 additions and 85 deletions
Showing only changes of commit d9e1cbcfa3 - Show all commits

View File

@@ -1,13 +1,27 @@
import React from 'react' import React from 'react'
import router from '@/router' import { getRouter } from '@/router'
import LoadingMask from '@/components/common/LoadingMask' import LoadingMask from '@/components/common/LoadingMask'
export const AppContext = createContext<{ refreshRouter: () => void }>({
refreshRouter: () => undefined
})
const App: React.FC = () => { const App: React.FC = () => {
const [routerState, setRouterState] = useState(getRouter)
return ( return (
<> <>
<AppContext.Provider
value={{
refreshRouter: () => {
setRouterState(getRouter())
}
}}
>
<Suspense fallback={<LoadingMask />}> <Suspense fallback={<LoadingMask />}>
<RouterProvider router={router} /> <RouterProvider router={routerState} />
</Suspense> </Suspense>
</AppContext.Provider>
</> </>
) )
} }

View File

@@ -22,8 +22,13 @@ const AuthRoute = () => {
) )
} }
if (isLogin && lastMatch.pathname === '/login') { if (isLogin && lastMatch.pathname === '/login') {
return <Navigate to="/" /> return <Navigate to={'/'} />
} }
if (location.pathname.length > 1 && location.pathname.endsWith('/')) {
return <Navigate to={location.pathname.substring(0, location.pathname.length - 1)} />
}
return outlet return outlet
}, [ }, [
handle?.title, handle?.title,

View File

@@ -2,7 +2,7 @@ import React from 'react'
import Icon from '@ant-design/icons' import Icon from '@ant-design/icons'
import '@/assets/css/pages/home-framework.scss' import '@/assets/css/pages/home-framework.scss'
import { COLOR_FONT_SECONDARY } from '@/constants/common.constants' import { COLOR_FONT_SECONDARY } from '@/constants/common.constants'
import router from '@/router' import { getRouter } from '@/router'
import LoadingMask from '@/components/common/LoadingMask' import LoadingMask from '@/components/common/LoadingMask'
import HideScrollbar, { HideScrollbarElement } from '@/components/common/HideScrollbar' import HideScrollbar, { HideScrollbarElement } from '@/components/common/HideScrollbar'
@@ -54,7 +54,8 @@ export const HomeFrameworkContext = createContext<{
const HomeFramework: React.FC = () => { const HomeFramework: React.FC = () => {
const routeId = useMatches()[1].id const routeId = useMatches()[1].id
const routeChildren = router.routes[0].children?.find((value) => value.id === routeId)?.children const routeChildren = getRouter().routes[0].children?.find((value) => value.id === routeId)
?.children
const pathname = useLocation().pathname const pathname = useLocation().pathname

View File

@@ -8,8 +8,10 @@ import {
} from '@/constants/common.constants' } from '@/constants/common.constants'
import { utcToLocalTime } from '@/util/datetime' import { utcToLocalTime } from '@/util/datetime'
import { getUserInfo, login, setToken } from '@/util/auth' import { getUserInfo, login, setToken } from '@/util/auth'
import { AppContext } from '@/App'
const Login: React.FC = () => { const Login: React.FC = () => {
const { refreshRouter } = useContext(AppContext)
const [messageApi, contextHolder] = message.useMessage() const [messageApi, contextHolder] = message.useMessage()
const navigate = useNavigate() const navigate = useNavigate()
const [searchParams] = useSearchParams() const [searchParams] = useSearchParams()
@@ -32,6 +34,7 @@ const Login: React.FC = () => {
navigate('/') navigate('/')
} }
void getUserInfo().then((user) => { void getUserInfo().then((user) => {
refreshRouter()
notification.success({ notification.success({
message: '欢迎回来', message: '欢迎回来',
description: ( description: (

View File

@@ -1,6 +1,6 @@
import React from 'react' import React from 'react'
import '@/assets/css/pages/system-framework.scss' import '@/assets/css/pages/system-framework.scss'
import system from '@/router/system' import { getSystemRouteJson } from '@/router/system'
import FitFullScreen from '@/components/common/FitFullScreen' 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'
@@ -25,7 +25,7 @@ const SystemFramework: React.FC = () => {
} }
> >
<SidebarItemList> <SidebarItemList>
{system.map((value) => { {getSystemRouteJson().map((value) => {
return value.menu ? ( return value.menu ? (
<SidebarItem <SidebarItem
end={value.id === 'system' ? true : undefined} end={value.id === 'system' ? true : undefined}

View File

@@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import '@/assets/css/pages/tools-framework.scss' import '@/assets/css/pages/tools-framework.scss'
import user from '@/router/user' import user from '@/router/user'
import { hasPathPermission } from '@/util/auth' import { hasPathPermission } from '@/util/route'
import FitFullScreen from '@/components/common/FitFullScreen' 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'

View File

@@ -1,41 +1,10 @@
import React from 'react' import React from 'react'
import _ from 'lodash'
import system from '@/router/system' import system from '@/router/system'
import home from '@/router/home' import home from '@/router/home'
import user from '@/router/user' import user from '@/router/user'
import tools from '@/router/tools' import tools from '@/router/tools'
import { getAuthRoute, mapJsonToRoute, setTitle } from '@/util/route'
const mapJsonToRoute = (jsonObject: RouteJsonObject[]): RouteObject[] => {
return jsonObject.map((value) => ({
path: value.path,
id: value.id,
element: value.element,
Component: value.component,
handle: {
absolutePath: value.absolutePath,
name: value.name,
titlePrefix: value.titlePrefix,
title: value.title,
titlePostfix: value.titlePostfix,
icon: value.icon,
menu: value.menu,
auth: value.auth,
permission: value.permission,
autoHide: value.autoHide
},
children: value.children && mapJsonToRoute(value.children)
}))
}
const setTitle = (jsonObject: RouteJsonObject[], title: string): RouteJsonObject[] => {
return jsonObject.map((value) => {
if (!value.title) {
value.title = title
}
value.children && setTitle(value.children, title)
return value
})
}
const root: RouteJsonObject[] = [ const root: RouteJsonObject[] = [
{ {
@@ -80,7 +49,8 @@ const root: RouteJsonObject[] = [
component: React.lazy(() => import('@/pages/SystemFramework')), component: React.lazy(() => import('@/pages/SystemFramework')),
children: setTitle(system, '系统设置'), children: setTitle(system, '系统设置'),
name: '系统设置', name: '系统设置',
auth: true auth: true,
permission: true
}, },
{ {
path: '', path: '',
@@ -98,7 +68,4 @@ const root: RouteJsonObject[] = [
} }
] ]
const routes = mapJsonToRoute(root) export const getRouter = () => createBrowserRouter(mapJsonToRoute(getAuthRoute(_.cloneDeep(root))))
const router = createBrowserRouter(routes)
export default router

View File

@@ -1,4 +1,5 @@
import React from 'react' import React from 'react'
import { getAuthRoute } from '@/util/route'
const system: RouteJsonObject[] = [ const system: RouteJsonObject[] = [
{ {
@@ -18,7 +19,6 @@ const system: RouteJsonObject[] = [
name: '用户管理', name: '用户管理',
icon: React.lazy(() => import('~icons/fatweb/user.jsx')), icon: React.lazy(() => import('~icons/fatweb/user.jsx')),
menu: true, menu: true,
permission: true,
autoHide: true autoHide: true
}, },
{ {
@@ -29,7 +29,6 @@ const system: RouteJsonObject[] = [
name: '角色管理', name: '角色管理',
icon: React.lazy(() => import('~icons/fatweb/role.jsx')), icon: React.lazy(() => import('~icons/fatweb/role.jsx')),
menu: true, menu: true,
permission: true,
autoHide: true autoHide: true
}, },
{ {
@@ -40,7 +39,6 @@ const system: RouteJsonObject[] = [
name: '群组管理', name: '群组管理',
icon: React.lazy(() => import('~icons/fatweb/group.jsx')), icon: React.lazy(() => import('~icons/fatweb/group.jsx')),
menu: true, menu: true,
permission: true,
autoHide: true autoHide: true
}, },
{ {
@@ -51,7 +49,6 @@ const system: RouteJsonObject[] = [
name: '系统日志', name: '系统日志',
icon: React.lazy(() => import('~icons/fatweb/log.jsx')), icon: React.lazy(() => import('~icons/fatweb/log.jsx')),
menu: true, menu: true,
permission: true,
autoHide: true autoHide: true
}, },
{ {
@@ -61,4 +58,6 @@ const system: RouteJsonObject[] = [
} }
] ]
export const getSystemRouteJson = () => getAuthRoute(system, true)
export default system export default system

View File

@@ -121,39 +121,6 @@ export const getUsername = async () => {
return user.username return user.username
} }
export const getPermissionPath = (): string[] => {
const s = getLocalStorage(STORAGE_USER_INFO_KEY)
if (s === null) {
return []
}
const user = JSON.parse(s) as UserWithPowerInfoVo
const paths: string[] = []
user.menus.forEach((menu) => {
paths.push(menu.url)
})
return paths
}
export const hasPathPermission = (path: string) => {
return getPermissionPath().indexOf(path) !== -1
}
/*
export const getAuthRoute = (route: RouteJsonObject[]): RouteJsonObject[] => {
return route.map((value) => {
if (value.absolutePath) {
value.absolutePath
}
if (value.children) {
value.children = getAuthRoute(value.children)
}
return value
})
}
*/
export const getCaptchaSrc = () => { export const getCaptchaSrc = () => {
captcha = getCaptcha(300, 150, 4) captcha = getCaptcha(300, 150, 4)
return captcha.base64Src return captcha.base64Src

View File

@@ -1,3 +1,6 @@
import { getLocalStorage } from '@/util/browser.tsx'
import { STORAGE_USER_INFO_KEY } from '@/constants/common.constants.ts'
export const getRedirectUrl = (path: string, redirectUrl: string): string => { export const getRedirectUrl = (path: string, redirectUrl: string): string => {
return `${path}?redirect=${encodeURIComponent(redirectUrl)}` return `${path}?redirect=${encodeURIComponent(redirectUrl)}`
} }
@@ -11,3 +14,72 @@ export const getFullTitle = (data: _DataNode, preTitle?: string) => {
return data return data
} }
export const getPermissionPath = (): string[] => {
const s = getLocalStorage(STORAGE_USER_INFO_KEY)
if (s === null) {
return []
}
const user = JSON.parse(s) as UserWithPowerInfoVo
const paths: string[] = []
user.menus.forEach((menu) => {
paths.push(menu.url)
})
return paths
}
export const hasPathPermission = (path: string) => {
return getPermissionPath().indexOf(path) !== -1
}
export const getAuthRoute = (
route: RouteJsonObject[],
parentPermission: boolean = false
): RouteJsonObject[] => {
return route
.filter(
(value) =>
!(value.permission || parentPermission) || hasPathPermission(value.absolutePath)
)
.map((value) => {
if (value.children) {
value.children = getAuthRoute(value.children, parentPermission || value.permission)
}
return value
})
}
export const mapJsonToRoute = (jsonObject: RouteJsonObject[]): RouteObject[] => {
return jsonObject.map((value) => ({
path: value.path,
id: value.id,
element: value.element,
Component: value.component,
handle: {
absolutePath: value.absolutePath,
name: value.name,
titlePrefix: value.titlePrefix,
title: value.title,
titlePostfix: value.titlePostfix,
icon: value.icon,
menu: value.menu,
auth: value.auth,
permission: value.permission,
autoHide: value.autoHide
},
children: value.children && mapJsonToRoute(value.children)
}))
}
export const setTitle = (jsonObject: RouteJsonObject[], title: string): RouteJsonObject[] => {
return jsonObject.map((value) => {
if (!value.title) {
value.title = title
}
value.children && setTitle(value.children, title)
return value
})
}