Tauri 2.3.1+Leptos 0.7.8開發桌面應用--Sqlite數據庫選中數據的表格輸出

在前期工作的基礎上(Tauri 2.3.1+Leptos 0.7.8開發桌面應用--Sqlite數據庫的寫入、展示和選擇刪除_tauri leptos sqlite 選擇刪除-CSDN博客),實現將選中的數據實時用表格展示出來,效果如下:

1. 后臺invoke調用命令

Tauri后臺lib.rs文件中send_seleted_pdt命令的代碼如下:?

#[tauri::command]
async fn send_selected_pdt(state: tauri::State<'_, DbState>, productlist:Vec<i64>) -> Result<Vec<Pdt>, String> {// 參數名productlist必須與前端定義的結構變量SelectedPdtArgs的鍵值一致let db = &state.db;// 處理空數組的情況if productlist.is_empty() {return Err(String::from("讀取失敗:未提供有效的產品ID"));}// 生成動態占位符(根據數組長度生成 ?, ?, ?)let placeholders = vec!["?"; productlist.len()].join(", ");let query_str = format!("SELECT * FROM products WHERE pdt_id IN ({})",placeholders);// 構建查詢并綁定參數let mut query = sqlx::query_as::<_, Pdt>(&query_str);for id in &productlist {query = query.bind(id);}// 執行讀取操作let query_result = query.fetch_all(db).await.map_err(|e| format!("查詢失敗: {}", e))?;Ok(query_result)}

?命令的返回格式為?Result<Vec<Pdt>, String>,Pdt為結構變量,定義如下:

#[derive(Debug, Serialize, Deserialize, FromRow)]
struct Pdt {pdt_id:i64,         //sqlx 會將 SQLite 的 INTEGER 類型映射為 i64(64 位有符號整數)pdt_name:String,pdt_si:f64,pdt_al:f64,pdt_ca:f64,pdt_mg:f64,pdt_fe:f64,pdt_ti:f64,pdt_ka:f64,pdt_na:f64,pdt_mn:f64,pdt_date:String,
}

然后還需對send_selected_pdt命令進行注冊:

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {tauri::Builder::default().plugin(tauri_plugin_opener::init()).invoke_handler(tauri::generate_handler![send_selected_pdt]).menu(|app|{create_menu(app)}).setup(|app| {let main_window = app.get_webview_window("main").unwrap();main_window.on_menu_event(move |window, event| handle_menu_event(window, event));#[cfg(all(desktop))]{let handle = app.handle();tray::create_tray(handle)?;         //設置app系統托盤}tauri::async_runtime::block_on(async move {let db = setup_db(&app).await;         //setup_db(&app:&mut App)返回讀寫的數據庫對象app.manage(DbState { db });                   //通過app.manage(DbState{db})把數據庫對象傳遞給state:tauri::State<'_, DbState>});Ok(())}).run(tauri::generate_context!()).expect("運行Tauri程序的時候出錯!");
}

2. Leptos前端調用并使用表格展示

首先要定義相應的信號,然后在展示的所有數據前面添加復選框,定義復選框選中事件,根據選中數據的Pdt_id列表,實時讀取數據庫的產品數據,并通過表格展示。

信號定義、復選框選中事件函數check_change、讀取數據庫所有數據庫按鈕事件函數receive_pdt_db代碼如下:

#[component]
pub fn AcidInput() -> impl IntoView {         //函數返回IntoView類型,即返回view!宏,函數名App()也是主程序view!宏中的組件名(component name)。let (div_content, set_div_content) = signal(view! { <div>{Vec::<View<_>>::new()}</div> });let (selected_items, set_selected_items) = signal::<Vec<i64>>(vec![]);let (selected_pdt_data, set_selected_pdt_data) = signal::<Vec<Pdt>>(vec![]);let (data, set_data) = signal::<Vec<DataPoint>>(vec![]);//處理復選框事件,選中的同時展示在表格中let check_change = move |ev:leptos::ev::Event|{//ev.prevent_default(); spawn_local(async move {let target = event_target::<HtmlInputElement>(&ev);let value_str = target.value(); // 直接獲取 value// 將字符串解析為 i64(需處理可能的錯誤)if let Ok(value) = value_str.parse::<i64>() {set_selected_items.update(|items| {if target.checked() {               //target.checked與prop:checked不一樣, 是瀏覽器 DOM 的實時狀態,用于事件處理items.push(value);} else {items.retain(|&x| x != value);}});};//接收讀取的數據log!("選中的數據列表: {:?}", selected_items.get_untracked());if selected_items.get_untracked().len() != 0 {let args = SelectedPdtArgs{productlist:selected_items.get_untracked(),};let args_js = serde_wasm_bindgen::to_value(&args).unwrap();   //參數序列化let pdt_js = invoke("send_selected_pdt", args_js).await;let pdt_vec: Vec<Pdt> = serde_wasm_bindgen::from_value(pdt_js).map_err(|_| JsValue::from("Deserialization error")).unwrap();set_selected_pdt_data.set(pdt_vec);//log!("返回的產品數據: {:?}", selected_pdt_data.get_untracked());}else{set_selected_pdt_data.set(vec![]);}});};let receive_pdt_db = move |ev: SubmitEvent| {ev.prevent_default();spawn_local(async move {                //使用Leptos的spawn_local創建一個本地線程(local_thread)Future, 提供一個異步move閉包。let pdt_js = invoke_without_args("send_pdt_db").await;let pdt_vec: Vec<Pdt> = serde_wasm_bindgen::from_value(pdt_js).map_err(|_| JsValue::from("Deserialization error")).unwrap();let mut receive_msg = String::from("讀取數據庫ID序列為:[");// 構建日志消息(注意:pdt_vec 已被消耗,需提前克隆或調整邏輯)let pdt_ids: Vec<i64> = pdt_vec.iter().map(|pdt| pdt.pdt_id).collect();for id in pdt_ids {receive_msg += &format!("{}, ", id);}receive_msg += "]";// 動態生成包裹在 div 中的視圖let div_views = view! {<div>{pdt_vec.into_iter().map(|pdt| {let pdt_id = pdt.pdt_id;view! {<div style="margin:5px;width:1500px;"><inputtype="checkbox"name="items"value=pdt_id.to_string()prop:checked=move || selected_items.get().contains(&pdt_id)     //Leptos 的狀態綁定,用于確保界面最終與數據同步。on:change=check_change      //用戶操作 → 更新 target.checked → 觸發事件check_change → 更新狀態 → prop:checked 驅動視圖更新。/><span>// 直接使用 Unicode 下標字符"PdtID: " {pdt_id}",產品名稱: " {pdt.pdt_name}",SiO?: " {pdt.pdt_si} "%"",Al?O?: " {pdt.pdt_al} "%"",CaO: " {pdt.pdt_ca} "%"",MgO: " {pdt.pdt_mg} "%"",Fe?O?: " {pdt.pdt_fe} "%"",TiO?: " {pdt.pdt_ti} "%"",K?O: " {pdt.pdt_ka} "%"",Na?O: " {pdt.pdt_na} "%"",MnO?: " {pdt.pdt_mn} "%"",生產日期: " {pdt.pdt_date}</span></div>}}).collect_view()}</div>}; // 關鍵的類型擦除;// 轉換為 View 類型并設置//log!("視圖類型: {:?}", std::any::type_name_of_val(&div_views));set_div_content.set(div_views); set_sql_error.set(receive_msg);});};
};

其中,結構變量Pdt定義如下:

#[derive(Serialize, Deserialize, Clone, Debug)]
struct Pdt {pdt_id:i64,pdt_name:String,pdt_si:f64,pdt_al:f64,pdt_ca:f64,pdt_mg:f64,pdt_fe:f64,pdt_ti:f64,pdt_ka:f64,pdt_na:f64,pdt_mn:f64,pdt_date:String,
}

views!視圖中表格部分內容如下:

<div style="flex: 1;"><PdtTable data=move || selected_pdt_data.get() x_bg_color="red-100"   // 對應 --red-100-bgx_text_color="red-800" // 對應 --red-800-text/>
</div>

其中調用了視圖命令PdtTable,具體代碼如下:

#[component]
fn PdtTable<F>(data: F,// 顏色參數(變量)用于設置 CSS 變量 (對應 styles.css 中定義的變量)#[prop(default = "blue-100")]  // 對應 --blue-100-bgx_bg_color: &'static str,#[prop(default = "blue-800")]  // 對應 --blue-800-textx_text_color: &'static str,#[prop(default = "green-100")] // 對應 --green-100-bgy_bg_color: &'static str,#[prop(default = "green-800")] // 對應 --green-800-texty_text_color: &'static str,
) -> impl IntoView
whereF: Fn() -> Vec<Pdt> + 'static + Send + Sync + Clone,
{view! {<table class="table-container" style="border-collapse: collapse; border: 3px double black;"><thead><tr><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>ID</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>產品名稱</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>"SiO2"</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>"Al2O3"</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>"CaO"</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>"MgO"</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>"Fe2O3"</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>"TiO2"</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>"K2O"</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>"Na2O"</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>"MnO2"</th><th class="table-header-cell" style:background-color=move || format!("var(--{}-bg)", x_bg_color) style:color=move || format!("var(--{}-text)", x_text_color)>生產日期</th></tr></thead><tbody>{move || data().into_iter().map(|pdt| view! {<tr><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{pdt.pdt_id}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{pdt.pdt_name}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{format!("{:.2}", pdt.pdt_si)}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{format!("{:.2}", pdt.pdt_al)}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{format!("{:.2}", pdt.pdt_ca)}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{format!("{:.2}", pdt.pdt_mg)}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{format!("{:.2}", pdt.pdt_fe)}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{format!("{:.2}", pdt.pdt_ti)}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{format!("{:.2}", pdt.pdt_ka)}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{format!("{:.2}", pdt.pdt_na)}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{format!("{:.2}", pdt.pdt_mn)}</td><td class="table-data-cell" style:background-color=move || format!("var(--{}-bg)", y_bg_color) style:color=move || format!("var(--{}-text)", y_text_color)>{pdt.pdt_date}</td></tr>}).collect_view()}</tbody></table>}
}

需要強調的是:Leptos 的響應式系統要求組件閉包能在多線程環境中安全傳遞,所以<PdtTable data= move || selected_pdt_data.get() />中閉包要實現線程安全約束(Send + Sync)。具體在程序中為泛型F添加線程安全約束:Send + Sync,為了便于后面克隆,添加Clone約束。

另外在PdtTable中定義了顏色參數(變量)用于設置 CSS 變量,以及用的自定義class,需要在styles.css中添加如下內容:

  .table-container {margin-left: auto;margin-right: auto;border-collapse: collapse;border: 3px double #d1d5db;}.table-header-cell {position: sticky;left: 0;background-color: #e5e7eb;padding: 0.5rem 1rem;border: 1px solid #d1d5db;}.table-data-cell {padding: 0.5rem 1rem;min-width: 20px;border: 1px solid #d1d5db;}:root {--blue-100-bg: #dbeafe;--blue-800-text: #1e40af;--red-100-bg: #fee2e2;--red-800-text: #991b1b;--green-100-bg: #dcfce7;--green-800-text: #166534;}

至此,基本就完成了將數據庫選中數據實時用表格顯示出來。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/78086.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/78086.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/78086.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用Tauri 2.3.1+Leptos 0.7.8開發桌面小程序匯總

近期斷斷續續學習了Rust編程&#xff0c;使用Tauri 2.3.1Leptos 0.7.8開發了一個自用的桌面小程序。Win10操作系統&#xff0c;使用VS Code及rust analyzer插件搭建的開發環境&#xff0c;后期開始使用Roo Code綁定DeepSeek API 輔助編程&#xff0c;對我這個初學者編程幫助很大…

考研英一學習筆記

2024 年全國碩士研究生招生考試 英語&#xff08;一&#xff09;試題 &#xff08;科目代碼&#xff1a;201&#xff09; Section Ⅰ Use of English Directions: Read the following text. Choose the best word(s) for each numbered blank and mark A, B, C or D on the ANS…

【技術筆記】Cadence實現Orcad與Allegro軟件交互式布局設置

【技術筆記】Cadence實現Orcad與Allegro軟件交互式布局設置 更多內容見專欄&#xff1a;【硬件設計遇到了不少問題】、【Cadence從原理圖到PCB設計】 在做硬件pcb設計的時候&#xff0c;原理圖選中一個元器件&#xff0c;希望可以再PCB中可以直接選中。 為了達到原理圖和PCB兩兩…

卷積神經網絡(CNN)詳解

文章目錄 引言1.卷積神經網絡&#xff08;CNN&#xff09;的誕生背景2.卷積神經網絡&#xff08;CNN&#xff09;介紹2.1 什么是卷積神經網絡&#xff1f;2.2 卷積神經網絡&#xff08;CNN&#xff09;的基本特征2.2.1 局部感知&#xff08;Local Connectivity&#xff09;2.2.…

8051單片機所有Keil C51匯編偽指令和C語言關鍵字大全

8051單片機所有Keil C51匯編偽指令和C語言關鍵字大全 作者將狼才鯨創建日期2025-04-21 CSDN閱讀地址&#xff1a;8051單片機所有Keil匯編偽指令和C語言關鍵字的詳細解釋 8051單片機所有Keil匯編偽指令和C語言關鍵字的詳細解釋&#xff0c;在Keil已安裝文件夾D:\Keil_v5\C51\H…

機器視覺的智能手機屏貼合應用

在智能手機制造領域&#xff0c;屏幕貼合工藝堪稱"微米級的指尖芭蕾"。作為影響觸控靈敏度、顯示效果和產品可靠性的關鍵工序&#xff0c;屏幕貼合精度直接決定了用戶體驗。傳統人工對位方式已無法滿足全面屏時代對極窄邊框和超高屏占比的嚴苛要求&#xff0c;而Mast…

運維打鐵:網絡基礎知識

文章目錄 一、網絡架構1. 網絡架構圖2. 各層級功能3. 機房網絡常見問題及解決方案 二、交換技術1. 交換技術基礎2. 交換技術分類3. 廣播域相關概念4. ARP 協議5. 三層交換機6. VLAN&#xff08;虛擬局域網&#xff09; 三、路由技術1. 路由器端口類型及功能2. 路由器功能3. 路由…

使用C#和FFmpeg開發RTSP視頻播放器的完整指南

RTSP(Real Time Streaming Protocol)是流媒體技術中廣泛使用的協議&#xff0c;廣泛應用于視頻監控、視頻會議和在線直播等領域。本文將詳細介紹如何使用C#和FFmpeg開發一個功能完整的RTSP視頻播放器&#xff0c;涵蓋從環境搭建到核心功能實現的全部過程。 一、開發環境準備 …

前端基礎之《Vue(9)—混入》

一、什么是混入 1、是一種代碼復用的技巧 Vue組件是由若干選項組成的&#xff0c;向組件中混入可復用的選項。 2、作用 比如我封裝兩個組件&#xff0c;一個是A組件&#xff0c;一個是B組件&#xff0c;發現它里面有相同的選項&#xff0c;就可以用混用的方式來復用它。 二、…

Anything V4/V5 模型匯總

??????二次元風格生成擴散模型-anything-v4.0Stable Diffusion anything-v5-PrtRE模型介紹及使用深度探索 Anything V5&#xff1a;安裝與使用全攻略anything-v5x0.25少兒插畫_v1xyn-ai/anything-v4.0

一天學完Servlet!!!(萬字總結)

文章目錄 前言Servlet打印Hello ServletServlet生命周期 HttpServletRequest對象常用api方法請求亂碼問題請求轉發request域對象 HttpServletResponse對象響應數據響應亂碼問題請求重定向請求轉發與重定向區別 Cookie對象Cookie的創建與獲取Cookie設置到期時間Cookie注意點Cook…

Springboot整合 xxljob,自定義添加、修改、刪除、停止、啟動任務

目錄 一、模擬登錄方式 二、注解方式 三、訪問者調用 四、測試 本次自定義方式分為兩種&#xff1a;一種是模擬登錄&#xff0c;另一種是使用注解的方式 一、模擬登錄方式 修改xxl-job-admin工程&#xff0c;在controller里面添加一個MyApiController&#xff0c;在里面添…

STM32F407使用ESP8266實現阿里云OTA(中)

文章目錄 前言一、程序分析二、程序講解1. main函數2. Get_Version()函數3. esp_Init()函數4. Check_Updata()函數結語前言 從上一章STM32F407使用ESP8266實現阿里云OTA(上)中我們已經對連接阿里云和從阿里云獲取升級包的流程非常的熟悉了。所以本章我們進行STM32的程序開發…

Docker部署DeepSeek常見問題及解決方案

在使用Docker部署DeepSeek的過程中,許多開發者可能會遇到一些常見問題。本文整理了幾個高頻問題及其解決方案,幫助大家更順利地完成部署。 鏡像拉取失敗 問題現象 執行 docker pull 命令時,提示超時或鏡像不存在。 可能原因 1. 網絡環境不穩定,導致連接Docker Hub失敗…

Linux 內核 IPv4 套接字創建機制與協議表管理深度解析

一、inet_create:IPv4 套接字創建的核心引擎 1.1 核心功能與執行流程 inet_create 是 Linux 內核處理 socket(AF_INET, type, protocol) 系統調用的核心實現,主要完成以下關鍵任務: 協議匹配與初始化:根據套接字類型和協議號匹配協議處理模塊 資源分配:創建并初始化套接…

網絡:手寫HTTP

目錄 一、HTTP是應用層協議 二、HTTP服務器 三、HTTP服務 認識請求中的uri HTTP支持默認首頁 響應 功能完善 套接字復用 一、HTTP是應用層協議 HTTP下層是TCP協議&#xff0c;站在TCP的角度看&#xff0c;要提供的服務是HTTP服務。 這是在原來實現網絡版計算器時&am…

論文筆記(七十八)Do generative video models understand physical principles?

Do generative video models understand physical principles? 文章概括Physics-IQ基準數據集評估協議為什么要創建一個真實世界的Physics-IQ數據集模型物理理解的評估指標動作發生在哪里&#xff1f;空間IoU&#xff08;Spatial IoU&#xff09;動作在哪里、何時發生&#xf…

AXP2101入門

目錄 核心功能與特性封裝與配置安全與可靠性 AXP2101 是一款由全志公司開發的單電池 NVDC 電源管理集成電路&#xff08;PMIC&#xff09;&#xff0c;專為鋰離子/鋰聚合物單電池應用設計&#xff0c;適用于需要多通道電源輸出的設備。 核心功能與特性 1.輸入與充電管理 輸入…

DAY8:Oracle高可用架構深度解析與Data Guard單節點搭建實戰

引言 在數據庫領域&#xff0c;高可用性&#xff08;High Availability&#xff09;是保障業務連續性的核心要求。Oracle作為企業級數據庫的領導者&#xff0c;提供了RAC、Data Guard、GoldenGate三大核心方案。本文將深入剖析這些技術的實現原理&#xff0c;并手把手指導搭建…