Update dependencies. Add page. Optimize code.

This commit is contained in:
2023-11-01 14:47:41 +08:00
parent aa295db6ae
commit b548fb8083
19 changed files with 734 additions and 515 deletions

1089
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,44 +15,44 @@
}, },
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.2.6", "@ant-design/icons": "^5.2.6",
"antd": "^5.8.6", "antd": "^5.10.3",
"axios": "^1.5.0", "axios": "^1.6.0",
"jwt-decode": "^3.1.2", "jwt-decode": "^4.0.0",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"match-sorter": "^6.3.1", "match-sorter": "^6.3.1",
"moment": "^2.29.4", "moment": "^2.29.4",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-router": "^6.15.0", "react-router": "^6.18.0",
"react-router-dom": "^6.15.0" "react-router-dom": "^6.18.0"
}, },
"devDependencies": { "devDependencies": {
"@svgr/core": "^8.1.0", "@svgr/core": "^8.1.0",
"@svgr/plugin-jsx": "^8.1.0", "@svgr/plugin-jsx": "^8.1.0",
"@types/jsdom": "^21.1.2", "@types/jsdom": "^21.1.4",
"@types/lodash": "^4.14.198", "@types/lodash": "^4.14.200",
"@types/node": "^20.5.9", "@types/node": "^20.8.10",
"@types/react": "^18.2.21", "@types/react": "^18.2.33",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.14",
"@typescript-eslint/eslint-plugin": "^6.6.0", "@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.6.0", "@typescript-eslint/parser": "^6.9.1",
"@vitejs/plugin-react": "^4.0.4", "@vitejs/plugin-react": "^4.1.0",
"eslint": "^8.48.0", "eslint": "^8.52.0",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^9.0.0",
"eslint-config-standard-with-typescript": "^39.0.0", "eslint-config-standard-with-typescript": "^39.1.1",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.29.0",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-promise": "^6.1.1", "eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3", "eslint-plugin-react-refresh": "^0.4.4",
"jsdom": "^22.1.0", "jsdom": "^22.1.0",
"prettier": "^3.0.3", "prettier": "^3.0.3",
"sass": "^1.66.1", "sass": "^1.69.5",
"stylelint-config-prettier": "^9.0.5", "stylelint-config-prettier": "^9.0.5",
"typescript": "^5.2.2", "typescript": "^5.2.2",
"unplugin-auto-import": "^0.16.6", "unplugin-auto-import": "^0.16.7",
"unplugin-icons": "^0.17.0", "unplugin-icons": "^0.17.1",
"vite": "^4.4.9" "vite": "^4.5.0"
} }
} }

1
src/assets/svg/group.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M620.8 611.2c67.2-38.4 115.2-112 115.2-195.2 0-124.8-99.2-224-224-224s-224 99.2-224 224c0 83.2 44.8 156.8 115.2 195.2-89.6 35.2-156.8 115.2-179.2 211.2-3.2 16 6.4 35.2 25.6 38.4H256c16 0 28.8-9.6 32-25.6 22.4-105.6 115.2-182.4 224-182.4s201.6 76.8 224 182.4c3.2 16 19.2 28.8 38.4 25.6 16-3.2 28.8-19.2 25.6-38.4-22.4-96-89.6-176-179.2-211.2zM352 416c0-89.6 70.4-160 160-160s160 70.4 160 160-70.4 160-160 160-160-70.4-160-160zM992 630.4c-12.8-64-54.4-115.2-118.4-144 35.2-32 54.4-76.8 54.4-128C928 265.6 857.6 192 768 192c-19.2 0-32 12.8-32 32s12.8 32 32 32c54.4 0 96 44.8 96 102.4 0 51.2-28.8 89.6-73.6 99.2-16 3.2-28.8 22.4-22.4 38.4 0 16 9.6 28.8 25.6 28.8 70.4 12.8 118.4 54.4 131.2 115.2 3.2 16 16 25.6 32 25.6h6.4c19.2 0 32-16 28.8-35.2zM252.8 499.2c6.4-19.2-6.4-35.2-22.4-41.6C188.8 448 160 409.6 160 358.4 163.2 300.8 201.6 256 256 256c19.2 0 32-12.8 32-32s-16-32-32-32c-89.6 0-156.8 70.4-156.8 166.4 0 51.2 19.2 96 51.2 128-60.8 28.8-105.6 80-118.4 144-3.2 16 6.4 35.2 25.6 38.4H64c16 0 28.8-9.6 32-25.6 12.8-60.8 60.8-102.4 131.2-115.2 16 0 25.6-12.8 25.6-28.8z" /></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
src/assets/svg/role.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M721.8 326.1c0-124.4-100.8-225.2-225.2-225.2S271.3 201.7 271.3 326.1c0 82.2 44 154.1 109.8 193.4-14.1 4.2-28.1 9.2-41.8 15-46.9 19.8-89.1 48.3-125.3 84.4s-64.6 78.3-84.4 125.3c-20.6 48.6-31 100.2-31 153.4 0 13.3 10.7 24 24 24s24-10.7 24-24c0-190.8 155.3-346.1 346.1-346.1 1 0 1.9-0.1 2.9-0.2h1c124.3 0.1 225.2-100.8 225.2-225.2z m-402.5 0c0-47.3 18.4-91.9 51.9-125.3 33.5-33.5 78-51.9 125.3-51.9s91.9 18.4 125.3 51.9c33.5 33.5 51.9 78 51.9 125.3s-18.4 91.9-51.9 125.3-78 51.9-125.3 51.9-91.9-18.4-125.3-51.9c-33.5-33.4-51.9-77.9-51.9-125.3zM905.3 679.7h-32.2v-18c0-76.6-62.4-139-139-139s-139 62.4-139 139v18h-23.8c-13.3 0-24 10.7-24 24v144.5c0 41.1 33.4 74.5 74.5 74.5h233c41.1 0 74.5-33.4 74.5-74.5V703.7c0-13.3-10.7-24-24-24z m-262.2-18c0-50.2 40.8-91 91-91s91 40.8 91 91v18h-182v-18z m238.2 186.4c0 14.6-11.9 26.5-26.5 26.5h-233c-14.6 0-26.5-11.9-26.5-26.5V727.7h286v120.4z" /><path d="M782.3 754.1h-88c-8.3 0-15 6.7-15 15s6.7 15 15 15h29v48.4c0 8.3 6.7 15 15 15s15-6.7 15-15v-48.4h29c8.3 0 15-6.7 15-15s-6.7-15-15-15z" /></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

