Neutralinojs教程项目实战初体验(踩坑指南),干翻 electron

Neutralinojs 项目实战初体验(踩坑指南),干翻 electron

大家好我是csdn的red润
Neutralinojs 官方文档

卧槽卧槽,!这个年轻人居然用浏览器把电脑关机了_哔哩哔哩_bilibili正是在下

本教程搭建的是纯原生项目,没有和其它前端框架绑定。

如果反响还不错的话,就出集成框架(vue3)的内容。(集成react官方已提供)

本文将会搭建一个桌面端程序如图所示

本项目实现了一个所见即所得的网页实时操作页面,旨在演示一些如何搭建项目,并介绍Neutralinojs中的一些常见api,包括IPC消息通讯,托盘,消息通知等

在这里插入图片描述
在这里插入图片描述

什么是 Neutralinojs?

Neutralinojs 是一个轻量级可移植的桌面应用程序开发框架适用于 Linux、macOS 和 Windows 的预构建 x64 二进制文件。它可以让你使用 JavaScript, HTML 和 CSS 开发轻量的跨平台桌面应用。 您可以使用任何编程语言(通过扩展 IPC)扩展 Neutranojs,并将 NeutranoJS 用作任何代码的一部分(通过子进程 IPC)。

在 Electron 和 NWjs 中,你必须安装 Node.js 和成百上千的依赖库。内嵌的 Chromium 和 Node 使简单的应用也变的很臃肿。 Neutralizojs 提供了一个轻量级和可移植的 SDK,它是 Electron 和 NW.js 的替代品。 Neutralizojs不捆绑 Chromium,而是在操作系统中使用现有的 web 浏览器库(例如在 Linux 中使用 gtk-webkit2)。 Neutralizojs 为本机操作实现了 WebSocket 连接,并嵌入了一个静态 web 服务器来提供 web 内容。 此外,它还为开发人员提供了一个内置的 JavaScript 客户端库。

在使用neu cli运行neu run时候会提供一个websocket服务,我扒代码的时候发现的,如图(neu cli源码片段)

请添加图片描述

neutralinojs 是官方提供的一个 JavaScript 客户端库(也称为 Neutralino.js)供开发人员进行交互,他是如何与neu cli进行交互的呢???

没错是websocket,neutralinojs会发起websocket连接,进行发送和接收数据,如图(neutralinojs源码片段)请添加图片描述

!!!!于是,这个框架的工作原理就很清楚了

当我们使用脚手架的时候执行neu run或运行neu build打包后的可执行exe文件的时候,后台会默认启动一个websocket服务,前端页面使用neutralinojs 会发起websocket连接,前端需要调用底层代码的时候,就发送websocket给后台,后台调用系统级别的api,执行相应的操作,然后返回对应的操作结果(可能是对象,或者其它类型的数据)

提供多种模式

  • window

    Neutralinojs 应用程序将在本机窗口上运行。该窗口将使用用户的操作系统主题。 此模式是跨平台应用程序开发的不错选择。

  • browser

    Neutralinojs 应用程序将使用用户的默认浏览器来加载应用程序。 因此,您可以使用本机操作构建 Web 应用程序。您通常无法访问操作 通过 Web 浏览器提供系统级功能。但是,Neutralinojs 浏览器模式可帮助您制作可以 使用所需的安全控制访问操作系统层。

  • cloud

    此模式将 Neutralinojs 进程作为后台服务器运行。 您将能够将应用程序公开到公共网络或 Internet。可以实现手机远程操作电脑客户端功能,类似ssh

    卧槽卧槽,!这个年轻人居然用浏览器把电脑关机了_哔哩哔哩_bilibili正是在下

  • chrome

    Neutralinojs 应用程序将作为 Chrome 应用程序运行。该框架使用以下 Chrome 命令行 使 Web 应用程序看起来更像本机应用程序的参数。

提供各种原生 api

  • 系统信息
  • 剪切板
  • 文件系统
  • os

可选开放的权限

