Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

这篇具有很好参考价值的文章主要介绍了Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于React18+Electron27+ArcoDesign仿macOS桌面端系统框架ElectronMacOS

electron-react-macOs 基于electron27.x+vite4+react18+arcoDesign+zustand等技术构建桌面版仿MacOs框架系统解决方案。支持中英文/繁体、dark+light主题、桌面多层级路由、多窗口路由页面、动态换肤、Dock悬浮菜单等功能。

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

ElectronReactOS系统是首创自研的桌面多层级路由菜单、支持electron多开窗口+弹窗路由窗口

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

技术栈

  • 开发工具:vscode
  • 框架技术:vite4+react18+zustand+react-router
  • 跨端技术:electron^27.0.1
  • 打包工具:electron-builder^24.6.4
  • UI组件库:arco-design (字节react轻量级UI组件库)
  • 图表组件:bizcharts^4.1.23
  • 拖拽库:sortablejs
  • 模拟请求:axios
  • 弹窗组件:rdialog (基于react多功能layer弹窗)
  • 美化滚动条:rscroll (基于react虚拟滚动条组件)

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

特性

  1. 桌面路由页面支持暗黑+亮色模式
  2. 内置中英文/繁体国际化
  3. 经典桌面Dock悬浮菜单
  4. 可拖拽桌面路由+程序坞Dock菜单
  5. 桌面路由支持多个子级路由配置
  6. 动态视觉效果,自定义桌面换肤背景
  7. 可视化多窗口路由,支持electron新开窗口+rdialog弹窗页面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

大家如果对Electron封装多窗口感兴趣,可以去看看下面这篇分享文章。

https://www.cnblogs.com/xiaoyan2017/p/17788495.html

项目结构

使用vite4构建react18项目,整合electron跨端技术,搭建桌面版OS管理系统。

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron桌面os布局模板

桌面os布局分为顶部操作栏+桌面端路由菜单+底部Dock菜单三大模块。

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

<div className="radmin__layout flexbox flex-col">
    {/* 导航栏 */}
    <Header />

    {/* 桌面区域 */}
    <div className="ra__layout-desktop flex1 flexbox" onContextMenu={handleDeskCtxMenu} style={{marginBottom: 70}}>
        <DeskMenu />
    </div>

    {/* Dock菜单 */}
    <Dock />
</div>

Electron+React实现Dock菜单

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

底部dock菜单采用背景滤镜模糊效果、支持自适应伸缩、拖拽排序等功能。

<div className="ra__docktool">
    <div className={clsx('ra__dock-wrap', !dock ? 'compact' : 'split')}>
        {dockMenu.map((res, key) => {
            return (
                <div key={key} className="ra__dock-group">
                    { res?.children?.map((item, index) => {
                        return (
                            <a key={index} className={clsx('ra__dock-item', {'active': item.active, 'filter': item.filter})} onClick={() => handleDockClick(item)}>
                                <span className="tooltips">{item.label}</span>
                                <div className="img">
                                    { item.type != 'icon' ? <img src={item.image} /> : <Icon name={item.image} size={32} style={{color: 'inherit'}} /> }
                                </div>
                            </a>
                        )
                    })}
                </div>
            )
        })}
    </div>
</div>
const dockMenu = [
    {
        // 图片图标
        children: [
            {label: 'Safari', image: '/static/mac/safari.png', active: true},
            {label: 'Launchpad', image: '/static/mac/launchpad.png'},
            {label: 'Contacts', image: '/static/mac/contacts.png'},
            {label: 'Messages', image: '/static/mac/messages.png', active: true}
        ]
    },
    {
        // 自定义iconfont图标
        children: [
            {label: 'Home', image: <IconDesktop />, type: 'icon'},
            {label: 'About', image: 've-icon-about', type: 'icon'}
        ]
    },
    {
        children: [
            {label: 'Appstore', image: '/static/mac/appstore.png'},
            {label: 'Mail', image: '/static/mac/mail.png'},
            {label: 'Maps', image: '/static/mac/maps.png', active: true},
            {label: 'Photos', image: '/static/mac/photos.png'},
            {label: 'Facetime', image: '/static/mac/facetime.png'},
            {label: 'Calendar', image: '/static/mac/calendar.png'},
            {label: 'Notes', image: '/static/mac/notes.png'},
            {label: 'Calculator', image: '/static/mac/calculator.png'},
            {label: 'Music', image: '/static/mac/music.png'}
        ]
    },
    {
        children: [
            {label: 'System', image: '/static/mac/system.png', active: true, filter: true},
            {label: 'Empty', image: '/static/mac/bin.png', filter: true}
        ]
    }
]