4
src/global.d.ts vendored
View File

@@ -16,7 +16,6 @@ type RouteJsonObject = {
id?: string id?: string
element?: React.JSX.Element element?: React.JSX.Element
component?: React.ComponentType component?: React.ComponentType
children?: RouteJsonObject[]
name?: string name?: string
titlePrefix?: string titlePrefix?: string
title?: string title?: string
@@ -26,6 +25,7 @@ type RouteJsonObject = {
auth?: boolean auth?: boolean
permission?: boolean permission?: boolean
autoHide?: boolean autoHide?: boolean
children?: RouteJsonObject[]
} }
type RouteHandle = { type RouteHandle = {
@@ -57,7 +57,7 @@ type TokenVo = {
token: string token: string
} }
type UserWithInfoVo = { type UserWithPowerInfoVo = {
id: string id: string
username: string username: string
locking: boolean locking: boolean

View File

@@ -4,10 +4,11 @@ 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'
ReactDOM.createRoot(document.getElementById('root')!).render( ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode> <React.StrictMode>
<AntdConfigProvider locale={zh_CN}> <AntdConfigProvider theme={{ token: { colorPrimary: COLOR_MAIN } }} locale={zh_CN}>
<App /> <App />
</AntdConfigProvider> </AntdConfigProvider>
</React.StrictMode> </React.StrictMode>

View File

@@ -5,6 +5,7 @@ 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 LoadingMask from '@/components/common/LoadingMask'
const SystemFramework: React.FC = () => { const SystemFramework: React.FC = () => {
return ( return (
@@ -16,6 +17,7 @@ const SystemFramework: React.FC = () => {
{system.map((value) => { {system.map((value) => {
return value.menu ? ( return value.menu ? (
<SidebarItem <SidebarItem
end={value.id === 'system' ? true : undefined}
path={value.absolutePath} path={value.absolutePath}
icon={value.icon} icon={value.icon}
text={value.name} text={value.name}
@@ -27,7 +29,15 @@ const SystemFramework: React.FC = () => {
</Sidebar> </Sidebar>
</div> </div>
<div className={'right-panel'}> <div className={'right-panel'}>
<Suspense
fallback={
<>
<LoadingMask />
</>
}
>
<Outlet /> <Outlet />
</Suspense>
</div> </div>
</FitFullScreen> </FitFullScreen>
</> </>

View File

@@ -30,6 +30,7 @@ const ToolsFramework: React.FC = () => {
{user.map((value) => { {user.map((value) => {
return value.menu ? ( return value.menu ? (
<SidebarItem <SidebarItem
end={value.id === 'user' ? true : undefined}
path={value.absolutePath} path={value.absolutePath}
icon={value.icon} icon={value.icon}
text={value.name} text={value.name}

View File

@@ -0,0 +1,7 @@
import React from 'react'
const Group: React.FC = () => {
return <></>
}
export default Group

View File

@@ -0,0 +1,7 @@
import React from 'react'
const Role: React.FC = () => {
return <></>
}
export default Role

View File

@@ -0,0 +1,7 @@
import React from 'react'
const User: React.FC = () => {
return <></>
}
export default User

View File

@@ -0,0 +1,7 @@
import React from 'react'
const System: React.FC = () => {
return <></>
}
export default System

7
src/pages/user/index.tsx Normal file
View File

@@ -0,0 +1,7 @@
import React from 'react'
const User: React.FC = () => {
return <></>
}
export default User

View File

@@ -21,6 +21,8 @@ const home: RouteJsonObject[] = [
path: '/tools', path: '/tools',
absolutePath: '/tools', absolutePath: '/tools',
id: 'url-tools', id: 'url-tools',
name: '工具',
menu: true,
children: [ children: [
{ {
path: 'translation', path: 'translation',
@@ -29,9 +31,7 @@ const home: RouteJsonObject[] = [
name: '翻译', name: '翻译',
menu: true menu: true
} }
], ]
name: '工具',
menu: true
} }
] ]

View File

@@ -5,10 +5,44 @@ const user: RouteJsonObject[] = [
path: '', path: '',
absolutePath: '/system', absolutePath: '/system',
id: 'system', id: 'system',
component: React.lazy(() => import('@/pages/system')),
name: '系统设置', name: '系统设置',
icon: React.lazy(() => import('~icons/fatweb/setting.jsx')), icon: React.lazy(() => import('~icons/fatweb/setting.jsx')),
menu: true menu: true
}, },
{
path: 'user',
absolutePath: '/system/user',
id: 'system-user',
component: React.lazy(() => import('@/pages/system/User')),
name: '用户管理',
icon: React.lazy(() => import('~icons/fatweb/user.jsx')),
menu: true,
permission: true,
autoHide: true
},
{
path: 'role',
absolutePath: '/system/role',
id: 'system-role',
component: React.lazy(() => import('@/pages/system/Role')),
name: '角色管理',
icon: React.lazy(() => import('~icons/fatweb/role.jsx')),
menu: true,
permission: true,
autoHide: true
},
{
path: 'group',
absolutePath: '/system/group',
id: 'system-group',
component: React.lazy(() => import('@/pages/system/Group')),
name: '群组管理',
icon: React.lazy(() => import('~icons/fatweb/group.jsx')),
menu: true,
permission: true,
autoHide: true
},
{ {
path: '*', path: '*',
absolutePath: '*', absolutePath: '*',

View File

@@ -6,8 +6,8 @@ export const tools: RouteJsonObject[] = [
absolutePath: '/tools', absolutePath: '/tools',
id: 'tools', id: 'tools',
component: React.lazy(() => import('@/pages/tools')), component: React.lazy(() => import('@/pages/tools')),
icon: React.lazy(() => import('~icons/fatweb/home.jsx')),
name: '主页', name: '主页',
icon: React.lazy(() => import('~icons/fatweb/home.jsx')),
menu: true, menu: true,
auth: false auth: false
}, },

View File

@@ -5,6 +5,7 @@ const user: RouteJsonObject[] = [
path: '', path: '',
absolutePath: '/user', absolutePath: '/user',
id: 'user', id: 'user',
component: React.lazy(() => import('@/pages/user')),
name: '个人档案', name: '个人档案',
icon: React.lazy(() => import('~icons/fatweb/user.jsx')), icon: React.lazy(() => import('~icons/fatweb/user.jsx')),
menu: true menu: true

View File

@@ -1,5 +1,5 @@
import axios, { type AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios' import axios, { type AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import jwtDecode, { JwtPayload } from 'jwt-decode' import { jwtDecode, JwtPayload } from 'jwt-decode'
import { message } from 'antd' import { message } from 'antd'
import { getToken, removeToken, setToken } from '@/utils/common' import { getToken, removeToken, setToken } from '@/utils/common'
import { import {

View File

@@ -26,19 +26,21 @@ export const getLoginStatus = () => {
return getLocalStorage(STORAGE_TOKEN_KEY) !== null return getLocalStorage(STORAGE_TOKEN_KEY) !== null
} }
export const getUserInfo = async (): Promise<UserWithInfoVo> => { export const getUserInfo = async (): Promise<UserWithPowerInfoVo> => {
if (getLocalStorage(STORAGE_USER_INFO_KEY) !== null) { if (getLocalStorage(STORAGE_USER_INFO_KEY) !== null) {
return new Promise((resolve) => { return new Promise((resolve) => {
resolve(JSON.parse(getLocalStorage(STORAGE_USER_INFO_KEY) as string) as UserWithInfoVo) resolve(
JSON.parse(getLocalStorage(STORAGE_USER_INFO_KEY) as string) as UserWithPowerInfoVo
)
}) })
} }
return requestUserInfo() return requestUserInfo()
} }
export const requestUserInfo = async () => { export const requestUserInfo = async () => {
let user: UserWithInfoVo | null let user: UserWithPowerInfoVo | null
await request.get<UserWithInfoVo>(URL_API_USER_INFO).then((value) => { await request.get<UserWithPowerInfoVo>(URL_API_USER_INFO).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
@@ -46,7 +48,7 @@ export const requestUserInfo = async () => {
} }
}) })
return new Promise<UserWithInfoVo>((resolve, reject) => { return new Promise<UserWithPowerInfoVo>((resolve, reject) => {
if (user) { if (user) {
resolve(user) resolve(user)
} }
@@ -72,7 +74,7 @@ export const getPermissionPath = (): string[] => {
return [] return []
} }
const user = JSON.parse(s) as UserWithInfoVo const user = JSON.parse(s) as UserWithPowerInfoVo
const paths: string[] = [] const paths: string[] = []
user.menus.forEach((menu) => { user.menus.forEach((menu) => {
paths.push(menu.url) paths.push(menu.url)