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.mzph.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;并手把手指导搭建…