// 点击dock菜单
const handleDockClick = (item) => {
    const { label } = item
    if(label == 'Home') {
        createWin({
            title: '首页',
            route: '/home',
            width: 900,
            height: 600
        })
    }else if(label == 'About') {
        setWinData({ type: 'CREATE_WIN_ABOUT' })
    }else if(label == 'System') {
        createWin({
            title: '网站设置',
            route: '/setting/system/website',
            isNewWin: true,
            width: 900,
            height: 600
        })
    }
}

useEffect(() => {
    const dockGroup = document.getElementsByClassName('ra__dock-group')
    // 组拖拽
    for(let i = 0, len = dockGroup.length; i < len; i++) {
        Sortable.create(dockGroup[i], {
            group: 'share',
            handle: '.ra__dock-item',
            filter: '.filter',
            animation: 200,
            delay: 0,
            onEnd({ newIndex, oldIndex }) {
                console.log('新索引:', newIndex)
                console.log('旧索引:', oldIndex)
            }
        })
    }
}, [])

Electron+React桌面多级路由菜单

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

如上图:桌面菜单配置支持多级路由。

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

export default [
    /* 桌面模块 */
    {
        path: '/desk',
        key: '/desk',
        element: <Desk />,
        meta: {
            icon: <IconDesktop />,
            name: 'layout__main-menu__desk',
            title: 'Appstore',
            isWhite: true, // 路由白名单
            isAuth: true, // 需要鉴权
            isHidden: false, // 是否隐藏菜单
        }
    },

    {
        path: '/home',
        key: '/home',
        element: <Layout>{lazyload(lazy(() => import('@views/home')))}</Layout>,
        meta: {
            icon: '/static/mac/appstore.png',
            name: 'layout__main-menu__home-index',
            title: '首页',
            isAuth: true,
            isNewWin: true
        }
    },
    {
        path: '/dashboard',
        key: '/dashboard',
        element: <Layout>{lazyload(lazy(() => import('@views/home/dashboard')))}</Layout>,
        meta: {
            icon: <IconDashboard />,
            name: 'layout__main-menu__home-workplace',
            title: '工作台',
            isAuth: true
        }
    },
    {
        path: 'https://react.dev/',
        key: 'https://react.dev/',
        meta: {
            icon: <IconLink />,
            name: 'layout__main-menu__home-apidocs',
            title: 'react.js官方文档',
            rootRoute: '/home'
        }
    },

    /* 组件模块 */
    {
        path: '/components',
        key: '/components',
        redirect: '/components/table/allTable', // 一级路由重定向
        element: <Blank />,
        meta: {
            icon: <IconCommand />,
            name: 'layout__main-menu__component',
            title: '组件示例',
            isAuth: true,
            isHidden: false
        },
        children: [
            {
                path: 'table',
                key: '/components/table',
                element: <Blank />,
                meta: {
                    icon: 've-icon-table',
                    name: 'layout__main-menu__component-table',
                    title: '表格',
                    isAuth: true
                },
                children: [
                    {
                        path: 'allTable',
                        key: '/components/table/allTable',
                        element: <Layout>{lazyload(lazy(() => import('@views/components/table/all')))}</Layout>,
                        meta: {
                            name: 'layout__main-menu__component-table_all',
                            title: '所有表格'
                        }
                    },
                    {
                        path: 'customTable',
                        key: '/components/table/customTable',
                        element: <Layout>{lazyload(lazy(() => import('@views/components/table/custom')))}</Layout>,
                        meta: {
                            name: 'layout__main-menu__component-table_custom',
                            title: '自定义表格'
                        }
                    },
                    {
                        path: 'search',
                        key: '/components/table/search',
                        element: <Blank />,
                        meta: {
                            name: 'layout__main-menu__component-table_search',
                            title: '搜索'
                        },
                        children: [
                            {
                                path: 'searchList',
                                key: '/components/table/search/searchList',
                                element: <Layout>{lazyload(lazy(() => import('@views/components/table/search')))}</Layout>,
                                meta: {
                                    name: 'layout__main-menu__component-table_search_list',
                                    title: '搜索列表'
                                }
                            }
                        ]
                    }
                ]
            },
            {
                path: 'list',
                key: '/components/list',
                element: <Layout>{lazyload(lazy(() => import('@views/components/list')))}</Layout>,
                meta: {
                    icon: 've-icon-order-o',
                    name: 'layout__main-menu__component-list',
                    title: '列表'
                }
            },
            {
                path: 'form',
                key: '/components/form',
                element: <Blank />,
                meta: {
                    icon: 've-icon-exception',
                    name: 'layout__main-menu__component-form',
                    title: '表单',
                    isAuth: true
                },
                children: [
                    {
                        path: 'allForm',
                        key: '/components/form/allForm',
                        element: <Layout>{lazyload(lazy(() => import('@views/components/form/all')))}</Layout>,
                        meta: {
                            name: 'layout__main-menu__component-form_all',
                            title: '所有表单'
                        }
                    },
                    {
                        path: 'customForm',
                        key: '/components/form/customForm',
                        element: <Layout>{lazyload(lazy(() => import('@views/components/form/custom')))}</Layout>,
                        meta: {
                            name: 'layout__main-menu__component-form_custom',
                            title: '自定义表单'
                        }
                    }
                ]
            },
            {
                path: 'markdown',
                key: '/components/markdown',
                element: <Layout>{lazyload(lazy(() => import('@views/components/markdown')))}</Layout>,
                meta: {
                    icon: <IconUnorderedList />,
                    name: 'layout__main-menu__component-markdown',
                    title: 'markdown编辑器'
                }
            },
            {
                path: 'qrcode',
                key: '/components/qrcode',
                meta: {
                    icon: 've-icon-qrcode',
                    name: 'layout__main-menu__component-qrcode',
                    title: '二维码'
                }
            },
            {
                path: 'print',
                key: '/components/print',
                meta: {
                    icon: 've-icon-printer',
                    name: 'layout__main-menu__component-print',
                    title: '打印'
                }
            },
            {
                path: 'pdf',
                key: '/components/pdf',
                meta: {
                    icon: 've-icon-pdffile',
                    name: 'layout__main-menu__component-pdf',
                    title: 'pdf'
                }
            }
        ]
    },

    /* 用户管理模块 */
    {
        path: '/user',
        key: '/user',
        redirect: '/user/userManage',
        element: <Blank />,
        meta: {
            // icon: 've-icon-team',
            icon: <IconUserGroup />,
            name: 'layout__main-menu__user',
            title: '用户管理',
            isAuth: true,
            isHidden: false
        },
        children: [
            ...
        ]
    },

    /* 配置模块 */
    {
        path: '/setting',
        key: '/setting',
        redirect: '/setting/system/website',
        element: <Blank />,
        meta: {
            icon: 've-icon-settings-o',
            name: 'layout__main-menu__setting',
            title: '设置',
            isHidden: false
        },
        children: [
            ...
        ]
    },

    /* 权限模块 */
    {
        path: '/permission',
        key: '/permission',
        redirect: '/permission/admin',
        element: <Blank />,
        meta: {
            // icon: 've-icon-unlock',
            icon: <IconLock />,
            name: 'layout__main-menu__permission',
            title: '权限管理',
            isAuth: true,
            isHidden: false
        },
        children: [
            ...
        ]
    }
]

