全新升级tauri2.12+vite8+vue3+pinia4+elementPlus仿微信/QQ聊天软件

全新升级Tauri2.12+Vite8+Pinia4仿微信/QQ桌面级聊天TauriWChat。

tauri2-vitechat:基于tauri2.12+vue3.5+vite8.3+pinia4+element-plus零到一手搓QQ/微信客户端界面聊天Exe软件。全新tauri2多窗口管理、自定义圆角阴影窗口/导航栏。实现聊天、通讯录、收藏、朋友圈/短视频、我的等板块。

360截图20251021233301430

使用技术

  • 开发工具:VScode
  • 跨平台框架:Tauri2.12.0
  • 前端技术框架:vite^8.3.4+vue^3.5.43+vue-router^5.4.0
  • 状态管理:pinia^4.0.3
  • 本地存储:pinia-plugin-persistedstate^4.7.1
  • 组件库:element-plus^2.14.7
  • 富文本编辑器:@vueup/vue-quill^1.5.5
  • 样式管理:sass^1.105.0
  • 短视频滑动组件:swiper^14.3.0

p2

p6

项目框架目录

tauri2-vite8-winchat客户端聊天项目采用最新跨平台技术tauri2.12集成vite8.3搭建项目模板。

360截图20251021221317393

image

👆微信/哔哩哔哩扫码预览

p5-1

Tauri2-Vue3Chat聊天项目已经发布到我的原创作品集,欢迎下载使用!

Tauri2.12+Vite8+ElementPlus桌面聊天Exe程序

tauri2结合vite搭建跨平台项目

image

之前有分享一篇关于tauri2结合vite.js搭建桌面端项目、创建多窗口、自定义托盘闪烁及右键菜单。有兴趣的可以去看看。

https://www.cnblogs.com/xiaoyan2017/p/18416811

image

tauri2-vue3-chat实现类似QQ登录/主窗口切换,支持主题壁纸、自定义最大化/最小化/关闭按钮,新窗口打开朋友圈/短视频。聊天模块支持新开窗口预览图片/视频、拖拽图片到聊天区域。

360截图20251021233301431

项目布局模板

360截图20251021221317394

项目布局结构如上图所示

image

<template>
  <div class="vu__chatbox">
    <template v-if="!route?.meta?.isNewWin">
      <div
        class="vu__container flexbox flex-alignc flex-justifyc"
        :style="{'--themeSkin': appstate.config.skin}"
      >
        <div class="vu__layout flexbox flex-col">
          <div class="vu__layout-body flex1 flexbox" @contextmenu.prevent>
            <!-- 菜单栏 -->
            <slot v-if="!route?.meta?.hideMenuBar" name="menubar">
              <MenuBar />
            </slot>

            <!-- 侧边栏 -->
            <div v-if="route?.meta?.showSideBar" class="vu__layout-sidebar flexbox">
              <aside class="vu__layout-sidebar__body flexbox flex-col">
                <slot name="sidebar">
                  <SideBar />
                </slot>
              </aside>
            </div>

            <!-- 主内容区 -->
            <div class="vu__layout-main flex1 flexbox flex-col">
              <ToolBar v-if="!route?.meta?.hideToolBar" />
              <router-view v-slot="{ Component, route }">
                <keep-alive>
                  <component :is="Component" :key="route.path" />
                </keep-alive>
              </router-view>
            </div>
          </div>
        </div>
      </div>
    </template>
    <template v-else>
      <WinLayout />
    </template>
  </div>
</template>

image

image

image

360截图20251021222258498

360截图20251021222634106

360截图20251021223625471

003360截图20251021235056245

003360截图20251021235217013

003360截图20251021235322345

image

image

image

image

005360截图20251022000829133

005360截图20251022000944690

005360截图20251022001304385

006360截图20251022001924526

image

007360截图20251022002458272

image

008360截图20251022003116183

008360截图20251022003542343

image

008360截图20251022003858385

008360截图20251022005139749

008360截图20251022005252085

008360截图20251022005500412

009360截图20251022072109849

010360截图20251022072510626

image

项目入口配置main.js

import { createApp } from 'vue'
import './style.scss'
import App from './App.vue'

// 引入组件库
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

// 引入路由/状态配置
import Router from './router'
import Pinia from './pinia'

createApp(App)
.use(ElementPlus)
.use(Router)
.use(Pinia)
.mount('#app')

tauri2+vue3自定义无边框圆角阴影窗口

image

image

image

image

image

image

设置decoration: false无边框窗口模式,结合transparent: true 和 shadow: false 实现自定义圆角阴影窗口。

image

<!-- 自定义系统导航条 -->