用户可以在neutralino.config.json中,配置设置开发的系统原生 api 权限

全局变量

用户可以在neutralino.config.json中,配置各种全局变量,统一配置管理

自动更新

  • 提供简单易操作的更新功能

  • 打包大小 neu build

    • 空项目打包只有 2.45M(electron40-50M)!!!
  • 打包速度

    • 毫秒级 (空项目)
    • 快!!!!按下键盘就打包完了!!!!
  • 项目运行速度 neu run

    • 基本秒起(空项目)

因为某些不可抗的原因,按照官方示例步骤,一步一步去搭建项目有时候会报错/(ㄒ o ㄒ)/~~

所以下面是遇到错误的一些解决方案

初始化项目(开始踩坑)

我们将搭建一个和框架的无关的程序

1. 安装 neu CLI

neu CLI 是用来创建 Neutralionjs 程序的脚手架程序

npm install -g @neutralinojs/neu

如果您不想进行全局安装,请将 neu CLI 与 npx 一起使用。

npx @neutralinojs/neu <command>

2. 创建新应用

输入以下命令以搭建新应用的基架

neu create newdemo

很多人在执行到 neu create newdemo 的时候卡住不动了如图

请添加图片描述

这是由于某些不可抗力,导致某些镜像下载不下来
如何解决呢??

如果下载没有问题的话(恭喜)会有这样的提示

请添加图片描述

你的项目结构是这样的!!! 执行neu run就可以启动项目了!!

请添加图片描述

我们先来认识一下,项目目录下面的文件是干什么的

  • .github

    • FUNDING.yml 作者用来拉赞助的
  • .tmp(前面介绍过)

    • **.**各种临时文件
  • bin(前面介绍过)

    • **.**
    • 存放的是一些用于启动 Neutralinojs 应用程序的主可执行程序,或者是一些辅助工具。用于配置或启动 Neutralinojs 应用,或者用于构建和打包应用程序。
    • 由于 Neutralinojs 旨在支持多个操作系统,因此 bin 文件夹可能包含针对不同操作系统(如 Windows、macOS、Linux)的特定二进制文件。
    • 用于存放与运行和构建应用程序相关的二进制文件和脚本。
  • resources

    • icons 图片 图标
    • js
      • **.js各种需要用到的js文件按
      • **.d.ts各种类型声明文件
    • index.html 项目主入口
    • index.css 样式
  • .gitignore git忽略文件

  • LICENSE 许可证书

  • neutralino.config.json 配置文件!!!!!!!非常重要,需要细说

  • neutralinojs.log 日志

3.如果下载一直卡顿,并且项目结构不是上面图片这样目录结构,或者缺失东西,项目跑步起来,那么请按照下面的步骤操作!!!(踩坑吧!!!!)

停止下载(很多时候是网络问题,多试一下,实在不行才进行下面的操作)

此时本地目录会存在一个 newdemo 文件夹,里面可能包含以下这些内容

请添加图片描述

和完整项目对比,明显会发现多了和少了很多文件

这时候我们就需要删除多余的文件,补充缺少的文件!!!!

删除.tmp目录
  • 这个文件是一个缓存临时文件夹的地方,会存在大量缓存内容,只会在搭建项目中途出现,网友们的这个文件夹中的内容应该是各不相同,因为不知道网络会卡在构建项目的某个步骤,所以这个临时缓存文件夹内容是不一样的。

  • 你咋知道.temp目录干啥的???答:我是在分析neu-cli脚手架源码的时候发现的,它会进行以下三步操作,每一步操作都会在临时文件夹里面产生一些东西,所以你会卡在什么奇怪的地方是不确定的请添加图片描述

