<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      基于Tauri2+Vue3搭建桌面端程序|tauri2+vite5多窗口|消息提醒|托盤閃爍

      基于tauri2+vite5+vue3封裝多窗口實(shí)踐|自定義消息提醒|托盤右鍵菜單及圖標(biāo)閃爍

      這段時(shí)間一直在搗鼓最新版Tauri2.x整合Vite5搭建桌面端多開窗體應(yīng)用實(shí)踐。tauri2.0相較于1.0版本api有了比較多的更改,而且tauri2支持創(chuàng)建android/ios應(yīng)用。至于具體的api變更,大家可以去官網(wǎng)查閱文檔資料。

      https://v2.tauri.app/start/migrate/from-tauri-1/

      Tauri2.8+Vue3聊天系統(tǒng)|vite7+tauri2+element-plus客戶端仿微信聊天程序

      Tauri2.0-Vue3OS桌面端os平臺(tái)|tauri2+vite6+arco電腦版OS管理系統(tǒng)

      Tauri2-Vite7Admin客戶端管理后臺(tái)|tauri2.9+vue3+element-plus后臺(tái)系統(tǒng)

      版本信息

      "@tauri-apps/api": ">=2.0.0-rc.0",
      "@tauri-apps/cli": ">=2.0.0-rc.0",
      "vue": "^3.3.4",
      "vite": "^5.3.1"

      創(chuàng)建tauri2+vue3項(xiàng)目模板

      官網(wǎng)提供了多種方式創(chuàng)建tauri2+vue3項(xiàng)目。

      // 創(chuàng)建項(xiàng)目模板
      yarn create tauri-app --rc
      // 進(jìn)入項(xiàng)目目錄
      cd tauri-app
      // 安裝依賴
      yarn
      // 運(yùn)行項(xiàng)目
      yarn tauri dev

      內(nèi)置了多種熱門前端框架模板可供選擇。

      // 運(yùn)行到桌面端
      yarn tauri dev
      // 初始化android
      yarn tauri android init
      // 運(yùn)行到android
      yarn tauri android dev

      至此一個(gè)簡(jiǎn)單的tauri2+vue3初始化項(xiàng)目模板就搭建好了。

      tauri2封裝多窗口管理

      通過封裝一個(gè)tauri多窗口類,只需傳入配置參數(shù),即可快速創(chuàng)建一個(gè)新窗體,簡(jiǎn)化調(diào)用方式。

      createWin({
          label: 'manage',
          title: '管理頁面',
          url: '/manage',
          width: 960,
          height: 750,
          center: false,
          x: 320,
          y: 500,
          resizable: false,
          alwaysOnTop: true,
      })

      /**
       * @desc    Tauri2多窗口封裝管理
       * @author: Andy  QQ:282310962
       * @time    2024.9
       */
      
      import { getAllWindows, getCurrentWindow } from '@tauri-apps/api/window'
      import { WebviewWindow, getAllWebviewWindows, getCurrentWebviewWindow} from '@tauri-apps/api/webviewWindow'
      import { relaunch, exit } from '@tauri-apps/plugin-process'
      import { emit, listen } from '@tauri-apps/api/event'
      
      import { setWin } from './actions'
      
      const appWindow = getCurrentWindow()
      
      // 創(chuàng)建窗口參數(shù)配置
      export const windowConfig = {
          label: null,            // 窗口唯一label
          title: '',              // 窗口標(biāo)題
          url: '',                // 路由地址url
          width: 1000,            // 窗口寬度
          height: 640,            // 窗口高度
          minWidth: null,         // 窗口最小寬度
          minHeight: null,        // 窗口最小高度
          x: null,                // 窗口相對(duì)于屏幕左側(cè)坐標(biāo)
          y: null,                // 窗口相對(duì)于屏幕頂端坐標(biāo)
          center: true,           // 窗口居中顯示
          resizable: true,        // 是否支持縮放
          maximized: false,       // 最大化窗口
          decorations: false,     // 窗口是否裝飾邊框及導(dǎo)航條
          alwaysOnTop: false,     // 置頂窗口
          dragDropEnabled: false, // 禁止系統(tǒng)拖放
          visible: false,         // 隱藏窗口
      
          // ...
      }
      
      class Windows {
          constructor() {
              // 主窗口
              this.mainWin = null
          }
      
          // 創(chuàng)建新窗口
          async createWin(options) {
              console.log('-=-=-=-=-=開始創(chuàng)建窗口')
      
              const args = Object.assign({}, windowConfig, options)
      
              // 判斷窗口是否存在
              const existWin = await this.getWin(args.label)
              if(existWin) {
                  console.log('窗口已存在>>', existWin)
                  // ...
              }
              // 創(chuàng)建窗口對(duì)象
              const win = new WebviewWindow(args.label, args)
      
              // 窗口創(chuàng)建完畢/失敗
              win.once('tauri://created', async() => {
                  console.log('tauri://created')
                  // 是否主窗口
                  if(args.label.indexOf('main') > -1) {
                      // ...
                  }
      
                  // 是否最大化
                  if(args.maximized && args.resizable) {
                      console.log('is-maximized')
                      await win.maximize()
                  }
              })
      
              win.once('tauri://error', async(error) => {
                  console.log('window create error!', error)
              })
          }
      
          // 獲取窗口
          async getWin(label) {
              return await WebviewWindow.getByLabel(label)
          }
      
          // 獲取全部窗口
          async getAllWin() {
              //  return getAll()
              return await getAllWindows()
          }
      
          // 開啟主進(jìn)程監(jiān)聽事件
          async listen() {
              console.log('——+——+——+——+——+開始監(jiān)聽窗口')
      
              // 創(chuàng)建新窗體
              await listen('win-create', (event) => {
                  console.log(event)
                  this.createWin(event.payload)
              })
      
              // 顯示窗體
              await listen('win-show', async(event) => {
                  if(appWindow.label.indexOf('main') == -1) return
                  await appWindow.show()
                  await appWindow.unminimize()
                  await appWindow.setFocus()
              })
      
              // 隱藏窗體
              await listen('win-hide', async(event) => {
                  if(appWindow.label.indexOf('main') == -1) return
                  await appWindow.hide()
              })
      
              // 關(guān)閉窗體
              await listen('win-close', async(event) => {
                  await appWindow.close()
              })
      
              // ...
          }
      }
       
      export default Windows

      actions.js封裝一些調(diào)用方法。

      import { emit } from '@tauri-apps/api/event'
      
      /**
       * @desc 創(chuàng)建新窗口
       * @param args {object} {label: 'new', url: '/new', width: 500, height: 300, ...}
       */
       export async function createWin(args) {
          await emit('win-create', args)
      }
      
      // ...
      
      /**
       * @desc 登錄窗口
       */
       export async function loginWin() {
          await createWin({
              label: 'main_login',
              title: '登錄',
              url: '/login',
              width: 400,
              height: 320,
              resizable: false,
              alwaysOnTop: true
          })
      }
      
      export async function mainWin() {
          await createWin({
              label: 'main',
              title: 'TAURI-WINDOWMANAGER',
              url: '/',
              width: 800,
              height: 600,
              minWidth: 500,
              minHeight: 360,
          })
      }
      
      export async function aboutWindow() {
          await createWin({
              label: 'about',
              title: '關(guān)于',
              url: '/about',
              width: 450,
              height: 360,
          })
      }

      最新原創(chuàng)重磅新作Tauri2+Vue3仿微信客戶端聊天同步到我的原創(chuàng)作品集。

      自研tauri2+vite5+element-plus客戶端仿微信Exe聊天實(shí)例

      tauri2創(chuàng)建系統(tǒng)托盤圖標(biāo)|托盤閃爍消息提醒|托盤右鍵菜單

      tauri2創(chuàng)建系統(tǒng)托盤圖標(biāo),實(shí)現(xiàn)類似QQ消息提醒,自定義托盤右鍵菜單。

      在src-tauri/src目錄下,新建一個(gè)tray.rs托盤文件。

      use tauri::{
          tray::{MouseButton, TrayIconBuilder, TrayIconEvent}, Emitter, Manager, Runtime
      };
      use std::thread::{sleep};
      use std::time::Duration;
      
      pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
          let _ = TrayIconBuilder::with_id("tray")
              .tooltip("tauri")
              .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 {} => {
                          // ...
                      }
                      MouseButton::Right {} => {
                          tray.app_handle().emit("tray_contextmenu", position).unwrap();
                      }
                      _ => {}
                  },
                  TrayIconEvent::Enter {
                      id: _,
                      position,
                      rect: _,
                  } => {
                      tray.app_handle().emit("tray_mouseenter", position).unwrap();
                  }
                  TrayIconEvent::Leave {
                      id: _,
                      position,
                      rect: _,
                  } => {
                      // sleep(Duration::from_millis(500));
                      tray.app_handle().emit("tray_mouseleave", position).unwrap();
                  }
                  _ => {}
              })
              .build(app);
          Ok(())
      }

      在lib.rs中引入托盤配置。

      // ...
      
      mod tray;
      
      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              // ...
              .setup(|app| {
                  #[cfg(all(desktop))]
                  {
                      let handle = app.handle();
                      tray::create_tray(handle)?;
                  }
                  Ok(())
              })
              .invoke_handler(tauri::generate_handler![greet])
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      • 托盤消息提醒

      新建一個(gè)msg新窗口,通過獲取鼠標(biāo)滑過托盤圖標(biāo)的position坐標(biāo)給到msg窗口x,y參數(shù)

      import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
      import { emit, listen } from '@tauri-apps/api/event'
      import { LogicalPosition } from '@tauri-apps/api/window'
      
      export let messageBoxWindowWidth = 280
      export let messageBoxWindowHeight = 100
      
      export default async function CreateMsgBox() {
          console.log('start create msgbox...')
      
          let webview = new WebviewWindow("msgbox", {
              url: "/msg",
              title: "消息通知",
              width: messageBoxWindowWidth,
              height: messageBoxWindowHeight,
              skipTaskbar: true,
              decorations: false,
              center: false,
              resizable: false,
              alwaysOnTop: true,
              focus: true,
              x: window.screen.width + 50,
              y: window.screen.height + 50,
              visible: false
          })
      
          // 托盤消息事件
          await webview.listen('tauri://window-created', async () => {
              console.log('msgbox create')
          })
          await webview.listen('tauri://blur', async () => {
              console.log('msgbox blur')
              const win = await WebviewWindow.getByLabel('msgbox')
              await win.hide()
          })
          await webview.listen('tauri://error', async(error) => {
              console.log('msgbox error!', error)
          })
      
      
          // 監(jiān)聽托盤事件
          let trayEnterListen = listen('tray_mouseenter', async (event) => {
              // console.log(event)
      
              const win = await WebviewWindow.getByLabel('msgbox')
              if(!win) return
      
              let position = event.payload
              if(win) {
                  await win.setAlwaysOnTop(true)
                  await win.setFocus()
                  await win.setPosition(new LogicalPosition(position.x - messageBoxWindowWidth / 2, window.screen.availHeight - messageBoxWindowHeight))
                  await win.show()
              }
          })
          let trayLeaveListen = listen('tray_mouseleave', async (event) => {
              console.log(event)
              const win = await WebviewWindow.getByLabel('msgbox')
              await win.hide()
          })
      }

      封裝設(shè)置托盤圖標(biāo)閃爍 flashTray(true) 和取消閃爍 flashTray(false) 

      <script setup>
          // ...
      
          const flashTimer = ref(false)
          const flashTray = async(bool) => {
              let flag = true
              if(bool) {
                  TrayIcon.getById('tray').then(async(res) => {
                      clearInterval(flashTimer.value)
                      flashTimer.value = setInterval(() => {
                          if(flag) {
                              res.setIcon(null)
                          }else {
                              // 支持把自定義圖標(biāo)放在默認(rèn)icons文件夾,通過如下方式設(shè)置圖標(biāo)
                              // res.setIcon('icons/msg.png')
                              // 支持把自定義圖標(biāo)放在自定義文件夾tray,需要配置tauri.conf.json參數(shù) "bundle": {"resources": ["tray"]}
                              res.setIcon('tray/msg.png')
                          }
                          flag = !flag
                      }, 500)
                  })
              }else {
                  clearInterval(flashTimer.value)
                  let tray = await TrayIcon.getById("tray")
                  tray.setIcon('icons/icon.png')
              }
          }
      </script>

      托盤圖標(biāo)也支持放在自定義文件夾。

      比如:托盤圖標(biāo)放在自定義文件夾tray,則需要配置tauri.conf.json文件resources字段。

      "bundle": {
          ...
          "resources": [
            "tray"
          ]
      },
      • 托盤右鍵菜單

      其實(shí)右鍵菜單窗口和消息提醒窗口原理差不多。

      import { ref } from 'vue'
      import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
      import { emit, listen } from '@tauri-apps/api/event'
      import { PhysicalPosition, LogicalPosition } from '@tauri-apps/api/window'
      import { TrayIcon } from '@tauri-apps/api/tray'
      import { invoke } from '@tauri-apps/api/core'
      
      export let menuBoxWindowWidth = 150
      export let menuBoxWindowHeight = JSON.parse(localStorage.getItem('logged')) ? 320 : 45
      
      export default async function CreateTraymenu() {
          console.log('start create traymenu...')
          
          let webview = new WebviewWindow("traymenu", {
              url: "/menu",
              title: "消息通知",
              width: menuBoxWindowWidth,
              height: menuBoxWindowHeight,
              skipTaskbar: true,
              decorations: false,
              center: false,
              resizable: false,
              alwaysOnTop: true,
              focus: true,
              x: window.screen.width + 50,
              y: window.screen.height + 50,
              visible: false
          })
      
          // 托盤消息事件
          await webview.listen('tauri://window-created', async () => {
              console.log('traymenu create')
          })
          await webview.listen('tauri://blur', async () => {
              console.log('traymenu blur')
              const win = await WebviewWindow.getByLabel('traymenu')
              await win.hide()
          })
          await webview.listen('tauri://error', async(error) => {
              console.log('traymenu error!', error)
          })
      
      
          // 監(jiān)聽托盤事件
          let trayEnterListen = listen('tray_contextmenu', async (event) => {
              console.log(event)
      
              const win = await WebviewWindow.getByLabel('traymenu')
              if(!win) return
      
              let position = event.payload
              if(win) {
                  await win.setAlwaysOnTop(true)
                  await win.setFocus()
                  await win.setPosition(new LogicalPosition(position.x, position.y - menuBoxWindowHeight))
                  await win.show()
              }
          })
      }
      <!--托盤右鍵菜單-->
      <script setup>
      import { ref } from 'vue'
      import { WebviewWindow } from "@tauri-apps/api/webviewWindow"
      import { TrayIcon } from '@tauri-apps/api/tray'
      import { invoke } from '@tauri-apps/api/core'
      
          const logged = JSON.parse(localStorage.getItem('logged'))
      
          const handleMainShow = async () => {
              const traywin = await WebviewWindow.getByLabel('traymenu')
              await traywin.hide()
      
              const homewin = await WebviewWindow.getByLabel('main')
              await homewin.show()
              await homewin.unminimize()
              await homewin.setFocus()
          }
      
          const flashTimer = ref(false)
          const flashTray = async(bool) => {
              let flag = true
              if(bool) {
                  TrayIcon.getById('tray').then(async(res) => {
                      clearInterval(flashTimer.value)
                      flashTimer.value = setInterval(() => {
                          if(flag) {
                              res.setIcon(null)
                          }else {
                              // res.setIcon(defaultIcon)
                              // 支持把自定義圖標(biāo)放在默認(rèn)icons文件夾,通過如下方式設(shè)置圖標(biāo)
                              // res.setIcon('icons/msg.png')
                              // 支持把自定義圖標(biāo)放在自定義文件夾tray,需要配置tauri.conf.json參數(shù) "bundle": {"resources": ["tray"]}
                              res.setIcon('tray/msg.png')
                          }
                          flag = !flag
                      }, 500)
                  })
              }else {
                  clearInterval(flashTimer.value)
                  let tray = await TrayIcon.getById("tray")
                  tray.setIcon('icons/icon.png')
              }
          }
      </script>
      
      <template>
          <div v-if="logged" class="traymenu">
              <p class="item">?? 我在線上</p>
              <p class="item">?? 隱身</p>
              <p class="item">?? 離開</p>
              <p class="item">?? 忙碌</p>
              <p class="item">關(guān)閉所有聲音</p>
              <p class="item" @click="flashTray(true)">開啟圖標(biāo)閃爍</p>
              <p class="item" @click="flashTray(false)">關(guān)閉圖標(biāo)閃爍</p>
              <p class="item" @click="handleMainShow">?? 打開主面板</p>
              <p class="item">?? 退出</p>
          </div>
          <div v-else class="traymenu">
              <p class="item">?? 退出</p>
          </div>
      </template>

      綜上就是tauri2+vue3開發(fā)多窗口實(shí)踐,自定義托盤圖標(biāo)消息提醒,右鍵菜單的一些簡(jiǎn)單分享,效果還是比較粗糙,主要是為了實(shí)現(xiàn)功能思路,希望以上分享對(duì)大家有所幫助哈!

      Uniapp-DeepSeek跨三端AI助手|uniapp+vue3+deepseek-v3流式ai聊天模板

      Electron35-DeepSeek桌面端AI系統(tǒng)|vue3.5+electron+arco客戶端ai模板

      uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天語音/朋友圈

      uniapp+vue3酒店預(yù)訂|vite5+uniapp預(yù)約訂房系統(tǒng)模板(h5+小程序+App端)

      分享兩篇最新Tauri v2.0+Vite5+ElementPlus實(shí)戰(zhàn)項(xiàng)目案例,感興趣的可以去看看。

      http://www.rzrgm.cn/xiaoyan2017/p/18437155

      http://www.rzrgm.cn/xiaoyan2017/p/18467237

      Ending,附上幾個(gè)重磅Electron桌面端原創(chuàng)實(shí)例項(xiàng)目

      Electron38-Vue3OS客戶端OS系統(tǒng)|vite7+electron38+arco桌面os后臺(tái)管理

      Electron38-Wechat電腦端聊天|vite7+electron38仿微信桌面端聊天系統(tǒng)

      electron38-admin桌面端后臺(tái)|Electron38+Vue3+ElementPlus管理系統(tǒng)

       

      posted @ 2024-09-17 00:45  xiaoyan2017  閱讀(8906)  評(píng)論(0)    收藏  舉報(bào)
      友情鏈接: UP主小店B站
      主站蜘蛛池模板: 国语精品一区二区三区| 成人亚洲一区二区三区在线| 性xxxx视频播放免费| 国产成人精品性色av麻豆| 大肉大捧一进一出视频| 日夜啪啪一区二区三区| 又大又紧又粉嫩18p少妇| 女人与牲口性恔配视频免费| 十八禁国产一区二区三区| 久久国产av影片| 中文字幕乱码人妻综合二区三区| 人妻另类 专区 欧美 制服| 不卡高清AV手机在线观看| 国产网友愉拍精品视频手机| 在线观看亚洲欧美日本| 国产青榴视频在线观看| 91中文字幕在线一区| 欧洲码亚洲码的区别入口| 久久夜夜免费视频| 亚洲gv天堂无码男同在线观看| 国产va免费精品观看| 久久天天躁狠狠躁夜夜躁2012| 浓毛老太交欧美老妇热爱乱| 精品国产一区二区亚洲人| 国产亚洲精品VA片在线播放| 日日噜噜夜夜狠狠视频| 九九热在线免费观看视频| 久久综合香蕉国产蜜臀av| 国产日韩av一区二区在线| 四虎国产精品永久入口| 精品卡通动漫亚洲AV第一页| 亚洲精品三区二区一区一| 国产老女人精品免费视频| 国产一区二区不卡91| 你懂的一区二区福利视频| 精品91在线| 水蜜桃av无码| 亚洲理论电影在线观看| 国产精品福利中文字幕| 国产日韩乱码精品一区二区| 婷婷四虎东京热无码群交双飞视频 |