SL-WX-Captcha 行为验证组件三合一插件市场操作视频组件简介单一组件统一支持三种主流前端行为验证方式通过mode属性零切换slide滑动验证经典滑块按住并拖动到底部最右侧即视为通过失败自动回弹。puzzle拼图验证背景图上随机生成一个缺口位置拖动下方滑块让图片拼图块精准对齐缺口容差可配置。click顺序点字验证背景图上随机散布多个汉字目标字 干扰字用户按提示依次点击所有目标字2~5 个可配。组件内部已兼容H5鼠标 mousedown/move/up与微信小程序touchstart/move/end两套事件链路失败/成功回调、刷新、关闭、容差 / 目标字数等全部参数化可控制。注当前背景图使用picsum.photos随机种子作为纯前端 mock 演示生产环境中建议由后端生成带签名 / 随机水印的验证图与答案并在success回调里携带后端校验。目录结构components/SL-WX-Captcha └── SL-WX-Captcha.vue三种模式对比模式值名称成功判定失败后处理slide滑动验证滑块进度 ≥ 98%即已滑到最右自动吸附 100%400ms easeOutQuad 回弹到 0puzzle拼图验证拼图块中心 − 缺口中心click顺序点字依次点中所有目标字任意一步点错立即失败也支持「确认」按钮手动提交700~900ms 自动清空重试实现要点 修复日志滑动 / 拼图滑块显示与拖拽可用修复问题修复方案滑块初始不可见slideX0时 thumb 完全在轨道外原写法left: X%; transform: translate(-100%, 0)叠加时X0 → translate(-100%)会把 thumb 向左平移一个 thumb 自身宽度挪到轨道外。改为纯像素left: Npxtop:50%; translateY(-50%)垂直居中slideThumbPx / puzzleThumbPx直接从 0 线性增长到轨道宽 - thumb 宽保证两端视觉与比例完全对齐。拼图块无内容、跟缺口对不上原写法里.sl-puzzle-piece__img用width:100% modeaspectFill展示的是拼图块左上角对应底图的 (0,0) 位置——根本不对应缺口的像素。改为piece 里的image宽高强制等于舞台宽高再transform: translate(-pieceLeft, -pieceTop)反向偏移这样 piece 滑到哪就显示底图对应哪一像素对齐缺口时内容完全吻合。缺口形状不明显、不显示原缺口只是一个半透明方块不够像拼图。改为clip-path: polygon()切出「正方形主体 右侧半圆凸块」的经典拼图形状gap缺口蒙版和 piece拼图块共用同一份 clip-path形状完全吻合。首次渲染拖不动原_sliderWidth依赖 SelectorQuery 异步回调结果mounted首次 touchmove 时回调可能还没返回 → 0 导致 dx 被除。在onSlideStart / onPuzzleStart里先调用_ensureSizesFallback()按widthprop 先兜底换算一套可用的轨道/thumb 尺寸保证拖拽启动瞬间就有正确行程。H5 拖出滑块外卡住手势在组件mounted时document.addEventListener(mousemove / mouseup)beforeDestroy统一解绑避免 mousedown 后拖到滑块外松开导致的再按下去无响应。click 模式点字事件平台差异小程序端用touchendchangedTouches[0]H5 端单独绑定tap.stop.prevent取e.clientX/Y避免某一端取不到坐标。失败回弹曲线slide / puzzle 失败后不再用setTimeout 一次性跳回改用requestAnimationFrame easeOutQuad逐帧回弹到 0视觉更自然。progressfail 回调为换算后的百分比便于日志。Props属性类型默认值说明modeStringslide验证模式slide/puzzle/clickwidthNumber|String620组件宽度Number 视为 rpxString 直接作为 CSS 值puzzleHeightNumber320拼图 / 点字模式图片舞台高度rpxtrackHeightNumber72滑块条高度rpxradiusNumber16拼图 / 点字模式圆角rpxpieceSizeNumber100拼图块边长rpx建议为舞台宽度的 1/5~1/6puzzleToleranceNumber4拼图容差像素 px拼图块中心与缺口中心的像素差。生产推荐 24px宽松体验 68pxslideLabelString请按住滑块拖动到最右边模式 1 的提示文案targetCountNumber3模式 3 的目标文字数量必须为 2~5。总随机字数 targetCount distractCountdistractCountNumber4模式 3 的干扰字数量showHeaderBooleantrue是否显示顶部标题与刷新栏showCloseBooleanfalse是否在顶部栏显示「✕」关闭按钮titleString自定义顶部标题留空则根据模式自动取「滑动验证 / 补全图片验证 / 文字顺序验证」Events事件名回调参数说明success{ mode, type, ...payload }验证通过触发type为对应模式名slide/puzzle/clickfail{ mode, type, ...payload }验证失败触发refresh{ mode }点击顶部刷新图标⟳触发close-点击顶部关闭按钮✕触发需要showClose truesuccess / fail 的 payload 详情// mode slidesuccess:{mode:slide,type:slide}fail:{mode:slide,type:slide,progress:Number}// progress 失败时的进度 0~100// mode puzzlesuccess:{mode:puzzle,type:puzzle,diff:1.3,tolerance:4}// diff像素偏差toleranceprops设定fail:{mode:puzzle,type:puzzle,diff:18.6,tolerance:4}// mode clicksuccess:{mode:click,type:click,seq:[0,1,2]}// seq用户依次点击的目标索引fail:{mode:click,type:click,reason:wrong-order-or-miss|incomplete}对外方法通过$refs.captcha.xxx()调用方法名说明onRefresh()与点击顶部刷新按钮等效重置所有状态、重新随机背景图、缺口位置、点字分布。模式 2 / 3 切换参数如 targetCount后建议手动调用一次。onClose()触发close事件。noop()空函数用作事件占位。使用示例示例 1基础滑块验证登录/注册前template view sl-wx-captcha refcap modeslide :width660 slide-label请按住滑块向右拖动完成验证 successonCapOk failonCapFail / /view /template script import SlWxCaptcha from /components/SL-WX-Captcha/SL-WX-Captcha.vue export default { components: { SlWxCaptcha }, methods: { onCapOk() { uni.showToast({ title: 验证通过正在登录, icon: none }) this.submitLogin() // 验证成功后再调用登录接口 }, onCapFail(e) { console.log(滑块未到底, e.progress %) } } } /script示例 2拼图验证容差 6px较宽松template sl-wx-captcha refcap modepuzzle :puzzle-tolerance6 :width620 :radius20 successonSuccess failonFail refreshonRefresh / /template示例 3顺序点字4 字验证作为重要操作二次确认template sl-wx-captcha refcap modeclick :target-count4 :distract-count5 :show-closetrue title请先完成二次验证 successonPay closeonCancel / /template script export default { methods: { onPay(e) { // e.seq 可上报后端进行二次审计 console.log(验证通过点字顺序, e.seq) this.confirmPay() }, onCancel() { uni.navigateBack() } } } /script示例 4弹层uni-popup / 自定义遮罩内使用 关闭按钮 刷新template view classmask tapclose/view view classpop tap.stop sl-wx-captcha refcap :modemode :show-closetrue successonOk closeclose refresh(e)console.log(刷新了, e.mode) / /view /template实现要点可二次开发事件链路滑块 / 拼图使用touchstart/move/end/capture.stop.prevent保证在小程序端优先锁定手势避免父容器 scroll-view 把横拖误识别为纵向滚动。H5 端在组件mounted时document级绑定mousemove / mouseupbeforeDestroy自动解绑防止鼠标抬出滑块外导致卡着手势。测量prepareStage()中用uni.createSelectorQuery().in(this)取舞台和滑块条的真实像素宽度兼容不同宽度配置下拼图比例/滑块行程正确。拼图实现用「相同背景图 × 2」一张铺底另一张放入.sl-puzzle-pieceoverflow:hidden 固定宽高 拼图块通过 piece 的top/left与滑块位置联动实现切片效果无需后端合成拼图。缺口用半透明白色蒙版 内描边提示用户拼图目标位置。点字命中判定以用户点击像素为圆心半径 26px 范围内取最近字作为命中候选字的样式随机倾斜/颜色/大小/字体贴近真实点字验证码观感。无障碍与反馈每次失败或成功都会在舞台顶部弹出半透明遮罩绿色通过/红色失败并且统一触发success/fail事件便于接入业务。注意事项拼图背景图域名白名单如果使用小程序端请在微信公众平台配置picsum.photos为合法 downloadFile 域名生产时换成自己的 OSS/CDN 即可。图片加载失败兜底onPuzzleImgError已经监听了底图失败会走白底 缺口形状交互依然可用建议后端额外监控图片 404。拼图容差与用户体验puzzleTolerance建议 2~4难~ 6~8宽松超过 10px 基本等同于无校验。不要把安全校验放前端本组件实现的是前端交互和基础判定在前端判定成功后建议把diff/seq/progress等摘要一并上报后端使用后端接口做最终决策或使用加密 token避免被自动化脚本绕过。mode 切换时自动重绘组件已 watchmode切换会立即resetAll prepareStage无需手动刷新但如果是在同一 mode 下改了targetCount / puzzleTolerance等参数建议调用this.$refs.cap.onRefresh()手动刷新一次题目。