基于tauri+vue3+pinia2客户端管理系统程序|tauri+vite4后台系统

news/2024/11/16 16:54:24/

TauriAdmin一款跨端通用后台系统模板解决方案

基于 tauri rust webview2 整合 vite4 搭建桌面端 vue3 管理后台模板TauriVue3Admin。支持多窗口切换管理、vue-i18n多语言、动态路由权限、常用业务功能模块及动态路由缓存等功能。

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

使用技术

  • 编码工具:Vscode
  • 框架技术:tauri+vite4+vue3+pinia+vue-router
  • UI组件库:ve-plus (基于vue3轻量级UI组件库)
  • 样式处理:sass^1.63.6
  • 图表组件:echarts^5.4.2
  • 国际化方案:vue-i18n^9.2.2
  • 编辑器组件:wangeditor^4.7.15
  • 本地缓存:pinia-plugin-persistedstate^3.1.0

在这里插入图片描述

特色

  1. 最新跨端技术tauri1.4 rust webview2
  2. 前端技术栈vite4、vue3、pinia、vue-router、vue-i18n
  3. 支持中文/英文/繁体多语言解决方案
  4. 支持动态路由权限验证
  5. 支持路由缓存功能/tabs控制切换路由页面
  6. 内置多个模板布局风格
  7. 搭配轻量级vue3组件库veplus

在这里插入图片描述

项目搭建结构目录

在这里插入图片描述
整个项目基于tauri脚手架创建,全部采用vue3 setup语法糖编码开发。

在这里插入图片描述
tauri-admin支持创建多窗口,如上图从登录窗口切换到主窗口。

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

tauri多窗口封装

在src目录下新建一个管理tauri多窗口文件夹。
在这里插入图片描述
创建新窗口配置参数

// 创建窗口参数配置
export const windowConfig = {label: null,            // 窗口唯一labeltitle: '',              // 窗口标题url: '',                // 路由地址urlwidth: 1000,            // 窗口宽度height: 640,            // 窗口高度minWidth: null,         // 窗口最小宽度minHeight: null,        // 窗口最小高度x: null,                // 窗口相对于屏幕左侧坐标y: null,                // 窗口相对于屏幕顶端坐标center: true,           // 窗口居中显示resizable: true,        // 是否支持缩放maximized: false,       // 最大化窗口decorations: false,     // 窗口是否装饰边框及导航条alwaysOnTop: false,     // 置顶窗口fileDropEnabled: false, // 禁止系统拖放visible: false          // 隐藏窗口
}

在这里插入图片描述

