diff --git a/.eslintrc.js b/.eslintrc.js index 65aacc04b8478288dfced070c1205d05d1806c00..19b83943a19f84826b5a9e6bfbd22e0879f1f447 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -20,5 +20,7 @@ module.exports = { sourceType: 'module', }, plugins: ['react', '@typescript-eslint'], - rules: {}, + rules: { + 'react/prop-types': 0, + }, }; diff --git a/config/defaultSettings.ts b/config/defaultSettings.ts index 731daf545e1963df6006d9ea88bf9e2bcf5af8e7..d4561524c4c4d102f705727f2178446a9b69d9af 100644 --- a/config/defaultSettings.ts +++ b/config/defaultSettings.ts @@ -7,7 +7,7 @@ type DefaultSettings = Partial & { }; const proSettings: DefaultSettings = { - logo: 'http://assets.jinxinapp.cn/img/logo.png', + logo: './src/assets/logo.png', // 拂晓蓝 primaryColor: '#4569D4', layout: 'side', diff --git a/config/mock/login.ts b/config/mock/login.ts index 4823fc13b78ebeb024709d60ca5cbc68a47ce916..930e0f65324939220e3b81d6ba0ca6539c9430d5 100644 --- a/config/mock/login.ts +++ b/config/mock/login.ts @@ -6,33 +6,33 @@ export default [ url: '/api/login', method: 'post', response: ({ body }: any) => { - const resObj: ResultType = { + const resObj: ResultType = { code: -1, message: '登陆失败', data: { authority: 'admin', name: 'admin', - avatar: 'http://assets.jinxinapp.cn/img/logo.png' + avatar: './src/assets/logo.png', }, }; resObj.data.loginType = body.loginType; - if ( body.loginType === 'account') { - resObj.data.username = body.username + if (body.loginType === 'account') { + resObj.data.username = body.username; if (body.username === 'admin' && body.password === 'admin') { - resObj.code = 0 - resObj.message = '登录成功' + resObj.code = 0; + resObj.message = '登录成功'; } else { - resObj.message = '登录失败, 用户名或者密码错误' + resObj.message = '登录失败, 用户名或者密码错误'; } } - if ( body.loginType === 'phone') { - resObj.data.mobile = body.mobile + if (body.loginType === 'phone') { + resObj.data.mobile = body.mobile; if (body.captcha === '1234') { - resObj.code = 0 - resObj.message = '登录成功' + resObj.code = 0; + resObj.message = '登录成功'; } else { - resObj.message = '登录失败, 验证码错误' + resObj.message = '登录失败, 验证码错误'; } } return resObj; diff --git a/config/mock/menu.ts b/config/mock/menu.ts index 8b0ffbbdb69849218ddfeeceaf5d90e0d46aea1d..fc1dc4884da7c0a5d614f7d84cc35df07b49596d 100644 --- a/config/mock/menu.ts +++ b/config/mock/menu.ts @@ -5,7 +5,7 @@ export default [ url: '/api/menu', method: 'get', response: ({ body }: any) => { - const resObj: ResultType = { + const resObj: ResultType = { code: 0, message: '菜单获取成功', data: { diff --git a/config/routes/index.ts b/config/routes/index.ts deleted file mode 100644 index 1dbd361bd239f76d77c6b11a36dea2d9a78b792f..0000000000000000000000000000000000000000 --- a/config/routes/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { lazy } from 'react'; -import type { RouteType } from './type'; - -const routes: RouteType[] = [ - { - path: '/login', - meta: { - title: '登录', - }, - component: lazy(() => import('@/pages/Login')), - }, - { - path: '/', - component: lazy(() => import('@/layouts/BasicLayout')), - routes: [ - { - path: '/home', - component: lazy(() => import('@/pages/Home')), - }, - { - path: '/admin', - component: lazy(() => import('@/layouts/BlankLayout')), - routes: [ - { - path: '/admin', - redirect: '/admin/test', - }, - { - path: '/admin/test', - component: lazy(() => import('@/pages/Admin/test')), - }, - ], - }, - ], - }, -]; - -export default routes; diff --git a/config/routes/index.tsx b/config/routes/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..586c8b204fa9db31637300bfe297d5fd27cce538 --- /dev/null +++ b/config/routes/index.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { lazy } from 'react'; +import type { RouteConfig } from 'react-router-config'; +import { Redirect } from 'react-router-dom'; + +const routes: RouteConfig[] = [ + { + path: '/', + component: lazy(() => import('@/layouts/BlankLayout')) as any, + routes: [ + { + path: '/', + exact: true, + // eslint-disable-next-line react/display-name + render: () => { + return ; + }, + }, + { + path: '/login', + component: lazy(() => import('@/pages/Login')), + }, + { + path: '/', + component: lazy(() => import('@/layouts/BasicLayout')) as any, + routes: [ + { + path: '/home', + component: lazy(() => import('@/pages/Home')), + }, + { + path: '/admin', + component: lazy(() => import('@/pages/Admin')) as any, + routes: [ + { + path: '/admin/test', + component: lazy(() => import('@/pages/Admin/test')), + }, + ], + }, + ], + }, + ], + }, +]; + +export default routes; diff --git a/config/routes/type.d.ts b/config/routes/type.d.ts deleted file mode 100644 index 2759e8df71f17209b44838e92a38259cf4634af3..0000000000000000000000000000000000000000 --- a/config/routes/type.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { ComponentType, FC, LazyExoticComponent } from "react"; - -export type RouteType = { - component?: LazyExoticComponent; - path?: string; - exact?: boolean; - redirect?: string; - authority?: string | string[]; - meta?: { - [key: string]: any; - }, - routes?: RouteType[]; -} \ No newline at end of file diff --git a/index.html b/index.html index e44ee7eb9c7acc8921a52bcd4fef5633ca45fc0a..3985b0ad27d9d24eed2d85431b2d1f9e6cd03e0a 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - + Vite App diff --git a/package.json b/package.json index daaa10bc68daa3a4b5c06da0e944e330b7f8cd5a..e4d7eb7652eef93c89005cf9a7864ef6edcb1a81 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@ant-design/pro-layout": "^6.9.0", "@types/lodash": "^4.14.173", "@types/qrcode.react": "^1.0.2", + "@types/react-router-config": "^5.0.3", "ahooks": "^2.10.9", "antd": "^4.16.13", "less": "^4.1.1", @@ -36,6 +37,7 @@ "react": "^17.0.2", "react-dom": "^17.0.0", "react-intl-hooks": "^1.0.11", + "react-router-config": "^5.1.1", "react-router-dom": "^5.3.0", "ts-node": "^10.2.1", "umi-request": "^1.4.0" diff --git a/src/assets/loading.gif b/src/assets/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..ebe0d72f76227bebfcb4fe5e9ac82cda963462e2 Binary files /dev/null and b/src/assets/loading.gif differ diff --git a/src/assets/logo.ico b/src/assets/logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..ad5f11588e117dc11f5238a17e18d650945cc4c0 Binary files /dev/null and b/src/assets/logo.ico differ diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1288bf2c29dea866ad3189b6df29d055aebb660e Binary files /dev/null and b/src/assets/logo.png differ diff --git a/src/components/Authorized/AuthorizedRoute.tsx b/src/components/Authorized/AuthorizedRoute.tsx index 731e8cd6e86e81801206f7c520ba550b61d73820..9340fb1fd2840f04a963c646a6770d3909f44237 100644 --- a/src/components/Authorized/AuthorizedRoute.tsx +++ b/src/components/Authorized/AuthorizedRoute.tsx @@ -1,11 +1,11 @@ -import { RouteType } from '@config/routes/type'; +import type { RouteConfig } from 'react-router-config'; import React from 'react'; import { Redirect, Route } from 'react-router-dom'; import Authorized from './Authorized'; import type { IAuthorityType } from './CheckPermissions'; type AuthorizedRouteProps = { - routes: RouteType[]; + routes: RouteConfig[]; currentAuthority: string; component: React.ComponentClass; render: (props: any) => React.ReactNode; diff --git a/src/components/Authorized/CheckPermissions.tsx b/src/components/Authorized/CheckPermissions.tsx index 021b7cb3c2ca71e176c61784143f057d447aed82..e636536f84862065599074ede27b1032907219fa 100644 --- a/src/components/Authorized/CheckPermissions.tsx +++ b/src/components/Authorized/CheckPermissions.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { CURRENT } from './renderAuthorize'; -// eslint-disable-next-line import/no-cycle import PromiseRender from './PromiseRender'; export type IAuthorityType = @@ -62,14 +61,18 @@ const checkPermissions = ( } // Deal with promise if (authority instanceof Promise) { - return ok={target} error={Exception} promise={authority} />; + return ( + ok={target} error={Exception} promise={authority} /> + ); } // Deal with function if (typeof authority === 'function') { const bool = authority(currentAuthority); // The return value after the function is executed is Promise if (bool instanceof Promise) { - return ok={target} error={Exception} promise={bool} />; + return ( + ok={target} error={Exception} promise={bool} /> + ); } if (bool) { return target; @@ -81,7 +84,11 @@ const checkPermissions = ( export { checkPermissions }; -function check(authority: IAuthorityType, target: T, Exception: K): T | K | React.ReactNode { +function check( + authority: IAuthorityType, + target: T, + Exception: K, +): T | K | React.ReactNode { return checkPermissions(authority, CURRENT, target, Exception); } diff --git a/src/components/GlobalHeader/AvatarDropdown.tsx b/src/components/GlobalHeader/AvatarDropdown.tsx index 831bab4ac174252074807ceeebc56134d9a07a05..e02d1d9ac0f445638bc054e7441fe0d70dd14c38 100644 --- a/src/components/GlobalHeader/AvatarDropdown.tsx +++ b/src/components/GlobalHeader/AvatarDropdown.tsx @@ -4,7 +4,7 @@ import { UserOutlined, } from '@ant-design/icons'; import { Avatar, Dropdown, Menu, Spin } from 'antd'; -import { Observer, useLocalStore } from 'mobx-react'; +import { Observer } from 'mobx-react'; import React from 'react'; import { localeLogin } from '@/stores/login'; import styles from './index.module.less'; @@ -46,7 +46,7 @@ const AvatarDropdown: React.FC = ({ menu = true }) => { ); - const currentUser = localeLogin.currentUser; + const currentUser: any = localeLogin.currentUser; return ( @@ -82,11 +82,3 @@ const AvatarDropdown: React.FC = ({ menu = true }) => { }; export default AvatarDropdown; -// const AvatarDropdown: React.FC = ({ onMenuClick, menu=true }) => { - -// return ( -//
2
-// ); -// }; - -// export default AvatarDropdown; diff --git a/src/components/Loading/index.tsx b/src/components/Loading/index.tsx index 616fd167a06899ef991c2d479d97d730a8347443..65672e2c25bd0fee709d2420b1ab552650aeae40 100644 --- a/src/components/Loading/index.tsx +++ b/src/components/Loading/index.tsx @@ -1,11 +1,12 @@ import React from 'react'; import { Image } from 'antd'; -const Loading: React.FC = () => { +const Loading: React.FC<{ imgUrl?: string }> = (props) => { + const { imgUrl } = props; return (
{ ); }; +Loading.defaultProps = { + imgUrl: './src/assets/loading.gif', +}; + export default Loading; diff --git a/src/components/RouterView/index.tsx b/src/components/RouterView/index.tsx index a00e41d1d98df5c1605380f2654489b0cd0608fe..030fea4b4be32c58a8b19eba4f66d1b5137b9833 100644 --- a/src/components/RouterView/index.tsx +++ b/src/components/RouterView/index.tsx @@ -1,37 +1,14 @@ import React, { Suspense } from 'react'; -import { Route, HashRouter, Switch } from 'react-router-dom'; +import { HashRouter, Switch } from 'react-router-dom'; +import { renderRoutes } from 'react-router-config'; import routes from '@config/routes'; -import Loading from '@/components/Loading' +import Loading from '@/components/Loading'; const RouterView = () => { return ( // 建议使用 HashRouter }> - - - {routes.map( - ({ path, component: ComponentName, exact = true, routes = [] }, key) => { - return ( - { - //登录情况下 - if (true) { - return ( - ComponentName && ( - - ) - ); - } - }} - /> - ); - }, - )} - - + {renderRoutes(routes)} ); }; diff --git a/src/hooks/UseRouteChild.tsx b/src/hooks/UseRouteChild.tsx deleted file mode 100644 index e3a97f1fb04093c71a97425f2869e58ade549933..0000000000000000000000000000000000000000 --- a/src/hooks/UseRouteChild.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import { Route, Redirect } from 'react-router-dom'; -import type { RouteType } from '@config/routes/type'; - -const UseRouteChild: React.FC<{ routes: RouteType[] }> = (props) => { - const { routes } = props; - const renderRoute = (val: RouteType[]) => ( - <> - {val?.map( - ({ - path, - component: ComponentName, - exact = true, - redirect, - routes: cRoutes, - }) => { - return ( - { - if (redirect) { - return ; - } - if (ComponentName) { - return ; - } - }} - /> - ); - }, - )} - - ); - - return <>{renderRoute(routes)}; -}; - -export default UseRouteChild; diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx index 27070e84a1d641b01d2eeeb3b64aaba325e3cbe3..d0269a7a899d052a03f30d40665a1e18a907926a 100644 --- a/src/layouts/BasicLayout.tsx +++ b/src/layouts/BasicLayout.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { Suspense, useEffect, useState } from 'react'; import { DefaultFooter, MenuDataItem, @@ -7,20 +7,21 @@ import { SettingDrawer, } from '@ant-design/pro-layout'; import ProLayout from '@ant-design/pro-layout'; -import UseRouteChild from '@/hooks/UseRouteChild'; +import { renderRoutes } from 'react-router-config'; import '@ant-design/pro-layout/dist/layout.css'; -import { RouteType } from '@config/routes/type'; import { GithubOutlined } from '@ant-design/icons'; import { queryMenu } from '@/services/global'; import { Link, useHistory, useLocation } from 'react-router-dom'; -import { Button, Input, Result } from 'antd'; +import { Button, Input } from 'antd'; import { useFormatMessage } from 'react-intl-hooks'; import RightContent from '@/components/GlobalHeader/RightContent'; import proSettings from '@config/defaultSettings'; import Authorized from '@/utils/Authorized'; import { getAuthorityFromRouter } from '@/utils/untils'; import NotFound from '@/components/NotFound'; -import loaclRoutes from '@config/routes' +import loaclRoutes from '@config/routes'; +import type { RouteConfig } from 'react-router-config'; +import Loading from '@/components/Loading'; const defaultFooterDom = ( item) as MenuDataItem[]; -const BasicLayout: React.FC<{ routes: RouteType[] }> = (props) => { - const { routes } = props; +const BasicLayout: React.FC<{ route: RouteConfig }> = (props) => { + const { route } = props; const [menuData, setMenuData] = useState([]); const [keyWord, setKeyWord] = useState(''); const [settings, setSetting] = useState | undefined>( @@ -154,7 +155,7 @@ const BasicLayout: React.FC<{ routes: RouteType[] }> = (props) => { }, ...routers, ]} - itemRender={(route, params, routes, paths) => { + itemRender={(route, params, routes) => { const first = routes.indexOf(route) === 0; return first ? ( {route.breadcrumbName} @@ -212,7 +213,11 @@ const BasicLayout: React.FC<{ routes: RouteType[] }> = (props) => { /> } > - {UseRouteChild({ routes })} + + }> + {renderRoutes(route.routes)} + + = (props) => { - const { routes } = props; - return <>{UseRouteChild({ routes })}; +const Layout: React.FC<{ route: RouteConfig }> = (props) => { + const { route } = props; + return <>{renderRoutes(route.routes)}; }; export default Layout; diff --git a/src/pages/Admin/index.tsx b/src/pages/Admin/index.tsx index bc429fb8c7470881270ce2737ef4de7c7c833e07..49fb73a5605ce943bc1073aed2fc95c4c535db18 100644 --- a/src/pages/Admin/index.tsx +++ b/src/pages/Admin/index.tsx @@ -1,13 +1,12 @@ -import UseRouteChild from '@/hooks/UseRouteChild'; -import ProCard from '@ant-design/pro-card'; -import { PageContainer } from '@ant-design/pro-layout'; -import { RouteType } from '@config/routes/type'; import React from 'react'; +import { renderRoutes } from 'react-router-config'; +import type { RouteConfig } from 'react-router-config'; -const Home: React.FC<{ routes: RouteType[] }> = (props) => { +const Home: React.FC<{ route: RouteConfig }> = (props) => { + const { route } = props; return ( <> - Admin + <>{renderRoutes(route.routes)} ); }; diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx index afb8b209bbc4fe13fe62e581df7b88110d5c3418..2acd168ff802a65399ec6af3fd914512e43cfd12 100644 --- a/src/pages/Login/index.tsx +++ b/src/pages/Login/index.tsx @@ -78,10 +78,10 @@ const Login: React.FC = () => { postLogin({ ...val, loginType }) .then((res) => { setBtnLoading(false); - setAuthority(res.data?.authority) - localeLogin.saveCurrentUser(res?.data) + setAuthority(res.data?.authority); + localeLogin.saveCurrentUser(res?.data); message.success(res.message || '登陆成功'); - history.push('/home') + history.push('/home'); }) .finally(() => { setBtnLoading(false); @@ -104,7 +104,7 @@ const Login: React.FC = () => { style={{ height: '100%' }} >