vite-react18-admin基于react+arcoDesign极简后台管理系统

#1

react-arco-admin:基于vite4+react18+arco-design+zustand4搭建后台管理系统模板。

004360%E6%88%AA%E5%9B%BE20231016070804655

005360%E6%88%AA%E5%9B%BE20231016071515087

react18-admin 支持暗夜+亮色主题模式。

026360%E6%88%AA%E5%9B%BE20231016083119704

react18-admin支持自定义主题配色、分栏+水平+垂直布局样式。

005360%E6%88%AA%E5%9B%BE20231016072811892

使用技术

  • 编辑器:vscode
  • 框架技术:react18+vite4+react-router-dom+zustand4+mockjs
  • 组件库:ArcoDesign (字节跳动react组件库)
  • 路由插件:react-router-dom^6.16.0
  • 状态管理:zustand^4.4.1
  • 模拟数据:mockjs^1.1.0
  • 模拟请求:axios^1.5.1
  • 图表库:bizcharts^4.1.22
  • 编辑器组件:@wangeditor/editor-for-react^1.0.6
  • markdown编辑器:@uiw/react-md-editor^3.23.6
  • 请求进度插件:nprogress^0.2.0

007360%E6%88%AA%E5%9B%BE20231016073105027

007360%E6%88%AA%E5%9B%BE20231016073135609

项目结构

使用vite4构建工具创建react18项目,遵循react18 hooks编码方式。

360%E6%88%AA%E5%9B%BE20231017081226615

p1

App.jsx模板

/**
 * 入口模板
 * @author Hs
*/

import { useEffect, useMemo } from 'react'
import { HashRouter } from 'react-router-dom'
// 通过 ConfigProvider 组件实现国际化
import { ConfigProvider } from '@arco-design/web-react'
// 引入语言包
import enUS from '@arco-design/web-react/es/locale/en-US'
import zhCN from '@arco-design/web-react/es/locale/zh-CN'
import zhTW from '@arco-design/web-react/es/locale/zh-TW'

import { AuthRouter } from '@/hooks/useRoutes'
import { appStore } from '@/store/app'

// 引入路由配置
import Router from './routers'

function App() {
    const { lang, config: { mode, theme }, setMode, setTheme } = appStore()

    const locale = useMemo(() => {
        switch(lang) {
            case 'en':
                return enUS
            case 'zh-CN':
                return zhCN
            case 'zh-TW':
                return zhTW
            default:
                return zhCN
        }
    }, [lang])

    useEffect(() => {
        setMode(mode)
        setTheme(theme)
    }, [])

    return (
        <ConfigProvider locale={locale}>
            <HashRouter>
                <AuthRouter>
                    <Router />
                </AuthRouter>
            </HashRouter>
        </ConfigProvider>
    )
}

export default App

公共模板布局

image

支持分栏+水平+垂直布局样式。

image

/**
 * Layout布局模板
 * @author YXY
*/

import { useMemo } from 'react'
import { appStore } from '@/store/app'

import Columns from './template/columns'
import Vertical from './template/vertical'
import Transverse from './template/transverse'

function Layout() {
    const { config: { skin, layout } } = appStore()

    // 布局模板
    const LayoutComponent = useMemo(() => {
        switch(layout) {
            case 'columns':
                return Columns
            case 'vertical':
                return Vertical
            case 'transverse':
                return Transverse
            default:
                return Columns
        }
    }, [layout])
    
    return (
        <div className="radmin__container">
            <LayoutComponent />
        </div>
    )
}

export default Layout

009360%E6%88%AA%E5%9B%BE20231016074313123

009360%E6%88%AA%E5%9B%BE20231016074512237

009360%E6%88%AA%E5%9B%BE20231016074410361

010360%E6%88%AA%E5%9B%BE20231016075824111

011360%E6%88%AA%E5%9B%BE20231016080157911

012360%E6%88%AA%E5%9B%BE20231016080511629

015360%E6%88%AA%E5%9B%BE20231016080837909

015360%E6%88%AA%E5%9B%BE20231016080858420

018360%E6%88%AA%E5%9B%BE20231016081046837

020360%E6%88%AA%E5%9B%BE20231016082812298

022360%E6%88%AA%E5%9B%BE20231016082846185

路由管理react-router配置

image

/**
 * @title    react-router v6路由配置
 * @author   Hs  Q:282310962
*/