<script setup>
  import { ref } from 'vue'
  import { isTrue } from '@/utils'

  import { winSet } from '@/windows/actions'

  import Winbtns from './btns.vue'

  const props = defineProps({
    // 标题
    title: {type: String, default: ''},
    // 标题颜色
    color: String,
    // 背景色
    background: String,
    // 标题是否居中
    center: {type: [Boolean, String], default: false},
    // 是否固定
    fixed: {type: [Boolean, String], default: false},
    // 背景是否镂空
    transparent: {type: [Boolean, String], default: false},
    // 层级
    zIndex: {type: [Number, String], default: 2024},

    /* 控制Winbtn参数 */
    // 窗口是否可最小化
    minimizable: {type: [Boolean, String], default: true},
    // 窗口是否可最大化
    maximizable: {type: [Boolean, String], default: true},
    // 窗口是否可关闭
    closable: {type: [Boolean, String], default: true},
    // 关闭前回调,会暂停实例关闭 function(done),done用于关闭
        beforeClose: Function
  })
</script>

<template>
  <div class="ev__winbar" :class="{'fixed': fixed || transparent, 'transparent': transparent}">
    <div class="ev__winbar-wrap flexbox flex-alignc vu__drag">
      <div class="ev__winbar-body flex1 flexbox flex-alignc">
        <!-- 左侧区域 -->
        <div class="ev__winbar-left"><slot name="left" /></div>
        <!-- 标题 -->
        <div class="ev__winbar-title" :class="{'center': center}">
          <slot name="title">{{title}}</slot>
        </div>
        <!-- 右侧附加区域 -->
        <div class="ev__winbar-extra vu__undrag"><slot name="extra" /></div>
      </div>
      <Winbtns :color="color" :minimizable="minimizable" :maximizable="maximizable" :closable="closable" :zIndex="zIndex" />
    </div>
  </div>
</template>

tauri设置无边框窗口后,开启拖拽功能直接在需要拖拽的元素设置 data-tauri-drag-region 或者通过如下css设置。

// 拖拽
.vu__drag {-webkit-app-region: drag;}
// 取消拖拽
.vu__undrag {-webkit-app-region: no-drag;}

Tauri2+Vite7封装多开窗口

360截图20251021233301432

/**
 * 创建新窗口
 * @param {object} args 窗口配置参数 {label: 'home', url: '/home', width: 850, height: 610, ...}
 */
export async function winCreate(args) {
  await emit('win-create', args)
}
// 主窗口
export async function mainWindow() {
  await winCreate({
    label: 'main',
    url: '/',
    title: 'TAURI-WINCHAT',
    width: 850,
    height: 620,
    minWidth: 700,
    minHeight: 450
  })
}

// 登录窗口
export async function loginWindow() {
  await winCreate({
    label: 'main-login',
    url: '/login',
    title: '登录',
    width: 320,
    height: 420,
    resizable: false,
    maximizable: false,
    alwaysOnTop: true
  })
}

// 关于窗口
export async function aboutWindow() {
  await winCreate({
    label: 'win-about',
    url: '/win/about',
    title: '关于',
    width: 320,
    height: 350,
    minWidth: 320,
    minHeight: 350,
    maximizable: false,
    alwaysOnTop: true,
  })
}

// 设置窗口
export async function settingWindow() {
  await winCreate({
    label: 'win-setting',
    url: '/win/setting',
    title: '设置',
    width: 550,
    height: 470,
    resizable: false,
    maximizable: false,
  })
}

自定义窗口参数

// 系统窗口参数(与tauri的new WebviewWindow()参数一致)
const windowBaseOptions = {
  // 窗口唯一标识label
  label: null,
  // 窗口标题
  title: '',
  // 窗口路由地址
  url: '',
  // 宽度
  width: 850,
  // 高度
  height: 620,
  // 最小宽度
  minWidth: null,
  // 最小高度
  minHeight: null,
  // 窗口x坐标
  x: null,
  // 窗口y坐标
  y: null,
  // 窗口居中显示(当设置x/y,则需要设置为false)
  center: true,
  // 是否可缩放
  resizable: true,
  // 是否可最小化
  minimizable: true,
  // 是否可最大化
  maximizable: true,
  // 是否可关闭
  closable: true,
  // 最大化窗口
  maximized: false,
  // 父窗口句柄label
  parent: null,
  // 窗口是否置顶
  alwaysOnTop: false,
  // 是否显示窗口边框(要创建无边框窗口,将decorations参数设置为false)
  decorations: false,
  // 是否透明窗口
  transparent: true,
  // 是否显示窗口阴影
  shadow: false,
  // 创建时是否显示窗口
  visible: false,
  // 禁止系统拖放
  dragDropEnabled: false
}

tauri2+vue3自定义托盘闪烁|消息提醒|托盘菜单

012360截图20251022073317041

012360截图20251022073147132

48b25ff48ccefb11103ab70a93001ad1_1289798-20240928105906610-113063713

/**
 * 自定义托盘图标
 */

use tauri::{
  tray::{MouseButton, TrayIconBuilder, TrayIconEvent}, Emitter, Manager, Runtime
};

