滑块拼图验证组件,支持触屏拖动、SVG 降级与自适应缩放,通常配合后端滑动校验接口(verify_token)使用。
<!-- 基础用法 -->
<re-slide-captcha ref="captchaRef" :background-image="basicBg" :puzzle-image="basicPuzzle" :puzzle-width="48" :puzzle-y="basicPuzzleY" :canvas-width="340" :canvas-height="190" @success="onCaptchaSuccess" @fail="onCaptchaFail" @refresh="onCaptchaRefresh" />
<!-- 方法演示 -->
<re-button theme="success" size="small" content="模拟验证成功" @click="simulateSuccess" />
<re-button theme="danger" size="small" content="模拟验证失败" @click="simulateFail" />
<re-button size="small" content="重置滑块" @click="resetCaptcha" />
<!-- 自适应缩放 -->
<re-slide-captcha ref="scaledCaptchaRef" :background-image="scaledBg" :puzzle-image="scaledPuzzle" :puzzle-width="48" :puzzle-y="scaledPuzzleY" :canvas-width="340" :canvas-height="190" :max-width="260" @success="onScaledSuccess" @fail="onScaledFail" @refresh="onScaledRefresh" />
<re-button size="small" content="重置滑块" @click="resetScaled" />
推荐使用 easycom 模式,配置后无需手动 import 即可直接使用 <re-slide-captcha />。
如需手动引入:
import ReSlideCaptcha from "@/uni_modules/reglow-review/components/re-slide-captcha/re-slide-captcha";
组件本身只负责「展示拼图 + 收集用户滑动位置」,不直接请求后端。通常流程为:
- 页面先调用后端获取滑块验证码,得到
background_image / puzzle_image / puzzle_width / puzzle_y / canvas_width / canvas_height 等字段; - 将字段绑定到组件展示;
- 用户完成滑动后组件通过
@success 抛出缺口坐标; - 页面把坐标提交后端校验,成功则继续发短信等业务,失败可调用组件暴露的
handleFail() 重置。
<template>
<view class="captcha-panel">
<re-slide-captcha
ref="slideCaptchaRef"
:background-image="captchaBg"
:puzzle-image="captchaPuzzle"
:puzzle-width="captchaPuzzleWidth"
:puzzle-y="captchaPuzzleY"
:canvas-width="captchaCanvasWidth"
:canvas-height="captchaCanvasHeight"
@success="onCaptchaSuccess"
@refresh="loadCaptcha"
/>
</view>
</template>
// 加载滑块验证码
const loadCaptcha = async () => {
const data = await authApi.slideCaptcha();
captchaKey.value = data.captcha_key || "";
captchaBg.value = data.background_image || "";
captchaPuzzle.value = data.puzzle_image || "";
captchaPuzzleWidth.value = data.puzzle_width || 48;
captchaPuzzleY.value = data.puzzle_y || 0;
captchaCanvasWidth.value = data.canvas_width || 340;
captchaCanvasHeight.value = data.canvas_height || 190;
};
// 滑动完成 → 校验 → 成功后发送短信验证码
const onCaptchaSuccess = async (slideX: number) => {
const res = await authApi.verifySlideCaptcha(captchaKey.value, slideX);
const verifyToken = res.verify_token || "";
await authApi.sendSmsCode(pendingPhone.value, verifyToken);
};
说明:@success 抛出的 slideX 为拼图在原始画布坐标系中的缺口位置,已按缩放比例换算,可直接提交后端做 ±5px 容差校验。
| 名称 | 类型 | 默认值 | 描述 | 必传 |
|---|
| backgroundImage | string | "" | 背景图 URL 或 data URL(SVG data URL 在不支持的平台会自动降级为渐变背景) | Y |
| puzzleImage | string | "" | 拼图块图片 URL 或 data URL(SVG data URL 自动降级为透明色块) | N |
| puzzleWidth | number | 48 | 拼图块尺寸(原始画布坐标,单位 px) | N |
| puzzleY | number | 0 | 拼图块纵向位置(原始画布坐标,单位 px) | N |
| canvasWidth | number | 340 | 画布宽度(原始画布坐标,单位 px) | N |
| canvasHeight | number | 190 | 画布高度(原始画布坐标,单位 px) | N |
| sliderWidth | number | 40 | 滑块宽度(原始画布坐标,单位 px) | N |
| maxWidth | number | 0 | 最大显示宽度(px),为 0 时按屏幕宽度自动计算(屏幕宽 - 32) | N |
| scale | number | 0 | 手动缩放比例,为 0 时按 maxWidth / canvasWidth 自动计算(上限 1) | N |
| customStyle | string | "" | 自定义样式 | N |
| 名称 | 参数 | 描述 |
|---|
| success | slideX: number | 滑动完成时触发,slideX 为缺口在原始画布坐标系中的 X 值 |
| fail | - | 校验失败时触发(组件内部 handleFail() 调用后发出) |
| refresh | - | 点击右上角刷新按钮时触发(组件已自动重置,可在此重新获取验证码) |
通过 ref 获取组件实例后调用:
| 名称 | 参数 | 说明 |
|---|
| handleFail | - | 校验失败时调用,展示失败状态,1 秒后自动重置 |
| handleVerifiedSuccess | - | 校验通过时调用,展示成功状态 |
| reset | - | 手动重置为初始状态(不触发 refresh) |
const slideCaptchaRef = ref<InstanceType<typeof ReSlideCaptcha>>();
// 示例:后端校验失败
slideCaptchaRef.value?.handleFail();