vue3-tauri-chat:基于tauri聊天实例|tauri仿微信客户端

news2024/12/21 17:02:41

Vue3.js+Tauri桌面端聊天实例|tauri仿微信/QQ聊天TauriChat。

基于tauri+vite3.x+vue3+element-plus等技术开发客户端仿微信/QQ聊天实战案例。实现发送消息、预览图片/视频/网址链接、拖拽/粘贴发送图片、朋友圈等功能。

 

使用技术

  • 编辑器: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,
    })
}

vue3+tauri 创建多开窗口桌面应用_xiaoyan_2018的博客-CSDN博客_tauri 例子

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+vite3创建登录窗口|tauri自定义拖拽区域_xiaoyan_2018的博客-CSDN博客

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开发仿制微信聊天实例就分享到这里了。 

svelte-admin 基于svelte+svelteUI后台管理系统模板

uniapp-admin 基于uniapp+uview手机端管理系统

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++笔试强训】第十五天

&#x1f387;C笔试强训 博客主页&#xff1a;一起去看日落吗分享博主的C刷题日常&#xff0c;大家一起学习博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a;夜色难免微凉&#xff0c;前方必有曙光 &#x1f31e;。 &#x1f4a6;&a…

C++模板

目录 ​一、认识模板 1.什么是模板 2.模板的分类 二、函数模板 1.泛型和函数模板 2.函数模板的格式 三、类模板 四、实例化 1.隐式实例化 2.显式实例化 3.隐式类型转换 4.模板参数的匹配原则 一、认识模板 1.什么是模板 模板&#xff08;Template&#xff09;指C…

Java笔记(十一)

文献种类&#xff1a;专题技术总结文献 开发工具与关键技术&#xff1a; IntelliJ IDEA、Java 语言 作者&#xff1a; 方建恒 年级&#xff1a; 2020 撰写时间&#xff1a; 2022 年 10 月 28 日 Java笔记(十一) 今天我给大家继续分享一下我的Java笔记&#xff0c; 我们来了解…

CTFHub | 报错注入

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习&#xff0c;实训平台。提供优质的赛事及学习服务&#xff0c;拥有完善的题目环境及配套 writeup &#xff0c;降低 CTF 学习入门门槛&#xff0c;快速帮助选手成长&#xff0c;跟随主流比赛潮流。 0x01 题目描述…

第二站:分支与循环(第二幕)

目录 三、循环 1.while循环 &#xff08;1&#xff09;基本原理与用法 &#xff08;2&#xff09;break在while循环中的作用 &#xff08;3&#xff09;continue在while循环中的作用 &#xff08;4&#xff09;一图总结while循环 2.for循环 &#xff08;1&#xff09;基…

[SpringBoot] 多模块统一返回格式带分页信息

✨✨个人主页:沫洺的主页 &#x1f4da;&#x1f4da;系列专栏: &#x1f4d6; JavaWeb专栏&#x1f4d6; JavaSE专栏 &#x1f4d6; Java基础专栏&#x1f4d6;vue3专栏 &#x1f4d6;MyBatis专栏&#x1f4d6;Spring专栏&#x1f4d6;SpringMVC专栏&#x1f4d6;SpringBoot专…

算法刷题路线总结与相关资料分享

算法刷题路线总结与相关资料分享前言一、算法刷题路线总结二、算法题刷题步骤三、基础数据结构与算法知识1、时间复杂度2、空间复杂度3、线性表4、栈与队列5、树四、算法学习相关资料推荐1.数据结构与算法基础2.专项刷题路线资料3.算法课程视频资料后记前言 本文为算法刷题路线…

双十一数码产品哪些值得买?双十一好物产品分享

双十一必然是数码产品最值得买的&#xff0c;因为这类产品的优惠力度往往是最大的&#xff0c;所以每年的双十一都是升级数码设备的好时机&#xff0c;今天为大家带来的是便是个人推荐的双十一数码好物。好了&#xff0c;废话不再多说&#xff0c;我们开车吧。 一、不伤耳的骨…

postman 实用教程(含带 token 访问需登录权限的接口)

下载安装 Postman 访问官网下载安装 Postman https://www.postman.com/downloads/?utm_sourcepostman-home 新建文档 右键菜单可以重命名 新建接口 选择接口类型输入接口若传入参数格式为 json &#xff0c;则选择 Body 中的 raw 和 JSON输入传入的参数&#xff08;json格式&a…