/*** @desc    窗口管理* @author: YXY  Q:282310962* @time    2023.07*/import { WebviewWindow, appWindow, getAll } from '@tauri-apps/api/window'
import { relaunch, exit } from '@tauri-apps/api/process'
import { emit, listen } from '@tauri-apps/api/event'import { setWin } from './actions'// 创建窗口参数配置
export const windowConfig = {label: null,            // 窗口唯一labeltitle: '',              // 窗口标题url: '',                // 路由地址urlwidth: 1000,            // 窗口宽度height: 640,            // 窗口高度minWidth: null,         // 窗口最小宽度minHeight: null,        // 窗口最小高度x: null,                // 窗口相对于屏幕左侧坐标y: null,                // 窗口相对于屏幕顶端坐标center: true,           // 窗口居中显示resizable: true,        // 是否支持缩放maximized: false,       // 最大化窗口decorations: false,     // 窗口是否装饰边框及导航条alwaysOnTop: false,     // 置顶窗口fileDropEnabled: false, // 禁止系统拖放visible: false          // 隐藏窗口
}class Windows {constructor() {// 主窗口this.mainWin = null}// 创建新窗口async createWin(options) {console.log('-=-=-=-=-=开始创建窗口')const args = Object.assign({}, windowConfig, options)// 判断窗口是否存在const existWin = getAll().find(w => w.label == args.label)if(existWin) {console.log('窗口已存在>>', existWin)if(existWin.label.indexOf('main') == -1) {// 自定义处理...}}// 是否主窗口if(args.label.indexOf('main') > -1) {console.log('该窗口是主窗口')// 自定义处理...}// 创建窗口对象let win = new WebviewWindow(args.label, args)// 是否最大化if(args.maximized && args.resizable) {win.maximize()}// 窗口创建完毕/失败win.once('tauri://created', async() => {console.log('window create success!')await win?.show()})win.once('tauri://error', async() => {console.log('window create error!')})}// 获取窗口getWin(label) {return WebviewWindow.getByLabel(label)}// 获取全部窗口getAllWin() {return getAll()}// 开启主进程监听事件async listen() {console.log('——+——+——+——+——+开始监听窗口')// 创建新窗体await listen('win-create', (event) => {this.createWin(event.payload)})// 显示窗体await listen('win-show', async(event) => {if(appWindow.label.indexOf('main') == -1) returnawait appWindow.show()await appWindow.unminimize()await appWindow.setFocus()})// 隐藏窗体await listen('win-hide', async(event) => {if(appWindow.label.indexOf('main') == -1) returnawait appWindow.hide()})// 关闭窗体await listen('win-close', async(event) => {await appWindow.close()})// 退出应用await listen('win-exit', async(event) => {setWin('logout')await exit()})// ...}
}

actions.js则是处理一些渲染进程/主进程通讯。

/*** 处理渲染器进程到主进程的异步通信*/import { WebviewWindow } from '@tauri-apps/api/window'
import { emit } from '@tauri-apps/api/event'/*** @desc 创建新窗口* @param args {object} {label: 'new', url: '/new', width: 500, height: 300, ...}*/
export async function createWin(args) {console.log(args)await emit('win-create', args)
}/*** @desc 获取窗口* @param args {string} 'main'|'main_login' ...*/
export async function getWin(label) {return await WebviewWindow.getByLabel(label)
}/*** @desc 设置窗口* @param type {string} 'show'|'hide'|'close'|'min'|'max'|'max2min'|'exit'|'relaunch'* @param id {number}*/
export async function setWin(type) {await emit('win-' + type)
}/*** @desc 主|渲染进程数据传递* @param args {object} {type: 'MSG_TYPE_XXX', value: 123}*/
export async function setWinData(args) {await emit('win-setdata', args)
}/*** @desc 屏蔽系统右键菜单*/
export function disableWindowMenu() {document.addEventListener('contextmenu', e => e.preventDefault())
}/*** @desc 登录窗口*/
export async function loginWin() {await createWin({label: 'main_login',title: '登录',url: '/login',width: 520,height: 420,resizable: false,alwaysOnTop: true})
}/*** @desc 主窗口*/
export async function mainWin() {await createWin({label: 'main',title: 'TAURI-ADMIN',url: '/',width: 1000,height: 640,minWidth: 750,minHeight: 500})
}

在这里插入图片描述

主入口main.js

import { createApp } from "vue"
import "./styles.scss"
import App from "./App.vue"// 引入路由及状态管理
import Router from './router'
import Pinia from './pinia'// 引入插件配置
import Libs from './libs'const app = createApp(App)app
.use(Router)
.use(Pinia)
.use(Libs)
.mount("#app")

布局模板

tauri-admin内置了3种常用的模板。

在这里插入图片描述

<script setup>import { computed } from 'vue'import { appStore } from '@/pinia/modules/app'// 引入布局模板import Columns from './template/columns/index.vue'import Vertical from './template/vertical/index.vue'import Transverse from './template/transverse/index.vue'const store = appStore()const config = computed(() => store.config)const LayoutConfig = {columns: Columns,vertical: Vertical,transverse: Transverse}
</script><template><div class="veadmin__container" :style="{'--themeSkin': store.config.skin}"><component :is="LayoutConfig[config.layout]" /></div>
</template>

路由vue-router配置

在这里插入图片描述

/*** 路由配置* @author YXY*/import { appWindow } from '@tauri-apps/api/window'
import { createRouter, createWebHistory } from 'vue-router'
import { appStore } from '@/pinia/modules/app'
import { hasPermission } from '@/hooks/usePermission'
import { loginWin } from '@/multiwins/actions'// 批量导入modules路由
const modules = import.meta.glob('./modules/*.js', { eager: true })
const patchRoutes = Object.keys(modules).map(key => modules[key].default).flat()/*** @description 动态路由参数配置* @param path ==> 菜单路径* @param redirect ==> 重定向地址* @param component ==> 视图文件路径* 菜单信息(meta)* @param meta.icon ==> 菜单图标* @param meta.title ==> 菜单标题* @param meta.activeRoute ==> 路由选中(默认空 route.path)* @param meta.rootRoute ==> 所属根路由选中(默认空)* @param meta.roles ==> 页面权限 ['admin', 'dev', 'test']* @param meta.breadcrumb ==> 自定义面包屑导航 [{meta:{...}, path: '...'}]* @param meta.isAuth ==> 是否需要验证* @param meta.isHidden ==> 是否隐藏页面* @param meta.isFull ==> 是否全屏页面* @param meta.isKeepAlive ==> 是否缓存页面* @param meta.isAffix ==> 是否固定标签(tabs标签栏不能关闭)* */
const routes = [// 首页{path: '/',redirect: '/home'},// 错误模块{path: '/:pathMatch(.*)*',component: () => import('@views/error/404.vue'),meta: {title: 'page__error-notfound'}},...patchRoutes
]const router = createRouter({history: createWebHistory(),routes
})// 全局钩子拦截
router.beforeEach((to, from, next) => {// 开启加载提示loading({text: 'Loading...',background: 'rgba(70, 255, 170, .1)'})const store = appStore()if(to?.meta?.isAuth && !store.isLogged) {loginWin()loading.close()}else if(!hasPermission(store.roles, to?.meta?.roles)) {// 路由鉴权appWindow?.show()next('/error/forbidden')loading.close()Notify({title: '访问限制!',description: `<span style="color: #999;">当前登录角色 ${store.roles} 没有操作权限,请联系管理员授权后再操作。</div>`,type: 'danger',icon: 've-icon-unlock',time: 10})}else {appWindow?.show()next()}
})router.afterEach(() => {loading.close()
})router.onError(error => {loading.close()console.warn('Router Error》》', error.message);
})export default router

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

vue3状态管理pinia配置

项目中使用的状态管理由之前的vuex替换为pinia了。
在这里插入图片描述

/*** 状态管理 Pinia util* @author YXY*/import { createPinia } from 'pinia'
// 引入pinia本地持久化存储
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)export default pinia