新建bin文件夹
  • 你咋知道bin文件的???答:我在分析neu-cli脚手架源码的时候发现的,请添加图片描述

    • 介绍一下:bin这个文件目录里面存放的是一些用于启动 Neutralinojs 应用程序的主可执行程序,或者是一些辅助工具。用于配置或启动 Neutralinojs 应用,或者用于构建和打包应用程序。
    • 由于 Neutralinojs 旨在支持多个操作系统,因此 bin 文件夹可能包含针对不同操作系统(如 Windows、macOS、Linux)的特定二进制文件。
    • 用于存放与运行和构建应用程序相关的二进制文件和脚本。
  • 长这样请添加图片描述

  • 你要问了?这些文件从哪里来的????

    • 首先到neutralinojs官方项目地址里面GitHub - neutralinojs/neutralinojs: Portable and lightweight cross-platform desktop application development framework

    • 长这样请添加图片描述

    • 然后点这里,找到官方发布的二进制文件请添加图片描述

    • 我这里最新是5.2.0(2024/07/29已经是5.3.0版本了,支持背景透明)版本点击下载解压就可以了请添加图片描述

    • 压缩包里面就是这样请添加图片描述

    • 把里面的文件全部放在bin文件目录就可以了!!!!!

添加neutralino.js
  • neutralinojs 是官方提供的一个 JavaScript 客户端库(也称为 Neutralino.js)供开发人员进行交互

  • 正常情况下会有这个文件目录请添加图片描述

  • 这个目录下面存放我们的自己写的项目代码

  • 如果下载存在问题会缺失js文件目录下面的neutralino.jsneutralino.d.ts

  • 他们俩分别是我们开发中要使用到的和它的类型声明文件

  • 你又要问了!!!如何获取呢????

  • 访问地址GitHub - neutralinojs/neutralino.js: JavaScript API for Neutralinojs
    请添加图片描述

  • 执行命令
    npm install @neutralinojs/lib
    # --- or ---
    yarn add @neutralinojs/lib
    
  • 然后再node_modules文件目录下面就能找到他们俩了,把他俩放在js目录下面,就ok了请添加图片描述

启动项目!!!!

经过上面的步骤,我们的代码目录结构就成这样了

请添加图片描述

然后在控制台执行命令

neu run

出现一下画面

请添加图片描述

!!!!!恭喜你,项目启动成功

开始实战项目

认识项目目录

经过前面的步骤,我们已经可以把项目完美的启动起来了。

现在我们先来认识一下,项目目录下面的文件是干什么的

  • .github

    • FUNDING.yml 作者用来拉赞助的
  • .tmp(前面介绍过)

    • **.**各种临时文件
  • bin(前面介绍过)

    • **.**
    • 存放的是一些用于启动 Neutralinojs 应用程序的主可执行程序,或者是一些辅助工具。用于配置或启动 Neutralinojs 应用,或者用于构建和打包应用程序。
    • 由于 Neutralinojs 旨在支持多个操作系统,因此 bin 文件夹可能包含针对不同操作系统(如 Windows、macOS、Linux)的特定二进制文件。
    • 用于存放与运行和构建应用程序相关的二进制文件和脚本。
  • resources

    • icons 图片 图标
    • js
      • **.js各种需要用到的js文件
      • **.d.ts各种类型声明文件
    • index.html 项目主入口
    • index.css 样式
  • .gitignore git忽略文件

  • LICENSE 许可证书

  • neutralino.config.json 配置文件!!!!!!!非常重要,需要细说

  • neutralinojs.log 日志

