当前位置: 首页 > news >正文

字玩FontPlayer开发笔记8 Tauri2文件系统

字玩FontPlayer开发笔记8 Tauri2文件系统

字玩FontPlayer是笔者开源的一款字体设计工具,使用Vue3 + ElementUI开发,源代码:
github: https://github.com/HiToysMaker/fontplayer
gitee: https://gitee.com/toysmaker/fontplayer

笔记

字玩目前是用Electron进行桌面端应用打包,但是性能体验不太好,一直想替换成Tauri。Tauri的功能和Electron类似,都可以把前端代码打包生成桌面端(比如Windows和Mac)应用。Tauri只使用系统提供的WebView,不像Electron一样内置Chromium和Node.js,性能体验更佳。

近几天开始着手将Electron替换成Tauri,前两天完成了系统原生菜单的基本设置,今天将菜单功能实装。笔者项目中菜单功能最常用的就是文件存储和读取,所以今天主要学习了文件系统的内容。Tauri2提供了js端可调用的plugin,可以方便前端轻松实现文件操作。

权限配置

文件操作需要进行权限配置,Tauri2去掉了tauri.conf.json中的allowList一项,变成在src-tauri/capabilities/default.json中进行权限设置。
具体权限对应的选项在文档中Permission Table一栏中有详述:https://tauri.app/plugin/file-system/

笔者的配置:
src-tauri/capabilities/default.json

{"$schema": "../gen/schemas/desktop-schema.json","identifier": "default","description": "enables the default permissions","windows": ["main"],"permissions": [{"identifier": "fs:scope","allow": [{"path": "$APPDATA"},{"path": "$APPDATA/**"}]},"core:default","fs:read-files","fs:write-files","fs:allow-appdata-read-recursive","fs:allow-appdata-write-recursive","fs:default","dialog:default"]
}
文件选择对话框

文件选择对话框的插件和文件操作的插件是分开的,首先安装对话框插件:

npm run tauri add dialog

打开文件选择窗口:

import { open } from '@tauri-apps/plugin-dialog'const file = await open({multiple: false,directory: false,
})

打开文件存储窗口:

import { save } from '@tauri-apps/plugin-dialog'const path = await save({defaultPath: 'untitled',filters: [{name: 'My Filter',extensions: ['png', 'jpeg'],},],
});
文件操作

文件操作封装在fs插件中,插件分别提供对纯文本读写和二进制读写的方法。

安装插件:

npm run tauri add fs

读取纯文本:

import { readTextFile, BaseDirectory } from '@tauri-apps/plugin-fs'const configToml = await readTextFile('config.toml', {baseDir: BaseDirectory.AppConfig,
})

读取二进制文本:

const icon = await readFile('icon.png', {baseDir: BaseDirectory.Resources,
})

写入纯文本:

import { writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs'const contents = JSON.stringify({ notifications: true });
await writeTextFile('config.json', contents, {baseDir: BaseDirectory.AppConfig,
});

写入二进制:

import { writeFile, BaseDirectory } from '@tauri-apps/plugin-fs'const contents = new Uint8Array();
await writeFile('config', contents, {baseDir: BaseDirectory.AppConfig,
});
涉及文件操作的具体逻辑实现
保存文本文件
const nativeSaveText = async (data, filename, formats) => {const path = await save({defaultPath: filename,filters: [{name: 'Filter',extensions: formats,},],})if (path) {await writeTextFile(path, data)}
}
保存二进制文件
const nativeSaveBinary = async (data, filename, formats) => {const path = await save({defaultPath: filename,filters: [{name: 'Filter',extensions: formats,},],})if (path) {await writeFile(path, data)}
}
打开文本文件
const nativeImportTextFile = async (formats) => {const path = await open({filters: [{name: 'Filter',extensions: formats,},],})let data = nulllet name = 'untitled'if (path) {data = await readTextFile(path)name = path.split('/').pop().split('.')[0]}return {data,name,}
}
打开二进制文件
const nativeImportFile = async (formats) => {const path = await open({filters: [{name: 'Filter',extensions: formats,},],})let uint8Array = nulllet name = 'untitled'if (path) {uint8Array = await readFile(path)name = path.split('/').pop().split('.')[0]}return {uint8Array,name,}
}
打开工程
const openFile_tauri = async (rawdata) => {if (files.value && files.value.length) {tips.value = '目前字玩仅支持同时编辑一个工程,请关闭当前工程再打开新工程。注意,关闭工程前请保存工程以避免数据丢失。'tipsDialogVisible.value = true} else {const { data } = await nativeImportTextFile(['json'])await _openFile_electron(data)}
}
保存工程
const saveFile_tauri = async () => {setSaveDialogVisible(true)
}
另存为工程
const saveAs_tauri = async () => {setSaveDialogVisible(true)
}
导入字体库
const importFont_tauri = async () => {if (files.value && files.value.length) {tips.value = '目前字玩仅支持同时编辑一个工程,请关闭当前工程再导入字体。注意,关闭工程前请保存工程以避免数据丢失。'tipsDialogVisible.value = true} else {const options = await nativeImportFile(['otf', 'ttf'])await _importFont_tauri(options)}
}
导入字形
const importGlyphs_tauri = async () => {const { data: rawdata } = await nativeImportTextFile(['json'])if (!rawdata) returnconst data = JSON.parse(rawdata)const plainGlyphs = data.glyphsif (data.constants) {for (let n = 0; n < data.constants.length; n++) {if (!constantsMap.getByUUID(data.constants[n].uuid)) {constants.value.push(data.constants[n])}}}if (data.constantGlyphMap) {const keys = Object.keys(data.constantGlyphMap)for (let n = 0; n < keys.length; n++) {constantGlyphMap.set(keys[n], data.constantGlyphMap[keys[n]])}}const _glyphs = plainGlyphs.map((plainGlyph) => instanceGlyph(plainGlyph))_glyphs.map((glyph) => {addGlyph(glyph, editStatus.value)addGlyphTemplate(glyph, editStatus.value)})if (editStatus.value === Status.GlyphList) {emitter.emit('renderGlyphPreviewCanvas')} else if (editStatus.value === Status.StrokeGlyphList) {emitter.emit('renderStrokeGlyphPreviewCanvas')} else if (editStatus.value === Status.RadicalGlyphList) {emitter.emit('renderRadicalGlyphPreviewCanvas')} else if (editStatus.value === Status.CompGlyphList) {emitter.emit('renderCompGlyphPreviewCanvas')}
}
导入SVG
const importSVG_tauri = async () => {const { data: rawdata } = await nativeImportTextFile(['svg'])if (!rawdata) returnconst svgEl: HTMLElement = parseStrToSvg(rawdata).childNodes[0] as HTMLElementconst components = parseSvgToComponents(svgEl as HTMLElement)components.forEach((component: IComponent) => {addComponentForCurrentCharacterFile(component)})
}
识别图片
const importPic_tauri = async () => {const options = await nativeImportFile(['jpg', 'png', 'jpeg'])const { name, uint8Array } = optionslet binary = ''uint8Array.forEach((byte) => {binary += String.fromCharCode(byte);})const base64str = btoa(binary)const type = name.split('.')[1] === 'png' ? 'imge/png' : 'image/jpeg'const dataUrl = `data:${type};base64,${base64str}`total.value = 0loaded.value = 0loading.value = trueconst img = document.createElement('img')img.onload = () => {setTimeout(() => {thumbnail(dataUrl, img, 1000)setEditStatus(Status.Pic)loading.value = false}, 100)}img.src = dataUrl
}
导出字体库
const exportFont_tauri = async (options: CreateFontOptions) => {const font = createFont(options)const buffer = toArrayBuffer(font) as ArrayBufferconst filename = `${selectedFile.value.name}.otf`nativeSaveBinary(buffer, filename, ['otf'])
}
导出字形
const exportGlyphs_tauri = async () => {if (editStatus.value === Status.GlyphList) {const _glyphs = glyphs.value.map((glyph: ICustomGlyph) => {return plainGlyph(glyph)})const data = JSON.stringify({glyphs: _glyphs,constants: constants.value,constantGlyphMap: mapToObject(constantGlyphMap),version: 1.0,})await nativeSaveText(data, `glyphs.json`, ['json'])} else if (editStatus.value === Status.StrokeGlyphList) {const _glyphs = stroke_glyphs.value.map((glyph: ICustomGlyph) => {return plainGlyph(glyph)})const data = JSON.stringify({glyphs: _glyphs,constants: constants.value,constantGlyphMap: mapToObject(constantGlyphMap),version: 1.0,})await nativeSaveText(data, `stroke_glyphs.json`, ['json'])} else if (editStatus.value === Status.RadicalGlyphList) {const _glyphs = radical_glyphs.value.map((glyph: ICustomGlyph) => {return plainGlyph(glyph)})const data = JSON.stringify({glyphs: _glyphs,constants: constants.value,constantGlyphMap: mapToObject(constantGlyphMap),version: 1.0,})await nativeSaveText(data, `radical_glyphs.json`, ['json'])} else if (editStatus.value === Status.CompGlyphList) {const _glyphs = comp_glyphs.value.map((glyph: ICustomGlyph) => {return plainGlyph(glyph)})const data = JSON.stringify({glyphs: _glyphs,constants: constants.value,constantGlyphMap: mapToObject(constantGlyphMap),version: 1.0,})nativeSaveText(data, `comp_glyphs.json`, ['json'])} else {const _glyphs = glyphs.value.map((glyph: ICustomGlyph) => {return plainGlyph(glyph)})const data = JSON.stringify({glyphs: _glyphs,constants: constants.value,constantGlyphMap: mapToObject(constantGlyphMap),version: 1.0,})await nativeSaveText(data, `glyphs.json`, ['json'])}
}
导出JPEG图片
const exportJPEG_tauri = async () => {// 导出JPEGconst _canvas = canvas.value as HTMLCanvasElementconst data = _canvas.toDataURL('image/jpeg')const buffer = base64ToArrayBuffer(data)const fileName = `${editCharacterFile.value.character.text}.jpg`nativeSaveBinary(buffer, fileName, ['jpg', 'jpeg'])
}
导出PNG图片
const exportPNG_tauri = async () => {// 导出PNGconst _canvas = canvas.value as HTMLCanvasElementrender(_canvas, false)const data = _canvas.toDataURL('image/png')const buffer = base64ToArrayBuffer(data)const fileName = `${editCharacterFile.value.character.text}.png`nativeSaveBinary(buffer, fileName, ['png'])render(_canvas, true)
}
导出SVG
const exportSVG_tauri = async () => {// 导出SVGif (editStatus.value !== Status.Edit && editStatus.value !== Status.Glyph ) returnconst components = editStatus.value === Status.Edit ? orderedListWithItemsForCurrentCharacterFile.value : orderedListWithItemsForCurrentGlyph.valueconst data = componentsToSvg(components, selectedFile.value.width, selectedFile.value.height)const fileName = `${editCharacterFile.value.character.text}.svg`nativeSaveText(data, fileName, ['svg'])
}
前端与Rust端通信

实现点击菜单按钮事件需要前后端通信,菜单由Rust生成并监听事件,但具体事件逻辑由前端实现。
Rust端代码,声明每个菜单按钮的事件函数,函数中逻辑比较简单,就是发送相应消息给前端,让前端知道目前要做的操作,具体逻辑在前端实现。

#[tauri::command]
fn create_file(app: AppHandle) {app.emit("create-file", ()).unwrap();
}#[tauri::command]
fn open_file(app: AppHandle) {app.emit("open-file", ()).unwrap();
}#[tauri::command]
fn save_file(app: AppHandle) {app.emit("save-file", ()).unwrap();
}#[tauri::command]
fn save_as(app: AppHandle) {app.emit("save-as", ()).unwrap();
}#[tauri::command]
fn undo(app: AppHandle) {app.emit("undo", ()).unwrap();
}#[tauri::command]
fn redo(app: AppHandle) {app.emit("redo", ()).unwrap();
}#[tauri::command]
fn cut(app: AppHandle) {app.emit("cut", ()).unwrap();
}#[tauri::command]
fn copy(app: AppHandle) {app.emit("copy", ()).unwrap();
}#[tauri::command]
fn paste(app: AppHandle) {app.emit("paste", ()).unwrap();
}#[tauri::command]
fn del(app: AppHandle) {app.emit("delete", ()).unwrap();
}#[tauri::command]
fn import_font_file(app: AppHandle) {app.emit("import-font-file", ()).unwrap();
}#[tauri::command]
fn import_templates_file(app: AppHandle) {app.emit("import-templates-file", ()).unwrap();
}#[tauri::command]
fn import_glyphs(app: AppHandle) {app.emit("import-glyphs", ()).unwrap();
}#[tauri::command]
fn import_pic(app: AppHandle) {app.emit("import-pic", ()).unwrap();
}#[tauri::command]
fn import_svg(app: AppHandle) {app.emit("import-svg", ()).unwrap();
}#[tauri::command]
fn export_font_file(app: AppHandle) {app.emit("export-font-file", ()).unwrap();
}#[tauri::command]
fn export_glyphs(app: AppHandle) {app.emit("export-glyphs", ()).unwrap();
}#[tauri::command]
fn export_jpeg(app: AppHandle) {app.emit("export-jpeg", ()).unwrap();
}#[tauri::command]
fn export_png(app: AppHandle) {app.emit("export-png", ()).unwrap();
}#[tauri::command]
fn export_svg(app: AppHandle) {app.emit("export-svg", ()).unwrap();
}#[tauri::command]
fn add_character(app: AppHandle) {app.emit("add-character", ()).unwrap();
}#[tauri::command]
fn add_icon(app: AppHandle) {app.emit("add-icon", ()).unwrap();
}#[tauri::command]
fn font_settings(app: AppHandle) {app.emit("font-settings", ()).unwrap();
}#[tauri::command]
fn preference_settings(app: AppHandle) {app.emit("preference-settings", ()).unwrap();
}#[tauri::command]
fn language_settings(app: AppHandle) {app.emit("language-settings", ()).unwrap();
}#[tauri::command]
fn import_template1(app: AppHandle) {app.emit("template-1", ()).unwrap();
}#[tauri::command]
fn remove_overlap(app: AppHandle) {app.emit("remove_overlap", ()).unwrap();
}

Rust端代码,监听事件:

app.on_menu_event(move |app, event| {if event.id() == "create-file" {create_file(app.app_handle().clone())} else if event.id() == "open-file" {open_file(app.app_handle().clone())} else if event.id() == "save-file" {save_file(app.app_handle().clone())} else if event.id() == "save-as" {save_as(app.app_handle().clone())} else if event.id() == "undo" {undo(app.app_handle().clone())} else if event.id() == "redo" {redo(app.app_handle().clone())} else if event.id() == "cut" {cut(app.app_handle().clone())} else if event.id() == "copy" {copy(app.app_handle().clone())} else if event.id() == "paste" {paste(app.app_handle().clone())} else if event.id() == "delete" {del(app.app_handle().clone())} else if event.id() == "import-font-file" {import_font_file(app.app_handle().clone())} else if event.id() == "import-templates-file" {import_templates_file(app.app_handle().clone())} else if event.id() == "import-glyphs" {import_glyphs(app.app_handle().clone())} else if event.id() == "import-pic" {import_pic(app.app_handle().clone())} else if event.id() == "import-svg" {import_svg(app.app_handle().clone())} else if event.id() == "export-font-file" {export_font_file(app.app_handle().clone())} else if event.id() == "export-glyphs" {export_glyphs(app.app_handle().clone())} else if event.id() == "export-jpeg" {export_jpeg(app.app_handle().clone())} else if event.id() == "export-png" {export_png(app.app_handle().clone())} else if event.id() == "export-svg" {export_svg(app.app_handle().clone())} else if event.id() == "add-character" {add_character(app.app_handle().clone())} else if event.id() == "add-icon" {add_icon(app.app_handle().clone())} else if event.id() == "font-settings" {font_settings(app.app_handle().clone())} else if event.id() == "preference-settings" {preference_settings(app.app_handle().clone())} else if event.id() == "language-settings" {language_settings(app.app_handle().clone())} else if event.id() == "template-1" {import_template1(app.app_handle().clone())} else if event.id() == "remove_overlap" {remove_overlap(app.app_handle().clone())}        
});

前端代码,监听消息:

const initTauri = () => {const keys = Object.keys(tauri_handlers)for (let i = 0; i < keys.length; i++) {const key = keys[i]listen(key, (event) => {tauri_handlers[key]()})}
}

相关文章:

字玩FontPlayer开发笔记8 Tauri2文件系统

字玩FontPlayer开发笔记8 Tauri2文件系统 字玩FontPlayer是笔者开源的一款字体设计工具&#xff0c;使用Vue3 ElementUI开发&#xff0c;源代码&#xff1a; github: https://github.com/HiToysMaker/fontplayer gitee: https://gitee.com/toysmaker/fontplayer 笔记 字玩目…...

http源码分析

一、HttpURLConnection http连接池源码分析 二、HttpClient 连接池&#xff0c;每个路由最大连接数 三、OkHttp okhttp的连接池与socket连接...

【vim】vim常用操作总结

vim常用操作总结 一&#xff0c;简介二&#xff0c;操作介绍2.1 命令模式2.1.1 删除&#xff08;剪切&#xff09;光标所在行2.1.2 复制2.1.3 粘贴2.1.4 跳到行末2.1.5 跳到行首2.1.6 撤销操作 2.2 视图模式2.3 命令模式2.4 编辑模式 三&#xff0c;总结 一&#xff0c;简介 在…...

【学Rust开发CAD】1 环境搭建

文章目录 一、搭建C/C编译环境二、安装Rust三、配置 PATH 环境变量四、验证安装结果五、安装编辑工具 一、搭建C/C编译环境 Rust 的编译工具依赖 C 语言的编译工具&#xff0c;这意味着你的电脑上至少已经存在一个 C 语言的编译环境。如果你使用的是 Linux 系统&#xff0c;往…...

RK3588开发笔记-spi接口调试

目录 前言 一、SPI接口简介 二、原理图连接 三、设备树配置 四、spi调试 五、spi应用软件接口 总结 前言 在嵌入式系统开发中,SPI(Serial Peripheral Interface)接口作为一种同步、全双工、多设备、多主机的通信协议,广泛应用于连接各种外围设备,如ADC、DAC、数据存…...

AlphaPi相关硬件驱动提取

初涉硬件编程&#xff0c;在咸鱼上搞了几块AlphaPi和microbit的板鼓捣了一下&#xff0c;alphapi生态不完善&#xff0c;网上又无任何文档&#xff0c;搞封闭&#xff0c;可玩性实在有限&#xff0c;但貌似相关扩展板是可以插microbit的&#xff0c;于是想把这些扩展版用microb…...

【Unity3D】Text文本文字掉落效果

相关技术&#xff1a;Text、TextMesh、Rigidbody&#xff08;刚体&#xff09;、BoxCollider&#xff08;碰撞体&#xff09;、TextGenerator、文本网格、文字网格 原理&#xff1a;使用UGUI Text获取其文字的每个字符网格坐标&#xff0c;转世界坐标生成对应的3D文本(TextMesh…...

MySQL内置函数详解

MySQL内置函数详解 1. 字符串函数 1.1 基本字符串处理 -- 字符串长度 SELECT LENGTH(Hello MySQL); -- 返回11-- 字符串大小写转换 SELECT LOWER(HELLO), UPPER(hello); -- 返回 hello, HELLO-- 字符串截取 SELECT SUBSTRING(MySQL Database, 1, 5); -- 返回 MySQL SELEC…...

【网络安全设备系列】9、WAF(Web应用防火墙)

0x00 定义: Web应用防火墙是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一种设备。 WAF需要部署在Web服务器的前面&#xff0c;串行接入&#xff0c;不仅在硬件性能上要求高&#xff0c;而且不能影响Web服务&#xff0c;所以HA功能、Bypass功能都是必…...

Express 加 sqlite3 写一个简单博客

例图&#xff1a; 搭建 命令&#xff1a; 前提已装好node.js 开始创建项目结构 npm init -y package.json:{"name": "ex01","version": "1.0.0","main": "index.js","scripts": {"test": &q…...

【C++数据结构——图】图的邻接矩阵和邻接表的存储(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 1. 带权有向图 2. 图的邻接矩阵 3. 图的邻接表 测试说明 通关代码 测试结果 任务描述 本关任务&#xff1a;编写一个程序实现图的邻接矩阵和邻接表的存储。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 带权有向图…...

基于单片机的直流稳压电源的设计(论文+源码)

1.系统方案设计 在本次直流稳压电源的设计中&#xff0c;其关键指标如下&#xff1a; 系统输入电压220V交流系统输出直流0到12V可调&#xff0c;步进可以达到0.1V电流最大输出可以到2A具有短路保护功能可以通过液晶或者数码管等显示设备显示当前输出电压 2. 电路图...

Golang开发-案例整理汇总

前言 CSDN的文章缺少一个索引所有文章分类的地方,所以手动创建这么一个文章汇总的地方,方便查找。Golang开发经典案例汇总 GoangWeb开发 GolangWeb开发- net/http模块 GolangWeb开发-好用的HTTP客户端httplib(beego) GolangWeb开发- Gin不使用Nginx部署Vue项目 Golang并发开…...

从入门到精通:Ansible Shell 模块的应用与最佳实践

Ansible是一款强大的自动化运维工具&#xff0c;通过其模块化的设计&#xff0c;可以方便地管理和配置远程主机。作为Ansible的一个常用模块&#xff0c;shell 模块使得我们可以在目标主机上执行复杂的命令或脚本。无论是单一的命令&#xff0c;还是复杂的Shell脚本&#xff0c…...

【Javascript Day1】javascript基础

javascript编程规则 弹窗&#xff08;举例&#xff09; alert("内容")&#xff0c;直接写在控制区生效 三种写法 1、行内js语法 &#xff1a;需要注意引号的问题 <input type"button" value"提示窗" οnclick alert("消息") &…...

dbeaver导入导出数据库(sql文件形式)

目录 前言dbeaver导出数据库dbeaver导入数据库 前言 有时候我们需要复制一份数据库&#xff0c;可以使用dbeaver简单操作&#xff01; dbeaver导出数据库 选中数据库右键->工具->转储数据库 dbeaver导入数据库 选中数据库右键->工具->执行脚本 mysql 默…...

字玩FontPlayer开发笔记6 Tauri2设置菜单

字玩FontPlayer开发笔记6 Tauri2设置菜单 字玩FontPlayer是笔者开源的一款字体设计工具&#xff0c;使用Vue3 ElementUI开发&#xff0c;源代码&#xff1a; github: https://github.com/HiToysMaker/fontplayer gitee: https://gitee.com/toysmaker/fontplayer 笔记 字玩目…...

大学生HTML5期末作业 Web前端网页制作 html5+css3+js html+css+js网页设计 美食 美食3个页面(带js)

大学生HTML5期末作业 Web前端网页制作 html5css3js htmlcssjs网页设计 美食 美食3个页面(带js) 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行…...

创龙3588——debian根文件系统制作

文章目录 build.sh debian 执行流程build.sh源码流程 30-rootfs.sh源码流程 mk-rootfs-bullseys.sh源码流程 mk-sysroot.sh源码流程 mk-image.sh源码流程 post-build.sh 大致流程系统制作步骤 build.sh debian 执行流程 build.sh 源码 run_hooks() {DIR"$1"shiftf…...

element组件el-select、el-tree-select有值,不渲染lable

大致情况是这个样子的............ 之前vue页面和script脚本是放在一个页面的&#xff0c;今天把页面和脚本拆开了。这一拆不打紧&#xff0c;完犊子&#xff01;它奶奶的el-select、el-tree-select这俩组件不正常显示了&#xff01;&#xff01;&#xff01; 我这个是vite-vue…...

【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 一、线性表的基本概念 二、初始化线性表 三、销毁线性表 四、判定是否为空表 五、求线性表的长度 六、输出线性表 七、求线性表中某个数据元素值 八、按元素值查找 九、插入数据元素 十、删除数据元素 测试说明 通关代码 测…...

2025第1周 | JavaScript中的正则表达式

目录 1. 正则表达式是个什么东东&#xff1f;1.1 怎么定义正则1.2 对象字面量方式1.3 类创建方式 2. 怎么使用2.1 实例方法2.1.1 exec方法2.1.2 test方法 2.2 字符串中的方法2.2.1 match/matchAll2.2.2 replace/replaceAll2.2.3 split2.2.4 search 3. 规则3.1 修饰符3.2 字符类…...

模型 九屏幕分析法

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。九屏幕法&#xff1a;全方位分析问题的系统工具。 1 九屏幕分析法的应用 1.1 新产品研发的市场分析 一家科技公司计划开发一款新型智能手机&#xff0c;为了全面评估市场潜力和风险&#xff0c;他们…...

快速排序(霍尔法),冒泡排序 【C语言】

冒泡排序 效率低&#xff0c;但是稳定性高 代码 // 冒泡排序 void maopao(int a[]);int main() {int a1[10] {34,78,29,46,12,85,63,92,57,31};printf("\n排序前:\n");print(a1);maopao(a2);printf("冒泡排序后:");print(a2); }//冒泡排序 void maopao(…...

国产编辑器EverEdit - 两种删除空白行的方法

1 使用技巧&#xff1a;删除空白行 1.1 应用场景 用户在编辑文档时&#xff0c;可能会遇到很多空白行需要删除的情况&#xff0c;比如从网页上拷贝文字&#xff0c;可能就会存在大量的空白行要删除。 1.2 使用方法 1.2.1 方法1&#xff1a; 使用编辑主菜单 选择主菜单编辑 …...

20241230 AI智能体-用例学习(LlamaIndex/Ollama)

AI小白一枚,入门实验。 1. Pg-Hydra 颠覆数据库体验:Hydra —— 开源的列式存储 PostgreSQL-CSDN博客 git clone https://github.com/hydradatabase/hydra && cd hydra cp .env.example .env docker compose up psql postgres://postgres:hydra@127.0.0.1:5432 do…...

2024年终总结及计划

24年收获不少&#xff0c;早就想总结下&#xff0c;但是有的问题不想去思考&#xff0c;也不想去面对&#xff0c;就晚了几天&#xff0c;趁着加班总结反思下。 一、计划完成情况 1、生活 ①运动&#xff1a;继续坚持每周慢跑15公里&#xff0c;这是必须要做的。另外&#x…...

基于深度学习算法的AI图像视觉检测

基于人工智能和深度学习方法的现代计算机视觉技术在过去10年里取得了显著进展。如今&#xff0c;它被广泛用于图像分类、人脸识别、图像中物体的识别等。那么什么是深度学习&#xff1f;深度学习是如何应用在视觉检测上的呢&#xff1f; 什么是深度学习&#xff1f; 深度学习是…...

分布式环境下定时任务扫描时间段模板创建可预订时间段

&#x1f3af; 本文详细介绍了场馆预定系统中时间段生成的实现方案。通过设计场馆表、时间段模板表和时间段表&#xff0c;系统能够根据场馆的提前预定天数生成未来可预定的时间段。为了确保任务执行的唯一性和高效性&#xff0c;系统采用分布式锁机制和定时任务&#xff0c;避…...

谷粒商城-高级篇完结-Sleuth+Zipkin 服务链路追踪

1、基本概念和整合 1.1、为什么用 微服务架构是一个分布式架构&#xff0c;它按业务划分服务单元&#xff0c;一个分布式系统往往有很多个服务单元。由于服务单元数量众多&#xff0c;业务的复杂性&#xff0c;如果出现了错误和异常&#xff0c;很难去定位 。主要体现在&#…...

GraphRAG:LLM之Graphrag接入milvus

前言 微软目前的graphrag更像个demo&#xff0c;数据量大的时候不是很友好的啊&#xff0c;所以将milvus接入了graphrag&#xff0c;看完这篇文章&#xff0c;其他数据库接入应该也没问题 注&#xff1a;这篇文章只是在search的时候接入进来&#xff0c;index过程或者说整个流…...

flink cdc oceanbase(binlog模式)

接上文&#xff1a;一文说清flink从编码到部署上线 环境&#xff1a;①操作系统&#xff1a;阿里龙蜥 7.9&#xff08;平替CentOS7.9&#xff09;&#xff1b;②CPU&#xff1a;x86&#xff1b;③用户&#xff1a;root。 预研初衷&#xff1a;现在很多项目有国产化的要求&#…...

【算法】算法初步

要学好数据结构和算法的设计与分析&#xff0c;请务必先打好C语言基础&#xff0c;因为C语言中的数据存储、内存映射、指针等等概念最接近计算机的底层原理&#xff0c;数据结构是数据在内存空间当中的组织形式&#xff0c;而算法则是提供了解决某个问题的一种思路&#xff0c;…...

Eureka原理

my: 服务注册与发现 心跳 自我保护 故障转移 Eureka 原理 Eureka 是一个由 Netflix 开源的服务注册与发现框架&#xff0c;广泛用于微服务架构中&#xff0c;尤其是 Spring Cloud 中的服务注册与发现。Eureka 的主要作用是管理和协调分布式系统中的服务实例&#xff0c;使…...

关于linux的ld.so.conf.d

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…...

Linux Shell 脚本编程基础知识篇—awk的条件判断(3)

ℹ️大家好&#xff0c;我是练小杰&#xff0c;今天周五了&#xff0c;又是一周过去了&#x1f606; 本文是有关Linux shell脚本编程的awk命令的条件语句&#xff0c;后续我会不断增加相关内容 ~~ 回顾:【awk字符串函数和内置变量】 更多Linux 相关内容请点击&#x1f449;【Li…...

安装Cockpit服务,使用Web页面管理你的Linux服务器

说起管理 Linux 服务器&#xff0c;大家首先想到的使用 SecureCRT、Xshell、MobaXterm 等工具远程到服务器&#xff0c;然后使用命令行管理服务器。今天给大家介绍一个好玩的工具&#xff0c;名字叫Cockpit&#xff0c; Cockpit 是一个免费开源的基于 web 的 Linux 服务器管理…...

基于微信小程序的面部动作检测

目录 引言系统架构概述前端实现细节后端实现细节防止欺骗与误导的措施前后端数据交互详细细节关键技术选型关键技术框架与算法详细说明优化与注意事项总结 引言 微信小程序的面部动作检测的核心功能包括检测用户的左右转头、眨眼和张嘴动作&#xff0c;并根据检测结果逐步引导…...

使用npm 插件[mmdc]将.mmd时序图转换为图片

使用npm 插件[mmdc]将.mmd时序图转换为图片 1. 安装 mmdc2. 转换为图片 可以使用 mmdc &#xff08;Mermaid CLI&#xff09;这个工具来将 .mmd 时序图&#xff08;Mermaid语法描述的时序图&#xff09;转换为图片&#xff0c;以下是使用步骤&#xff1a; 1. 安装 mmdc 确保…...

服务端错误的处理和web安全检测

文章目录 I 服务端错误的处理业务返回码处理前端处理业务返回码nginx处理http状态码II web安全检测区分服务器类型主机扫漏III 使用 micro_httpd 搭建一个PHP站点步骤下载micro_httpd 并安装它配置micro_httpd 来服务PHP文件I 服务端错误的处理 服务端发生错误时,返回给前端的…...

周记-Repeater中的children和item区别

Repeater中的children和item 在开发qml的界面时&#xff0c;用到了Repeater&#xff0c;表头需要根据Repeater是否存在显示的项&#xff0c;来进行显示。 repeater.children[i] repeater.itemAt(i)如果判断有没有存在显示的项&#xff0c;可以用下面的代码 function is_exis…...

JVM实战—8.如何分析jstat统计来定位GC

大纲 1.使用jstat了解线上系统的JVM运行状况 2.使用jmap和jhat了解线上系统的对象分布 3.如何分析JVM运行状况并合理优化 4.使用jstat分析模拟的BI系统JVM运行情况 5.使用jstat分析模拟的计算系统JVM运行情况 6.问题汇总 1.使用jstat了解线上系统的JVM运行状况 (1)JVM的…...

halcon三维点云数据处理(五)创建代表工具和机器人底座的3D模型

目录 一、gen_robot_tool_and_base_object_model_3d 函数调用二、gen_arrow_object_model_3d 函数调用 首先说明一下这部分代码在find_box_3d这个例程中&#xff0c;非常好用的一个坐标系生成函数。 一、gen_robot_tool_and_base_object_model_3d 函数调用 RobotToolSize : 0.…...

React Router 向路由组件传state参数浏览器回退历史页面显示效果问题

昨天在看尚硅谷张天禹老师讲的 React教程p90&#xff0c;老师讲到 React路由的 replace模式和push模式&#xff0c;老师的演示效果与自己本地操作不太一样。 老师的效果&#xff1a;点击查看消息1&#xff0c;消息2&#xff0c;消息3 再点回退&#xff0c;可以依次查看到 消息…...

LabVIEW四旋翼飞行器姿态监测系统

四旋翼飞行器姿态监测系统是一个集成了高度、速度、俯仰角与滚转角数据采集与分析的系统&#xff0c;提高飞行器在复杂环境中的操作精确度与安全性。系统利用LabVIEW平台与硬件传感器相结合&#xff0c;实现实时数据处理与显示&#xff0c;有效地提升了四旋翼飞行器的监测与控制…...

HTML——66.单选框

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>单选框</title></head><body><!--input元素的type属性&#xff1a;(必须要有)--> <!--单选框:&#xff08;如所住省会&#xff0c;性别选择&…...

av1学习笔记(二):sequence_header_obu

av1学习笔记&#xff08;二&#xff09;&#xff1a;sequence_header_obu 目录 av1学习笔记&#xff08;二&#xff09;&#xff1a;sequence_header_obu1&#xff0c;图片的编解码方式1.1 seq_profile:1.2 still_picture1.3 reduced_still_picture_header1.4 编解码图像的宽高…...

嵌入式驱动开发详解8(阻塞/非阻塞/异步通信)

文章目录 前言阻塞非阻塞异步通知后续 前言 首先来回顾一下“中断”&#xff0c;中断是处理器提供的一种异步机制&#xff0c;我们配置好中断以后就 可以让处理器去处理其他的事情了&#xff0c;当中断发生以后会触发我们事先设置好的中断服务函数&#xff0c; 在中断服务函数…...

CSS进阶和SASS

目录 一、CSS进阶 1.1、CSS变量 1.2、CSS属性值的计算过程 1.3、做杯咖啡 1.4、下划线动画 1.5、CSS中的混合模式(Blending) 二、SASS 2.1、Sass的颜色函数 2.2、Sass的扩展(extend)和占位符(%)、混合(Mixin) 2.3、Sass的数学函数 2.4、Sass的模块化开发 2.5、Sass…...

求交错序列前N项和(PTA)C语言

本题要求编写程序&#xff0c;计算交错序列 1-2/33/5-4/75/9-6/11... 的前N项之和。 输入格式: 输入在一行中给出一个正整数N。 输出格式: 在一行中输出部分和的值&#xff0c;结果保留三位小数。 输入样例: 5输出样例: 0.917 代码&#xff1a; #include<stdio.h&g…...