import { useRoutes, Navigate } from 'react-router-dom'

import Error from '@views/error/404'

// 批量导入modules路由
const modules = import.meta.glob('./modules/*.jsx', { eager: true })
const patchRoutes = Object.keys(modules).map(key => modules[key].default).flat()

// useRoutes集中式路由配置
export const routes = [
    {
        path: '/',
        element: <Navigate to="/home" replace={true} />,
        meta: {
            isWhite: true // 路由白名单
        }
    },
    ...patchRoutes,
    // 404模块 path="*"不能省略
    {
        path: '*',
        element: <Error />,
        meta: {
            isWhite: true
        }
    }
]

const Router = () => useRoutes(routes)

export default Router

路由配置参数如下:

/**
 * @description 路由参数说明
 * @param path ==> 路由地址标识
 * @param key ==> 用于Menu组件跳转路由地址
 * @param redirect ==> 重定向地址
 * @param element ==> 视图页面路径
 * 菜单信息(meta)
 *         @param meta.icon ==> 菜单图标
 *         @param meta.title ==> 菜单标题
 *         @param meta.name ==> i18n国际化标题
 *         @param meta.roles ==> 页面权限 ['admin', 'dev', 'test']
 *         @param meta.isAuth ==> 是否需要验证
 *         @param meta.isHidden ==> 是否隐藏页面
 *         @param meta.isAffix ==> 是否固定标签(tabs标签栏不能关闭)
 * */

路由菜单模板

image

如上图:在分栏/垂直/水平布局模板中,使用不同的路由菜单。

/**
 * 路由菜单模板
*/

import './index.scss'
import { useState, useMemo, useEffect } from 'react'
import { useNavigate, useLocation } from 'react-router-dom'
import { Menu } from '@arco-design/web-react'
import Icon from '@components/Icon'
import RouteSubMenu from './submenu'
import { routes } from '@/routers'
import { getCurrentRootRoute, findParentRoute } from '@/hooks/useRoutes'
import Locales from '@/locales'

export default function RouteMenu(props) {
    const {
        // 菜单类型(垂直vertical 水平菜单horizontal 弹出pop)
        mode = 'vertical',
        // 菜单风格('light' | 'dark')
        theme = 'light',
        // 是否开启一级路由菜单
        rootRouteEnable = false,

        style = {}
    } = props

    const navigate = useNavigate()
    const { pathname } = useLocation()
    const t = Locales()
    const [openKeys, setOpenKeys] = useState([])
    const rootRoute = getCurrentRootRoute()
    const filterRoutes = routes.filter(item => !item?.meta?.isWhite)

    const menuRoutes = useMemo(() => {
        if(rootRouteEnable) {
            return filterRoutes
        }
        // 过滤一级菜单
        return filterRoutes.find(item => item.path == rootRoute && item.children)?.children
    }, [pathname])

    useEffect(() => {
        setOpenKeys(getKeys(pathname))
    }, [pathname])

    // 获取选中菜单路由keys数组
    const getKeys = (key) => {
        return findParentRoute(menuRoutes, key)?.map(item => item?.key)
    }

    const handleNavigate = (key) => {
        const reg = /[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/
        if(reg.test(key)) {
            window.open(key)
        }else {
            navigate(key)
        }
    }

    return (
        <Menu
            className="ra__menus"
            mode={mode}
            theme={theme}
            selectedKeys={[pathname]}
            openKeys={openKeys}
            levelIndent={28}
            style={{ ...style }}
            onClickMenuItem={handleNavigate}
            onClickSubMenu={(_, openKeys) => {
                setOpenKeys(openKeys)
            }}
        >
            { menuRoutes.map(item => {
                if(item?.children) {
                    return RouteSubMenu(item, t)
                }
                return (
                    !item?.meta?.isHidden &&
                    <Menu.Item className="ra__menuItem" key={item.redirect || item.key}>
                        { item?.meta?.icon && <Icon name={item.meta.icon} size={18} style={{marginRight: 10}} /> }
                        { item?.meta?.name && <span>{t[item.meta.name]}</span> }
                    </Menu.Item>
                )
            })}
        </Menu>
    )
}

https://juejin.cn/post/7290800838623789112

Okr,以上就是react18 hooks+arcoDesign开发管理后台的一些实战分享。