<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"></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;
    }

    // 将计算结果转换为字符串,赋值给currentInput
    currentInput = result.toString();
    // 将计算结果添加到history中
    history.value =history.value + '=' + currentInput + '\n';
    // 将计算结果显示在display中
    display.value = currentInput;
    // 将display的值赋值给predisplay
    predisplay=display.value;

    // 将operator置为null
    operator = null;
    // 将previousInput置为空
    previousInput = '';
    // 将currentInput置为空
    currentInput='';
    // 将calflag置为true
    calflag=true;
  })
    
}

// 导出一个函数,用于清除显示
export function clearDisplay(element,operator,display,history) {

    // 为element添加点击事件监听器
    element.addEventListener('click',()=>{
      // 将currentInput设置为空字符串
      currentInput = '';
      // 将operator设置为null
      operator = null;
      // 将previousInput设置为空字符串
      previousInput = '';
      // 将display的值设置为空字符串
      display.value = '';
      // 将predisplay设置为空字符串
      predisplay='';
      // 将history的值设置为空字符串
      history.value='';
    })
}

// 导出一个函数,用于返回上一个输入的字符
export function backLast(element,display,history) {
  // 给element添加点击事件
  element.addEventListener('click',()=>{
    // 如果calflag为false
    if (!calflag) {
      // 将currentInput的最后一个字符删除
      currentInput = currentInput.slice(0, -1);
      // 将删除后的currentInput赋值给display的value
      display.value = currentInput;
      // 将history的最后一个字符删除
      history.value = history.value.slice(0, -1);
    } else {
      // 将currentInput的最后一个字符删除
      currentInput = currentInput.slice(0, -1);
      // 将删除后的currentInput赋值给display的value
      display.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的值设置为true
    calflag=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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/966492.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每日学习 设计模式 五种不同的单例模式

狮子大佬原文 https://blog.csdn.net/weixin_40461281/article/details/135050977 第一种 饿汉式 为什么叫饿汉,指的是"饿" 也就是说对象实例在程序启动时就已经被创建好,不管你是否需要,它都会在类加载时立即实例化,也就是说 实例化是在类加载时候完成的,早早的吃…

从技术体系到实践案例:浪潮信息解码金融算力演进路径

作为金融科技领域的重要参与者&#xff0c;浪潮信息作为核心参编单位&#xff0c;联合中国金电、工商银行等33家机构共同完成《中国金融科技发展报告&#xff08;2024&#xff09;》&#xff08;以下简称蓝皮书&#xff09;编撰。浪潮信息凭借在数字基础设施领域的技术积累&…

题海拾贝:【高精度】减法

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞&#xff0c;关注&#xff01; 1、题…

知识库升级新思路:用生成式AI打造智能知识助手

在当今信息爆炸的时代&#xff0c;企业和组织面临着海量数据的处理和管理挑战。知识库管理系统&#xff08;Knowledge Base Management System, KBMS&#xff09;作为一种有效的信息管理工具&#xff0c;帮助企业存储、组织和检索知识。然而&#xff0c;传统的知识库系统往往依…

设计模式-生产者消费者模型

阻塞队列&#xff1a; 在介绍生产消费者模型之前&#xff0c;我们先认识一下阻塞队列。 阻塞队列是一种支持阻塞操作的队列&#xff0c;常用于生产者消费者模型&#xff0c;它提供了线程安全的队列操作&#xff0c;并且在队列为空或满时&#xff0c;能够阻塞等待&#xff0c;…

1Panel应用推荐:WordPress开源博客软件和内容管理系统

1Panel&#xff08;github.com/1Panel-dev/1Panel&#xff09;是一款现代化、开源的Linux服务器运维管理面板&#xff0c;它致力于通过开源的方式&#xff0c;帮助用户简化建站与运维管理流程。为了方便广大用户快捷安装部署相关软件应用&#xff0c;1Panel特别开通应用商店&am…

计算机毕业设计Tensorflow+LSTM空气质量监测及预测系统 天气预测系统 Spark Hadoop 深度学习 机器学习 人工智能

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

语言月赛 202308【小粉兔做麻辣兔头】题解(AC)

》》》点我查看「视频」详解》》》 [语言月赛 202308] 小粉兔做麻辣兔头 题目描述 粉兔喜欢吃麻辣兔头&#xff0c;麻辣兔头的辣度分为若干级&#xff0c;用数字表示&#xff0c;数字越大&#xff0c;兔头越辣。为了庆祝粉兔专题赛 #1 的顺利举行&#xff0c;粉兔要做一些麻…

激活函数篇 02 —— 双曲正切函数tanh

本篇文章收录于专栏【机器学习】 以下是激活函数系列的相关的所有内容: 一文搞懂激活函数在神经网络中的关键作用 逻辑回归&#xff1a;Sigmoid函数在分类问题中的应用 tanh ⁡ ( x ) e x − e − x e x e − x \tanh(x)\frac{e^x - e^{-x}}{e^x e^{-x}} tanh(x)exe−xex…

STM32G0B1 ADC DMA normal

目标 ADC 5个通道&#xff0c;希望每1秒采集一遍&#xff1b; CUBEMX 配置 添加代码 #define ADC1_CHANNEL_CNT 5 //采样通道数 #define ADC1_CHANNEL_FRE 3 //单个通道采样次数&#xff0c;用来取平均值 uint16_t adc1_val_buf[ADC1_CHANNEL_CNT*ADC1_CHANNEL_FRE]; //传递…

【数据结构】链表应用1

链表应用 面试题 02.02.返回倒数第k个节点题目描述思路解题过程复杂度 查找相同后缀题目描述解题思路完整代码&#xff1a; 删除绝对值相等的节点题目描述解题思路代码 面试题 02.02.返回倒数第k个节点 题目描述 实现一种算法&#xff0c;找出单向链表中倒数第 k 个节点。返回…

【JVM详解一】类加载过程与内存区域划分

一、简介 1.1 概述 JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。JVM屏蔽了与操作系统平台相关…

基于STM32设计的仓库环境监测与预警系统

目录 项目开发背景设计实现的功能项目硬件模块组成设计思路系统功能总结使用的模块的技术详情介绍总结 1. 项目开发背景 随着工业化和现代化的进程&#xff0c;尤其是在制造业、食品业、医药业等行业&#xff0c;仓库环境的监控和管理成为了至关重要的一环。尤其是在存储易腐…

“可通过HTTP获取远端WWW服务信息”漏洞修复

环境说明&#xff1a;①操作系统&#xff1a;windows server&#xff1b;②nginx&#xff1a;1.27.1。 1.漏洞说明 “可通过HTTP获取远端WWW服务信息”。 修复前&#xff0c;在“响应标头”能看到Server信息&#xff0c;如下图所示&#xff1a; 修复后&#xff0c;“响应标头…

创建一个javaWeb Project

文章目录 前言一、eclipse创建web工程二、web.xmlservlet.xml< mvc:annotation-driven/ > Spring MVC 驱动< context:component - scan >&#xff1a;扫描< bean > ... < /bean >< import > config/beans.xml beans.xmlmybatis.xml 前言 javaWe…

aspectFill(填充目标区域的同时保持图像的原有宽高比 (aspect ratio)图像不会被拉伸或压缩变形

“aspectFill” 是一个常用于图像和视频处理的术语&#xff0c;尤其是在用户界面 (UI) 设计和图形编程领域。它描述的是一种图像缩放或调整大小的方式&#xff0c;旨在填充目标区域的同时保持图像的原有宽高比 (aspect ratio)。 更详细的解释: Aspect Ratio (宽高比): 指的是图…

界址点成果表批量生成(新增.docx格式)-附工具下载链接

界址点编号工具20250208更新&#xff08;成果表新增.docx格式&#xff09;。 【工具简介】工具可根据面图层&#xff0c;西北角顺时针批量生成界址点&#xff0c;可以设置角度、距离参数&#xff0c;来减少生成界址点的数量&#xff08;不用全部节点生成界址点&#xff09;。生…

《redis缓存淘汰机制》

【redis缓存淘汰机制导读】redis作为一款内存型数据库&#xff0c;其设计的初衷就是为了给广大业务层提供高效的数据读、写能力&#xff0c;因为访问内存的速度肯定是要比直接访问磁盘的速度快几个数量级&#xff0c;假设业务方所有数据读、写请求全部都转发到后台的数据库&…

AWK系统学习指南:从文本处理到数据分析的终极武器 介绍

目录 一、AWK核心设计哲学解析 1.1 记录与字段的原子模型 1.2 模式-动作范式 二、AWK编程语言深度解析 2.1 控制结构 说明&#xff1a; 2.2 关联数组 代码说明&#xff1a; 示例输入和输出&#xff1a; 注意事项&#xff1a; 2.3 内置函数库 三、高级应用技巧 3.1…

深入解析AI技术原理

序言 在当今数字化时代,人工智能(AI)已经成为科技领域最炙手可热的话题之一。从智能家居到自动驾驶汽车,从医疗诊断到金融风险预测,AI的应用无处不在。然而,对于许多人来说,AI背后的技术原理仍然充满了神秘色彩。本文将深入探讨AI的核心技术原理,从基础理论到前…