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 | 外部判定失败回执:失败计数、回弹或失败展示 |
插槽
无(滑块图标为内置形态,参考源未提供插槽)。