uniapp、vue实现滑动拼图验证码
uniapp、vue实现滑动拼图验证码
实际开发工作中,在登陆的时候需要短信验证码,但容易引起爬虫行为,需要用到反爬虫验证码,今天介绍一下拼图验证码,解决验证码反爬虫中的滑动验证码反爬虫。滑动拼图验证码是在滑块验证码的基础上增加了一个随机滑动距离,用户需要将滑块滑到拼图的缺口处,使拼图完整,才能通过校验。平台兼容性,H5、微信小程序、字节、百度、qq等。
实际开发工作中,在登陆的时候需要短信验证码,但容易引起爬虫行为,需要用到反爬虫验证码,今天介绍一下拼图验证码,解决验证码反爬虫中的滑动验证码反爬虫。
原理
滑动拼图验证码是在滑块验证码的基础上增加了一个随机滑动距离,用户需要将滑块滑到拼图的缺口处,使拼图完整,才能通过校验。
一、不对接口版本
平台兼容性,H5、微信小程序、字节、百度
XXX.vue文件引入
template标签中引入
<slider-verify :isShow="sliderVerifyFLag" @touchSliderResult="verifyResult" ref="verifyElement"></slider-verify>
script标签中引入组件
import sliderVerify from '@/components/slider-verify/slider-verify.vue';//组件存放的路径export default {components: {'slider-verify': sliderVerify},data() {return {sliderVerifyFLag: false //滑块验证};},onLoad() {},methods: {// 滑块验证结果回调函数verifyResult(res) {this.sliderVerifyFLag = false;if (res) { //校验通过}else{// 校验失败,点击关闭按钮}}}
};
slider-verify.vue文件代码
<template><view class="slider-verify-box" v-if="isShow"><view class="verifyBox"><view class="slider-title">图形验证</view><view class="slide-content"><view class="slide-tips">拖动下方滑块完成拼图</view><view class="slider-pintu"><image id="pintuImg" :src="'/static/images/slider-verify/' + img + '.jpg'" class="pintu"></image><view class="pintukuai" :style="{ top: top + 'px', left: oldx + 'px' }"><image :src="'/static/images/slider-verify/' + img + '.jpg'" :style="{ top: '-' + top + 'px', left: '-' + left + 'px'}"></image></view><view class="yinying" :style="{ top: top + 'px', left: left + 'px' }"></view></view><view class="slider-movearea" @touchend="endTouchMove"><movable-area :animation="true"><movable-view :x="x" direction="horizontal" @change="startMove"></movable-view></movable-area><view class="huadao">拖动左边滑块完成上方拼图</view></view></view><view class="slider-btn-group"><view class="slider-btn" @tap="closeSlider">关闭</view><view class="slider-btn slide-btn-refresh" @tap="refreshVerify">刷新</view></view></view></view>
</template><script>
export default {name: 'slider-verify',props: {isShow: true},data() {return {x: 0, //初始距离oldx: 0, //移动的距离img: '1', //显示哪张图片left: 0, //随机拼图的最终X轴距离top: 0, //拼图的top距离};},watch: {// 每次打开重新刷新拼图isShow(newValue, oldValue) {if(newValue){this.refreshVerify(); //刷新}}},mounted() {var that = this;that.refreshVerify();},methods: {//刷新验证refreshVerify() {var gl = Math.random().toFixed(2);this.left = uni.upx2px(560) * gl > uni.upx2px(280) ? uni.upx2px(280) : uni.upx2px(560) * gl + uni.upx2px(150); //生成随机X轴最终距离this.top = uni.upx2px(190) * gl; //生成随机Y轴初始距离if (gl <= 0.2) {this.img = 1;}if (gl > 0.2 && gl <= 0.4) {this.img = 2;}if (gl > 0.4 && gl <= 0.6) {this.img = 3;}if (gl > 0.6 && gl <= 0.8) {this.img = 4;}if (gl > 0.8 && gl <= 1) {this.img = 5;}this.resetMove(); //重置阴影位置},/* 滑动中 */startMove(e) {this.oldx = e.detail.x;},/* 滑动结束 */endTouchMove() {var that = this;if (Math.abs(that.oldx - that.left) <= 5) {uni.showToast({title: '验证成功',duration: 2500,success() {that.$emit('touchSliderResult', true);}});} else {that.refreshVerify();}},/* 重置阴影位置 */resetMove() {this.x = 1;this.oldx = 1;setTimeout(() => {this.x = 0;this.oldx = 0;}, 300);},// 关闭closeSlider(){this.$emit('touchSliderResult', false);} }
};
</script><style lang="less">
.slider-verify-box {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.5);z-index: 999;
}
.verifyBox {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);// width: 85%;background-color: #fff;border-radius: 20upx;box-shadow: 0 0 5upx rgba(0, 0, 0);.slider-title {font-size: 36upx;text-align: center;padding: 1em 0;color: rgba(2, 20, 33, 0.85);border-bottom: 1px solid rgba(2, 20, 33, 0.15);}.slide-content {width: 560rpx;padding: 0 1em;margin: 0 auto;.slide-tips {font-size: 28rpx;color: rgba(2, 20, 33, 0.45);padding: 0.5em 0;}.slider-pintu {position: relative;width: 100%;border-radius: 10rpx;overflow: hidden;.pintu {width: 560rpx;height: 315rpx;display: block;margin: 0 auto;}.pintukuai {position: absolute;top: 0;left: 0;width: 120rpx;height: 120rpx;z-index: 100;box-shadow: 0 0 5upx rgba(0, 0, 0, 0.3);overflow: hidden;image {display: block;position: absolute;top: 0;left: 0;width: 560rpx;height: 315rpx;}}}.yinying {position: absolute;width: 120rpx;height: 120rpx;background-color: rgba(0, 0, 0, 0.5);}}
}.slider-movearea {position: relative;height: 80upx;width: 100%;margin: 25upx auto;movable-area {height: 80upx;width: 100%;movable-view {width: 80upx;height: 80upx;border-radius: 50%;background-color: #007cff;background-image: url(../../static/images/slider-verify/icon-button-normal.png);background-repeat: no-repeat;background-size: auto 30upx;background-position: center;position: relative;z-index: 100;}}
}.huadao {width: 100%;height: 66upx;line-height: 66upx;background: #eee;box-shadow: inset 0 0 5upx #ccc;border-radius: 40rpx;color: #999;text-align: center;box-sizing: border-box;position: absolute;top: 7rpx;left: 0;font-size: 28rpx;z-index: 99;
}.slider-btn-group{width: 100%;display: flex;justify-content: center;align-items: center;border-top: 1px solid rgba(2, 20, 33, 0.15);.slider-btn{flex: 1;height: 100rpx;line-height: 100rpx;text-align: center;font-size: 36rpx;color:rgba(2,20,33,0.85);&:active{opacity: 0.8;}}.slide-btn-refresh{color:rgba(14,107,176,1);border-left: 1px solid rgba(2, 20, 33, 0.15);}
}
</style>
二、对接口版本

平台兼容性,H5、微信小程序、字节、百度、qq等
XXX.vue文件引入
template标签中引入
<view @tap="getCode()" >获取验证码</view>
<validationPT class="setVef" ref="vefCode" @VefCodeTrue="getVefCodeTrue" :inputPhone="mobile" theme="dialog"></validationPT>
script标签中引入组件
import validationPT from '@/components/validationPT/validationPT.vue'export default {components: {'slider-verify': sliderVerify},data() {},onLoad() {},methods: {// 效验手机号getCode() {this.getCodePT();},//获取弹窗getCodePT(msg) {this.$refs.vefCode.GetSlideBlockApi(); //调用图片接口,获取验证图片this.$refs.vefCode.clkOpenRef(); //验证通过,打开拼图验证this.$refs.vefCode.initial();//重置},// 滑块验证结果回调函数//拼图验证是否成功getVefCodeTrue(msg) {this.VefInfosBk = msg;if (msg.Res == true) {//获取验证码} },}
};
validationPT.vue文件代码
<template><view :class="[{'frame--dialog':theme}]"><view class="frameBg" v-show="showModal" style="z-index:10"></view><view class="framework" v-if="isVefCode"><view class="boxTopTitle"><text>图形验证码</text><text class="cuIcon-close font16 fontB" @click="clkCloseRef"></text></view><view class="boxImg"><view class="cutImgSet" :class="isAnimation?'animation':''":style="{top:CutImgY+'px', left: blockLeft + 'px'}"><image :src="CutImg" style="cursor:pointer; width: 40px;height: 40px;z-index: 10;"></image></view><image :src="BGImg" style="border-radius:8px; width: 300px;height: 150px;"></image><view class="reset" @click="clkNext"><text class="cuIcon-refresh font16 text-white"></text></view></view><view class="checkBox"><view class="checkBar"><view class="slide" :class="bgColSet?'active':''"><view :class="'moveBac '+(isAnimation?' animation':'')+(bgColSet?' moveBacError':'')":style="'width:'+(isSuccess ? 300 : blockLeft)+'px;'"></view><view :class="(bgColSet?'swiperTipsError':'swiperTips') + (!isSuccess?' paddingL40':'')"><text v-if="!isSuccess">请拖动滑块验证</text><text v-if="isSuccess" class="cuIcon-check margin-right-sm fontB"></text><text v-if="isSuccess">验证成功</text></view><view v-if="!isSuccess":class="'swiperBlock '+(bgColSet?' errorBlock':' successBlock')+(isAnimation?' animation':'') ":style="'left:'+blockLeft+'px'" ref="sliderBtn" @touchstart="touchstartHandle"@mousedown="startMove" @touchmove.stop.prevent="touchmoveHandle"@touchend="touchendHandle"><!-- #ifndef MP-BAIDU --><image v-if="!bgColSet" :src="ImgUrl + 'Images/doubleArrow.svg'" mode="widthFix"style="width: 16px;"></image><text v-else class="cuIcon-close font16 text-white"></text><!-- #endif --><!-- #ifdef MP-BAIDU --><text v-if="bgColSet" class="cuIcon-close font16 text-white"></text><!-- #endif --></view></view></view></view></view></view>
</template>
<script>export default {props: {inputPhone: '',theme: {type: String,},swiperColor: {type: String,default: 'rgba(21, 132, 223, 0.08)'},title: {type: String,default: '人机校验'},barWidth: {type: Number,default: 300}},data() {return {ImgUrl: this.hostwapUrl,BGImg: '',CutImg: '',CutImgY: '',MarkCode: '', //验证拼图是否成功用,bgColSet: false, //拼图是否验证成功isSuccess: false, //是否验证成功isVefCode: false,showModal: false,startInfo: {},blockLeft: 0,//随机拼图的最终X轴距离isAnimation: false,msgType: '',}},computed: {trueMoveableW: function() {return this.barWidth - 40}},methods: {//获取图片接口GetSlideBlockApi() {let that = this;uni.request({url: url,//获取拼图接口data: data,//需要传给接口的参数headers: {Accept: "application/json; charset=utf-8"},dataType: 'json',method: 'GET',success: (res) => {this.BGImg = '';//大图this.CutImg = '';//拼图this.CutImgY = 0;//接口位置},complete: () => {}})},//手指按下touchstartHandle({changedTouches}) {if (this.isSuccess) {return}this.isAnimation = falsethis.startInfo = changedTouches[0]},// 手指移动touchmoveHandle({changedTouches}) {if (this.isSuccess) {return}let blockLeft = changedTouches[0].clientX - this.startInfo.clientXlet blockLeftRpx = blockLeft;if (blockLeftRpx < 0) {this.blockLeft = 0} else {this.blockLeft = blockLeftRpx <= this.trueMoveableW ? blockLeftRpx : this.trueMoveableW}},// 手指离开touchendHandle(e) {if (this.isSuccess) {return}this.CheckSlideBlockApi();},//验证图片接口CheckSlideBlockApi() {let that = this;uni.request({url: url,//接口名称data: data,//接口需要的参数headers: {Accept: "application/json; charset=utf-8"},dataType: 'json',method: 'POST',success: (res) => {let infos = {}if (res.data.IsOK == true) {//成功that.isSuccess = true;infos = {Res: res.data.Results,};//返回传给父组件的值,判断是否成功setTimeout(() => {that.bgColSet = false;that.$emit('VefCodeTrue', infos)that.isVefCode = false;that.showModal = false;}, 1000);} else {that.bgColSet = true;that.isSuccess = false;that.GetSlideBlockApi();that.isAnimation = truelet timeid = setTimeout(() => {clearTimeout(timeid)that.isAnimation = falsethat.bgColSet = false;}, 500)that.blockLeft = 0;}},complete: () => {}})},/* 鼠标按住滑块后初始化移动监听,记录初始位置 */startMove(e) {e.preventDefault() //禁止图片img拖动的解决方法e = e || window.event;this.moveStart = e.pageX || e.targetTouches[0].pageX;this.addMouseMoveListener();},/* 鼠标滑块移动 */moving(e) {// e.preventDefault() //禁止图片img拖动的解决方法let self = this;e = e || window.event;let moveX = (e.pageX || e.targetTouches[0].pageX);let d = moveX - self.moveStart;let w = self.dataWidth;let PL_Size = this.puzzleSize;let padding = this.padding;if (self.moveStart === "") {return "";}if (d < 0 || d > w - padding - PL_Size) {return "";}if (d <= 260) {self.blockLeft = d}},/* 鼠标移动结束,验证并回调 */moveEnd(e) {let self = this;e = e || window.event;let moveEnd_X = (e.pageX || e.changedTouches[0].pageX) - self.moveStart;if (moveEnd_X > 0) {self.CheckSlideBlockApi(); //验证拼图是否成功}self.moveStart = "";document.removeEventListener("mousemove", self.moving);document.removeEventListener("mouseup", self.moveEnd);},/* 鼠标全局绑定滑块移动与滑动结束,移动过程中鼠标可在页面任何位置 */addMouseMoveListener() {let self = this;document.addEventListener("mousemove", self.moving);document.addEventListener("mouseup", self.moveEnd);},//换一张clkNext() {this.GetSlideBlockApi();},// 重置滑块位置initial() {this.blockLeft = 0;this.bgColSet = false;this.isSuccess = false;},clkCloseRef() {this.showModal = false;this.isVefCode = false;},clkOpenRef(msg) {this.showModal = true;this.isVefCode = true;},}}
</script>
<style lang="scss" type="text/css" rel="stylesheet" scoped="scoped">.framework {box-sizing: border-box;width: 332px;height: 270px;background: #fff;margin: 24px auto;z-index: 11;position: relative;padding: 0 16px;user-select: none;border-radius: 16px;}.framework .boxTopTitle {height: 48px;line-height: 48px;display: flex;justify-content: space-between;}.framework .boxImg {width: 300px;height: 150px;background: #fff;margin-bottom: 16px;border-radius: 8px;position: relative;}.reset {position: absolute;top: 0;right: 0;background-color: rgba(0, 0, 0, 0.24);border-radius: 0 8px 0 8px;padding: 0 12px;line-height: 32px;}.cutImgSet {position: absolute;}.frame--dialog {.framework {// margin: 38vh auto;z-index: 88888888;position: fixed;// top: 25vh;transform: translateX(-50%);left: 50%;}.frameBg {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.24);z-index: 8887 !important;}}.checkBox .checkBar {width: 100%;padding: 0px;}.slide {box-sizing: border-box;width: 100%;height: 40px;line-height: 40px;border-radius: 8px;background-color: #FFFFFF;position: relative;font-size: 13px;overflow: hidden;border: 1px solid rgba(65, 157, 231, 0.56);}.slide.active {border: 1px solid #FA7F7F;}.moveBac {background-color: rgba(21, 132, 223, 0.08);width: 100%;height: 100%;}.moveBacError {background-color: rgba(216, 63, 63, 0.08) !important;}.swiperTips {box-sizing: border-box;position: absolute;left: 0;top: 0;width: 100%;color: rgba(255, 255, 255, 0.24);text-align: center;background: -webkit-gradient(linear, left top, right top, color-stop(0, #0076D6), color-stop(.4, #0076D6), color-stop(.5, #fff), color-stop(.6, #0076D6), color-stop(1, #0076D6));animation: tipsBlinkan 3s infinite;-webkit-background-clip: text;-webkit-text-fill-color: transparent;line-height: 40px;}.swiperTipsError {box-sizing: border-box;position: absolute;left: 0;top: 0;width: 100%;text-align: center;color: rgba(255, 255, 255, 0.24);background: -webkit-gradient(linear, left top, right top, color-stop(0, #FA7F7F), color-stop(.4, #FA7F7F), color-stop(.5, #fff), color-stop(.6, #FA7F7F), color-stop(1, #FA7F7F));animation: tipsBlinkan 3s infinite;-webkit-background-clip: text;-webkit-text-fill-color: transparent;line-height: 40px;}.swiperBlock {width: 40px;height: 40px;border-radius: 8px;/* #ifdef MP-BAIDU */background-repeat: no-repeat;background-size: 16px;background-position: center;/* #endif */display: flex;justify-content: center;align-items: center;position: absolute;left: 0px;top: -1px;}.successBlock {background-color: #0076D6;/* #ifdef MP-BAIDU */background-image: url('https://m.by56.com/Images/doubleArrow.svg');/* #endif */}.errorBlock {background-color: #FA7F7F !important;}.paddingL40 {padding-left: 40px;}.animation {transition: all 0.5s;}@keyframes tipsBlinkan {0% {background-position: -100px 0;}100% {background-position: 100px 0;}}
</style>
相关文章:

uniapp、vue实现滑动拼图验证码
uniapp、vue实现滑动拼图验证码 实际开发工作中,在登陆的时候需要短信验证码,但容易引起爬虫行为,需要用到反爬虫验证码,今天介绍一下拼图验证码,解决验证码反爬虫中的滑动验证码反爬虫。滑动拼图验证码是在滑块验证码…...

【ArcGIS】土地利用变化分析详解(矢量篇)
土地利用变化分析详解-矢量篇 土地利用类型分类1 统计不同土地利用类型的面积/占比1.1 操作步骤Step1:Step2:计算面积Step3:计算占比 2 统计不同区域各类土地利用类型的面积2.1 操作步骤 3 土地利用变化转移矩阵3.1 研究思路3.2 操作步骤 4 分…...

VS2022创建控制台应用程序后没有Main了,如何显示Main?
文章目录 问题描述原因解决方案简单的顶级语句试用计算器 其他文章 问题描述 用VS2022创建一个控制台应用后,没有名称空间和Main函数了,只有一个WriteLine,如下所示。 // See https://aka.ms/new-console-template for more information Co…...

当当网商品详情数据接口
当当网商品详情数据接口可以通过当当网的开放平台获取相关信息。您可以注册当当开放平台账号,并按照要求提交申请获取API接口的调用凭证。获得授权后,您将会收到一组AccessKey和SecretKey。使用编程语言(如Java)调用API接口&#…...

ultraEdit正则匹配多行(xml用)
在ultraEdit中,我想选取<channel到</channel>之间的多行(进行删除)。在perl模式下,命令为“<channel[\s\S]?</channel>”。下面是xml文件: <!--This XML file does not appear to have any sty…...
Mac上的utools无法找到本地搜索插件
utools安装地址 utools本地搜索用法 目前本地搜索只在win下,mac无福了 Mac可用cmdspace方法使用聚焦搜索,来搜索本地文件...

docker部署nginx下日志自动切割方法
前言:nginx采用docker部署,简单方便,但出现一个问题,就是日志没有自动切割,导致access.log 无限增大。如果非docker安装,则nginx的日志默认有切割的,那docker为何没有呢,最后发现&am…...

3D目标检测实战 | 图解KITTI数据集与数据格式
目录 1 数据集简介2 传感器坐标系3 数据集下载与组织4 数据内容说明4.1 矫正文件calib4.2 图像文件image4.3 点云文件velodyne4.4 标签文件label4.5 平面文件plane 1 数据集简介 KITTI数据集是一个广泛应用于自动驾驶和计算机视觉领域的公开数据集。该数据集由德国卡尔斯鲁厄理…...

周界警戒AI算法+视频智能分析在安全生产场景中的应用
长期以来,周界防范安防系统在大型园区、工厂、社区、机场、火车站站台、重点单位等领域应用较为广泛和常见。随着AI人工智能等新兴技术的快速发展与落地应用,通过AI智能检测与视频智能分析技术,现代化的周界安防系统可以做到全天候快速、准确…...
C++中执行shell命令,popen与system的区别
C中执行shell命令,popen与system的区别_c popen_Op_chaos的博客-CSDN博客 2.system system()函数执行过程: 1.fork一个子进程; 2.在子进程中调用exec函数去执行command; 3.在父进程中调用wait去等待子进程结束。 由于system没…...
Flink相关
墨滴社区 用 Flink 取代 Spark Streaming!知乎实时数仓架构演进_天池技术圈-阿里云天池 关于flink实时数仓的实际问题_flink datastream 按天,小时写入hdfs_一个写湿的程序猿的博客-CSDN博客 基于 Flink Hudi 的实时数仓在 Shopee 的实践 - 墨天轮...
数据结构题型9-顺序栈
#include <iostream> //引入头文件 using namespace std;typedef int Elemtype;#define Maxsize 10 #define ERROR 0 #define OK 1typedef struct {Elemtype data[Maxsize];int top; }SqStack;void InitStack(SqStack& S) {S.top -1; } bool StackEmpty(SqStack…...

时间复杂度、空间复杂度
一、时间复杂度 1、概念 时间复杂度:计算的是当一个问题量级增加的时间,时间增长的趋势; O(大O表示法):渐进的时间复杂度 2、举例 ① 以下 for 循环的时间复杂度:O(1 3n) O(n) 去掉常数…...

C++---多态
多态 前言多态的概念多态的定义及实现多态的构成条件虚函数虚函数的重写虚函数重写的两个例外协变(基类与派生类虚函数返回值类型不同)析构函数的重写 override和final 虚函数的默认参数 抽象基类 前言 在买火车票的时候,如果你是学生,是买半价票&#…...

Android 滑动事件消费监控,Debug 环境下通用思路
Android Debug 环境下滑动事件消费监控通用思路 背景 Android 开发中,经常会遇到滑动事件冲突。在一些简单的场景下,我们如果能够知道是那个 View 拦截了事件,那我们能够很容易得解决。解决方法通常就是内部拦截法或者外部拦截法。ViewPage…...

Unity中Shader用到的向量的乘积
文章目录 前言一、向量的乘法1、点积2、差积 二、点积(结果是一个标量)1、数学表示法2、几何表示法 三、叉积1、向量叉积的结果 与 两个相乘的向量互相垂直2、判断结果正负方向的方法:右手法则 前言 Unity中Shader用到的向量的点积 一、向量…...

帆软FineReport决策报表之页面布局
最近在用帆软决策报表绘制首页大屏,记录使用过程,方便查看。 版本:FineReport10.0 第一步、页面布局 页面布局其实就是组件的排列组合,决策报表主区域body有两种布局方式:自适应布局和绝对布局。 1)自适应…...

[Linux入门]---进程的概念
文章目录 1.进程的概念①描述进程-PCB②task_struct-PCB的一种③task_ struct内容分类 2.查看进程3.通过系统调用获取进程表示符4.通过系统调用创建进程---fork初识 1.进程的概念 在我们的电脑开机的时候,操作系统会被加载到内存中,点击多个应用进行时&a…...

Leetcode—— 20.有效的括号
20. 有效的括号 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...