DeskMenu.jsx模板

/**
 * Desk桌面多层级路由菜单
 * Create by andy  Q:282310962
*/

export default function DeskMenu() {
    const t = Locales()
    const filterRoutes = routes.filter(item => !item?.meta?.isWhite)

    // 桌面二级菜单弹框
    const DeskPopup = (item) => {
        const { key, meta, children } = item

        return (
            !meta?.isHidden &&
            <RScroll maxHeight={220}>
                <div className="ra__deskmenu-popup__body">
                    { children.map(item => {
                        if(item?.children) {
                            return DeskSubMenu(item)
                        }
                        return DeskMenu(item)
                    })}
                </div>
            </RScroll>
        )
    }

    // 桌面菜单项
    const DeskMenu = (item) => {
        const { key, meta, children } = item

        return (
            !meta?.isHidden &&
            <div key={key} className="ra__deskmenu-block">
                <a className="ra__deskmenu-item" onClick={()=>handleDeskClick(item)} onContextMenu={handleDeskCtxMenu}>
                    <div className="img">
                        {meta?.icon ?
                            isImg(meta?.icon) ? <img src={meta.icon} /> : <Icon name={meta.icon} size={40} />
                            :
                            <Icon name="ve-icon-file" size={40} />
                        }
                    </div>
                    { meta?.name && <span className="title clamp2">{t[meta.name]}</span> }
                </a>
            </div>
        )
    }
    // 桌面二级菜单项
    const DeskSubMenu = (item) => {
        const { key, meta, children } = item

        return (
            !meta?.isHidden &&
            <div key={key} className="ra__deskmenu-block">
                <a className="ra__deskmenu-item group" onContextMenu={e=>e.stopPropagation()}>
                    <Popover
                        title={<div className="ra__deskmenu-popup__title">{meta?.name && t[meta.name]}</div>}
                        content={() => DeskPopup(item)}
                        trigger="hover"
                        position="right"
                        triggerProps={{
                            popupStyle: {padding: 5},
                            popupAlign: {
                                right: [10, 45]
                            },
                            mouseEnterDelay: 300,
                            // showArrow: false
                        }}
                        style={{zIndex: 100}}
                    >
                        <div className="img">
                            {children.map((child, index) => {
                                if(child?.meta?.isHidden) return
                                return child?.meta?.icon ?
                                    isImg(child?.meta?.icon) ? <img key={index} src={child.meta.icon} /> : <Icon key={index} name={child.meta.icon} size={10} />
                                    :
                                    <Icon key={index} name="ve-icon-file" size={10} />
                            })}
                        </div>
                    </Popover>
                    { meta?.name && <span className="title clamp2">{t[meta.name]}</span> }
                </a>
            </div>
        )
    }

    // 点击dock菜单
    const handleDeskClick = (item) => {
        const { key, meta, element } = item

        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 {
            if(meta?.isNewWin) {
                // 新窗口打开
                createWin({
                    title: t[meta?.name] || meta?.title,
                    route: key,
                    width: 900,
                    height: 600
                })
            }else {
                // 弹窗打开
                rdialog({
                    title: t[meta?.name] || meta?.title,
                    content: <BrowserRouter>{element}</BrowserRouter>,
                    maxmin: true,
                    showConfirm: false,
                    area: ['900px', '550px'],
                    className: 'rc__dialogOS',
                    customStyle: {padding: 0},
                    zIndex: 100
                })
            }
        }
    }

    // 右键菜单
    const handleDeskCtxMenu = (e) => {
        e.stopPropagation()
        let pos = [e.clientX, e.clientY]
        rdialog({
            type: 'contextmenu',
            follow: pos,
            opacity: .1,
            dialogStyle: {borderRadius: 3, overflow: 'hidden'},
            btns: [
                {text: '打开'},
                {text: '重命名/配置'},
                {
                    text: '删除',
                    click: () => {
                        rdialog.close()
                    }
                }
            ]
        })
    }

    useEffect(() => {
        const deskEl = document.getElementById('deskSortable')
        Sortable.create(deskEl, {
            handle: '.ra__deskmenu-block',
            animation: 200,
            delay: 0,
            onEnd({ newIndex, oldIndex }) {
                console.log('新索引:', newIndex)
                console.log('旧索引:', oldIndex)
            }
        })
    }, [])

    return (
        <div className="ra__deskmenu" id="deskSortable">
            { filterRoutes.map(item => {
                if(item?.children) {
                    return DeskSubMenu(item)
                }
                return DeskMenu(item)
            })}
        </div>
    )
}

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

