vue3+tauri聊天室|tauri+rust跨端实例|tauri仿微信

上一篇有给大家分享Tauri创建多窗口应用实践。今天分享最新开发的Tauri+Vite3客户端聊天实例项目。

tauri-vue3-chat 基于 tauri+vue3+vite3+element-plus+v3layer 等技术开发仿微信客户端应用。

实现了发送图文消息、图片+视频+网址预览、拖拽发送图片、朋友圈等功能。支持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多开窗体

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,
    })
}

支持如下参数配置

// 窗口配置
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,         // 隐藏窗口
}

tauri自定义拖拽块

配置 decorations: false 参数,则创建的窗口没有顶部导航栏及边框。需要自定义拖拽功能。

设置 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创建系统拖拽

/**
 * 创建系统托盘图标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+vue3创建聊天实例就先分享这么多吧。

https://segmentfault.com/a/11...

https://segmentfault.com/a/11...

web前端开发爱好者,专注于前端h5、jquery、vue、react、angular等技术研发实战项目案例。

723 声望
272 粉丝
0 条评论
推荐阅读
Vite4-MobileGPT:基于vue3+vant4移动端仿ChatGPT聊天模板
随着最近openAi推出了Iphone版ChatGPT应用APP。标志着chatgpt已经步入了移动领域。闲暇之余运用vite4.x构建了一个mobile版chatgpt聊天实例。vue3-mobileGPT 支持白色/暗黑两种主题模式。技术栈编辑器:Cursor框架...

xiaoyan2017阅读 435

Vite开发环境搭建
Vite现在可谓是炙手可热,可能很多小伙伴还没有使用过Vite,但是我相信大多数小伙伴已经在使用Vite了,因为是太香了有没有。可能在使用过程中很多东西Vite不是配置好的,并不像Vue-cli配置的很周全,那么今天就说...

Aaron7阅读 5.8k

写一个Vue DevTools,让开发体验飞一会
近年来,人们越来越关注开发者体验 (DX)。工具和框架也一直在努力改进 DX,比如这两年光速发展的Vite。在大多数人的印象中,Vite的特点是快,但是在我看来让它发展迅速并在前端构建工具占据一席之地的主要原因是...

null仔2阅读 872

封面图
Grow Admin 中后台框架简介
Grow Admin是开源的中后台模版,使用目前较新的主流技术栈开发,是一款开箱即用的中台前端/设计解决方案,具有轻松构建规范且美观的系统,丰富的布局模式,具有高可配性,满足您的各类布局需求。

Aaron2阅读 649

封面图
Vele-Admin 一个基于Vue3+Element-Plus的后台管理系统
vele-admin是一个基于 vue3, vite2, element-plus, vuex-module-decorators, vue-router-next, typescript 的后台管理系统

shellingfordly阅读 5.4k评论 1

面试官桀桀一笑:你没做过大文件上传功能?那你回去等通知吧!
本文略长,建议收藏,文末会附上完整前后端代码(vue2&vue3+springboot)凑合算是一套解决方案吧😁😁😁前端vscode大家都有,后端大家需要下载一个idea,搞一下maven,这一点可以请后端同事帮忙对于普通的单个的大文...

水冗水孚2阅读 844

Everright-formEditor低代码拖拉拽的表单编辑器,开源咯!!!
编辑器介绍先来个图,有个初步的认识抱歉,原谅图有点模糊哈github: [链接]demo: [链接]Everright-formEditor是一个基于vue3的可视化编辑器,依赖于element-plus和vant进行开发。内部提供了适配器进行参数转码。...

Liberty_liu2阅读 470

封面图

web前端开发爱好者,专注于前端h5、jquery、vue、react、angular等技术研发实战项目案例。

723 声望
272 粉丝
宣传栏