基于react18+arco+zustand通用后台管理系统React18Admin

news2024/12/28 19:30:18

React-Arco-Admin轻量级后台管理系统解决方案

基于vite4构建react18后台项目ReactAdmin。使用了react+arco-design+zustand+bizcharts等技术架构非凡后台管理框架。支持 dark/light主题、i18n国际化、动态路由鉴权、3种经典布局、tabs路由标签 等功能。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

技术框架

  • 编辑器:Vscode
  • 使用技术:react18+vite4+react-router+zustand+axios
  • 组件库:arco-design (字节前端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

在这里插入图片描述
在这里插入图片描述

特点

  • 基于vite4.x搭建react18后台系统
  • 使用最新前端技术栈react18、zustand、bizcharts、react-router
  • 搭配字节react组件库arco.design
  • 支持中英文/繁体国际化
  • 支持动态路由权限验证
  • 支持动态tabs标签栏菜单
  • 内置多种通用模板布局

在这里插入图片描述
在这里插入图片描述

项目结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

react-admin通用布局模板

在这里插入图片描述

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

在这里插入图片描述

/**
 * 主布局模板
 * @author Hs Q:282310962
*/

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

react-router-dom路由管理

在这里插入图片描述

/**
 * @title    react-router-dom v6路由配置管理
 * @author    andy
*/

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

lazyload.jsx懒加载

import { Suspense } from 'react'
import { Spin } from '@arco-design/web-react'
import NprogressLoading from './nprogress'

// 加载提示
const SpinLoading = () => {
    return (
        <Spin
            tip='loading...'
            style={{
                width: '100%'
            }}
        />
    )
}

// 延迟加载
const lazyload = LazyComponent => {
    // React 16.6 新增了<Suspense>组件,懒加载的模式需要我们给他加上一层 Loading的提示加载组件
    // return <Suspense fallback={<SpinLoading />}><LazyComponent /></Suspense>
    return <Suspense fallback={<NprogressLoading />}><LazyComponent /></Suspense>
}

export default lazyload

nprogress.jsx加载进度条

import { Component } from 'react'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

export default class NprogressLoading extends Component {
    constructor(props) {
        super(props)
        NProgress.set(.4)
        NProgress.start()
    }

    componentDidMount() {
        NProgress.done()
    }

    render() {
        return <div />
    }
}
/**
 * 主路由配置
 * @author Hs
*/

import { lazy } from 'react'
import {
    IconHome, IconDashboard, IconLink, IconCommand, IconUserGroup, IconLock,
    IconMenu, IconSafe, IconBug, IconHighlight, IconUnorderedList, IconStop
} from '@arco-design/web-react/icon'
import Layout from '@/layouts'
import Blank from '@/layouts/blank'
import lazyload from '../lazyload'

export default [
    /*首页模块*/
    {
        path: '/home',
        key: '/home', // 用于Menu组件跳转路由地址
        element: <Layout />,
        meta: {
            // icon: 've-icon-home', // 菜单图标
            icon: <IconHome />,
            name: 'layout__main-menu__home', // i18n国际化标题
            title: '主页',
            isAuth: true, // 需要鉴权
            isHidden: false, // 是否隐藏菜单
            isAffix: true // 固定tabview标签栏(不可关闭)
        },
        children: [
            {
                key: '/home',
                index: true,
                element: lazyload(lazy(() => import('@views/home'))),
                meta: {
                    // icon: 've-icon-home',
                    icon: <IconHome />,
                    name: 'layout__main-menu__home-index',
                    title: '首页',
                    isAuth: true
                }
            },
            // 工作台
            {
                path: 'dashboard',
                key: '/home/dashboard',
                element: lazyload(lazy(() => import('@views/home/dashboard'))),
                meta: {
                    // icon: 've-icon-computer',
                    icon: <IconDashboard />,
                    name: 'layout__main-menu__home-workplace',
                    title: '工作台',
                    isAuth: true
                }
            },
            // 外部链接
            {
                path: 'https://react.dev/',
                key: 'https://react.dev/',
                meta: {
                    // icon: 've-icon-clip',
                    icon: <IconLink />,
                    name: 'layout__main-menu__home-apidocs',
                    title: 'react.js官方文档',
                    rootRoute: '/home'
                }
            }
        ]
    },

    /*组件模块*/
    {
        ...
    },

    /*用户管理模块*/
    {
        ...
    },

    /*权限模块*/
    {
        ...
    },

    /*错误模块*/
    {
        ...
    }
]

路由配置参数:

/**
 * @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标签栏不能关闭)
 * */

react18路由菜单RouterMenu

在这里插入图片描述
如上图:react-admin提供了三种不同menu风格样式。

<RouteMenu rootRouteEnable={false} />

<RouteMenu rootRouteEnable />

<RouteMenu rootRouteEnable mode="horizontal" />

Menu.jsx路由模板

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

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>
    )
}

