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

我用Tauri开发的待办效率工具开源了!

开源仓库地址 gitee

Git仓库地址:https://gitee.com/zhanhongzhu/zhanhongzhu.git

应用地址

windows应用地址下载 https://kestrel-task.cn

具体内容

也可以看🎉使用Tauri+vite+koa2+mysql开发了一款待办效率应用 这篇文章。

💻技术栈

  • Tauri: Tauri是一个用于构建现代桌面应用程序的工具,结合了Rust、Vue.js和Web技术,提供了强大的跨平台能力。
  • Vue3: Vue3是流行的JavaScript框架Vue.js的最新版本,具有更好的性能、更好的TypeScript支持和更多的特性。
  • Vite5: Vite是一个现代化的构建工具,Vite5是其最新版本,具有快速的冷启动、热模块替换和原生ES模块支持。
  • Koa2: Koa2是一个基于Node.js的轻量级Web框架,使用异步函数处理中间件,提供了简洁而强大的Web开发体验。
  • MySQL: MySQL是一个流行的关系型数据库管理系统,具有高性能、可靠性和广泛的应用领域,适用于各种规模的应用程序。

我的待办

快速添加待办任务,快速查看任务进度,摘要等。新增标签,分类,更好管理待办任务。通过标签、分类筛选待办任务,方便快捷。

OKR目标管理

我的想法是通过OKR管理系列的任务,这样每完成一个小任务,就可以关闭一个小任务,直观又方便,等到所有关键的小任务都完成了,整个任务也就完成了。

番茄工作法

主要是一个计时的时钟,可以在专注计时的时候,专注地完成某项任务,快捷方便,使用番茄工作法,选择一个待完成的任务,将番茄时间设为25分钟,也可以选择其他的区间,专注工作,中途不允许做任何与该任务无关的事。时刻保持专注。

日历视图

打开日历界面,通过视图的形式查看公历或农历日历下每个日期的待办提醒或任务事项。也可以在日历视图,添加任务。

MEMO快速记录

为了更好地帮你捕捉想法与灵感,提供了快速记录的输入框。专注记录想法,无需思考标题和排版。控制记录长度,降低记录压力,快速捕捉。

统计功能

展示了每天的待办数,以及每天新增的待办数量。

展示功能点

打包发布版本

脚本命令

  "scripts": {"dev": "vite","build": "vite build","preview": "vite preview","tauri": "tauri","pub": "cd build && node ./updateVersion.js && pnpm tauri build && node ./publish.js"}
npm run pub

更新版本号以及更新publicKey

//build/publish.js
import fs from 'fs'
// 读取 tauri.conf.json
const tauriConf = JSON.parse(fs.readFileSync('../src-tauri/tauri.conf.json', 'utf8'));
let newVersion = tauriConf.package.version; //更新的版本号// 读取 update.json
let updateJson = JSON.parse(fs.readFileSync('update.json', 'utf8'));
// 更新 update.json version
updateJson.version = newVersion;//获取版本更新的内容
//签名、版本路径、发版日期
const signature =  fs.readFileSync(`../src-tauri/target/release/bundle/msi/kestrel-task_${newVersion}_x64_zh-CN.msi.zip.sig`, 'utf8');
updateJson.platforms['windows-x86_64'].signature = signature;
updateJson.platforms['windows-x86_64'].url = `https://kestrel-task.cn/kestrel-task_${newVersion}_x64_zh-CN.msi.zip`
updateJson.pub_date = new Date();
fs.writeFileSync('update.json', JSON.stringify(updateJson, null, 2));

版本json信息

