基于tauri+vue3.js+vite3跨桌面端仿微信聊天实例TauriVue3Chat。
tauri-chat 运用最新tauri+vue3+vite3+element-plus+v3layer等技术跨桌面端仿微信|QQ聊天程序EXE。基本实现了发送图文混排消息、图片/视频/网址预览、拖拽聊天区发送图片、朋友圈等功能。支持tauri打开多个窗体、更换主题皮肤等功能。
一、技术框架
- 编辑器:VScode
- 使用技术:tauri+vue^3.2.37+vite^3.0.2+vuex4+vue-router@4
- UI组件库:element-plus^2.2.17 (饿了么vue3组件库)
- 弹窗组件:v3layer(基于vue3自定义pc端弹窗组件)
- 滚动条组件:v3scroll(基于vue3模拟滚动条组件)
- 矢量图标:阿里iconfont字体图标库
二、项目结构
◆ Tauri新建多开窗口
项目中主题换肤、朋友圈、关于、视频预览等窗口均是新开窗口。
// 关于 const openAboutWin = () => { createWin({ label: 'about', title: '关于', url: '/about', width: 430, height: 330, resizable: false, alwaysOnTop: true, }) } // 主题换肤 const openThemeSkinWin = () => { createWin({ label: 'skin', title: '换肤', url: '/skin', width: 630, height: 400, resizable: false, }) } // 朋友圈 const openQzoneWin = () => { createWin({ label: 'fzone', title: '朋友圈', url: '/fzone', width: 550, height: 700, resizable: false, }) }
tauri多窗口参数配置
// 窗口配置 export const windowConfig = { label: null, // 窗口唯一label title: '', // 窗口标题 url: '', // 路由地址url width: 900, // 窗口宽度 height: 640, // 窗口高度 minWidth: null, // 窗口最小宽度 minHeight: null, // 窗口最小高度 x: null, // 窗口相对于屏幕左侧坐标 y: null, // 窗口相对于屏幕顶端坐标 center: true, // 窗口居中显示 resizable: true, // 是否支持缩放 maximized: false, // 最大化窗口 decorations: false, // 窗口是否无边框及导航条 alwaysOnTop: false, // 置顶窗口 fileDropEnabled: false, // 禁止系统拖放 visible: false, // 隐藏窗口 }
由于之前有写过一篇vue3+tauri创建多窗口的分享文章,这里就不详细介绍了。
https://www.cnblogs.com/xiaoyan2017/p/16812092.html
◆ Tauri自定义拖拽窗体|最大化/最小化/关闭功能
创建窗口的时候配置 decorations: false 参数,则创建的窗口没有顶部导航栏及边框。拖拽区域/最大化/最小化及关闭按钮都需要自定义功能。
tauri提供了 data-tauri-drag-region 属性,在需要拖拽的元素上设置该属性,该区域就能*拖拽了。
<template> <div class="nt__navbar"> <div data-tauri-drag-region class="nt__navbar-wrap"> <div class="nt__navbar-title"> <template v-if="$slots.title"><slot name="title" /></template> <template v-else>{{title}}</template> </div> </div> <WinTool :minimizable="minimizable" :maximizable="maximizable" :closable="closable"> <slot name="wbtn" /> </WinTool> </div> </template>
下面这篇文章介绍tauri自定义最大化/最小化及关闭按钮功能。
https://www.cnblogs.com/xiaoyan2017/p/16818283.html
◆ Tauri创建系统托盘图标
当关闭窗体的时候,会判断是否主窗口,并给出关闭提示。当不是主窗口,则直接关闭,是主窗口则给出下图弹窗提示。最小化至托盘 则是隐藏窗口,退出程序则直接执行exit方法退出应用了。
// 关闭窗体 const handleCloseWindow = async() => { if(appWindow.label.indexOf('main') > -1) { let $el = v3layer({ type: 'android', content: '确认退出应用程序吗?', btns: [ { text: '最小化托盘', style: 'color:#24c8db', click: () => { $el.close() await appWindow.hide() } }, { text: '退出程序', style: 'color:#ff5438', click: async() => { $el.close() store.commit('LOGOUT') await exit() } } ] }) }else { await appWindow.close() } }
/** * 创建系统托盘图标Tray */ use tauri::{ AppHandle, Manager, CustomMenuItem, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, SystemTraySubmenu }; // 托盘菜单 pub fn menu() -> SystemTray { let exit = CustomMenuItem::new("exit".to_string(), "退出"); let relaunch = CustomMenuItem::new("relaunch".to_string(), "重启应用"); let show = CustomMenuItem::new("show".to_string(), "显示窗口"); let hide = CustomMenuItem::new("hide".to_string(), "隐藏窗口"); let change_ico = CustomMenuItem::new("change_ico".to_string(), "更换托盘图标"); let tray_menu = SystemTrayMenu::new() .add_submenu(SystemTraySubmenu::new( "国际化", // 语言菜单 SystemTrayMenu::new() .add_item(CustomMenuItem::new("lang_english".to_string(), "English")) .add_item(CustomMenuItem::new("lang_zh_CN".to_string(), "简体中文")) .add_item(CustomMenuItem::new("lang_zh_HK".to_string(), "繁体中文")), )) .add_native_item(SystemTrayMenuItem::Separator) // 分割线 .add_item(change_ico) .add_native_item(SystemTrayMenuItem::Separator) .add_item(hide) .add_item(show) .add_native_item(SystemTrayMenuItem::Separator) .add_item(relaunch) .add_item(exit); SystemTray::new().with_menu(tray_menu) } // 托盘事件 pub fn handler(app: &AppHandle, event: SystemTrayEvent) { match event { SystemTrayEvent::LeftClick { position: _, size: _, .. } => { println!("点击左键"); } SystemTrayEvent::RightClick { position: _, size: _, .. } => { println!("点击右键"); } SystemTrayEvent::DoubleClick { position: _, size: _, .. } => { println!("双击"); app.emit_all("win-show", {}).unwrap(); } SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() { // 更新托盘图标 "change_ico" => { app.tray_handle() .set_icon(tauri::Icon::Raw( include_bytes!("../icons/tray-empty.ico").to_vec() )) .unwrap(); } // 选择语言,匹配 id 前缀包含 `lang_` 的事件 lang if lang.contains("lang_") => { Lang::new( app, id, vec![ Lang { name: "English", id: "lang_english", }, Lang { name: "繁体中文", id: "lang_zh_HK", }, Lang { name: "简体中文", id: "lang_zh_CN", }, ], ); } "hide" => { // println!("点击隐藏"); app.emit_all("win-hide", {}).unwrap(); } "show" => { // println!("点击显示"); app.emit_all("win-show", {}).unwrap(); } "relaunch" => { // println!("点击重启"); app.emit_all("win-relaunch", {}).unwrap(); } "exit" => { // println!("点击退出"); app.emit_all("win-exit", {}).unwrap(); } _ => {} }, _ => {} } } struct Lang<'a> { name: &'a str, id: &'a str, } impl Lang<'static> { fn new(app: &AppHandle, id: String, langs: Vec<Lang>) { // 获取点击的菜单项的句柄 langs.iter().for_each(|lang| { let handle = app.tray_handle().get_item(lang.id); if lang.id.to_string() == id.as_str() { // 设置菜单名称 handle.set_title(format!(" {}", lang.name)).unwrap(); handle.set_selected(true).unwrap(); } else { handle.set_title(lang.name).unwrap(); handle.set_selected(false).unwrap(); } }); } }
tauri创建托盘图标默认读取 src-tauri/icons 目录下图标,如果自定义的.ico图标,可在tauri.cong.json文件中配置。
"systemTray": {
"iconPath": "icons/tray.ico",
"iconAsTemplate": true,
"menuOnLeftClick": false
}
使用ico图标报错,需要在 src-tauri/src/Cargo.toml 中配置 icon-ico 或 icon-png
tauri build 打包构建,如果打包的时候报错,需要在 src-tauri/tauri.conf.json 这个配置文件中找到 identifier 这个字段,将它的值进行更改即可。
tauri.conf.json配置文件
{ "build": { "beforeDevCommand": "npm run dev", "beforeBuildCommand": "npm run build", "devPath": "http://localhost:1420", "distDir": "../dist", "withGlobalTauri": false }, "package": { "productName": "tauri-chat", "version": "0.0.0" }, "tauri": { "allowlist": { "all": true }, "bundle": { "active": true, "category": "DeveloperTool", "copyright": "", "deb": { "depends": [] }, "externalBin": [], "icon": [ "icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico" ], "identifier": "com.tauri.chat", "longDescription": "", "macOS": { "entitlements": null, "exceptionDomain": "", "frameworks": [], "providerShortName": null, "signingIdentity": null }, "resources": [], "shortDescription": "", "targets": "all", "windows": { "certificateThumbprint": null, "digestAlgorithm": "sha256", "timestampUrl": "" } }, "security": { "csp": null }, "updater": { "active": false }, "windows": [ { "fullscreen": false, "height": 640, "resizable": true, "title": "TAURI-CHAT", "width": 900, "center": true, "decorations": false, "fileDropEnabled": false, "visible": false } ], "systemTray": { "iconPath": "icons/tray.ico", "iconAsTemplate": true, "menuOnLeftClick": false } } }
Oker,基于tauri+vue3实战桌面端聊天应用就分享到这里,希望对大家有些帮助。????
最后附上一个uniapp+uview跨端后台管理系统
https://www.cnblogs.com/xiaoyan2017/p/15836112.html