tauri vue3 国际化解决方案

tauri-admin国际化多语言采用vue-i18n插件实现功能。

在这里插入图片描述

# 安装插件
npm i vue-i18n
yarn add vue-i18n

在这里插入图片描述

import { createI18n } from 'vue-i18n'
import { appStore } from '@/pinia/modules/app'// 引入语言配置
import enUS from './en-US'
import zhCN from './zh-CN'
import zhTW from './zh-TW'// 默认语言
export const langVal = 'zh-CN'export default async (app) => {const store = appStore()const lang = store.lang || langValconst i18n = createI18n({legacy: false,locale: lang,messages: {'en': enUS,'zh-CN': zhCN,'zh-TW': zhTW}})app.use(i18n)
}

在这里插入图片描述
支持中英文/繁体切换,可自定义多语言包配置文件。

tauri.conf.json配置

配置一些打包参数、窗口启动配置参数及托盘参数。

{"build": {"beforeDevCommand": "yarn dev","beforeBuildCommand": "yarn build","devPath": "http://localhost:1420","distDir": "../dist","withGlobalTauri": false},"package": {"productName": "tauri-admin","version": "0.0.0"},"tauri": {"allowlist": {"all": true,"shell": {"all": false,"open": true}},"bundle": {"active": true,"targets": "all","identifier": "com.tauri.admin","icon": ["icons/32x32.png","icons/128x128.png","icons/128x128@2x.png","icons/icon.icns","icons/icon.ico"]},"security": {"csp": null},"windows": [{"fullscreen": false,"resizable": true,"title": "tauri-admin","width": 1000,"height": 640,"center": true,"decorations": false,"fileDropEnabled": false,"visible": false}],"systemTray": {"iconPath": "icons/icon.ico","iconAsTemplate": true,"menuOnLeftClick": false}}
}