neutralino.config.json详解
{"$schema": "https://raw.githubusercontent.com/neutralinojs/neutralinojs/main/schemas/neutralino.config.schema.json",// 配置schema。。没研究过"applicationId": "js.neutralino.sample",// 应用id"version": "1.0.0",// 版本号"defaultMode": "window",// 默认模式 有四种模式 对应下面的 modes属性"port": 0,// 开发端口"documentRoot": "/resources/",// 对应项目文件中的文件目录"url": "/",// url相对路径"enableServer": true,// 能够启动服务"enableNativeAPI": true,// 支持原生api"tokenSecurity": "one-time",//【cloud模式】 one-time服务器只发送一次token,客户端将保留,其它客户端访问的时候将报错,推荐;如果不传,所有客户端都能访问;您可以使用该身份验证详细信息从外部进程连接到 Neutralinojs WebSocket 作为 IPC 机制"exportAuthInfo":true,// 将身份验证详细信息导出到文件中。${NL_PATH}/.tmp/auth_info.json //您可以使用该身份验证详细信息从外部进程连接到 Neutralinojs WebSocket 作为 IPC 机制"logging": {// 日志"enabled": true,"writeToLogFile": true},// 原生api允许列表 !!!!!!!这个很重要,需要自己设置开放那些权限,官方文档有对这些权限的介绍  "nativeAllowList": ["app.*","os.*","debug.log"],
// 项目中可以使用到的全局变量  "globalVariables": {"TEST1": "Hello","TEST2": [2,4,5],"TEST3": {"value1": 10,"value2": {}}},// 可选的模式,使用不同的模式,项目使用的效果也不一样"modes": {
// 窗口设置  "window": {"title": "test1","width": 800,"height": 500,"minWidth": 400,"minHeight": 200,"center": true,"fullScreen": false,"alwaysOnTop": false,"icon": "/resources/icons/appIcon.png","enableInspector": true,"borderless": false,"maximize": false,"hidden": false,"resizable": true,"exitProcessOnClose": false,"trasparent":true,// 窗口透明,5.3v版本开始支持(我现在是5.2v,快了)"nativeAllowList": ["app.*"]// 允许的权限},"browser": {// 全局变量"globalVariables": {"TEST": "Test value browser"},// 锁定权限列表"nativeBlockList": ["filesystem.*"]},"cloud": {// 请求路径"url": "/resources/#cloud","nativeAllowList": ["app.*"]},"chrome": {"width": 800,"height": 500,"args": "--user-agent=\"Neutralinojs chrome mode\"",// 锁定的权限"nativeBlockList": ["filesystem.*","os.*"]}},// 脚手架相关的"cli": {"binaryName": "test1","resourcesPath": "/resources/","extensionsPath": "/extensions/","clientLibrary": "/resources/js/neutralino.js","binaryVersion": "5.2.0",//!!!!!!!!!!!!!!!!!!!!!!!!!!!这里版本对应的二进制文件的版本,一定要是同一个版本"clientVersion": "5.2.0"//!!!!!!!!!!!!!!!!!!!!!!!!!!!!这里版本对应的二进制文件的版本,一定要是同一个版本}
}

具体更详细内容,请参考官方文档Introduction | Neutralinojs

resources目录详解
  • icons图标图片
  • js
    • main.js业务逻辑代码
    • neutralino.js项目核心库(neutralino支持的各种api都在它身上)
    • neutralino.d.ts项目核心库类型声明文件
  • index.html应用界面
  • styles.css样式

