Skip to content

n-slide-verify 滑动验证 ​

平台兼容性 ​

App-Android App-iOS App-Harmony Web 微信小程序
✓ ✓ ✓ ✓ ✓

使用说明 ​

滑动验证条:拖动滑块完成行为验证,用于登录 / 注册 / 下单等场景的人机识别。四种验证形态经 mode 切换:

  • block(默认):拖动滑块到随机虚线目标框内,连续失败自动更换目标位;
  • bar:拖动滑块到轨道最右端;
  • rotate:拖动滑块旋转圆图回正;
  • puzzle:拖动拼图块对准缺口(前端自动出图,或服务端出图 + 判定回执)。
html
<template>
	<!-- 随机目标框验证:拖进虚线框 ±3px 即通过 -->
	<n-slide-verify mode="block" @success="onSuccess" @fail="onFail" />
	<!-- 拖动旋转圆图回正,容差 10° -->
	<n-slide-verify mode="rotate" image-url="/static/logo.png" :angle-threshold="10" />
	<!-- 拼图验证:前端自动出图 -->
	<n-slide-verify mode="puzzle" src="/static/photo.jpg" />
</template>

弹窗形态:组件本体是内嵌验证条,弹窗验证码用弹层组件包裹即可——

html
<template>
	<n-popup :visible="show" direction="center" @update:visible="show = $event">
		<view class="verify-card">
			<n-slide-verify
				ref="verify"
				mode="puzzle"
				:src="bgUrl"
				:cut-src="cutUrl"
				:location="hole"
				@verify="onVerify"
			/>
		</view>
	</n-popup>
</template>

<script setup lang="uts">
	import { ref } from "vue";

	const verify = ref<NSlideVerifyComponentPublicInstance | null>(null);
	// 服务端判定模式:location.x1 传 -1(缺口真实位置只有服务端知道)
	const hole = ref({ x: 40, y: 49, x1: -1 });

	function onVerify(detail: NSlideVerifyVerifyDetail): void {
		// 把 slipDistance 提交给服务端判定,结果经回执方法落到组件
		const pass = checkWithServer(detail.slipDistance);
		if (pass) verify.value?.success();
		else verify.value?.fail();
	}
</script>

服务端协同协议:拼图出图就绪时组件发 init({width, height, cutSize}),把这三个参数交给服务端按实际渲染尺寸出图;用户拖动松手后组件发 verify({slipDistance, angle, x, x1}),服务端判定后调用实例方法 success() / fail() 回执。

前端判定模式(默认):block 按目标框容差(range)、rotate 按角度容差(angle-threshold)、puzzle 传 location.x1 ≥ 0 时按缺口容差自动判定,通过后回发 update:modelValue 与 success。验证成功后组件锁定,调用 reset() 开始新一轮。

实现说明(机制对照) ​

机制 参考做法 本库做法 分歧理由
形态组织 内嵌验证条与弹窗验证码是四个独立组件 单组件内嵌验证条四模式;弹窗壳由弹层组件组合承担 弹层壳是弹层组件已有能力(遮罩 / 居中卡片 / 关闭钮),验证条内嵌化后可进任意容器;不重复造弹层
默认形态 参考一默认拖到底,参考二默认随机目标框 默认 block(随机目标框) 本组件定位是行为验证,随机目标的验证强度高于拖到底(拖到底可被脚本直達);拖到底场景传 mode="bar"
判定通道 参考一 / 二本地判定;拼图 / 旋转验证码走服务端上抛 全模式松手发 verify 上抛拖动值;block / bar / rotate 本地判定,puzzle 由 location.x1 是否提供决定本地或服务端 统一上抛口便于风控埋点;本地判定路径保持与参考一致
成功 / 失败视觉 参考一浅底深字(失败后锁定须重置);参考二实色底白字、失败可重试 实色底白字(成功绿 / 失败红)+ 滑块图标切换;失败展示常驻、再次触摸即复位重试 实色白字在深浅主题下对比度恒定(浅底深字在深色主题对比不足);失败可重试符合验证码使用直觉,重置方法仍保留
rotate 角度映射 参考一按进度 ×3 系数旋转(终态不一定回正);参考三由服务端出图 滑块满程映射 0→360°,总角归一化到 ±180° 后按容差判定;initial-angle 显式传入用指定值,否则内部随机 100~180 满程一圈的映射有唯一回正点,行为可预期;初始角随机区间与参考一一致
拼图块产出 canvas 绘制后转临时文件再交给 image canvas 裁块直接导出 dataURL 交给 image 临时文件路径依赖各端差异 API(库内画布族导出先例:统一 dataURL,三端一致)
拼图缺口形状 以坐标和的奇偶同步方 / 圆(配合服务端约定) 随机方 / 圆(前端出图);服务端出图模式形状在图内,前端按随机值渲染拼图块圆角 显式随机替代奇偶约定;拼图块与服务端图内缺口形状需一致时,业务侧约定 location 与图同时生成
配色 十余个颜色属性逐项配置 轨道 / 滑块 / 文字 / 虚线框走主题变量(深浅自动),状态色用语义色;整体换肤走 customClass / customStyle 参考各颜色默认值全部等价于主题与语义色,库内令牌系统承担;显式配色通道由根节点定制承担
触感 拖动起止震动 触摸开始时短震动 与参考一致(触感入口收敛到手势起点)
图片旋转验证的弹窗形态 圆图 + 滑块装在弹窗卡片内 mode="rotate" 内嵌圆图 + 验证条;弹窗形态用弹层组件组合 同形态组织条目

