Electron13-Vue3-MacUI仿mac桌面UI后台管理框架
ccwgpt 2024-10-11 11:09 20 浏览 0 评论
这段时间一直在捣鼓electron13+vite2结合开发vue3桌面端项目。网上也有一些桌面管理项目,不过很多都是基于jQuery开发,要么就是使用vue2.x开发。于是自己就整了个ElectronVue3MacUI项目。
electron-vite2-macui 一款基于最新技术栈electron13+vite2.3+vue3+element-plus开发的仿制mac big sur桌面UI管理框架。
技术框架
- 使用技术:vite2.3.4+vue3.0.11+vuex@4+vue-router4.x
- 跨端框架:electron13.0.1
- 组件库:element-plus1.0.2
- 图表组件:echarts5.1.1
- 拖拽排序:sortablejs1.13
- 预处理器:sass1.34
- 弹窗组件:maclayer
整个项目采用背景透明模糊化效果。底部dock菜单可自适应收缩动画。
功能特性
?经典的图标+dock菜单模式
?流畅的操作体验
?可拖拽桌面+dock菜单
?符合macOS big sur操作窗口管理
?丰富的视觉效果,自定义桌面壁纸
?可视化创建多窗口,支持拖拽/缩放/最大化,可传入自定义组件页面。
项目结构目录
采用vite2清晰标准的目录结构模式。
自定义导航条
如上图:项目中的所有弹窗顶部均是自定义组件实现的功能。
<template>
<div class="vui__macbtn flexbox flex-alignc" :style="{'z-index': zIndex}">
<div class="vui__macbtn-groups flexbox flex-alignc" :style="{'color': color}">
<a v-if="JSON.parse(minimizable)" class="mbtn min" title="最小化" @click="handleWinMin"><svg x="0" y="0" width="10" height="10" viewBox="0 0 10 10"><path fill="#995700" d="M8.048,4.001c0.163,0.012 0.318,0.054 0.459,0.137c0.325,0.191 0.518,0.559 0.49,0.934c-0.007,0.097 -0.028,0.192 -0.062,0.283c-0.04,0.105 -0.098,0.204 -0.171,0.29c-0.083,0.098 -0.185,0.181 -0.299,0.24c-0.131,0.069 -0.271,0.103 -0.417,0.114c-2.031,0.049 -4.065,0.049 -6.096,0c-0.163,-0.012 -0.318,-0.054 -0.459,-0.137c-0.325,-0.191 -0.518,-0.559 -0.49,-0.934c0.007,-0.097 0.028,-0.192 0.062,-0.283c0.04,-0.105 0.098,-0.204 0.171,-0.29c0.083,-0.098 0.185,-0.181 0.299,-0.24c0.131,-0.069 0.271,-0.103 0.417,-0.114c2.031,-0.049 4.065,-0.049 6.096,0Z"></path></svg></a>
<a v-if="JSON.parse(maximizable)&&winCfg.window.resize" class="mbtn max" :title="hasMaximized ? '向下还原' : '最大化'" @click="handleWinMax2Min">
<svg v-if="hasMaximized" x="0" y="0" width="10" height="10" viewBox="0 0 10 10"><path fill="#4d0000" d="M5,10c0,0 0,-2.744 0,-4.167c0,-0.221 -0.088,-0.433 -0.244,-0.589c-0.156,-0.156 -0.368,-0.244 -0.589,-0.244c-1.423,0 -4.167,0 -4.167,0l5,5Z"></path><path fill="#006400" d="M5,0c0,0 0,2.744 0,4.167c0,0.221 0.088,0.433 0.244,0.589c0.156,0.156 0.368,0.244 0.589,0.244c1.423,0 4.167,0 4.167,0l-5,-5Z"></path></svg>
<svg v-else x="0" y="0" width="10" height="10" viewBox="0 0 10 10"><path fill="#4d0000" d="M2,3c0,0 0,2.744 0,4.167c0,0.221 0.088,0.433 0.244,0.589c0.156,0.156 0.368,0.244 0.589,0.244c1.423,0 4.167,0 4.167,0l-5,-5Z"></path><path fill="#006400" d="M8,7c0,0 0,-2.744 0,-4.167c0,-0.221 -0.088,-0.433 -0.244,-0.589c-0.156,-0.156 -0.368,-0.244 -0.589,-0.244c-1.423,0 -4.167,0 -4.167,0l5,5Z"></path></svg>
</a>
<a v-if="JSON.parse(closable)" class="mbtn close" title="关闭" @click="handleWinClose"><svg x="0" y="0" width="10" height="10" viewBox="0 0 10 10"><path fill="#4d0000" d="M5,3.552c0.438,-0.432 0.878,-0.861 1.322,-1.287c0.049,-0.044 0.101,-0.085 0.158,-0.119c0.149,-0.091 0.316,-0.137 0.49,-0.146c0.04,0 0.04,0 0.08,0.001c0.16,0.011 0.314,0.054 0.453,0.135c0.08,0.046 0.154,0.104 0.218,0.171c0.252,0.262 0.342,0.65 0.232,0.996c-0.045,0.141 -0.121,0.265 -0.218,0.375c-0.426,0.444 -0.855,0.884 -1.287,1.322c0.432,0.438 0.861,0.878 1.287,1.322c0.097,0.11 0.173,0.234 0.218,0.375c0.04,0.126 0.055,0.26 0.043,0.392c-0.011,0.119 -0.043,0.236 -0.094,0.344c-0.158,0.327 -0.49,0.548 -0.852,0.566c-0.106,0.005 -0.213,-0.007 -0.315,-0.035c-0.156,-0.043 -0.293,-0.123 -0.413,-0.229c-0.444,-0.426 -0.884,-0.855 -1.322,-1.287c-0.438,0.432 -0.878,0.861 -1.322,1.287c-0.11,0.097 -0.234,0.173 -0.375,0.218c-0.126,0.04 -0.26,0.055 -0.392,0.043c-0.119,-0.011 -0.236,-0.043 -0.344,-0.094c-0.327,-0.158 -0.548,-0.49 -0.566,-0.852c-0.005,-0.106 0.007,-0.213 0.035,-0.315c0.043,-0.156 0.123,-0.293 0.229,-0.413c0.426,-0.444 0.855,-0.884 1.287,-1.322c-0.432,-0.438 -0.861,-0.878 -1.287,-1.322c-0.106,-0.12 -0.186,-0.257 -0.229,-0.413c-0.025,-0.089 -0.037,-0.182 -0.036,-0.275c0.004,-0.363 0.211,-0.704 0.532,-0.874c0.13,-0.069 0.272,-0.105 0.418,-0.115c0.04,-0.001 0.04,-0.001 0.08,-0.001c0.174,0.009 0.341,0.055 0.49,0.146c0.057,0.034 0.109,0.075 0.158,0.119c0.444,0.426 0.884,0.855 1.322,1.287Z"></path></svg></a>
<i class="mr-10"></i>
<slot />
</div>
</div>
</template>
<script>
import { onMounted, reactive, inject, toRefs } from 'vue'
import { useStore } from 'vuex'
import { winCfg, setWin } from '@/windows/actions'
export default {
props: {
color: { type: String, default: '#fff' },
// 窗口是否可以最小化
minimizable: { type: [Boolean, String], default: true },
// 窗口是否可以最大化
maximizable: { type: [Boolean, String], default: true },
// 窗口是否可以关闭
closable: { type: [Boolean, String], default: true },
// 设置层级
zIndex: { type: [Number, String], default: '2021' },
},
setup() {
let win = window.remote.getCurrentWindow()
const store = useStore()
const v3layer = inject('v3layer')
const data = reactive({
hasMaximized: false
})
onMounted(() => {
if(win.isMaximized()) {
data.hasMaximized = true
}
win.on('maximize', () => {
data.hasMaximized = true
})
win.on('unmaximize', () => {
data.hasMaximized = false
})
})
// 最小化
const handleWinMin = () => {
setWin('min', winCfg.window.id)
}
// 最大化/还原
const handleWinMax2Min = () => {
setWin('max2min', winCfg.window.id)
}
// 关闭
const handleWinClose = () => {
if(winCfg.window.isMainWin) {
let $el = v3layer({
type: 'android',
content: '是否最小化至托盘,不退出程序?',
anim: 'fadeInUp',
xclose: true,
shade: true,
btns: [
{
text: '残忍退出',
style: 'color:#ff2e13',
click: () => {
$el.close()
store.commit('LOGOUT')
setWin('close')
}
},
{
text: '最小化至托盘',
click: () => {
$el.close()
setTimeout(() => {
win.hide()
}, 300)
}
},
]
})
}else {
setWin('close', winCfg.window.id)
}
}
return {
...toRefs(data),
winCfg,
handleWinMin,
handleWinMax2Min,
handleWinClose
}
}
}
</script>
底部Dock菜单
<script>
import { onMounted, ref, inject } from "vue"
import Sortable from "sortablejs"
import { winCfg, createWin } from '@/windows/actions'
export default {
components: {},
setup() {
const dockRef = ref(null)
const v3layer = inject('v3layer')
// 拖拽Dock菜单
const dragDockMenu = () => {
Sortable.create(dockRef.value, {
handle: '.macui__dock-item',
filter: '.macui__dock-filter',
animation: 200,
delay: 0,
onEnd({ newIndex, oldIndex }) {
console.log('新索引:', newIndex)
console.log('旧索引:', oldIndex)
}
})
}
const openMaps = () => {
createWin({
title: '地图',
route: '/map',
width: 1000,
height: 500,
})
}
const openCalendar = () => {
createWin({
title: '日历',
route: '/calendar',
width: 500,
height: 500,
resize: false,
})
}
onMounted(() => {
dragDockMenu()
})
return {
dockRef,
openMaps,
openCalendar,
}
}
}
</script>
桌面菜单支持拖拽及自定义icon图标和img图片功能。
import Home from '@/views/home/index.vue'
import ControlPanel from '@/views/home/dashboard.vue'
import CustomTpl from '@/views/home/customTpl.vue'
import Table from '@/views/component/table/custom.vue'
import Form from '@/views/component/form/all.vue'
import UserSetting from '@/views/setting/manage/user/index.vue'
import Ucenter from '@/views/setting/ucenter.vue'
const deskmenu = [
{
type: 'component',
icon: 'el-icon-monitor',
title: '首页',
component: Home,
},
{
type: 'component',
icon: 'icon-gonggao',
title: '控制面板',
component: ControlPanel,
},
{
type: 'component',
img: '/static/mac/reminders.png',
title: '自定义组件模板',
component: CustomTpl,
area: ['600px', '360px'],
},
{
type: 'iframe',
img: '/static/vite.png',
title: 'vite.js官方文档',
component: 'https://cn.vitejs.dev/',
},
{
type: 'component',
icon: 'el-icon-s-grid',
title: '表格',
component: Table,
},
{
type: 'component',
icon: 'icon-peizhi',
title: '表单',
component: Form,
},
{
type: 'component',
img: '/static/mac/keychain.png',
title: '用户设置',
component: UserSetting,
},
{
type: 'component',
img: '/static/mac/user.png',
title: '个人中心',
component: Ucenter,
area: ['850px', '550px'],
},
// ...
]
// 点击菜单
const handleMenuClicked = (menu) => {
let icon = menu.icon ? `<i class="iconfont ${menu.icon}"></i>` : menu.img ? `<img src="${menu.img}" />` : ''
let title = menu.title ? `<div class="macui__customTitle">${icon}${menu.title}</div>` : '标题'
v3layer({
type: menu.type || null,
layerStyle: menu.style || '',
customClass: 'macui__deskLayer',
title: title,
content: menu.component || '<div style="color:red;margin-top:50px;">嗷嗷!您似乎忘记了填充内容。</div>',
area: menu.area || ['1000px', '550px'],
shade: false,
xclose: true,
maximize: menu.maximize != false ? true : false,
resize: menu.resize != false ? true : false,
fullscreen: menu.fullscreen || false,
zIndex: 500,
topmost: true,
})
}
好了,以上就是基于electron+vue3开发跨端仿mac桌面UI框架的介绍。希望对大家有所帮助哈!
相关推荐
- 盲盒小程序背后的技术揭秘:如何打造个性化购物体验
-
在2025年的今天,盲盒小程序作为一种新兴的购物方式,正以其独特的魅力和个性化体验吸引着越来越多的消费者。这种将线上购物与盲盒概念相结合的应用,不仅为消费者带来了未知的惊喜,还通过一系列技术手段实现了...
- 小程序·云开发已支持单日亿级调用量,接口可用率高达99.99%
-
2019-10-1914:1210月19日,由腾讯云与微信小程序团队联合举办的“小程序·云开发”技术峰会在北京召开。会上,微信小程序团队相关负责人表示“小程序·云开发”系统架构已经支持每天亿级别的...
- 程序员副业开启模式:8个GitHub上可以赚钱的小程序
-
前言开源项目作者:JackonYang今天推荐的这个项目是「list-of-wechat-mini-program-list」,开源微信小程序列表的列表、有赚钱能力的小程序开源代码。这个项目分为两部分...
- 深度科普:盲盒小程序开发的底层逻辑
-
在当下的数字化浪潮中,盲盒小程序以其独特的趣味性和互动性,吸引着众多消费者的目光。无论是热衷于收集玩偶的年轻人,还是享受拆盒惊喜的上班族,都对盲盒小程序情有独钟。那么,这种备受欢迎的盲盒小程序,其开发...
- 微信小程序的制作步骤
-
SaaS小程序制作平台,作为数字化转型时代下的创新产物,不仅将易用性置于设计的核心位置,让非技术背景的用户也能轻松上手,快速制作出功能丰富、界面精美的小程序,更在性能和稳定性方面投入了大量精力,以确保...
- 携程开源--小程序构建工具,三分钟搞定
-
前言今天推荐的这个项目是「wean」,一个小程序构建打包工具。在wean之前,大量小程序工具使用webpack进行打包,各种loader、plugin导致整个开发链路变长。wean旨在解...
- 校园小程序的搭建以及营收模式校园外卖程序校园跑腿校园圈子系统
-
校园小程序的架构设计主要包括云端架构和本地架构两部分。云端架构方面,采用Serverless架构可以降低技术门槛,通过阿里云、腾讯云等平台提供的云服务,可以实现弹性扩容和快速部署。例如,使用云数据库、...
- 盲盒小程序开发揭秘:技术架构与实现原理全解析
-
在2025年的今天,盲盒小程序作为一种结合了线上购物与趣味性的创新应用,正受到越来越多用户的喜爱。其背后的技术架构与实现原理,对于想要了解或涉足这一领域的人来说,无疑充满了神秘与吸引力。本文将为大家科...
- 月活百万的小程序架构设计:流量暴增秘籍
-
从小程序到"大"程序的蜕变之路当你的小程序用户量从几千跃升至百万级别时,原有的架构就像一件不合身的衣服,处处紧绷。这个阶段最常遇到的噩梦就是服务器崩溃、接口超时、数据丢失。想象一下,在...
- 认知智能如何与产业结合?专家学者共探理论框架与落地实践
-
当前,以大模型为代表的生成式人工智能等前沿技术加速迭代,如何将认知智能与产业结合,成为摆在各行各业面前的一个问题。论坛现场。主办方供图7月4日,2024世界人工智能大会暨人工智能全球治理高级别会议在...
- 现代中医理论框架
-
...
- 认知行为(CBT)中的ABC情绪理论
-
情绪ABC理论是由美国心理学家阿尔伯特·艾利斯(AlbertEllis1913-2007)创建的理论,A表示诱发性事件(Activatingevent),B表示个体针对此诱发性事件产生的一些信...
- 说说卡伦霍妮的理论框架,对你调整性格和人际关系,价值很大
-
01自在今天我主要想说下霍妮的理论框架。主要说三本书,第一本是《我们时代的神经症人格》,第二本是《我们内心的冲突》,第三本是《神经症与人的成长》。根据我的经验,三本书价值巨大,但并不是每个人都能读进去...
- 供应链管理-理论框架
-
一个最佳价值的供应链,应该是一个具有敏捷性、适应性和联盟功能(3A)的供应链,其基本要素包括战略资源、物流管理、关系管理以及信息系统,目标是实现速度、质量、成本、柔性的竞争优势。篇幅有...
- 微信WeUI设计规范文件下载及使用方法
-
来人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。WeUI是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信Web开发量身设计,可以令用户的使用感知...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- bootstrap框架 (43)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- laravel框架 (46)
- express框架 (43)
- scrapy框架 (52)
- beego框架 (42)
- java框架spring (43)
- grpc框架 (55)
- 前端框架bootstrap (42)
- orm框架有哪些 (43)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)