Zustand:基于react新状态管理库

在这里插入图片描述

/**
 * react18状态管理库Zustand4,中间件persist本地持久化存储
*/
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'
import { generate, getRgbStr } from '@arco-design/color'

export const appStore = create(
    persist(
        (set, get) => ({
            // 语言(中文zh-CN 英文en 繁体字zh-TW)
            lang: 'zh-CN',
            // 角色类型 roles: ['admin'] / roles: ['admin', 'dev'] / roles: ['dev', test']
            roles: ["dev"],
            // 配置信息
            config: {
                // 布局(分栏columns 纵向vertical 横向transverse)
                layout: 'columns',
                // 模式(亮色light - 暗黑dark)
                mode: 'light',
                // 主题色
                theme: '#3491FA',
                // 是否折叠菜单
                collapsed: false,
                // 开启面包屑导航
                breadcrumb: true,
                // 开启标签栏
                tabsview: true,
                tabRoutes: [],
                // 显示搜索
                showSearch: true,
                // 显示全屏
                showFullscreen: true,
                // 显示语言
                showLang: true,
                // 显示公告
                showNotice: true,
                // 显示底部
                showFooter: false
            },
            
            // 更新配置
            updateConfig: (key, value) => set({
                config: { ...get().config, [key]: value }
            }),
            // 设置角色
            setRoles: (roles) => set({roles}),
            // 设置多语言
            setLang: (lang) => set({lang}),
            // 设置主题模式
            setMode: (mode) => {
                if(mode == 'dark') {
                    // 设置为暗黑主题
                    document.body.setAttribute('arco-theme', 'dark')
                }else {
                    // 恢复亮色主题
                    document.body.removeAttribute('arco-theme')
                }
                get().updateConfig('mode', mode)
            },
            // 设置主题样式
            setTheme: (theme) => {
                const colors = generate(theme, { list: true })
                colors.map((item, index) => {
                    const rgbStr = getRgbStr(item)
                    document.body.style.setProperty(`--arcoblue-${index + 1}`, rgbStr)
                })
                get().updateConfig('theme', theme)
            }
        }),
        {
            name: 'appState',
            // name: 'app-store', // name of the item in the storage (must be unique)
            // storage: createJSONStorage(() => sessionStorage), // by default, 'localStorage'
        }
    )
)

react多语言配置i18n

在这里插入图片描述

在这里插入图片描述

/**
 * 国际化配置
 * @author YXY
 */

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

// 引入语言配置
import enUS from './en-US'
import zhCN from './zh-CN'
import zhTW from './zh-TW'

export const locales = {
    'en': enUS,
    'zh-CN': zhCN,
    'zh-TW': zhTW
}

export default (locale) => {
    const appState = appStore()
    const lang = appState.lang || 'zh-CN'

    return (locale || locales)[lang] || {}
}

lang.jsx语言配置

import { Dropdown, Menu, Button } from '@arco-design/web-react'
import Icon from '@components/Icon'
import { appStore } from '@/store/app'

export default function Lang() {
    const { lang, setLang } = appStore()

    const handleLang = val => {
        setLang(val)
    }

    return (
        <Dropdown
            position="bottom"
            droplist={
                <Menu className="radmin__dropdownLang" defaultSelectedKeys={[lang]} onClickMenuItem={handleLang}>
                    <Menu.Item key='zh-CN'>简体中文 <span>zh-CN</span></Menu.Item>
                    <Menu.Item key="zh-TW">繁体字 <span>zh-TW</span></Menu.Item>
                    <Menu.Item key="en">英文 <span>en</span></Menu.Item>
                </Menu>
            }
        >
            <Button
                shape="circle"
                size="small"
                icon={<Icon name="ve-icon-lang" />}
            />
        </Dropdown>
    )
}

Tabs路由菜单栏

在这里插入图片描述

<Tabs
    activeTab={pathname}
    editable
    showAddButton={false}
    onDeleteTab={key => delTabs(key)}