pub fn tray_create<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
  let _ = TrayIconBuilder::with_id("tray")
    .tooltip("TAURI-WINCHAT")
    .icon(app.default_window_icon().unwrap().clone())
    .on_tray_icon_event(|tray, event| match event {
      TrayIconEvent::Click {
        id: _,
        position,
        rect: _,
        button,
        button_state: _,
      } => match button {
        MouseButton::Left {} => {
          let windows = tray.app_handle().webview_windows();
          for (key, value) in windows {
            println!("点击左键: {}", key);
            if key == "main-login" || key == "main" {
              value.show().unwrap();
              value.unminimize().unwrap();
              value.set_focus().unwrap();
            }
          }
        }
        MouseButton::Right {} => {
          println!("点击右键");
          tray.app_handle().emit("tray_contextmenu", position).unwrap();
        }
        _ => {}
      },
      TrayIconEvent::Enter {
        id: _,
        position,
        rect: _,
      } => {
        println!("鼠标滑过托盘");
        tray.app_handle().emit("tray_mouseenter", position).unwrap();
      }
      TrayIconEvent::Leave {
        id: _,
        position,
        rect: _,
      } => {
        println!("鼠标离开托盘");
        tray.app_handle().emit("tray_mouseleave", position).unwrap();
      }
      _ => {}
    })
    .build(app);
  Ok(())
}

p7

image

/**
 * Tauri自定义系统托盘右键菜单
 */

import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
import { LogicalPosition } from '@tauri-apps/api/window'
import { listen } from '@tauri-apps/api/event'

import { authState } from '@/pinia/modules/auth'

export default async function TrayContextMenu() {
  console.log('create tray contextmenu...')

  const authstate = authState()

  // 右键菜单宽度
  let menuW = 150
  // 右键菜单高度
  let menuH = authstate.authorization ? 300 : 48

  let webview = new WebviewWindow('win-traymenu', {
    url: '/tray/contextmenu',
    title: '托盘右键菜单',
    width: menuW,
    height: menuH,
    x: window.screen.width,
    y: window.screen.height,
    skipTaskbar: true,
    transparent: true,
    shadow: false,
    decorations: false,
    center: false,
    resizable: false,
    alwaysOnTop: true,
    focus: true,
    visible: false
  })

  await webview.listen('tauri://window-created', async() => {
    const win = await WebviewWindow.getByLabel('win-traymenu')
    win.hide()
  })
  await webview.listen('tauri://blur', async() => {
    const win = await WebviewWindow.getByLabel('win-traymenu')
    win.hide()
  })
  await webview.listen('tauri://error', async(error) => {
    console.log('traymenu error!', error)
  })

  // 监听托盘右键菜单事件
  listen('tray_contextmenu', async(event) => {
    console.log('tray_contextmenu: ', event)

    let position = event.payload
    const win = await WebviewWindow.getByLabel('win-traymenu')
    if(!win) return

    win.setAlwaysOnTop(true)
    win.setFocus()
    win.setPosition(new LogicalPosition(position.x - 5, position.y - menuH + 5))
    win.show()
  })
}

基于tauri2+vite8+vue3搭建桌面端聊天项目就分享到这里了,希望对大家有所帮助!

原创实战进阶项目作品👇

a88e58ebeaaf5f5a09a52686a388ed71_1289798-20251223105825806-389288273

附上几个最新版项目案例

Tauri2.9+Vue3桌面版OS系统|vite7+tauri2+arcoDesign电脑端os后台模板

最新版Flutter3.41+Dart3.11仿写抖音APP直播+短视频+聊天应用程序

Tauri2-Vite7Admin客户端管理后台|tauri2.9+vue3+element-plus后台系统

Electron38-Wechat电脑端聊天|vite7+electron38仿微信桌面端聊天系统

Electron38-Vue3OS客户端OS系统|vite7+electron38+arco桌面os后台管理

electron38-admin桌面端后台|Electron38+Vue3+ElementPlus管理系统

vite8-webos网页版os管理|Vue3+Vite8.0+ArcoDesign搭建pc端os桌面系统

Vite8+DeepSeek-V4.1网页版AI助手|vue3+arco手搓web版ai流式问答系统

uniapp+deepseek-v4.1-flash+vue3跨端流式ai应用【h5+小程序+app端】

最新版uni-app+vue3+uv-ui跨三端仿微信app聊天应用【h5+小程序+app端】

Flutter3-MacOS桌面OS系统|flutter3.41+window_manager客户端OS模板

最新版Flutter3.41+Dart3.11跨平台仿微信app聊天界面|朋友圈

最新版uni-app+vue3+uv-ui跨端仿携程酒店预订模板【H5+小程序+App端】

bc4aece373eb151cc7b3f713b82c0b33_1289798-20250802113616778-934603975

 

posted @ 2026-10-10 11:48  xiaoyan2017  阅读(16)  评论(0)    收藏  举报
友情链接: UP主小店B站