//build/update.json{"version": "1.0.8","notes": "kestrel-task","pub_date": "2024-03-23T04:23:39.799Z","platforms": {"windows-x86_64": {"signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVSNVRCUit5Zjc1Y3JLV085djl6eTMza2NqMXFIV0paNkl2ckgrTGZTRm9wcEJwcUlkaTBhM2hvN3pSVkRUZXlTZ2NSejJremg2Vklja041VkZmdGlZZ0hxTGVVM2xlL3dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMTY3ODE5CWZpbGU6a2VzdHJlbC10YXNrXzEuMC44X3g2NF96aC1DTi5tc2kuemlwCldSWVdwb0dwRU1aQUJ2ckFra2FTMjBkcnZtL0FWU3grd3MzeHZVTDhWRFFFUC9QWkpzdUNvUG9HZXBrVmhWMkoxTkpGc2pkYU5rRHYwcVdHdlk5dkFBPT0K","url": "https://kestrel-task.cn/kestrel-task_1.0.8_x64_zh-CN.msi.zip"}}
}

更新tauri.conf.json版本信息

// build/updateVersion.js
import fs from 'fs' // 读取 tauri.conf.json
const tauriConf = JSON.parse(fs.readFileSync('../src-tauri/tauri.conf.json', 'utf8'));
let version = tauriConf.package.version; //更新的版本号//更新版本号
let versionParts = version.split('.').map(Number);
versionParts[2] += 1;
let newVersion =versionParts.join('.');
// 更新 tauri.conf.json version
tauriConf.package.version = newVersion;
fs.writeFileSync('../src-tauri/tauri.conf.json', JSON.stringify(tauriConf, null, 2));

使用tauri的http模块

此处进行简单的封装,接口请求在控制台无法被查看到。如果觉得不方便,完全可以使用axios库。也是可以的。

import { http } from "@tauri-apps/api";export function request(config) {return new Promise((resolve, reject) => {http.fetch("https://kestrel-task.cn" + config.url, {method: "POST",body: http.Body.json(config.data),headers: {Authorization: token,},}).then((res) => {resolve(res.data.data);}).catch((err) => {reject(err);});});
}

http封装get请求

export function requestGet(config, d) {let url = d ? config.url : "https://kestrel-task.cn" + config.url;return new Promise((resolve, reject) => {http.fetch(url, {method: "get",headers: {Authorization: token,},}).then((res) => {resolve(d ? res.data : res.data.data);}).catch((err) => {reject(err);});});
}

使用封装的request函数

export const login = (data) => {return request({url: "/web/login",method: "post",data,});
};

使用WebviewWindow封装公共的窗口