>
    { tabRoutes.map(item => (
        <Tabs.TabPane
            closable={!item?.meta?.isAffix}
            key={item?.redirect || item?.key}
            title={
                <Dropdown
                    trigger='contextMenu'
                    position='bl'
                    droplist={
                        <Menu className="ra__dropdownContext" onClickMenuItem={(key, e) => handleClickMenuItem(key, e, item)}>
                            <Menu.Item key="close" disabled={item?.meta?.isAffix}><Icon name="ve-icon-close" />{t['tabview__contextmenu-close']}</Menu.Item>
                            <Menu.Item key="closeLeft" disabled={isFirstTab()}><Icon name="ve-icon-prev" />{t['tabview__contextmenu-closeleft']}</Menu.Item>
                            <Menu.Item key="closeRight" disabled={isLastTab()}><Icon name="ve-icon-next" />{t['tabview__contextmenu-closeright']}</Menu.Item>
                            <Menu.Item key="closeOther"><Icon name="ve-icon-reset" />{t['tabview__contextmenu-closeother']}</Menu.Item>
                            <Menu.Item key="closeAll"><Icon name="ve-icon-close-circle-o" />{t['tabview__contextmenu-closeall']}</Menu.Item>
                        </Menu>
                    }
                    onVisibleChange={visible=>handleOpenContextMenu(visible, item)}
                >
                    <span className="ra__tabsview-title" onClick={() => navigate(item?.redirect || item?.key)}>
                        <TabIcon path={item?.key} />
                        { t[item?.meta?.name] }
                    </span>
                </Dropdown>
            }
        />
    ))}
</Tabs>

好了,以上就是react18+vite4+arco构建后台系统模板的一些分享了。

webchat-react基于react18+arco网页版聊天实例

electron-chatgpt基于electron25+vite4仿制ChatGPT模板

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1106058.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pip install huggingface_hub时报错

pip install huggingface_hub时报错&#xff1a; 可以尝试&#xff1a;pip install --upgrade huggingface_hub 进行安装 方法参考了&#xff1a;https://blog.csdn.net/m0_72295867/article/details/132060750

vue.js - 断开发送的请求,解决接口重复请求数据错误问题(vue中axios多次相同请求中断上一个)

描述 进入页面时第一个接口还在请求,立即切换tab请求第二个接口。但是第二个接口响应比第一个接口响应快,页面展示的时第一个接口的数据,如图: 解决方法 判断如果是相同的接

谷歌浏览器跨域及--disable-web-security无效解决办法

谷歌浏览器跨域设置 &#xff08;1&#xff09;创建一个目录&#xff0c;例如我在C盘创建MyChromeDevUserData文件夹 &#xff08;2&#xff09; 在桌面选择谷歌浏览器右键 -> 属性 -> 快捷方式 -> 目标&#xff0c;添加--disable-web-security --user-data-dirC:\M…

第六届物业管理创新发展论坛在深召开,鹏业受邀参加并发表主题演讲

10月12日至14日&#xff0c;由中国物业管理协会&#xff08;以下简称“中物协”&#xff09;主办&#xff0c;物业管理行业唯一报备商务部的国际性展会——2023中国国际物业管理产业博览会&#xff08;以下简称“物博会”&#xff09;在深圳会展中心隆重举行。 本届物博会同期还…

Docker是一个流行的容器化平台,用于构建、部署和运行应用程序。

文章目录 Web应用程序数据库服务器微服务应用开发环境持续集成和持续部署 (CI/CD)应用程序依赖项云原生应用程序研究和教育 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;…

基于PHP的创意设计分享系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

Cron表达式每月20号晚18点执行

Cron表达式每月20号晚18点执行 0 0 18 20 * ?验证正确性

linux性能分析(一)如何查看网络的性能指标

一 如何查看网络的性能指标 说明&#xff1a; 以下案例中的相关命令只是粗略讲解,后续会有针对性的细讲补充&#xff1a; 各个案例通过不同维度衡量网络的性能指标 ① 如何进行性能分析 思考&#xff1a;如何进行性能分析?1、前提&#xff1a;一定是系统出现不符合预期的…

MS35774,高精度、低噪声的两相步进电机驱动芯片

兼容替代ADI的TMC2225&#xff08;方案替代&#xff09;.TMC2208&#xff08;P2P&#xff09;&#xff0c;车规MS35774A 低噪声 256 细分微步进电机驱动 MS35774/MS35774A 是一款高精度、低噪声的两相步进 电机驱动芯片&#xff0c;芯片内置功率 MOSFET &#xff0c;长时…

