<tauri><rust><GUI>基于rust和tauri,在已有的前端框架上手动集成tauri示例
前言
本文是基于rust和tauri,由于tauri是前、后端结合的GUI框架,既可以直接生成包含前端代码的文件,也可以在已有的前端项目上集成tauri框架,将前端页面化为桌面GUI。
环境配置
系统:windows 10
平台:visual studio code
语言:rust、javascript
库:tauri2.0
概述
本文使用vite构建一个前端页面,实现简单的计算器功能,然后使用tauri集成前端,实现桌面端的计算器窗口,并使用rust后端进行计算器的功能计算,然后返回前端。
1、创建前端页面
前端框架有很多,本文是基于一个常用的vite框架,来创建一个前端项目,使用原始模板,即不使用vue3或者react这样的前端模板,而是vite框架下,原生的javascript和html。
我们打开visual studio code,如果你有现成的根文件夹,直接打开,或者创建一个新的根文件夹:
mkdir tauri
cd tauri
然后初始化一个vite项目:
npm create vite@latest
初始化时,将需要填写一个基本信息:
如上图,项目名称自定义,前端框架选原生,语言选js。然后会在你的根文件夹下生成一个项目:
我们可以先看一下这个前端页面运行起来的效果,但这之前还需要安装以下npm包:
cd vitepro
npm install
npm run dev
这里是vite提供的模板示例,是一个计数器,点击网页下端的按钮,计数值会改变。
但我们需要的是一个计算器界面,所以需要对代码进行修改。先看一下vite提供的示例代码的结构:
如上图所示,main.js是主函数入口,counter.js才是计数功能模块。
main.js源码
import './style.css'
import javascriptLogo from './javascript.svg'
import viteLogo from '/vite.svg'
import { setupCounter } from './counter.js'document.querySelector('#app').innerHTML = `<div><a href="https://vite.dev" target="_blank"><img src="${viteLogo}" class="logo" alt="Vite logo" /></a><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank"><img src="${javascriptLogo}" class="logo vanilla" alt="JavaScript logo" /></a><h1>Hello Vite!</h1><div class="card"><button id="counter" type="button"></button></div><p class="read-the-docs">Click on the Vite logo to learn more</p></div>
`setupCounter(document.querySelector('#counter'))
其中,setupCounter是由counter.js中导出的模块。官方提供的这个示例比较简单,我们希望稍作修改,首先是将app这个div的内容提取出来,写在单独的html文件中,可以将其命名为template.html
<div><a href="https://vite.dev" target="_blank"><img src="${viteLogo}" class="logo" alt="Vite logo" /></a><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank"><img src="${javascriptLogo}" class="logo vanilla" alt="JavaScript logo" /></a><h1>Hello Vite!</h1><div class="card"><button id="counter2" type="button"></button></div><p class="read-the-docs">Click on the Vite logo to learn more</p></div>
然后将template.html放在public文件夹中,方便调用。
接着修改main.js,以便于获取template.html中的内容:
import './style.css'
import javascriptLogo from './javascript.svg'
import viteLogo from '/vite.svg'
import { setupCounter } from './counter.js'async function loadTemplate(path,divid) {const response = await fetch(path);const template = await response.text();document.querySelector(divid).innerHTML = template.replace('${viteLogo}', viteLogo).replace('${javascriptLogo}', javascriptLogo);setupCounter(document.querySelector('#counter'))
}loadTemplate('./template.html','#app')
此处,使用fetch来获取本地html文件的内容,效果是一致的。接着,我们修改template.html的页面,设计一个简单的计算器布局,此处是前端程序,比较简单,代码如下,可以参考,也可以直接去使用人工智能生成。
template.html
<label for="history">历史:</label><input type="text" class="history" id="history" disabled><label for="display">实时:</label><input type="text" class="display" id="display" disabled><div class="buttons"><button class="button" id="clearbtn" >C</button><button class="button" id="squarebtn">X²</button><button class="button" id="backbtn">←</button><button class="button operator" id="mulbtn" >*</button><button class="button" id="sevenbtn" >7</button><button class="button" id="eightbtn" >8</button><button class="button" id="ninebtn" >9</button><button class="button operator" id="divbtn" >/</button><button class="button" id="fourbtn" >4</button><button class="button" id="fivebtn" >5</button><button class="button" id="sixbtn" >6</button><button class="button operator" id="addbtn" >+</button><button class="button" id="onebtn" >1</button><button class="button" id="twobtn" >2</button><button class="button" id="threebtn" >3</button><button class="button operator" id="subbtn" >-</button><button class="button" id="zerobtn" >0</button><button class="button" id="dotbtn" >.</button><button class="button equal" id="equalbtn" >=</button></div>
上面的代码在网页上看起来如下:
注意,页面布局还需要配合css样式:
global.css
body {font-family: Arial, sans-serif;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #ffffff;
}
.app {background-color: #73b4f1;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);display: flex;flex-direction: column;
}
.display {height: 30px;text-align: right;margin-bottom: 10px;padding: 10px;font-size: 18px;border: 1px solid #e7adad;border-radius: 5px;
}
.history{height: 30px;text-align: right;margin-bottom: 10px;padding: 10px;font-size: 18px;border: 1px solid #e7adad;border-radius: 5px;
}
.buttons {display: grid;grid-template-columns: repeat(4, 1fr);gap: 10px;
}
.button {padding: 20px;font-size: 18px;border: none;border-radius: 5px;background-color: #f0f0f0;cursor: pointer;
}
.button:hover {background-color: #ddd;
}
.button.operator {background-color: #ff9500;color: white;
}
.button.operator:hover {background-color: #e08900;
}
.button.equal {background-color: #34c759;color: white;grid-column: span 2;
}
.button.equal:hover {background-color: #2da94f;
}
页面布局写好了,就需要为按钮实现功能了,这部分需要写在js中,我们将修改counter.js的代码,为其中添加以下函数:
1、清除函数
2、数字输入函数
3、计算函数(加减乘除以及平方)
4、退格函数
以上是本文将要实现的计算器功能,当然只是简单的实现,并非是一个完整的计算器功能,本文的目的是通过这个小的计算器程序来说明tauri集成前端的示例。
counter.js
let currentInput='';
let previousInput='';
let operator=null;
let predisplay=''
let calflag=false;// 导出一个函数,用于在输入框中添加数字
export function appendnumber(element,number,display,history) {// 给元素添加点击事件element.addEventListener('click',() =>{///如果连续输入,则直接拼接currentInput += number;///输入值将实时显示在输入框内display.value = currentInput;///判断是否进行了计算,如果进行了计算,则历史值清空,显示新的实时输入if (calflag){history.value = currentInput;calflag=false;} else {history.value =history.value + number;}})}
// 导出一个函数,用于在元素上添加功能符号的点击事件
export function appendOperator(element,op,display,history) {// 为元素添加点击事件element.addEventListener('click',() => {///如果点击了功能符号,但计算完成标记存在,则不进行任何回应if (calflag){return;}///如果多次点击功能符号而不是输入下一个数值,则切换功能符号if (currentInput === '') {operator = op;history.value =previousInput + ' ' + operator;return;};///如果前次输入值不为空,则直接计算结果if (previousInput !== '') {//calculate();insidecalculate();}operator = op;previousInput = currentInput;display.value = previousInput;history.value =currentInput + ' ' + operator;predisplay=display.value;currentInput = '';})}function insidecalculate(){if (currentInput === '' || previousInput === '') return;let result;const prev = parseFloat(previousInput);const current = parseFloat(currentInput);switch (operator) {case '+':result = prev + current;break;case '-':result = prev - current;break;case '*':result = prev * current;break;case '/':result = prev / current;break;default:return;}currentInput = result.toString();
}// 导出一个函数,用于计算
export function calculate(element,display,history) {// 给element添加点击事件监听element.addEventListener('click',()=>{// 如果currentInput或previousInput为空,则返回if (currentInput === '' || previousInput === '') return;let result;// 将previousInput和currentInput转换为浮点数const prev = parseFloat(previousInput);const current = parseFloat(currentInput);// 根据operator的值进行计算switch (operator) {case '+':result = prev + current;break;case '-':result = prev - current;break;case '*':result = prev * current;break;case '/':result = prev / current;break;default:return;}// 将计算结果转换为字符串,赋值给currentInputcurrentInput = result.toString();// 将计算结果添加到history中history.value =history.value + '=' + currentInput + '\n';// 将计算结果显示在display中display.value = currentInput;// 将display的值赋值给predisplaypredisplay=display.value;// 将operator置为nulloperator = null;// 将previousInput置为空previousInput = '';// 将currentInput置为空currentInput='';// 将calflag置为truecalflag=true;})}// 导出一个函数,用于清除显示
export function clearDisplay(element,operator,display,history) {// 为element添加点击事件监听器element.addEventListener('click',()=>{// 将currentInput设置为空字符串currentInput = '';// 将operator设置为nulloperator = null;// 将previousInput设置为空字符串previousInput = '';// 将display的值设置为空字符串display.value = '';// 将predisplay设置为空字符串predisplay='';// 将history的值设置为空字符串history.value='';})
}// 导出一个函数,用于返回上一个输入的字符
export function backLast(element,display,history) {// 给element添加点击事件element.addEventListener('click',()=>{// 如果calflag为falseif (!calflag) {// 将currentInput的最后一个字符删除currentInput = currentInput.slice(0, -1);// 将删除后的currentInput赋值给display的valuedisplay.value = currentInput;// 将history的最后一个字符删除history.value = history.value.slice(0, -1);} else {// 将currentInput的最后一个字符删除currentInput = currentInput.slice(0, -1);// 将删除后的currentInput赋值给display的valuedisplay.value = currentInput;}})
}// 导出一个函数,用于计算平方
export function squarenumber(element,display,history) {// 给element元素添加点击事件element.addEventListener('click',()=>{// 将currentInput的值平方currentInput = Math.pow(currentInput,2);// 将平方后的值显示在display元素中display.value = currentInput;// 将计算过程添加到history元素中history.value = history.value + '^2' + '=' + currentInput + '\n';// 将previousInput和currentInput的值重置为空previousInput = '';currentInput='';// 将calflag的值设置为truecalflag=true;})
}
然后在main.js中导入上述函数:
import { appendnumber,appendOperator,calculate,clearDisplay,backLast,squarenumber } from './counter.js'
2、tauri集成
完成了前端页面后,我们现在来手动集成tauri。tauri的官网提供了详细的步骤,在我们上面创建的项目文件夹vitepro下,安装Tauri 的 CLI 工具:
npm install -D @tauri-apps/cli@latest
安装完成后,node包文件夹下显示tauri库:
还是在当前项目文件夹的根目录下,我们使用tauri的cli工具,初始化一个tauri,使其包含在我们已经创建好的前端项目中:
npx tauri init
运行后,会让你填写几个问题:
✔ What is your app name? · vitepro
✔ What should the window title be? · vitepro
? Where are your web assets (HTML/CSS/JS) located, relative to the "<current dir>/src-tauri/tauri.conf.json" file that will be created? ›
✔ Where are your web assets (HTML/CSS/JS) located, relative to the "<current dir>/src-tauri/tauri.conf.json" file that will be created? · ..
✔ What is the url of your dev server? · http://localhost:5173
✔ What is your frontend dev command? · npm run dev
✔ What is your frontend build command? · npm run build
由于我们是集成在vite构建的前端项目中,所以url可以使用默认的
http://localhost:5173
初始化完成后,可以看到项目文件夹下会多出一个src-tauri文件夹:
此时,我们可以使用:
npx tauri dev
来运行一下看看:
看起来还可以,不过默认的窗口尺寸并不匹配,我们可以修改一下窗口参数。
在src-tauri文件夹下,有一个配置文件:tauri.conf.json,其中有个app参数,修改其中的windows项,将窗口宽度设置为400。
"app": {"windows": [{"title": "vitepro","width": 400,"height": 600,"resizable": true,"fullscreen": false}],"security": {"csp": null}},
修改后如下:
看起来要好多了,事实上,窗口还可以美化,但是本文暂不再赘述。
3、后端函数替代
现在,我们想把之前在javascript中的函数功能放到rust中实现,再通过接口在前端调用,实现前后端的数据通讯。此处,tauri提供了两种方法,一种是使用javascript API库,另一个是使用withGlobalTauri这个配置,实现预构建API。
1、如果使用javascript API,那么需要先安装@tauri-apps/api
:
使用
npm install @tauri-apps/api
指令安装api库,安装完成后调用invoke函数:
import { invoke } from '@tauri-apps/api/core'
2、如果使用withGlobalTauri配置,那么,需要修改tauri.conf.json文件中的build项:
{"build": {..."withGlobalTauri": true},
添加withGlobalTauri,并设置为true。这里省略了其他参数的设置。
然后在js中调用:
const invoke = window.__TAURI__.invoke
其中,invoke函数的参数有三个,第一个是要调用的函数名,第二个是函数的参数(如果有的话),第三个是一个可选项(一个headers参数,用于操作http请求和响应的接口)
如果要在前端调用rust,首先你需要在rust中编写好函数,然后才能在前端使用,在tauri初始化的src-tauri文件夹中,我们打开lib.rs文件,添加一个函数:
#[tauri::command]
fn greet(name:&str) -> String {format!("hello,this is from rust msg,your name is {}!",name)
}
注意到,这里函数被标记了,使用#[tauri::command]
来表明这是一个可以被前端使用的rust函数,但是这还不够,还需要将这个函数传递给构建列表:
pub fn run() {tauri::Builder::default().invoke_handler(tauri::generate_handler![greet]).setup(|app| {if cfg!(debug_assertions) {app.handle().plugin(tauri_plugin_log::Builder::default().level(log::LevelFilter::Info).build(),)?;}Ok(())}).run(tauri::generate_context!()).expect("error while running tauri application");
}
注意上面代码中的invoke_handler,标记的函数通过它来传递。我们来测试一下,为前端添加一个文本标签,然后程序运行后,显示一个从rust函数传递过来的字符串。
我们先修改template.html,添加一个新标签:
<div id="titlediv" class="titlediv"><p id="titlep">等待rust传递的字符:</p></div>
设置一下背景色,以做区分。先看下效果:
现在我们还没有调用rust的函数,所以只显示设定的内容。
然后在main.js中,我们来修改这个标签,将其内容替换为从rust函数获取的字符串:
const titlep=document.getElementById('titlep');const greeting=await invoke('greet');titlep.innerHTML +=greeting;console.log(greeting);
同时修改一下rust端的函数:
#[tauri::command]
fn greet() -> String {format!("hello,这里是rust数据!")
}
再次运行:
说明是正确的从前端调用了rust的函数,并获取了返回的内容。
现在,我们尝试将之前的计算函数写到rust中,然后前端这边点击相应按钮时,调用rust函数,并返回结果。
以等号的功能为例,原先的等号功能的核心逻辑是:
// 根据operator的值进行计算switch (operator) {case '+':result = prev + current;break;case '-':result = prev - current;break;case '*':result = prev * current;break;case '/':result = prev / current;break;default:return;}
我们就将这段替换掉,先在rust中新建一个calculate_rs函数:
#[tauri::command]
fn calculate_rs(current_input:f32,previous_input:f32,operator:&str
) -> f32 {match operator {"+" => current_input + previous_input,"-" => current_input - previous_input,"*" => current_input * previous_input,"/" => current_input / previous_input,_ => 0.0,}
}
这个函数就是根据输入数字和计算符返回相应结果,当然这里比较简单,没有进行错误处理。
在js中调用此函数来计算:
const cal=await invoke('calculate_rs',{currentInput:current,previousInput:prev,operator:operator})
4、实例演示
上面介绍了代码,下面来看一下动态演示:
tauri简单计算器程序演示
5、源代码
https://download.csdn.net/download/normer123456/90354147
相关文章:

<tauri><rust><GUI>基于rust和tauri,在已有的前端框架上手动集成tauri示例
前言 本文是基于rust和tauri,由于tauri是前、后端结合的GUI框架,既可以直接生成包含前端代码的文件,也可以在已有的前端项目上集成tauri框架,将前端页面化为桌面GUI。 环境配置 系统:windows 10 平台:visu…...

模型 冗余系统(系统科学)
系列文章分享模型,了解更多👉 模型_思维模型目录。为防故障、保运行的备份机制。 1 冗余系统的应用 1.1 冗余系统在企业管理中的应用-金融行业信息安全的二倍冗余技术 在金融行业,信息安全是保障业务连续性和客户资产安全的关键。随着数字化…...

Deepseek部署的模型参数要求
DeepSeek 模型部署硬件要求 模型名称参数量显存需求(推理)显存需求(微调)CPU 配置内存要求硬盘空间适用场景DeepSeek-R1-1.5B1.5B4GB8GB最低 4 核(推荐多核)8GB3GB低资源设备部署,如树莓派、旧…...

AI-学习路线图-PyTorch-我是土堆
1 需求 PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】_哔哩哔哩_bilibili PyTorch 深度学习快速入门教程 配套资源 链接 视频教程 https://www.bilibili.com/video/BV1hE411t7RN/ 文字教程 https://blog.csdn.net/xiaotudui…...

[LeetCode]day17 349.两个数组的交集
https://leetcode.cn/problems/intersection-of-two-arrays/description/ 题目描述 给定两个数组 nums1 和 nums2 ,返回它们的交集。 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序 。 示例 1: 输入:nums1 [1,2,2,1…...

axios 发起 post请求 json 需要传入数据格式
• 1. axios 发起 post请求 json 传入数据格式 • 2. axios get请求 1. axios 发起 post请求 json 传入数据格式 使用 axios 发起 POST 请求并以 JSON 格式传递数据是前端开发中常见的操作。 下面是一个简单的示例,展示如何使用 axios 向服务器发送包含 JSON 数…...

linux交叉编译paho-mqtt-c
下载源代码: https://github.com/eclipse-paho/paho.mqtt.c.git 编译: 如果mqtt不需要SSL安全认证,可以直接执行(注意把编译工具链路径改成自己的) cd paho.mqtt.c-1.3.13/ mkdir install # 创建安装目录 mkdir…...

feign Api接口中注解问题:not annotated with HTTP method type (ex. GET, POST)
Bug Description 在调用Feign api时,出现如下异常: java.lang.IllegalStateException: Method PayFeignSentinelApi#getPayByOrderNo(String) not annotated with HTTPReproduciton Steps 1.启动nacos-pay-provider服务,并启动nacos-pay-c…...

安装指定版本的pnpm
要安装指定版本的 pnpm,可以使用以下方法: 方法 1: 使用 pnpm 安装指定版本 你可以通过 pnpm 的 add 命令来安装指定版本: pnpm add -g pnpm<版本号>例如,安装 pnpm 的 7.0.0 版本: pnpm add -g pnpm7.0.0方法…...

【系统设计】Spring、SpringMVC 与 Spring Boot 技术选型指南:人群、场景与实战建议
在 Java 开发领域,Spring 生态的技术选型直接影响项目的开发效率、维护成本和长期扩展性。然而,面对 Spring、SpringMVC 和 Spring Boot 这三个紧密关联的框架,开发者常常陷入纠结:该从何入手?如何根据团队能力和业务需…...

常用数据结构之String字符串
字符串 在Java编程语言中,字符可以使用基本数据类型char来保存,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。 操作字符串常用的有三种类:String、StringBuilder、StringBuffer 接下来看看这三类常见用…...

深入Linux系列之进程地址空间
深入Linux系列之进程地址空间 1.引入 那么在之前的学习中,我们知道我们创建一个子进程的话,我们可以在代码层面调用fork函数来创建我们的子进程,那么fork函数的返回值根据我们当前所处进程的上下文是返回不同的值,它在父进程中返…...

HAL库外设宝典:基于CubeMX的STM32开发手册(持续更新)
目录 前言 GPIO(通用输入输出引脚) 推挽输出模式 浮空输入和上拉输入模式 GPIO其他模式以及内部电路原理 输出驱动器 输入驱动器 中断 外部中断(EXTI) 深入中断(内部机制及原理) 外部中断/事件控…...

网络安全-HSTS
什么是HSTS? HTTP严格传输安全协议(HTTP Strict Transport Security,简称:HSTS) 是互联网安全策略机制。网站可以选择使用HSTS策略,来让浏览器强制使用HTTPS与网站进行通信,以减少会话劫持风险。…...

全程Kali linux---CTFshow misc入门(38-50)
第三十八题: ctfshow{48b722b570c603ef58cc0b83bbf7680d} 第三十九题: 37换成1,36换成0,就得到长度为287的二进制字符串,因为不能被8整除所以,考虑每7位转换一个字符,得到flag。 ctfshow{5281…...

HarmonyOS:时间日期国际化
一、使用场景 在不同的国家和文化中,时间和日期格式的表示方法有所不同,使用惯例的不同点包括:日期中年月日的顺序、时间中时分秒的分隔符等。若应用中需展示时间日期,要确保界面以合适的方式显示,以便用户能够理解。 …...

使用miniforge代替miniconda
conda作为Python数据科学领域的常用软件,是对Python环境及相关依赖进行管理的经典工具,通常集成在anaconda或miniconda等产品中供用户日常使用。 但长久以来,conda在很多场景下运行缓慢卡顿、库解析速度过慢等问题也一直被用户所诟病…...

LIMO:少即是多的推理
25年2月来自上海交大、SII 和 GAIR 的论文“LIMO: Less is More for Reasoning”。 一个挑战是在大语言模型(LLM)中的复杂推理。虽然传统观点认为复杂的推理任务需要大量的训练数据(通常超过 100,000 个示例),但本文展…...

【玩转 Postman 接口测试与开发2_018】第14章:利用 Postman 初探 API 安全测试
《API Testing and Development with Postman》最新第二版封面 文章目录 第十四章 API 安全测试1 OWASP API 安全清单1.1 相关背景1.2 OWASP API 安全清单1.3 认证与授权1.4 破防的对象级授权(Broken object-level authorization)1.5 破防的属性级授权&a…...

如何编写测试用例
代码质量管理是软件开发过程中的关键组成部分,比如我们常说的代码规范、代码可读性、单元测试和测试覆盖率等,对于研发人员来说单元测试和测试覆盖率是保障自己所编写代码的质量的重要手段;好的用例可以帮助研发人员确保代码质量和稳定性、减…...

复原IP地址(力扣93)
有了上一道题分割字符串的基础,这道题理解起来就会容易很多。相同的思想我就不再赘述,在这里我就说明一下此题额外需要注意的点。首先是终止条件如何确定,上一题我们递归到超过字符串长度时,则说明字符串已经分割完毕,…...

zzcms接口index.php id参数存在SQL注入漏洞
zzcms接口index.php id参数存在SQL注入漏洞 漏洞描述 ZZCMS 2023中发现了一个严重漏洞。该漏洞影响了文件/index.php中的某些未知功能,操纵参数id会导致SQL注入,攻击可能是远程发起的,该漏洞已被公开披露并可被利用。攻击者可通过sql盲注等手段,获取数据库信息。 威胁等级:…...

Redis03 - 高可用
Redis高可用 文章目录 Redis高可用一:主从复制 & 读写分离1:主从复制的作用2:主从复制原理2.1:全量复制2.2:增量复制(环形缓冲区) 3:主从复制实际演示3.1:基本流程准…...

系统URL整合系列视频四(需求介绍补充)
视频 系统URL整合系列视频四(需求补充说明) 视频介绍 (全国)大型分布式系统Web资源URL整合需求(补充)讲解。当今社会各行各业对软件系统的web资源访问权限控制越来越严格,控制粒度也越来越细。…...

激活函数篇 03 —— ReLU、LeakyReLU、ELU
本篇文章收录于专栏【机器学习】 以下是激活函数系列的相关的所有内容: 一文搞懂激活函数在神经网络中的关键作用 逻辑回归:Sigmoid函数在分类问题中的应用 整流线性单位函数(Rectified Linear Unit, ReLU),又称修正线性单元&a…...

山东大学软件学院人机交互期末复习笔记
文章目录 2022-2023 数媒方向2023-2024 软工方向重点题目绪论发展阶段 感知和认知基础视觉听觉肤觉知觉认知过程和交互设计原则感知和识别注意记忆问题解决语言处理影响认知的因素 立体显示技术及其应用红蓝眼镜偏振式眼镜主动式(快门时)立体眼镜 交互设…...

python 语音识别方案对比
目录 一、语音识别 二、代码实践 2.1 使用vosk三方库 2.2 使用SpeechRecognition 2.3 使用Whisper 一、语音识别 今天识别了别人做的这个app,觉得虽然是个日记app 但是用来学英语也挺好的,能进行语音识别,然后矫正语法,自己说的时候 ,实在不知道怎么说可以先乱说,然…...

docker常用命令及案例
以下是 Docker 的所有常用命令及其案例说明,按功能分类整理: 1. 镜像管理 1.1 拉取镜像 命令: docker pull <镜像名>:<标签>案例: 拉取官方的 nginx 镜像docker pull nginx:latest1.2 列出本地镜像 命令: docker images案例: 查看本地所有…...

DeepSeek-R1 云环境搭建部署流程
DeepSeek横空出世,在国际AI圈备受关注,作为个人开发者,AI的应用可以有效地提高个人开发效率。除此之外,DeepSeek的思考过程、思考能力是开放的,这对我们对结果调优有很好的帮助效果。 DeepSeek是一个基于人工智能技术…...

Java_双列集合
双列集合特点 存放的是键值对对象(Entry) Map 因为都是继承Map,所以要学会这些API,后面的类就都知道了 put 有两个操作,添加(并返回null)或者覆盖(返回被覆盖的值)…...