import { WebviewWindow } from '@tauri-apps/api/window'
import { emit } from '@tauri-apps/api/event'// 创建新窗口
export async function createWin(args) {await emit('win-create', args)
}// 获取窗口
export async function getWin(label) {return await WebviewWindow.getByLabel(label)
}/*** @desc 设置窗口* @param type {string} 'show'|'hide'|'close'|'min'|'max'|'max2min'|'exit'|'relaunch'*/
export async function setWin(type) {await emit('win-' + type)
}// 登录窗口
export async function loginWin() {await createWin({label: 'Login',title: '登录',url: '/login',width: 320,height: 420,resizable: false,alwaysOnTop: true,})
}// ...
/*** @desc    封装新开多窗体*/import {WebviewWindow,appWindow,getAll,getCurrent,
} from "@tauri-apps/api/window";
import { relaunch, exit } from "@tauri-apps/api/process";
import { emit, listen } from "@tauri-apps/api/event";import { setWin } from "./actions.js";// 系统参数配置
export const windowConfig = {label: null, // 窗口唯一labeltitle: "", // 窗口标题url: "", // 路由地址urlwidth: 900, // 窗口宽度height: 640, // 窗口高度minWidth: null, // 窗口最小宽度minHeight: null, // 窗口最小高度x: null, // 窗口相对于屏幕左侧坐标y: null, // 窗口相对于屏幕顶端坐标center: true, // 窗口居中显示resizable: true, // 是否支持缩放maximized: false, // 最大化窗口decorations: true, // 窗口是否无边框及导航条alwaysOnTop: false, // 置顶窗口
};class Windows {constructor() {this.mainWin = null;}// 获取窗口getWin(label) {return WebviewWindow.getByLabel(label);}// 获取全部窗口getAllWin() {return getAll();}// 创建新窗口async createWin(options) {const args = Object.assign({}, windowConfig, options);// 判断窗口是否存在const existWin = getAll().find((w) => w.label == args.label);if (existWin) {if (existWin.label.indexOf("main") == -1) {await existWin?.unminimize();await existWin?.setFocus();return;}await existWin?.close();}// 创建窗口对象let win = new WebviewWindow(args.label, args);// 是否最大化if (args.maximized && args.resizable) {win.maximize();}// 窗口创建完毕/失败win.once("tauri://created", async () => {console.log("window create success!");});win.once("tauri://error", async () => {console.log("window create error!");});}// 开启主进程监听事件async listen() {// 创建新窗体await listen("win-create", (event) => {this.createWin(JSON.parse(event.payload));});// 显示窗体await listen("win-show", async (event) => {if (appWindow.label.indexOf("main") == -1) return;await appWindow.show();await appWindow.unminimize();await appWindow.setFocus();});// 隐藏窗体await listen("win-hide", async (event) => {if (appWindow.label.indexOf("main") == -1) return;await appWindow.hide();});// 退出应用await listen("win-exit", async (event) => {setWin("logout");await exit();});// 重启应用await listen("win-relaunch", async (event) => {await relaunch();});// 主/渲染进程传参await listen("win-setdata", async (event) => {await emit("win-postdata", JSON.parse(event.payload));});}
}export default Windows;

封装Echart组件,便于使用