计算机网络--数据链路层

今天来讲网络协议栈的最后一层&#xff0c;数据链路层(物理层我们不考虑了)&#xff0c;我们之前学到&#xff0c;TCP协议提供了数据传输的可靠性&#xff0c;IP层决定数据报从哪到哪&#xff0c;那么数据报是如何从一个结点到下一个结点呢&#xff1f;得到相应如何返回呢&…

(02)Cartographer源码无死角解析-(09) gflags与glog简介、及其main函数讲解

本人讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解(02)Cartographer源码无死角解析-接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/127350885 文…

软件工程结构化设计

目录 结构化分析与结构化设计的关系&#xff1a; 体系结构设计概念&#xff1a; 图形工具&#xff1a; 层次图&#xff1a;调用关系​编辑 HIPO图&#xff1a;层次图IPO图 软件结构图&#xff1a; 软件设计原则&#xff1a; 模块化&#xff1a; 模块划分注意事项&#xf…

巴什博弈——范围拿物品问题

巴什博弈 巴什博弈&#xff08;Bash game&#xff09; 是一个双人博弈&#xff1a;有一堆总数为n的物品&#xff0c;2名玩家轮流从中拿取物品。每次至少拿1件&#xff0c;至多拿m件&#xff0c;不能不拿&#xff0c;最终将物品拿完者获胜。 巴什博弈除了两人轮流按一定数量拿物…

【黄啊码】MySQL入门—14、细说数据库的MVCC机制

大家好&#xff0c;我是黄啊码。上一篇文章中&#xff0c;我们讲到了锁的划分&#xff0c;以及乐观锁和悲观锁的思想。今天我们就来看下 MVCC&#xff0c;它就是采用乐观锁思想的一种方式。那么它到底有什么用呢&#xff1f; 我们知道事务有 4 个隔离级别&#xff0c;以及可能…

共谋韬略、共巢未来,电巢与韬略“战略合作签约仪式”圆满举办!

前言 2022年10月27日下午&#xff0c;电巢科技与韬略科技齐聚深圳南山&#xff0c;共同举办了隆重的战略合作签约仪式&#xff0c;双方就整合核心资源、共同打造高质量数字化内容等战略方针达成了一致&#xff0c;携手开启合作新篇章。 电巢科技和韬略科技基于相契合的发展战略…

Numpy基础教程

1 Numpy 对象2 Numpy创建numpy.array 构造器来创建numpy.emptynumpy.zerosnumpy.onesnumpy.arangeNumpy索引3 Numpy常用操作numpy.reshapenumpy.reshape(arr,newshape,order C)numpy.transposenumpy.expand_dimsnumpy.squeezeNumpy功能十分强大的python扩展库&#xff0c;数学…

基于Java+Springboot+Vue+elememt美食论坛平台设计实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取联系&#x1f345;精彩专栏推荐订阅&#x1f447;&#x1f…

07-树(Tree)结构分析

文章目录树(Tree)结构分析什么是树&#xff1f;树中的相关名词如何理解&#xff1f;什么是二叉树&#xff1f;什么是二叉搜索树&#xff1f;什么是AVL树&#xff1f;什么是2-3树&#xff1f;什么是红黑树&#xff1f;总结&#xff08;Summary&#xff09;树(Tree)结构分析 什么…

【飞桨PaddleSpeech语音技术课程】— 语音识别-流式服务

FastAPI websocket 流式语音识别服务 0. 背景 流式语音识别(Streaming ASR)或者在线语音识别(Online ASR) 是随着输入语音的数据不断增加&#xff0c;实时给出语音识别的文本结果。与之相对的是非实时或者离线语音识别&#xff0c;是传入完整的音频数据&#xff0c;一次给出整…

ppocrlabel简单教学

前言 给我们小白成员的快速上手ppocrlabel的指南 1. ppocr环境配置 建议是先创建一个虚拟环境 【直接参考】&#xff1a;https://blog.csdn.net/weixin_42708301/article/details/119864744 2. ppocrlabel环境安装 【参考文档】PaddleOCR-release-2.6\PPOCRLabel\README_c…