API ​

属性 ​

属性 类型 默认值 说明
model-value boolean false 验证通过状态;支持 v-model,外部置 true 渲染成功态、置 false 复位
mode string "block" 验证形态:"bar" 拖到最右 / "block" 随机虚线目标框 / "rotate" 圆图旋转回正 / "puzzle" 拼图缺口
text string "" 提示文字;留空按形态使用内置词条
success-text string "" 验证成功文案;留空用内置词条
fail-text string "" 验证失败文案;留空用内置词条
show-fail boolean true 失败时是否显示失败视觉(滑块停住展示,再次触摸复位重试);false 直接回弹
range number 3 block / puzzle 判定容差(px),拖动落点与目标距离不超过该值即通过
error number 3 block 连续失败达到该次数后自动更换目标位(成功后清零)
disabled boolean false 禁用交互:拦手势并整体降透明(保色相)
height number 44 验证条高度(px),滑块与目标框为该值的正方形
image-url string "" rotate 圆图地址
image-size number 150 rotate 圆图直径(px)
initial-angle number 0 rotate 初始偏角(deg);0 = 组件内部随机取 100~180,显式传入用指定值(服务端协同)
angle-threshold number 10 rotate 本地判定容差(deg)
src string "" puzzle 原图地址;cut-src 为空时组件在图上随机取缺口并裁出拼图块
cut-src string "" puzzle 拼图块图地址(服务端出图时提供,原图需自带缺口视觉);留空由组件裁图
location Object null puzzle 缺口位置 { x, y, x1 }:x/y 拼图块初始显示位,x1 缺口位(页面已知传值走本地判定,服务端判定传 -1);留空由组件随机生成
img-height number 160 puzzle 图区高度(px),宽度随容器铺满
custom-class string "" 组件根节点类名
custom-style string "" 组件根节点行内样式

事件 ​

事件 参数 说明
update:modelValue (value: boolean) 验证通过状态变化时回发
success (detail: { mode: string, progress: number, angle: number }) 验证通过(本地判定通过或 success() 回执)
fail (detail: { mode: string, times: number, progress: number, angle: number }) 验证失败(本地判定失败或 fail() 回执),times 为连续失败次数
change (detail: { progress: number, angle: number }) 拖动中实时触发
verify (detail: { slipDistance: number, angle: number, x: number, x1: number }) 松手上抛拖动值(服务端判定通道,判定结果经 success()/fail() 回执);前端随机出图时 x1 为 -1(缺口位不外泄)
init (detail: { width: number, height: number, cutSize: number }) 拼图出图就绪,服务端按此尺寸出图
error (message: string) 拼图前端出图失败(原图加载失败或画布通道失败)

方法 ​

方法 签名 说明
reset () => void 复位:清状态与计数、滑块回位、block 重掷目标、rotate 重掷初始角、puzzle 重出拼图
success () => void 外部判定通过回执:锁定成功态并回发事件
fail () => void 外部判定失败回执:失败计数、回弹或失败展示

插槽 ​

无(滑块图标为内置形态,参考源未提供插槽)。

记录 · 思考 · 创作