<template><div ref="MyEcharts" :style="{ height: height, width: width }"></div></template><script>import * as echarts from 'echarts'import T from './echarts-theme-T.js'echarts.registerTheme('T', T)const unwarp = obj => obj && (obj.__v_raw || obj.valueOf() || obj)export default {...echarts,name: 'Charts',props: {// 高度height: { type: String, default: '100%' },// 宽度width: { type: String, default: '100%' },// 是否无数据nodata: { type: Boolean, default: false },// 配置项option: { type: Object, default: () => {} }},data() {return {isActivat: false,myChart: null,MyEcharts:null}},watch: {option: {deep: true,handler(v) {unwarp(this.myChart).setOption(v)}}},computed: {myOptions: function() {return this.option || {}}},activated() {if (!this.isActivat) {this.$nextTick(() => {this.myChart.resize()})}},deactivated() {this.isActivat = false},mounted() {this.isActivat = truethis.$nextTick(() => {this.draw()})},methods: {draw() {const myChart = echarts.init(this.$refs.MyEcharts, 'T')myChart.setOption(this.myOptions)this.myChart = myChartwindow.addEventListener('resize', () => myChart.resize())}}}</script>

echart主题模块

//echarts-theme-T.js
const T = {color: ['#409EFF', '#36CE9E', '#f56e6a', '#626c91', '#edb00d', '#909399'], // 颜色数组grid: { // 网格left: '3%', // 左边距right: '3%', // 右边距bottom: '10', // 下边距top: '40', // 上边距containLabel: true // 包含标签},legend: { // 图例textStyle: { // 文本样式color: '#999' // 颜色},inactiveColor: 'rgba(128,128,128,0.4)' // 不活跃颜色},categoryAxis: { // 类别轴axisLine: { // 轴线show: true, // 显示lineStyle: { // 线条样式color: 'rgba(128,128,128,0.2)', // 颜色width: 1 // 宽度}},axisTick: { // 刻度线show: false, // 不显示lineStyle: { // 线条样式color: '#000' // 颜色}},axisLabel: { // 轴标签color: '#999' // 颜色},splitLine: { // 分隔线show: false, // 不显示lineStyle: { // 线条样式color: ['#eee'] // 颜色}},splitArea: { // 分隔区域show: false, // 不显示areaStyle: { // 区域样式color: ['rgba(255,255,255,0.01)', 'rgba(0,0,0,0.01)'] // 颜色}}},valueAxis: { // 数值轴axisLine: { // 轴线show: false, // 不显示lineStyle: { // 线条样式color: '#999' // 颜色}},splitLine: { // 分隔线show: true, // 显示lineStyle: { // 线条样式color: 'rgba(128,128,128,0.2)' // 颜色}}}
}export default T

封装公共的弹窗组件

<template><el-dialog class="my-dialog" draggable v-bind="$attrs" v-model="modelValue" :modal-append-to-body="modalAppendToBody":append-to-body="appendToBody" :fullscreen="fullscreen" :close-on-click-modal="closeOnClickModal":close-on-press-escape="closeOnPressEscape" :width="comWidth" :top="top" @closed="closed"><template v-slot:title><slot name="title"><span class="my-dialog-title">{{ dialogTitle || ''}}</span></slot></template><div v-loading="loading" class="body-content" :style="{'height':comHeight}"><slot></slot></div><template #footer><div class="dialog-footer" v-if="closeBtn"><el-button type="close" size="small1" @click="closed">关闭</el-button></div></template></el-dialog>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({visible: { type: Boolean, default: false }, // 是否可见loading: { type: Boolean, default: false }, // 是否加载中top: { type: String, default: '20vh' }, // 距离顶部的距离fullscreen: { type: Boolean, default: false }, // 是否全屏size: { type: String, default: 'big' }, // 大小width: { type: [Number, String], default: 0 }, // 宽度height: { type: [Number, String], default: '55vh' }, // 宽度dialogTitle: { type: String, default: '' }, // 弹出框标题modalAppendToBody: { type: Boolean, default: false }, // 是否将弹出框插入到body中appendToBody: { type: Boolean, default: false }, // 是否将内容插入到body中closeOnClickModal: { type: Boolean, default: false }, // 是否在点击模态框时关闭closeOnPressEscape: { type: Boolean, default: false }, // 是否在按下ESC键时关闭dblclickDisabled: { type: Boolean, default: false }, // 是否禁用双击放大closeBtn: { type: Boolean, default: false }, // 关闭按钮},['modelValue']
)const comWidth = computed(() => {if (props.size === 'small') {return props.width || '30%'} else if (props.size === 'middle') {return props.width || '40%'} else if (props.size === 'big') {return props.width || '60%'}return props.width || '40%'
})const comHeight = computed(() => {return props.height || '55vh'
})const emit = defineEmits(['update:modelValue','closed'])
const closed = () => {emit('update:modelValue')emit('closed',false)
}
</script>

封装ResizeObserver函数

主要是监听元素的变化或者窗口的变化。有一部分用到了可以拉伸的左右布局的模块。

//directive/index.js
// 监听元素大小变化的指令
const map = new WeakMap();
const ob = new ResizeObserver((entries) => {for (const entry of entries) {// 获取dom元素的回调const handler = map.get(entry.target);//存在回调函数if (handler) {// 将监听的值给回调函数handler({width: entry.borderBoxSize[0].inlineSize,height: entry.borderBoxSize[0].blockSize,});}}
});export const Resize = {mounted(el, binding) {//将dom与回调的关系塞入mapmap.set(el, binding.value);//监听el元素的变化ob.observe(el);},unmounted(el) {//取消监听ob.unobserve(el);},
};
const directives = { Resize };const registerDirective = (app) => {Object.keys(directives).forEach((key) => {app.directive(key, directives[key]);});
};
export default registerDirective;

公共拖曳布局的函数

主要是用于左右布局宽度的变化,可以使用鼠标进行拖曳,改变左右盒子的高度。

export const useCommon = ()=>{function setLayoutDrag(dragId) {const resize = document.getElementById(dragId)let previousElement = resize.previousSiblinglet nextElement = resize.nextSiblinglet previousTag = previousElement.tagNamelet nextTag = nextElement.tagNameresize.onmousedown = (e) => {const startX = e.clientXconst startY = e.clientYlet type = ''if (previousTag === 'ASIDE' && nextTag === 'MAIN') {type = 'ASIDE-MAIN'} else if (previousTag === 'MAIN' && nextTag === 'ASIDE') {type = 'MAIN-ASIDE'} else if ((previousTag === 'HEADER' && nextTag === 'MAIN') ||(previousTag === 'FOOTER' && nextTag === 'MAIN')) {type = 'HEADER-MAIN'} else if ((previousTag === 'MAIN' && nextTag === 'HEADER') ||(previousTag === 'MAIN' && nextTag === 'FOOTER')) {type = 'MAIN-HEADER'}let initWidth = 0,initHeight = 0if (type === 'ASIDE-MAIN') {initWidth = previousElement.clientWidth // 初始位置} else if (type === 'MAIN-ASIDE') {initWidth = nextElement.clientWidth // 初始位置} else if (type === 'HEADER-MAIN') {initHeight = previousElement.clientHeight} else if (type === 'MAIN-HEADER') {initHeight = nextElement.clientHeight}document.onmousemove = (k) => {const endX = k.clientXconst endY = k.clientYlet moveLen = endX - startX // 横向移动宽度let moveHeight = endY - startY // 纵向移动高度switch (type) {case 'ASIDE-MAIN':let asideMainWidth = initWidth + moveLenif (moveLen < 0) {// 向左移if (asideMainWidth > 400) {// 左侧剩90previousElement.style.width = asideMainWidth + 'px'}} else {// 向右移动if (nextElement.clientWidth > 400) {// 右侧剩90previousElement.style.width = asideMainWidth + 'px'}}breakcase 'MAIN-ASIDE':let mainAsideWidth = initWidth - moveLenif (moveLen < 0) {// 向左移if (previousElement.clientWidth > 400) {// 左侧剩90nextElement.style.width = mainAsideWidth + 'px'}} else {// 向右移动if (mainAsideWidth > 400) {nextElement.style.width = mainAsideWidth + 'px'}}breakcase 'HEADER-MAIN': {let headerMainHeight = initHeight + moveHeightif (moveHeight < 0) {// 向上移if (headerMainHeight > 60) {// 上侧剩90previousElement.style.height = headerMainHeight + 'px'}} else {// 向下移动if (nextElement.clientHeight > 60) {// 下侧剩90previousElement.style.height = headerMainHeight + 'px'}}break}case 'MAIN-HEADER': {let mainHeaderHeight = initHeight - moveHeightif (moveHeight < 0) {// 向上移if (previousElement.clientHeight > 60) {// 左侧剩90nextElement.style.height = mainHeaderHeight + 'px'}} else {// 向下移动if (mainHeaderHeight > 60) {nextElement.style.height = mainHeaderHeight + 'px'}}break}default:}}document.onmouseup = (evt) => {document.onmousemove = nulldocument.onmouseup = nullresize.releaseCapture && resize.releaseCapture()}resize.setCapture && resize.setCapture()return false}}return {setLayoutDrag}
}

公共布局

此处的可以自己查看代码。

invoke调用rust函数,关闭splash

import { invoke } from '@tauri-apps/api/tauri'onMounted(() => {// window.addEventListener('contextmenu', (e) => e.preventDefault(), false)document.addEventListener('DOMContentLoaded', () => {// This will wait for the window to load, but you could// run this function on whatever trigger you wantsetTimeout(() => {invoke('close_splashscreen')}, 1000)})
})

🎉结语 感兴趣的可以试试,有不清楚的问题,关于tauri开发方面的问题,也可以一起交流。欢迎加我:zhan_1337608148。一起成长,一起进步。

相关文章:

我用Tauri开发的待办效率工具开源了!

开源仓库地址 gitee Git仓库地址:https://gitee.com/zhanhongzhu/zhanhongzhu.git 应用地址 windows应用地址下载 https://kestrel-task.cn 具体内容 也可以看&#x1f389;使用Taurivitekoa2mysql开发了一款待办效率应用 这篇文章。 &#x1f4bb;技术栈 Tauri: Tauri…...

【黑科技】:Laravel 项目性能提升 20 倍

令人激动的黑科技&#xff1a;Laravel 项目性能提升 20 倍 这个项目能够在无需修改任何代码且无需第三方扩展的前提下&#xff0c;将你的 Laravel 项目性能提高 20 倍。它仅依赖于 PHP 原生的 pcntl、posix、fiber 和 sockets。 项目灵感 起因是看到官方发布的 PHP 8.1 更新…...

User Allocation In MEC: A DRL Approach 论文笔记

论文&#xff1a;ICWS 2021 移动边缘计算中的用户分配&#xff1a;一种深度强化学习方法 代码地址&#xff1a;使用强化学习在移动边缘计算环境中进行用户分配 目录 Ⅰ.Introduction II. MOTIVATION-A.验证假设的观察结果 II. MOTIVATION-A Motivating Example 数据驱动…...

leetcode 69. x 的平方根

可以使用二分查找法或牛顿迭代法来实现 LeetCode 问题 69. x 的平方根。下面是使用二分查找法和牛顿迭代法的 C 实现。 二分查找法 #include <iostream>class Solution { public:int mySqrt(int x) {if (x 0) return 0;int left 1, right x, ans 0;while (left <…...

基于词级ngram的词袋模型对twitter数据进行情感分析

按照阿光的项目做出了学习笔记&#xff0c;pytorch深度学习实战项目100例 基于词级ngram的词袋模型对twitter数据进行情感分析 什么是 N 符&#xff1f; N 格是指给定文本或语音样本中 n 个项目的连续序列。这些项目可以是音素、音节、字母、单词或碱基对&#xff0c;具体取…...

Linux-Centos-改密码(单用户登陆)

笔记一&#xff1a; centos7单用户修改root密码 在CentOS 7中&#xff0c;如果您是唯一的用户或者您确信其他用户不会登录&#xff0c;您可以按照以下步骤来修改root密码&#xff1a; 1.重启系统。 2.启动时出现引导界面时&#xff0c;按任意键进入GRUB菜单。 3.选择要启动的内…...

java实现OCR图片识别,RapidOcr开源免费

先看一下识别效果&#xff08;自我感觉很牛逼&#xff09;&#xff0c;比Tess4J Tesseract省事&#xff0c;这个还需要训练&#xff0c;安装软件、下载语言包什么的 很费事&#xff0c;关键识别率不高 RapidOcr不管文字的横竖&#xff0c;还是斜的都能识别&#xff08;代码实现…...

PCB工艺边设计准则

在PCB设计时&#xff0c;通常会在电路板的边缘预留一定的空间&#xff0c;这部分空间被称为工艺边。它有助于在生产过程中确保电路板的尺寸和形状的准确性。以使得组装时更加顺畅、便捷。而工艺边的加工&#xff0c;使得线路板上的元件可以精准地与设备对接&#xff0c;从而提高…...

CTF-NSSCTF题单[GKCTF2020]

[GKCTF 2020]CheckIN 这道题目考察&#xff1a;php7-gc-bypass漏洞 打开这道题目&#xff0c;开始以为考察反序列化&#xff0c;但实际并不是&#xff0c;这里直接用$_REQUEST传入了参数便可以利用了。这里出现了一个eval&#xff08;&#xff09;函数&#xff0c;猜测考察命…...

redis的分片集群(仅供自己参考)

前言&#xff1a;为什么使用分片集群&#xff1a;因为redis的主从和哨兵机制主要是用来解决redis的高并发读的问题&#xff0c;还有redis的高并发的写的问题没有解决。使用分片集群就可以很好的解决redis写的问题&#xff0c;有多个master就可以实现并发的写。同时&#xff0c;…...

自动驾驶-机器人-slam-定位面经和面试知识系列01之常考公式推导(01)

李群李代数扰动bundle adjustment 这个博客系列会分为C STL-面经、常考公式推导和SLAM面经面试题等三个系列进行更新&#xff0c;基本涵盖了自己秋招历程被问过的面试内容&#xff08;除了实习和学校项目相关的具体细节&#xff09;。在知乎和牛客也会同步更新&#xff0c;全网…...

netty入门-5 ServerBootstrap与Bootstarp

前言 本来这篇应该紧接着说明Future和Promise。 但是考虑前文第三篇即用到了ServerBootstrap来启动一个服务器&#xff0c;并且我读的闪电侠netty&#xff0c;先写的服务器与客户端启动这部分。索性就先写出来了。主要内容来自闪电侠netty ServerBootstrap ServerBootstrap就…...

JavaEE - Spring Boot 简介

1.Maven 1.1 什么是Maven 翻译过来就是: Maven是⼀个项⽬管理⼯具。基于POM(Project Object Model,项⽬对象模型)的概念&#xff0c;Maven可以通 过⼀⼩段描述信息来管理项⽬的构建&#xff0c;报告和⽂档的项⽬管理⼯具软件。 可以理解为&#xff1a;Maven是一个项目管理工具…...

SwiftUI革新:Xcode UI开发的新纪元

SwiftUI革新&#xff1a;Xcode UI开发的新纪元 SwiftUI作为Apple推出的声明式UI框架&#xff0c;彻底改变了在Xcode中构建用户界面的方式。它不仅简化了代码&#xff0c;还提高了开发效率&#xff0c;并且使得UI设计更加直观和灵活。本文将深入探讨如何在Xcode中使用SwiftUI进…...

22、基于共享内存的数据结构——用十个块来提高并发性

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

【ffmpeg命令入门】实现画中画

文章目录 前言画中画是什么画中画的外观描述效果展示为什么要用画中画应用场景示例 使用FFmpeg添加画中画示例命令参数解释调整嵌入视频的位置调整嵌入视频的大小处理音频 总结 前言 FFmpeg 是一款强大的多媒体处理工具&#xff0c;广泛用于音视频的录制、转换和流处理。它不仅…...

基于 LangChain+LangGraph 来实现一个翻译项目

相信大家在看文档的时候&#xff0c;有时会比较苦恼&#xff0c;比如 AI 相关的文档都是外文&#xff0c;中文文档比较少&#xff0c;看起来会比较吃力&#xff0c;有的时候会看不懂&#xff0c;翻译软件又翻得很乱&#xff0c;完全看不了&#xff0c;今天就基于 LangChain 和 …...

javascript 如何将 json 格式数组转为 excel 表格| sheetJS

案例 // https://unpkg.com/xlsx0.18.5/dist/xlsx.full.min.js function exportXlsx(jsonData, fileName , mine null) {const workbook XLSX.utils.book_new();// 将JSON数组转换成工作表const worksheet XLSX.utils.json_to_sheet(jsonData);// 向工作簿添加工作表XLSX.…...

网页制作技术在未来会如何影响人们的生活?

网页制作技术在未来会如何影响人们的生活&#xff1f; 李升伟 网页制作技术在未来可能会从以下几个方面显著影响人们的生活&#xff1a; 1. 工作与学习方式的变革&#xff1a;远程办公和在线教育将更加普及和高效。通过精心制作的网页&#xff0c;人们能够实现更便捷的协作…...

【计算机网络】网络层——IPv4地址(个人笔记)

学习日期&#xff1a;2024.7.24 内容摘要&#xff1a;IPv4地址&#xff0c;分类编址&#xff0c;子网&#xff0c;无分类编址 IPv4地址概述 在TCP/IP体系中&#xff0c;IP地址是一个最基本的概念&#xff0c;IPv4地址就是给因特网上的每一台主机的每一个接口分配一个在全世界…...

c++ 学习笔记之多线程:线程锁,条件变量,唤醒指定线程

基于CAS线程加锁方式 CAS&#xff08;Compare-And-Swap&#xff09;和 mutex 都是用于实现线程安全的技术&#xff0c;但它们适用于不同的场景&#xff0c;具有不同的性能和复杂性。下面是对两者的区别和使用场景的详细解释&#xff1a; CAS&#xff08;Compare-And-Swap&…...

《0基础》学习Python——第二十三讲__网络爬虫/<6>爬取哔哩哔哩视频

一、在B站上爬取一段视频&#xff08;B站视频有音频和视频两个部分&#xff09; 1、获取URL 注意&#xff1a;很多平台都有反爬取的机制&#xff0c;B站也不例外 首先按下F12找到第一条复制URL 2、UA伪装&#xff0c;下列图片中&#xff08;注意代码书写格式&#xff09; 3、Co…...

第13周 简历职位功能开发与Zookeeper实战

第13周 简历职位功能开发与Zookeeper实战 本章概述1. Mysql8窗口函数over使用1.1 演示表结构与数据1.2 案例1:获取男女总分数1.3 案例2****************************************************************************************本章概述 1. Mysql8窗口函数over使用 参考案例…...

什么是大型语言模型 (LLM)

本章探讨下&#xff0c;人工智能如何彻底改变我们理解和与语言互动的方式 大型语言模型 (LLM) 代表了人工智能的突破&#xff0c;它采用具有广泛参数的神经网络技术进行高级语言处理。 本文探讨了 LLM 的演变、架构、应用和挑战&#xff0c;重点关注其在自然语言处理 (NLP) 领…...

【人工智能】AI时代:探索个人潜能的新视角

文章目录 &#x1f34a;Al时代的个人发展1 AI的高速发展意味着什么1.1 生产力大幅提升1.2 生产关系的改变1.3 产品范式1.4 产业革命1.5 Al的局限性1.5.1局限一:大模型的幻觉1.5.2 局限二&#xff1a;Token 2 个体如何应对这种改变?2.1 职场人2.2 K12家长2.3 大学生2.4 创业者 …...

pyaudio VAD通过声音音频值分贝大小检测没人说话自动停止录制

效果可能说话声音小可能不被监听到,需要更改QUIET_DB阈值,另外delay_time值是低于阈值多久就可以停止保存当前的语音 import pyaudio import waveimport sys import numpy as npdef record_auto(MIC_INDEX=1):开启麦克风录音,保存至temp/speech_record.wav音频文件音量超过…...

《后端程序猿 · @Value 注释说明》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

【LeetCode】71.简化路径

1. 题目 2. 分析 3. 代码 我写了一版很复杂的代码&#xff1a; class Solution:def simplifyPath(self, path: str) -> str:operator [] # 操作符的栈dir_name [] # 文件名的栈idx 0cur_dir_name ""while(idx < len(path)):if path[idx] /:operator.ap…...

DockerCompose 安装环境

1. Redis version: 3 services:redis:image: redis:6.2.12container_name: redisports:- "6379:6379"environment:TZ: Asia/Shanghaivolumes:# 本地数据目录要先执行 chmod 777 /usr/local/docker/redis/data 赋予读写权限&#xff0c;否则将无法写入数据- /usr/loc…...

学习笔记之JAVA篇(0724)

p 方法 方法声明格式&#xff1a; [修饰符1 修饰符2 ...] 返回值类型 方法名&#xff08;形式参数列表&#xff09;{ java语句;......; } 方法调用方式 普通方法对象.方法名&#xff08;实参列表&#xff09;静态方法类名.方法名&#xff08;实参列表&#xff09; 方法的详…...