Files
workspace/code/g3soft-libs/docs/content/ui/form/slider-captcha.md
T
2026-10-11 22:14:13 +08:00

5.4 KiB
Raw Blame History

title, description
title description
SliderCaptcha 滑块验证码 按住滑块拖到行内结束端完成验证,支持键盘操作与 RTL

SliderCaptcha 滑块验证码

SliderCaptcha 是一个「按住滑块拖到最右端」的验证控件,v-model 绑 boolean,true 表示已验证通过。

何时使用

  • 登录 / 注册 / 短信验证码等需要「一次人为停顿」的入口;
  • 轻量混淆脚本、降低误触强度的场景;
  • 不要把它当安全边界:拖拽与键盘都能被脚本模拟,它能挡住的只是「顺手连点」,真正的风控要靠服务端。

基础用法

v-model 绑 boolean;success 在通过的那一刻触发一次,方便埋点或联动下一步。

text / successText 可覆盖语言包文案(默认取 captcha 语言包分组)。

尺寸

size 取 small / medium / large,高度分别跟随 --g3-control-height-sm / --g3-control-height / --g3-control-height-lg;手柄是正方形,宽度自动等于高度。

与表单一起使用

放进 G3FormItem 时,label 与校验交给表单,滑块只负责提供值。验证是有状态的,每轮提交都要复位:清掉绑定值后调 resume(),让用户重新拖一次。

键盘与无障碍

手柄是 role="slider",带 aria-valuemin / aria-valuemax / aria-valuenow(0~100 的完成度)与 aria-valuetext(当前提示文案,通过后是成功文案),读屏可直接播报状态。

按键 行为
Tab 聚焦手柄(未通过时才可聚焦,通过后 tabindex="-1")
→ / ↑ 沿屏幕上「向右」推进一档(行程的 1/10,最少 20px)
← / ↓ 回退一档
Home 回到起点(不复位通过状态)
End 直达终点并通过验证

keyboard={false} 可关掉键盘通道(只保留指针拖拽)。

RTL

位置用逻辑属性 inset-inline-start 表达,镜像由 dir 自动完成:RTL 下手柄从右侧起步、向左拖到终点。指针位移按行内方向折算(useDirection),方向键的左右也随方向翻转 —— 对用户而言始终是「朝屏幕上那个方向推到底」。

API

Props

名称 类型 默认值 说明
modelValue boolean false 双向绑定:是否已验证通过
text string 语言包 未通过时的提示文案
successText string 语言包 通过后的文案
disabled boolean false 禁用态:不响应拖拽与键盘(样式不作整体半透明)
size 'small' | 'medium' | 'large' 'medium' 尺寸
keyboard boolean true 是否支持键盘操作

Events

名称 参数 说明
update:modelValue (value: boolean) 验证状态变化
success ({ isPassing: true }) 通过时触发一次
start (event: PointerEvent) 开始拖拽
move ({ event, moveDistance, offset }) 拖拽过程中触发(键盘操作不触发)
end (event: PointerEvent) 拖拽结束(含取消)

Slots

名称 参数 说明
text { isPassing } 覆盖提示文案
action { isPassing } 覆盖手柄里的图标(默认 ChevronsRight / 通过后 Check,RTL 下由全库的图标镜像规则翻面)

实例方法

名称 签名 说明
resume () => void 复位到未通过状态(清绑定值 + 回弹动画),校验失败后调用

类型定义

export type SliderCaptchaSize = 'small' | 'medium' | 'large'

export interface SliderCaptchaProps {
  modelValue?: boolean
  text?: string
  successText?: string
  disabled?: boolean
  size?: SliderCaptchaSize
  keyboard?: boolean
}

样式变量

变量 默认值 说明
--g3-control-height 32px 默认高度(手柄宽 = 高度)
--g3-control-height-sm 24px size="small" 的高度
--g3-control-height-lg 40px size="large" 的高度
--g3-fill rgba(0, 0, 0, 0.04) 轨道底色
--g3-border-color #d9d9d9 轨道描边
--g3-color-success hsl(144 57% 58%) 进度条与通过后的手柄图标色
--g3-bg-container #fff 手柄底色

实现说明

  • 拖拽走 Pointer Events + setPointerCapture(与 bindDrag / bindResize 同一套):指针移出组件、触屏、手写笔都能正确收尾,不需要往 document 上挂全局监听;捕获失败的老环境会退化成「移出即松手」,不会卡住。
  • 跟手不加过渡:拖拽期间进度条与手柄必须实时跟随指针,只有回弹 / Home / End 跳转才启用 300ms 过渡(is-returning),否则会有「拖不动」的手感。
  • 行程 = 容器宽 - 手柄宽:每次交互开始时量一次 getBoundingClientRect(),因此容器宽度自适应、字体缩放、size 变化都不需要监听 resize。
  • 只有从「已通过」回退时才 emit('update:modelValue', false):中途松手的回弹不该对外重复报一次 false。
  • 文案不硬编码:默认值来自语言包 captcha.slide / captcha.verified / captcha.sliderLabel。
  • 初始 modelValue = true(回填已通过状态)时,手柄在挂载后一帧落到行程末端,不会停在起点。