Flutter之Widget生命周期

目录 初始化构造函数initStatedidChangeDependencies 运行时builddidUpdateWidget 组件移除deactivatedisposereassemble 函数生命周期说明&#xff1a;实际场景App生命周期 前言&#xff1a;生命周期是一个组件加载到卸载的整个周期&#xff0c;熟悉生命周期可以让我们在合适的…

Android11 移植memtester压测内存

需求如题&#xff0c;从网上下载了memtest源码压缩包&#xff0c;准备放到系统源码编译&#xff0c;然后push到板子上执行&#xff0c;结果&#xff0c;编译出来一堆问题&#xff0c;报build err。 做如下代码改动&#xff1a; external/memtester-4.5.1/Android.mk | 16 exte…

绝地求生msvcp140.dll丢失的解决方法,教你轻松解决

在计算机的使用过程中&#xff0c;我们可能会遇到各种技术问题。其中&#xff0c;“msvcp140.dll丢失”是一个常见的错误提示。这个错误通常出现在运行某些程序或游戏时&#xff0c;表示找不到所需的DLL文件。本文将详细介绍五种解决此问题的有效方法。 方法一&#xff1a;重新…

java中关键字

主要是java开发面试或笔试中常见或者常考的关键字特性介绍 文章目录 类方法和变量修饰符final关键字abstract关键字static 关键字关于static执行顺序 implements 和 interface 关键字 类方法和变量修饰符 final关键字 用于声明不可变性&#xff0c;它可以应用于变量、方法和类…

浅谈云原生

目录 1. 云原生是什么&#xff1f; 2. 云原生四要素 2.1 微服务 2.2 容器化 2.3 DevOps 2.4 持续交付 3. 具体的云原生技术有哪些&#xff1f; 3.1 容器 (Containers) 3.2 微服务 (Microservices) 3.3 服务网格 (Service Meshes) 3.4 不可变基础设施 (Immutable Inf…

VUE:侧边弹出栏组件,组件中有树状图,搜索框可筛选树状图节点,可收缩

作者:CSDN @ _乐多_ 本文记录了一个侧边弹出栏组件代码。代码即插即用。 弹出栏中有树状图,搜索框,可收缩。 其中,搜索框可筛选树状图节点。点击右侧小按钮可以收缩弹出框,点击X号也可以收缩弹出框。 文章目录 一、组件代码代码依赖element-plus库。且需要下载几个svg图…

CNVD-2021-26422:亿邮电子邮件系统moni_detail.do远程命令执行漏洞复现 [附POC]

文章目录 亿邮电子邮件系统 moni_detail.do 远程命令执行 CNVD-2021-26422漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 亿邮电子邮件系统 moni_detail.do 远程命令执行 CNVD-2021-26422漏洞复…

TSINGSEE智慧港口可视化智能监管解决方案,助力港口码头高效监管

一、方案背景 全球经济一体化进程以及国际市场的不断融合&#xff0c;使得港口码头成为了大型货运周转中心&#xff0c;每天数以百计的大型货轮、数以千计的大型集装箱、数以万计的人员流动。港口作为货物、集装箱堆放及中转机构&#xff0c;具有昼夜不歇、天气多变、环境恶劣…

基于内存的分布式NoSQL数据库Redis(三)常用命令

文章目录 知识点07&#xff1a;String类型的常用命令知识点08&#xff1a;Hash类型的常用命令知识点09&#xff1a;List类型的常用命令知识点10&#xff1a;Set类型的常用命令知识点11&#xff1a;Zset类型的常用命令知识点12&#xff1a;BitMap类型的常用命令知识点13&#xf…

PMP考完后应该考什么?

PMP&#xff08;项目管理专业&#xff09;认证是全球范围内最受认可和尊重的项目管理资格证书之一。通过PMP考试的人已经展示了他们在项目管理领域的知识和技能。然而&#xff0c;项目管理是一个不断发展和变化的领域&#xff0c;持续学习和进一步提升自己的能力是非常重要的。…

【web前端】web前端设计入门到实战第一弹——html基础精华

前端 一&#xff1a;图片属性二&#xff1a;音频标签三&#xff1a; 视频标签四&#xff1a;链接标签五&#xff1a;列表标签5.1.无序列表5.2.有序列表3.自定义列表 六&#xff1a;表格6.1合并单元格 七&#xff1a;input标签八&#xff1a;select系列九&#xff1a; 文本域标签…