• Tauri-Vue3桌面端聊天室|tauri+vite3仿微信|tauri聊天程序EXE


    基于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) {
            // 获取点击的菜单项的句柄
            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

     

  • 相关阅读:
    国际腾讯云账号云服务器网络访问丢包问题解决办法!!
    AI强势入场,成就史上最快足球
    【Qt】界面优化
    五大亮点探索互联网医院源码的创新应用方式
    快鲸scrm系统教你从0到1搭建私域社群
    操作系统真相还原_第1~2章:环境配置
    react学习笔记3--数据双向绑定,组件通信
    条例11~12(构造/析构/赋值函数)
    DNS基础之通过dig命令理解DNS域名解析中的A记录,AAAA记录,CNAME记录,MX记录,NS记录
    怎样提升小程序日活?签到抽奖可行吗?
  • 原文地址:https://www.cnblogs.com/xiaoyan2017/p/16830689.html