以上就是tauri+vue3创建跨端桌面管理后台应用的一些分享,希望大家喜欢~~
如果大家觉得有些帮助,也可以关注公众号,不定期分享一些项目实例。
在这里插入图片描述

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

Electron25+vue3桌面端仿制ChatGPT会话模板实例

Vue3+Tauri跨端聊天实例|tauri仿微信聊天室

在这里插入图片描述


http://www.ppmy.cn/news/886315.html

相关文章

uniapp实现微信小程序自带的分享功能

定义 share.js 文件 export default {data() {return {// 默认的全局分享内容share: {title: 标题,path: /pages/index/index, // 全局分享的路径imageUrl: , // 全局分享的图片(可本地可网络)}}},// 定义全局分享// 1.发送给朋友onShareAppMessage(res) {return {title: this…

Kotlin笔记22——面向对象实战——洗衣机

前言 前面学习的都是面向对象的入门&#xff0c;利用基本数据类型描述复杂的事务&#xff0c;理解Kotlin语言中的静态属性和动态行为。 面向对象实战——洗衣机 我们在生活中会使用到洗衣机&#xff0c;我们创造一个程序员A生产出售洗衣机&#xff0c;另一个程序员B要购买洗…

Kotlin面向对象之开发一个洗衣机 - 封装

一、简陋版洗衣机 Test.kt /*** 程序员B写的代码* 洗衣服*/ fun main(args:Array<String>){var washMachine WashMachine("小天鹅",size 12)washMachine.openDoor() // washMachine.closeDoor()washMachine.start() } WashMachine.kt /*** 程序员A创建…

python学习笔记(3)

接python学习笔记(2) python学习笔记3 一、面向对象基础1、理解面向对象2、类和对象3、添加和获取对象属性4、魔法方法5、综合应用 二、面向对象-继承1、继承的概念2、单继承3、多继承4、子类重写父类的同名属性和方法5、子类调用父类的同名属性和方法6、多层继承7、super()8、…

如何开发一个软件

一、软件开发流程 1. 需求分析 主要有两个文档&#xff0c;一个需求规格说明书和一个产品原型图 2. 设计 UI设计、数据库设计、接口设计 3. 编码 项目代码编写、单元测试 4. 测试 测试用例、测试报告 5. 上线运维 软件环境安装、配置 二、角色分工 项目经理 对整个…

个人Scratch程序合集 第二版 主页

个人Scratch程序合集 第二版 主页 本程序为本人的转换为HTML的Scratch程序制作的第二个主页。改用了响应式图片廊文字说明的形式&#xff0c;对不同尺寸的页面适配较好&#xff0c;但在一些分辨率上右侧空白区域过大。由于通常只有文字说明行数相同的图片才能并排&#xff0c;本…

计算机一级之WORD

1.设置阴影效果&#xff0c;发光效果&#xff0c;在开始界面 2.主题色和个性色表达一样 3.渐变也在开始界面 4.页面纸张大小在布局设置&#xff0c;页边距设置&#xff0c;在对话框具体设置页边距 5.设置页码格式&#xff0c;页码格式主要考核编号格式 6.页面填充颜色&…

wps带阴影的边框怎么设置_wps如何添加阴影边框-wps设置阴影边框的方法 - 河东软件园...

WPS是一款非常专业的办公软件&#xff0c;它包括PPT、word、Excel等组件。在使用Wps软件时&#xff0c;为了让文本看起来更加好看一些&#xff0c;我们经常要在其中插入图片并添加一些效果。比如为了表现图片的立体感时&#xff0c;可以添加阴影效果&#xff1b;如果为了保持图…