初始化代码

  • main.js

    • 先清空,后面我们交互逻辑都会放在这个文件里面
  • index.html

    • <!DOCTYPE html>
      <html><head><meta charset="UTF-8" /><title>所见即所得</title><link rel="shortcut icon" href="./icon.ico" /><link rel="stylesheet" href="./styles.css" /></head><body><!-- <div id="neutralinoapp"><h1>嘻嘻嘻嘻嘻嘻嘻嘻neutralino.js嘻嘻嘻嘻嘻嘻嘻嘻嘻</h1><div id="info"></div><img src="/icons/logo.gif" alt="Neutralinojs" /></div><div style="display: flex"></div> --><div class="contain"><div class="left"><div class="box"><div class="title">HTML</div><textarea id="html-val"></textarea></div><div class="box"><div class="title">CSS</div><textarea id="css-val"></textarea></div><div class="box"><div class="title">JS</div><textarea id="js-val"></textarea></div></div><div class="right"><div class="box"><div class="title">实际效果</div><iframe id="show-container"></iframe></div><div class="box"><div class="title">控制台</div><div id="log-val"></div></div></div></div><script src="./js/neutralino.js"></script><script src="./js/index.js"></script><!-- Your app's source files --><!-- <script src="/js/main.js"></script> --></body>
      </html>
  • styles.css

    • * {margin: 0;padding: 0;box-sizing: border-box;
      }
      html,
      body {width: 100%;height: 100%;
      }
      .contain {width: 100%;height: 100%;display: flex;.left {color: white;min-width: 350px;width: 30%;height: 100%;background-color: white;padding: 0 20px;.box {width: 100%;height: 33%;display: flex;flex-direction: column;.title {background-color: silver;height: 10%;text-align: center;}textarea {background-color: black;color: white;padding: 20px;width: 100%;height: 90%;font-size: 20px;}}}.right {width: 70%;height: 100%;display: flex;flex-direction: column;.box {width: 100%;height: 50%;background-color: white;padding: 0 20px;.title {background-color: silver;height: 10%;text-align: center;}iframe {background-color: white;width: 100%;height: 89%;}#log-val::before {color: white;white-space: pre-wrap;content: '控制台输出 : ';}#log-val {height: 89%;overflow-y: scroll;color: rgb(240, 240, 132);background-color: black;width: 100%;padding: 10px;content: 'gege';}}}
      }
      

经过上面的初始化步骤,你的界面会变成这样!!!!!请添加图片描述

main.js实现核心业务代码(建议提前去官网看看api文档)

main.js

// 防抖函数
let debounce = (func, delay) => {let timeout = null;return function () {const _this = thisconst args = [...arguments]if (timeout) {clearTimeout(timeout)}timeout = setTimeout(() => {func.apply(_this, args)}, delay)};
};
// 节流函数
let throttle = (func, wait) => {let previous = Date.now();return function () {let now = Date.now();let context = this;let args = arguments;if (now - previous > wait) {func.apply(context, args);previous = now;}}
};// console.log(Neutralino, 'Neutralino')
// 设置系统右下角托盘
const setTray = () => {// 托盘只在window模式下支持if (NL_MODE != "window") {console.log("INFO: 托盘只在window模式下支持.");return;}// 托盘项let tray = {icon: "/resources/icons/trayIcon.png",menuItems: [{ id: "openBaidu", text: "打开百度" },// 分割线条{ id: "SEP", text: "-" },{ id: "VERSION", text: "Get version" },// 分割线条{ id: "SEP", text: "-" },{ id: "提示文字", text: "提示文字" },// 分割线条{ id: "SEP", text: "-" },{ id: "QUIT", text: "Quit" }]};// 设置系统托盘Neutralino.os.setTray(tray);
}
// 托盘右击事件
const onTrayMenuItemClicked = (event) => {switch (event.detail.id) {case "VERSION":// Display version informationNeutralino.os.showMessageBox("Version information",`Neutralinojs server: v${NL_VERSION} | Neutralinojs client: v${NL_CVERSION}`);break;case "openBaidu":// 打开指定网页Neutralino.os.open("https://www.baidu.com");break;case "提示文字":Neutralino.os.showMessageBox("我是提示标题", `我是提示文字内容`);break;case "QUIT":// Exit the applicationNeutralino.app.exit();break;}
}
// 窗口关闭事件
const onWindowClose = () => {Neutralino.app.exit();
}
/*** 万物起源,先调用init方法,然后才能使用任何 原生 API 函数!!!!* 执行init方法的时候,内部会发起websocket连接,打通交互逻辑*/
Neutralino.init()
// 监听 客户端库与 Neutralino 服务器连接成功触发事件。
Neutralino.events.on('ready', async () => {// 弹出一个提示窗口Neutralino.os.showMessageBox('red润提醒您', 'Hello Neutralinojs');// 从剪切板获取数据// let format = await Neutralino.clipboard.getFormat();// console.log(`Format: ${format}`);// 给剪切板设置文字// await Neutralino.clipboard.writeText('Test value');// 给剪切板设置图片// let image = prepareClipboardImage();// await Neutralino.clipboard.writeImage(image);// 从剪切板获取文字// let clipboardText = await Neutralino.clipboard.readText();// console.log(`Text: ${clipboardText}`);// // 从剪切板获取图片// let clipboardImage = await Neutralino.clipboard.readImage();// console.log(`Image: ${clipboardImage}`);// 选择提示框// let button = await Neutralino.os//     .showMessageBox('Confirm',//         'Are you sure you want to quit?',//         'YES_NO', 'QUESTION');// if (button == 'YES') {//     Neutralino.app.exit();// }// 右下角提示,目前win11支持异常,已经有人提了pr,待官方更新中// await Neutralino.os.showNotification('Hello world', 'It works! Have a nice day');// // 错误类型的提示// await Neutralino.os.showNotification('Oops :/', 'Something went wrong', 'ERROR');});
// 苹果系统没有托盘
if (NL_OS != "Darwin") {setTray();
}
// 监听用户单击托盘时候触发
Neutralino.events.on("trayMenuItemClicked", onTrayMenuItemClicked);
// 监听用户关闭窗口时触发事件。
Neutralino.events.on("windowClose", onWindowClose);// 获取配置文件信息
// Neutralino.app.getConfig().then(res => {
//     console.log(res, 'getConfig')
// })
// 获取windows系统环境变量
// Neutralino.os.getEnvs().then(res => {
//     console.log(res, 'getEnvs')
// })
// 输出系统信息
console.log(`APPID:${NL_APPID}PORT:${NL_PORT}OS:${NL_OS}SERVER:v${NL_VERSION}CLIENT:v${NL_CVERSION}MODE:${NL_MODE}
`);const htmlValEle = document.querySelector("#html-val");
const cssValEle = document.querySelector("#css-val");
const jsValEle = document.querySelector("#js-val");
const logValEle = document.querySelector('#log-val')
/*** @type {HTMLIFrameElement}*/
const showContainerEle = document.querySelector('#show-container')
// 初始化值
let htmlVal = htmlValEle.value = "<button onclick='test()'>hello world</button>";
let cssVal = cssValEle.value = "h1{color:red;}";
let jsVal = jsValEle.value = "function test(){alert('12334');}";
// 控制台记录行数
let countLine = 1;const run = (htmlVal, cssVal, jsVal) => {// 界面和样式showContainerEle.contentDocument.body.innerHTML = htmlVal + `<style>${cssVal}</style>`;// 计算jsshowContainerEle.contentWindow.eval(jsVal);// 拦截console,自定义自己的逻辑showContainerEle.contentWindow.console.log = (val) => {logValEle.innerText = logValEle.innerText + "\n第" + countLine + "行:" + val;countLine++;}
}run(htmlVal, cssVal, jsVal)
// 节流稳定输出
const htmlFunc = throttle((e, d) => {// oldconsole(e.target.value, 'e,d')htmlVal = e.target.value;run(htmlVal, cssVal, jsVal)
}, 100)
const cssFunc = throttle((e, d) => {// oldconsole(e.target.value, 'e,d')cssVal = e.target.value;run(htmlVal, cssVal, jsVal)
}, 100)
// 防抖防止拼写错误的时候,频繁提示错误
const jsFunc = debounce((e, d) => {// oldconsole(e.target.value, 'e,d')jsVal = e.target.value;run(htmlVal, cssVal, jsVal)
}, 1000)// 监听事件
htmlValEle.addEventListener('input', htmlFunc)
cssValEle.addEventListener('input', cssFunc)
jsValEle.addEventListener('input', jsFunc)

最终效果!!!

请添加图片描述

完结。

还有很多东西没讲完,比如比如和前端框架整合vue,react,自动更新,实现远程控制等。如果需要学习这块的人比较多的话,就更新。

这个库相对于electron还是简单许多,把官方api文档读一遍就基本没问题了

拜!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode每日一题_3143.正方形中的最多点数

解题思路&#xff1a;自己&#xff1a;先把points里的点拿来求出坐标系的离原点最远的点&#xff0c;然后根据最远距离新建一个数组&#xff0c;然后把points的点都在新建的数组上标记出来。然后再便利从边长为0的正方形开始&#xff0c;里面是否有重复的标签。但是代码写不出来…

vulhub-wordpress

1.打开wordpress关卡&#xff0c;选择简体中文 添加信息——点击安装WordPress 安装完成——登录 点击外观——编辑主题 可以加入一句话木马&#xff0c;但是我写入的是探针文件 也可以去上传一个带有木马的主题 上传之后会自动解压 1.php就是里面的木马文件

数据结构与算法 - 堆

1. 建堆 Floyd建堆算法作者&#xff08;也是之前龟兔赛跑判环作者&#xff09;&#xff1a; ①找到最后一个非叶子节点②从后往前&#xff0c;对每个节点执行下潜 一些规律 一棵满二叉树节点个数为2^h - 1&#xff0c;如下例中高度h 3节点数是2 ^ 3 - 1 7非叶子节点范围为…

PMP--冲刺--敏捷中的角色职责与3个工件--题干关键词

文章目录 敏 捷 中 的 角 色 职 责 与 3 个 工 件--题干关键词说明题目 敏 捷 中 的 角 色 职 责 与 3 个 工 件–题干关键词 角色职责 1、产品负责人&#xff1a;题干关键词 “优先级排序、与客户沟通、下次迭代做什么、接受或拒绝用户故事”。 2、Scrum Master&#xff1a;题…

uniapp自定义网格布局用于选择金额、输入框焦点事件以及点击逻辑实战

样式 <view class="withdraw-section"><text class="section-title">提现金额</text><view class="amount-options"><view v-for="(item, index) in list" :key="index" class="amount-opt…

学习Java的日子 Day59 学生管理系统 web1.0版本

Day59 学生管理系统 web1.0 1.项目需求 有两个角色&#xff0c;老师和学生&#xff0c;相同的功能提取到父类用户角色 2.数据库搭建 设计学生表 设计老师表 插入数据 (超级管理员) 设计学科表 3.项目搭建 处理基础页面&#xff0c;分包&#xff0c;实体类&#xff0c;导入数据…

【初学人工智能原理】【12】循环:序列依赖问题

前言 本文教程均来自b站【小白也能听懂的人工智能原理】&#xff0c;感兴趣的可自行到b站观看。 代码及工具箱 本专栏的代码和工具函数已经上传到GitHub&#xff1a;1571859588/xiaobai_AI: 零基础入门人工智能 (github.com)&#xff0c;可以找到对应课程的代码 正文 对于…

LabVIEW水下根石监测系统

开发了一种基于LabVIEW平台开发的水下根石监测系统。该系统利用高精度姿态传感器与位移传感器&#xff0c;实现了水下根石状态的实时自动监测&#xff0c;提高了水利工程安全管理的现代化和精细化水平&#xff0c;具有高精度、高稳定性和良好的操作性。 项目背景&#xff1a; …

canvas绘制文本时,该如何处理首行缩进、自动换行、多内容以省略号结束、竖排的呢?

实现如标题所示的这些文本效果&#xff0c;在css看来&#xff0c;不就是一两行css属性。然而&#xff0c;对于canvas来讲&#xff0c;要想呈现这样的文字样式&#xff0c;就没css那么轻松简便了。 既然如此&#xff0c;那为何还要使用对文本支持度不友好的canvas来绘制文字呢&a…

【开发视角】大模型 RAG 检索增强生成究竟是什么

【大白话讲懂】大模型 RAG 检索增强生成 话先说在前面&#xff0c;本文不讲不会讲太多原理&#xff0c;仅面向工程开发&#xff0c;从工作流程的宏观角度进行梳理&#xff0c;旨在快速上手。 RAG 是什么 基本定义 让我们先来解释名词&#xff0c;看看宏观框架。 RAG 的意思…

科普文:微服务之SpringBoot性能优化器动态线程池【Dynamic-Tp】特性和源码解读

一、简述 gitee地址&#xff1a;https://gitee.com/yanhom/dynamic-tp github地址&#xff1a;https://github.com/lyh200/dynamic-tp dynamic-tp是一个轻量级的动态线程池插件&#xff0c;它是一个基于配置中心的动态线程池&#xff0c;线程池的参数可以通过配置中心配置进…

C++中lambda使用mutable关键字详解

C中lambda使用mutable关键字详解 在《C初学者指南-5.标准库(第二部分)–更改元素算法》中&#xff0c;讲“generate”算法时有下面这段代码&#xff1a; auto gen [i0]() mutable { i 2; return i; }; std::vector<int> v; v.resize(7,0); generate(begin(v)1, begin…

C++ STL在算法题中的常用语法

Vector 1.将vector<int>中的元素全部置换为0 fill(vec.begin(), vec.end(), 0); 2.vector容器是可以直接用比较是否值等的&#xff01; Unordered_set 1. unordered_set的删除&#xff08;count的值也会减少&#xff09; 2.unordered_map中的int默认值是0&#xff0c;…

在Jira中使用AI

Jira已经可以使用AI功能了。 如果您使用的是Jira Cloud&#xff0c;您需要请管理员在管理页面中打开AI功能开关。&#xff08;AI功能在Standard版中未提供&#xff0c;请使用Premium或更高级的版本&#xff09;如果您使用的是自己部署的Jira Data Center&#xff0c;您需要请管…

算法学习day28

一、寻找右区间(二分法) 题意&#xff1a;题目很容易理解 但是转换为二分法有点晦涩 给你一个区间数组 intervals &#xff0c;其中 intervals[i] [starti, endi] &#xff0c;且每个 starti 都 不同 。区间 i 的 右侧区间 可以记作区间 j &#xff0c;并满足 startj > e…

OpenCV||超详细的灰度变换和直方图修正

一、点运算 概念&#xff1a;点运算&#xff08;也称为像素级运算或单像素操作&#xff09;是指对图像中每一个像素点进行独立、相同的操作&#xff0c;而这些操作不会考虑像素点之间的空间关系。点处理优势也称对比度拉伸、对比度增强或灰度变换等。 目的&#xff1a;点运算…

【EtherCAT】Windows+Visual Studio配置SOEM主站——静态库配置+部署

目录 一、准备工作 1. Visual Studio 2022 2. Npcap 1.79 3. SOEM源码 二、静态库配置 1. 修改SOEM源码配置 2. 编译SOEM源码 3. 测试 三、静态库部署 1. 新建Visual Studio工程 2. 创建文件夹 3. 创建主函数 4. 复制静态库 5. 复制头文件 6. 配置头文件…

链接、装载和库——1 简介

前言 关于个人的读书笔记 第一章 温故而知新 1.1 从hello&#xff0c;world说起 ​计算机在执行hello&#xff0c;world的时候发生了什么&#xff1f; 1.2 万变不离其宗 ​在计算机多如牛毛的硬件设备中。有三个部件最为关键&#xff0c;它们分别是 CPU、内存和 I/O 控制芯…

一次多波束和浅地层处理的经历—信标机出问题?

最近处理多波束和浅地层时&#xff0c;一个从来没有过的问题出现了。 多波束数据(.pds)是由PDS2000采集的&#xff0c;使用设备型号为T50P。浅地层数据(.raw)是有SESWIN采集的&#xff0c;使用设备型号为SES2000 Standard。 1、多波束处理 多波束数据采用CARIS11.3处理的。船…

开源LivePortrait,快速实现表情包自定义

最近可灵AI很火&#xff0c;看到网上生成的效果也很赞啊&#xff0c;之前发现快手可灵开源了LivePortrait&#xff0c;今天去玩了一下&#xff0c;很有意思。 比如下图官方展示效果&#xff1a; 这些图片开始自带表情了&#xff0c;主要就是通过LivePortrait来实现。 LivePor…