OK,以上就是Electron27+React18开发仿制MacOS桌面系统的一些分享,希望对大家有些帮助哈~~

最后附上两个最近实例项目

https://www.cnblogs.com/xiaoyan2017/p/17695193.html

https://www.cnblogs.com/xiaoyan2017/p/17552562.html

Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面

 文章来源地址https://www.toymoban.com/news/detail-746818.html

到了这里,关于Electron-React18-MacOS桌面管理系统|electron27+react仿mac桌面的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • eletron+react+antd+node开发桌面小程序并打包(electron-packager+electron-builder)

    首先罗列一下项目中用到的技术: electron, react,antd, typescript, node,及打包命令:pkg,electron-packager,electron-builder及child_process实现多进程 需求:开发一个桌面应用,左侧展示视频(需要用到node服务进行rtsp转码),右侧一些获取视频流需要的表单数据。 因为从需求到完成小

    2024年02月11日
    浏览(42)
  • react18-webchat网页聊天实例|React Hooks+Arco Design仿微信桌面端

    React18 Hooks+Arco-Design+Zustand 仿微信客户端聊天 ReactWebchat 。 react18-webchat 基于 react18+vite4.x+arco-design+zustand 等技术开发的一款仿制微信网页版聊天实战项目。实现 发送带有emoj消息文本、图片/视频预览、红包/朋友圈、局部模块化刷新/美化滚动条 等功能。 编辑器:vscode 技术栈:

    2024年02月09日
    浏览(48)
  • React-Admin后台管理模板|react18+arco+zustand后台解决方案

    基于 react18.x+vite4+arco-design 自研中后台管理系统解决方案 ReactAdmin 。 react-vite-admin 基于vite4搭建react18.x后台管理项目。使用了 react18 hooks+arco.design+zustand+bizcharts 等技术实现权限管理模板框架。 支持暗黑/亮色主题、i18n国际化、动态权限鉴定、3种布局模板、tab路由标签栏 等功能

    2024年02月08日
    浏览(102)
  • Java项目:18 基于SpringBoot的学生成绩管理系统

    作者主页:舒克日记 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 基于springboot的学生成绩管理系统主要功能 分为两个端,教师和学生 教师的主要功能:学生信息、成绩信息的增删改查 学生的主要功能:我的成绩、我的总成绩的查看 1.运行环境:

    2024年02月21日
    浏览(62)
  • React--》从零开始搭建一个文章后台管理系统

    目录 项目准备 项目搭建 scss预处理器的使用 配置基础路由 组件库antd的使用 开发者工具的安装 登录模块 基本样式搭建 创建表单结构 获取表单数据并进行相关登录操作 对登录模块的token进行相关处理 路由鉴权实现 后台页面模块 基本页面结构搭建 菜单高亮显示 展示个人信

    2023年04月17日
    浏览(49)
  • Mac菜单栏图标管理工具:Bartender 5 完美兼容MacOS Sonoma 14系统

    Bartender 5 是一款流行的软件程序,专为酒店行业的调酒师和专业人士设计。它提供了一系列功能和工具来简化酒吧或餐厅的饮料订单、库存和客户偏好的管理流程。Bartender 5 的一些主要功能包括: 1. 饮料配方:该软件包括一个全面的饮料配方数据库,使调酒师可以轻松搜索和

    2024年02月08日
    浏览(45)
  • 银河麒麟桌面操作系统V10-常见运维问题类别:外设管理 03

    目录 问题类别 3:外设管理 3.1 添加网络共享打印机后,无法进行打印 【适用版本】 【问题现象】 【解决方案】 方法 1:图形软件关闭防火墙。  方法 2:使用命令关闭防火墙。 3.2 系统设置共享打印机问题 【适用版本】 【问题现象】 【解决方案】 3.3 系统共享打印认证问

    2024年02月09日
    浏览(46)
  • SpringBoot+React学科竞赛管理系统 附带详细运行指导视频

    项目演示地址: 视频地址 项目描述:这是一个 基于SpringBoot+React框架 开发的学科竞赛管理系统。首先,这是一个 前后端分离 的项目,代码简洁规范,注释说明详细,易于理解和学习。其次,这项目功能丰富,具有一个学科竞赛管理系统系统该有的所有功能。 项目功能:此

    2024年02月16日
    浏览(39)
  • 基于react18+vite4+arco.design搭建极简版后台管理模板

    趁着国庆前夕整了一个 vite4 结合 react18 搭建后台管理模板,搭配上字节团队react组件库 ArcoDesign ,整体操作功能非常丝滑。目前功能 支持多种模板布局、暗黑/亮色模式、国际化、权限验证、多级路由菜单、tabview标签栏快捷菜单、全屏控制 等功能。极简非凡的布局界面、高定

    2024年02月08日
    浏览(48)
  • Tauri-Admin通用后台管理系统|tauri+vue3+pinia桌面端后台EXE

    基于 tauri+vite4+pinia2 跨端后台管理系统应用实例 TauriAdmin 。 tauri-admin 基于最新跨端技术  Tauri Rust webview2  整合  Vite4  构建桌面端通用后台管理解决方案。 搭载轻量级ve-plus组件库 、支持 多窗口切换管理、vue-i18n多语言包、动态路由权限、常用业务功能模块、3种布局模板及动

    2024年02月15日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包