uniapp滑块验证码对接tianai-captcha前端
·
uniapp滑块验证码对接tianai-captcha
滑块验证码的功能大家都不陌生,天爱大佬的滑块验证码给我的体验感非常的好,下文详细讲解如何在uniapp中对接滑块验证码

tianai-captcha
tianai-captcha其实是滑块验证码的后端,从后端生成图片,前端操作后提交到后端进行验证
- tianai-captcha 目前支持的行为验证码类型
- 滑块验证码
- 旋转验证码
- 滑动还原验证码
- 文字点选验证码
本文只拿旋转验证码作为例子
天爱大佬是有自己的前端的,但是不适配uniapp,这里采用uniapp中的插件进行改造适配
1. 封装滑块验证码插件,组件代码如下
<template> <view class="lang-dialog__wrapper" v-if="dialogVisible"> <view class="lang-dialog"> <view class="lang-dialog__header"> <view class="lang-dialog__title"><slot name="title">{{title}}</slot></view> <view type="button" class="lang-dialog-header-btn" @click="close"> <i class="lang-icon-close"></i> </view> </view> <view class="lang-dialog__body"> <view class="tips" v-show="failed"><slot name="errorText">{{ errorText }}</slot></view> <view class="tips" v-show="!failed"><slot name="tips">{{ tips }}</slot></view> <view class="slider-body" :class="{'slider-shock':shock}"> <view class="loading-transparent-mask" v-show="mask"></view> <view class="loading-body" v-if="loading"> <view class="loading slider-loading"></view> </view> <view class="view-slider"> <image class="slider-bg slider-img rotate-image" :src="sliderImg" v-show="sliderImg"></image> <view class="rotate-image-img" v-show="sliderImg" @touchstart.stop="sliderTouchStart" @touchmove.catch="sliderTouchMove" @touchend.stop="sliderEnd" @mousedown="sliderStart"> <image :src="rotateImg" v-show="sliderImg" :style="dynamicStyles" class="rotate-image-image"></image> </view> </view> <view class="slider-progress"></view> <view class="slider-success" v-show="success"> <view class="slider-success-icon"> <image src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAzFBMVEUAAAAs0AAu1AAs0AAr0AAq1QAs0AAt0AAs0AAs0AAr0AAq0wAs0AAq0QAs0AAs0AAs0AAs0AAr0AAs0AAr0AAs0AAr0QAs0QAs0AApygAs0AAs0AAs0AAs0AAs0QAr0QAt0gAs0AAt0QAtzwAq0QArzwAs0AAqzQAs0QAs0AAs0AAs0AD////l+d/8/vty4FVG1iCI5W/X989G1h881BNy31My0gd34Vr5/vjt++qk65Gd6omO5naB42Za2jdL1ybR9cjA8bNp3kpZ2jY9PuX7AAAAK3RSTlMA/APuFwfUZln0OxLIVEbr49vZzsKxmW1MDvmsqIxpXiGejlA3NGgk1pyDVbbBQAAAArxJREFUaN7Nmody2kAURZ9QQRIyTTTRDDauV3GsFNzjlP//p8CQjAZLwLY3w/mAc9EWZvftIzGS8HIyitp2AAR2OxpNLsOETFHzex5K8Hp+Td/u9DsWdmJ1+o6OvTLoWjiA1R1UFPVutQ0h2lVX5ddXmxCmWZX+ijCGFHEot3BuIM1cYkmd21DAPhcd/TMociY0E7MIysQzgdltQIPGxSH/yRBaBPX9/lMLmgz9vX4Y4HTP+FgwgHWyy78IYIThYsf6bMAQjasyvxvDGLFLRW5gkHnJBMMohYl2bBjFdmibMQwz3vbXYZz61j+0B+N4FcqpgoFq7nebYKDpFj6A6xMqLbDQ+j8LAzAxoA1dMNH9t4kt6PL+/Ov5DwpYm+3chy7fH9M0vctQoE9rOtr+u3TN3Ts+0ln7a5a+f8NrcYzWx0nflD99QQF/FdAz5U8fUKC3CvCgw+fc/2WJAh5RYsr/6R4lJHTB6kdIPqsfU7pl9WNCY1Y/RhSx+hFRCzv4/fPx6Xmp6UeLbJTzsFnb3/T8sClAKcunNE9Q9yMglPMjTfMEdT+wOyBP0PFjzxDlCRr+YN8k5wnKfti7l2lWSFDwo0URhBIU/YhoDLEENT9GdAvBhIL/KwSYkA/RBBU/pnQB4QQFP0JKIJzwJu9HQuQJJ6Tyfk/g2JJp+NETOXhl6n74QkfHTNlv1cQOv5miHx3R43um5kdf+AKSKfktR/wKlSn40ZW5BL49rvealB8DqWvs/evLwxIytCrMF/FL9lICdzGEvZzDXZBiLqmN2IuC7GXNAnMYZM5cWvZcKuGKqTiesxjCCMGC94FiWGd+YvG5H4m4n7nYH+oOMouhTDwjAVz1x1L3OJ57VzhjSDN2SIa6Bym8+rE1Daxwp6JtD1P3OBs3+FtP8uaZa5RwnTfP6JOE0+32n6lo+89fOWa8/GcTqREAAAAASUVORK5CYII=" alt=""> </view> <view class="slider-success-text"><slot name="successText">{{successText}}</slot></view> </view> <view class="slider-btn slider-move-btn" :style="{'left': sliderMoveLeft}" :class="{'slider-shock':shock}" @touchstart.stop="sliderTouchStart" @touchmove.stop="sliderTouchMove" @touchend.stop="sliderEnd" @mousedown="sliderStart" > <i> </i> <image src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAcAgMAAABuexVFAAAACVBMVEUAAADCwsL9/f1P0DqbAAAAAXRSTlMAQObYZgAAAB1JREFUGNNjCGVgYGANABKhyMwoEHMBkIgaZWIwAdyJJQnaJRg5AAAAAElFTkSuQmCC" alt=""> <i> </i> </view> </view> <view style="position:relative;"> <!-- #ifndef MP --> <view class="slider-refresh" style="font-size: 29px;" @click.stop="" @mouseenter="questionMessage = true" @mouseleave="questionMessage = false"> <!-- #endif --> <!-- #ifdef MP --> <view class="slider-refresh" style="font-size: 29px;" @click.stop="" @touchstart="questionMessage = true" @touchend="questionMessage = false"> <!-- #endif --> <view class="slider-tools-btn lang-tips"> <view class="lang-tips-item lang-tips-bottom" v-show="questionMessage"> <slot name="question"> <view v-if="question">{{question}}</view> <view v-else> 拖动滑块完成拼图,欢迎提建议! </view> </slot> </view> <image src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAVgSURBVHgBzVrZUdxMEG7EcjzuH8EvIvA6Ai8ZmAhgqziLByACRASGB4qzChwBZOAlgl1HYDmDfaIoTn/ferQlNSNpRpJd/qrG8s7ZPdPT1zAlDeDq6qr98PDweWpqqoPyP6o6KG1TEsRoi19fX7/jO8D3bmtrK5aamJKKINHPz887b29vXRapADAyxNjDOsx4M5AQjkV3JbvDtQBmrl9eXg58GfFi4OLiYr9pwjWCIIjW1tYOXPs7MXBychJOT0/f4Lg7eX3Q1seH8t0Hk8P5+flRr9cbsY2ndn9/H7ZarRBtvCefULoFS/KuLLqcRikDl5eXyzjaQ7Hv+ggLHYHYw4RYV3BT8Olix/fxDW1zo/Q2NjZui+YpZMCITJQz+QEmP5QGAGZW8hgpE6lcBvKIh6gczc3NRb47XgZzIhEIXtZtRUxYGTg7O/uMz42laa+pXc8D1qaS+KLrcQdXVldXv+r6dwxwJ8DxQLIyT1lfwqXqy1/A8fFxBxf+m4WGj/pit/RgEK8HCvT+4vb29lAcQa3z9PQU4vInWiv2YZ5rYSOXDC0J2tSE+H5M982cQI7cO4tNiZEbQXXe+hgrmzhhbo6PRDNgROdHujOt4/r6ek8cYI6dOxSWdKVPtIR5nU709PT0EP13UlWj2dnZhUSJBKmGSC/E3RIHkHkjs6FD9xCa7Nv5+XnHoa9Q48lvtZ2AjuNu8iNICLCor8j1qG33houC0GsUGqJYtbVRfyMOMDt9oNbbobiO/2/qumpcDLn/Kg6gERK187QVGP/f5uZmD2UJ/1+g7KqhIWR82WUNcwetpzBmgBypMZE4ApohQwTvDYje1f148ciY6rsijqDLotb9xG9gLGBHdb4TR1gcvKO8vtio65KxuaC/pcZ2KUY8ga5q6Hv65BnZL9IuljZnt5x3gZ5uuo5RYMAwMF0JBpx3n1CTFqpGc9ppePlTDEfV2h2cavBBVQ7EA1C1Pco2C92Nor5QtZn7gjHO1t3Q1ldVYQuThOkaMPRTPGDEbbesH3a/q608L7x4gIES6EuP/0BfKEx3mpmZiaUhkGjOT01lCfxjH2VBMMp7fHxMV7UD3akpPx86/gsNHMpVTtYi8g3gLbS9Z6BB5IoVjZqroSwDGchwlZjoPwGqaBOsR1IBNtp4B8jApAG6tS2e6s0FhvC+1ABjDFUV8wQyqow3W/4AmojmtMbE7zjAP1ptLso/CuaUVNX3QBsTbdiqwsdCuyJx4FJrDALo1tt0ZeIkSU34WGgX0A3R6ph2pEXdiuion240vnYkNeBqoT3QVb+HXGOclcBu3UF0Jh1MfBBJDSRvBphrVJYedIHJ3KUxdq/Hhsz42pmIx2QEKoHEw+QPaIXx8wZz/agjlraoL3FDxgxQjHTEA+xXXZQ7rxYMwdCKVICJ1zO7TycwcUMmroTtFLDovlQA7lOT1jwStfvpbMmEgZxT2K0iSkxgSXYzOLf3PYBy2dHZEpPYiidr6UEgmAGNjpG93QAePRgZM893MF/P0yTKdHDFbMlCusI5uQtiFl2zaXXBOAI03IhDcvedO80O6LinqpmIGtTRTK4wYmNLlPVsp5j7wIFdiCy6t/JrYhmM6uV67zZJJ3Qz9EgB8piQ36nCqKmghLuOE47EkmYpIp4ofeQzrzVXYs/hxChRlYdqh/dmyvwe5r0umsf5mdXIZZg7EbxP45IM+ScFTA6kn1kZKKGtQ5+LHm/R6z5f8DHXUiPPrIqRPJFqCmNb5BNyev+pQdFrYg1Ufm+u/MceqYdqeq4dqQAG+UxlViE8QWUG0kiYMXlWRnS0wmGqCx87SCAN4U9GgQykmshB/QKLND1fMNqj0gAAAABJRU5ErkJggg==" alt=""> </view> </view> <view class="slider-refresh" style="left: 35px;" @click.stop="refresh" @mouseenter="refreshMessage = true" @mouseleave="refreshMessage = false"> <view class="slider-tools-btn lang-tips" style="width:24px;height: 24px;margin-top: -2px;"> <!-- 刷新 --> <view class="lang-tips-item lang-tips-bottom" v-show="refreshMessage"> 刷新</view> <image src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAPZSURBVHgB7VpLTuNAEC2b8NlNboDnBJgbJCdgOAFkAQixGDgB9gkIC4T4SIETTOYEhBOQOcF4buAVQojPvGfZGbv9iWMbE0vzpMam3e7Uq66u7q6yJhXh/PzcwKWjaZqJsop7E6XtF8JlwTPn7e3tF64jXMf7+/uOlIAmJTAYDNovLy/f39/fOyxSACSCd29A5r4ImUIEfG1buq5vyD8NlwbI3Ly+vtp5iFAGtpuJQKBxaOtQKhRcgQvF9Hd2duy0BldXV8eQQwMBKzeBs7Mzs9Vq/cCtkdYGpkBzuIcAY9r3ysqK2+v1aPse+cfHRwN9GL65rUHjnYyf5FzpqqNB4VFvodi5CVxeXtLOLUnWuoNn/eXl5dtA2LwIJj4IH0uyYthfb29vbxgWnve5CYRfUgVHsdD5rVQAkNnOIHKEZ1/CcgQE9KxO04SHxk+XlpbWqxKegDD0RF2UpD5PUpQoLUkBzSbhJRd1R/wx+QD49r6N0XD80ZiKxBGgbdKulWoXM7/7UcKHQdOAonp52sYI0FuA/Z1S7Ql/cHAwlpoAb7Wap12MAP28xCeSXafwGY4jhggBmo76IicsJmtfasIswhPqCFjK/w78uyU1YVbhiYkXovZh+1vKc2vWxako+PvcHuDWzvnKiH+0UAeW4rocmM5XmXNMTChJ+9IAeASwaPHwYYQfYKX9KQ2ARwB7cDNcyV1lXbZfFh4B/2AyAba5jdA+4RGAwJFtMvfy0hB4BGAyplLvSEMQeKHICJSNFNQJXRqO/wQ+GwGBiM/3D9uNQEDAUeoNaQg8AoxVRip13ZSGIFgHIgsXFrYNaQiClXgYruTCxrOxNAAeAX/hckL17efn521pACZuVA0oNcWMJgQQiI0c3BmAvbi4+CZzjgkB7v8Twnon8z4XpkUlDMyFXCG+z0KEACczo75Km8Pr6+stmVPEwus0GWj9QaKrMZNz3d3d3VoPOkyq+IvqKG2LH9vMcS4gPrMp0f1RG5P6zj/81wKOOuKjDyAwQPmN/VknqV3ibtSPg6qm5JGAZzqUDwZD+wg03CjVnaS2mRmahGBXgD7CLnbVkQvffAe4jblvmPB6kglPTTFlkHCkohRTjuznUVqAOVeSzzebk5THDopVJFGdQ/BIki8JudOsfvCXiQ8jtTNk3WG797gdLSwsuIuLi044zfr09MTkiclVHte1rOw++hqjr81pSpk5U59hUlWBhO28OYmynxpUucBxK3PKPdkszqHUxx6hRDXTUoXWCMZhcRkWSZQTpQiEEf7cBtc1FAP3RqiJC2EpIF3hH54Coe1hWVf8FxUNF4vY5AiIAAAAAElFTkSuQmCC" alt=""> </view> </view> </view> </view> </view> </view> </template> <script> export default { name: 'SliderCaptcha', props: { value: { type: Boolean, defalut: false }, modelValue: { type: Boolean, defalut: false }, loading: { type: Boolean, defalut: false }, title: { type: String, default: '滑块安全验证' }, tips: { type: String, default: '拖动下方滑块完成拼图' }, successText: { type: String, default: '验证成功' }, errorText:{ type: String, default: '是不是太难了,咱换一个' }, question: { type: String, default: '' }, options: { type: Object, default() { return { sliderImg:'', rotateImg:'', sliderKey:'', bgImageWidth:'', bgImageHeight:'', templateImageWidth:'', templateImageHeight:'', sliderY: '' } } } }, watch: { value: { handler: function(val) { this.init(val) }, immediate: true }, modelValue: { handler: function(val) { this.init(val) }, immediate: true }, options: { handler: function(option) { this.clear() this.sliderImg = option.sliderImg this.rotateImg = option.rotateImg this.sliderKey = option.sliderKey this.bgImageWidth = option.bgImageWidth this.bgImageHeight = option.bgImageHeight this.templateImageWidth = option.templateImageWidth this.templateImageHeight = option.templateImageHeight this.sliderKey = option.sliderKey this.sliderY = option.sliderY }, deep:true, immediate: true } }, data() { return { dialogVisible: false, mask: false, success: false, failed: false, sliderImg:'', rotateImg:'', bgImageWidth:'', bgImageHeight:'', templateImageWidth:'', templateImageHeight:'', sliderKey: '', sliderX: 27, sliderY: '', dynamicStyles:{ transform:'', }, currentCaptchaData:{ startTime: new Date(), trackArr: [], movePercent: 0, clickCount: 0, bgImageWidth: '', bgImageHeight: '', templateImageWidth: '', templateImageHeight:'', end: '', pageX: 0, left : 0 }, sliderMoveDrawLeft: '27px', sliderMoveLeft: '20px', shock: false, tipEvents: {}, sliderMoveX: 0, questionMessage: false, refreshMessage: false, } }, methods: { init(open) { this.dialogVisible = open if (open) { this.clear() } //初始化校验 }, clear() { this.mask = false this.success = false this.failed = false this.sliderImg = '' this.rotateImg = '' this.sliderKey = '' this.bgImageWidth='' this.bgImageHeight='' this.templateImageWidth = '' this.templateImageHeight = '' this.sliderX = 27 this.sliderMoveDrawLeft = '27px', this.sliderMoveLeft = '20px', this.sliderY = '' }, check(sliderKey,type) { const data = { bgImageWidth: this.currentCaptchaData.bgImageWidth, bgImageHeight: this.currentCaptchaData.bgImageHeight, templateImageWidth: this.currentCaptchaData.templateImageWidth, templateImageHeight: this.currentCaptchaData.templateImageHeight, startTime: this.currentCaptchaData.startTime, stopTime: this.currentCaptchaData.stopTime, trackList: this.currentCaptchaData.trackArr }; if (type === 'ROTATE') { data.bgImageWidth = this.currentCaptchaData.end; } this.currentCaptchaData = undefined; this.$emit('check', sliderKey, data, this.done, this.error) }, done() { this.success = true }, error() { this.failed = true this.mask = true this.shock = true setTimeout(() => { this.shock = false this.$emit('error') }, 1000) }, close() { this.dialogVisible = false this.$emit('input', this.dialogVisible) this.$emit('update:modelValue', this.dialogVisible) this.$emit('close') }, refresh() { this.$emit('refresh') }, sliderTouchStart(e) { // 移动触摸移动 const that = this const slider = e.target //sliderMoveX是鼠标触摸下不在变化 e.touches[0].clientX会变化 //slider.offsetLeft固定为20 that.sliderMoveX = e.touches[0].clientX - slider.offsetLeft that.dynamicStyles.transform = "rotate(0deg)" that.currentCaptchaData.end = e.touches[0].clientX }, sliderTouchMove(e) { const that = this const left = e.touches[0].clientX - that.sliderMoveX if (left >= 20 && left <= 280) { that.sliderMoveDrawLeft = 5 + left + 'px'; that.sliderMoveLeft = left + 'px'; that.dynamicStyles.transform = "rotate(" + ((left-20) / (260 / 360)) + "deg)" that.currentCaptchaData.bgImageWidth = that.bgImageWidth that.currentCaptchaData.bgImageHeight = that.bgImageHeight that.currentCaptchaData.templateImageWidth = that.templateImageWidth that.currentCaptchaData.templateImageHeight =that.templateImageHeight //初始大概有10左右的误差在里面 that.currentCaptchaData.end = 280 - 20 - 10 that.currentCaptchaData.stopTime = new Date(new Date().getTime()-that.currentCaptchaData.startTime.getTime()) const trackArr = that.currentCaptchaData.trackArr; trackArr.push({ x: left-20, y: that.bgImageHeight, type: "down", t: (new Date().getTime() - that.currentCaptchaData.startTime.getTime()) }); } }, sliderEnd(){ this.check(this.sliderKey, 'ROTATE'); }, sliderStart(e) { var that = this const slider = e.target // 获取目标元素 // 算出鼠标相对元素的位置 that.sliderMoveX = e.clientX - slider.offsetLeft document.onmousemove = (e) => { const left = e.clientX - that.sliderMoveX if (left >= 20 && left <= 280) { // slider.style.left = left + 'px' that.sliderMoveDrawLeft = 5 + left + 'px'; that.sliderMoveLeft = left + 'px'; that.sliderX = 5 + left; } } document.onmouseup = (e) => { document.onmousemove = null document.onmouseup = null this.check(this.sliderKey, 'ROTATE'); } } } } </script> <style scoped> a + a { margin-left: 10px; } /* 弹窗开始 */ .lang-dialog__wrapper { position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: hidden; width: 100%; height: 100%; background: rgba(0, 0, 0, .5); text-align: left; z-index: 88888888; } .lang-dialog { position: relative; margin: 0 auto 50px; border-radius: 2px; box-shadow: 0 1px 3px rgba(0, 0, 0, 30%); box-sizing: border-box; background: #FFF; width: 50%; margin-top: calc(50vh - 185px); width: 360px; } .lang-dialog__header { padding: 20px 10px 10px; } .lang-dialog__title { line-height: 20px; font-size: 18px; color: #525252; } .lang-dialog-header-btn { position: absolute; top: 20px; right: 20px; padding: 0; background: 0 0; border: none; outline: 0; cursor: pointer; font-size: 16px } .lang-icon-close { color: rgba(0, 0, 0, 0.68); font-size: 20px; } .lang-icon-close:before { content: '×'; } .lang-icon-close:hover { color: rgba(0, 0, 0, 0.88); } .lang-dialog__body { color: #828282; font-size: 14px; word-break: break-all; padding: 0 10px; height: 320px; } .loading-transparent-mask{ position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; z-index: 999; } /* 弹窗结束 */ /* loading start */ .loading-body { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.6); z-index: 999; } .loading { position: relative; display: inline-block; width: 30px; height: 30px; border-radius: 50%; border-top: 2px solid transparent; border-bottom: 2px solid transparent; border-left: 2px solid #409eff; border-right: 2px solid #409eff; animation: loading 1s infinite linear; } @keyframes loading { to { transform: rotate(360deg); } } .slider-loading { position: absolute; top: calc(50% - 15px); left: calc(50% - 15px); z-index: 999; } /* loading end */ .tips { color: #525252; line-height: 36px; font-size: 18px; } .slider-body { position: relative; width: 100%; height: 245px; } .slider-bg { position: absolute; top: 0; left: 0; background-position: 0px 0px; background-size: 340px 251px; background-repeat: no-repeat; width: 340px; height: 191px; overflow: hidden; } .slider-draw { position: absolute; left: 27px; width: 50px; height: 50px; background: #fff; background-position: -5px -196px; background-size: 340px 251px; background-repeat: no-repeat; z-index: 1; cursor: pointer; opacity: 1; box-shadow: 0px 0px 10px 2px #000000; } .slider-progress { position: absolute; width: 100%; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAqoAAAJsCAYAAAA1NIHDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE7mlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNy4xLWMwMDAgNzkuOWNjYzRkZSwgMjAyMi8wMy8xNC0xMToyNjoxOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIzLjMgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMi0xMi0wNlQxNzoyOToxNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjItMTItMDZUMTc6MzI6MDIrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjItMTItMDZUMTc6MzI6MDIrMDg6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOmJhYmMyMDIzLTdkNDgtZTg0Zi05ZTFlLTNkZDQ2YTFiMWNkZCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpiYWJjMjAyMy03ZDQ4LWU4NGYtOWUxZS0zZGQ0NmExYjFjZGQiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpiYWJjMjAyMy03ZDQ4LWU4NGYtOWUxZS0zZGQ0NmExYjFjZGQiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmJhYmMyMDIzLTdkNDgtZTg0Zi05ZTFlLTNkZDQ2YTFiMWNkZCIgc3RFdnQ6d2hlbj0iMjAyMi0xMi0wNlQxNzoyOToxNSswODowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIzLjMgKFdpbmRvd3MpIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmbOvQUAABmXSURBVHic7d1rrKVXfd/x33qefebqwdgJl0ZpwdzKtZiYijQSzBhQFUUggsmxkrYUqZHavKERSGmlqtV42qpSG5W+SFW1jXpRkhdoTnAohCpVQOMhTYsru5AmQLhpEEJCwRCwPTOec/Zl9cUZD/axPZ7Lsfd/cz4faTQ6R/vZe82MNPqe9ay1ntZ7PxQAAChmWPYAAADgyQhVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAkoQoAQElCFQCAkoQqAAAlCVUAAEoSqgAAlCRUAQAoSagCAFCSUAUAoCShCgBASUIVAICShCoAACUJVQAAShKqAACUJFQBAChJqAIAUJJQBQCgJKEKAEBJQhUAgJKEKgAAJQlVAABKEqoAAJQkVAEAKEmoAgBQklAFAKAk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'); background-position: 0px -213.512px; background-size: 345.06px 313.69px; width: 340px; height: 16px; left: 0px; top: 210px; z-index: 1; opacity: 1; } .slider-success { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 4; background: hsla(0, 0%, 100%, .8); } .slider-success .slider-success-icon { width: 64px; height: 64px; margin: 15% auto 0; } .slider-success .slider-success-icon image { width: 100%; height: 100%; } .slider-success .slider-success-text { color: #1bc300; text-align: center; margin-top: 16px; font-size: 18px; } .slider-btn { position: absolute; left: 20px; top: 200px; z-index: 2; width: 65px; height: 35px; line-height: 35px; background-color: rgb(0, 87, 212); box-shadow: rgba(0, 87, 212, 50%) 0px 0px 5.05952px 0.505952px; position: absolute; text-align: center; border-radius: 999px; font-size: 0; cursor: pointer; opacity: 1; z-index: 1; -moz-user-select: none; /* 禁止双击节点被选中 */ -o-user-select: none; -khtml-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; -moz-user-drag: none; /* 禁止被拖动 */ -webkit-user-drag: none; /* 禁止被拖动 */ } .slider-btn i { display: inline-block; width: 0; vertical-align: middle; } .slider-btn image { width: 18px; height: 13px; -moz-user-select: none; /* 禁止双击节点被选中 */ -o-user-select: none; -khtml-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; -moz-user-drag: none; /* 禁止被拖动 */ -webkit-user-drag: none; /* 禁止被拖动 */ pointer-events: none; display: inline-block; vertical-align: middle; } .slider-refresh { position: absolute; cursor: pointer; left: 0px; top: 0px; z-index: 2; font-size: 30px; height: 30px; line-height: 30px; } .slider-tools-btn { position: relative; width: 25px; height: 25px; } /* tips */ .lang-tips a { text-decoration: none; color: #409eff; } .lang-tips-item { position: fixed; font-size: 14px; color: #525252; max-width: 340px; margin-top: 40px; margin-left: 0; background: white; padding: 7px 10px; border-radius: 4px; margin-left: -8px; } .lang-tips-left { margin-top: -10px; margin-left: -140px; } .lang-tips-left:after { content: ""; position: absolute; border-top: 10px solid transparent; border-bottom: 10px solid transparent; border-left: 10px solid #000; border-right: 10px solid transparent; right: -18px; top: 12px; } .lang-tips-bottom { margin-top: 50px; } .lang-tips-bottom:after { content: ""; position: absolute; border-top: 10px solid transparent; border-bottom: 10px solid #fff; border-left: 10px solid transparent; border-right: 10px solid transparent; /* right: calc(50% - 10px); */ left: 10px; top: -20px; } /* tips */ .slider-tools-btn image { width: 100%; height: 100%; } .slider-shock { animation-delay: 0s; animation-name: shock; animation-duration: .1s; animation-iteration-count: 5; animation-direction: normal; animation-timing-function: linear; } .view-slider{ position: relative; height: 200px; /* 设置为所需的高度 */ } .rotate-img { width: 100%; height: 100%; object-fit: cover; /* 确保图片覆盖整个容器 */ } .rotate-image-img{ position: absolute; top: 50%; left: 50%; width: 115px; height: 200px; transform: translate(-50%, -50%); /* 使图片位于容器的中心 */ .rotate-image-image{ height: 200px; } } @keyframes shock { 0% { margin-left: 2px; } 100% { margin-left: -2px; } } </styleprops中写入前端传递参数,将参数绑定相关组件上,旋转验证码最重要的是滑块移动的X轴的距离占整个背景图的距离比例 乘以360代表旋转的角度采用动态样式的方式处理
初始值 that.dynamicStyles.transform = “rotate(0deg)”
随着X轴的变化旋转的角度跟着改变
that.dynamicStyles.transform = “rotate(” + ((left-20) / (260 / 360)) + “deg)”,入参和后台保持一致

2.应用代码如下
<template> <view> <button @click="open">验证</button> <slider-captcha v-model="visible" :options="options" :loading="loading" @check="check" @close="close" @refresh="getSliderOptions" @error="getSliderOptions" > <!-- vue2 --> <view slot="title">自定义标题-安全验证</view> <view slot="successText">自定义成功提示-登录中</view> <view slot="errorText">自定义错误提示-是不是太难了换一个</view> <view slot="tips">自定义提示拖动下方滑块完成拼图</view> <!-- <view slot="question">自定义提示</view> --> <!-- vue2 --> <!-- vue3 --> <template #title>自定义标题-安全验证</template> <template #successText>自定义成功提示-登录中</template> <template #errorText>自定义错误提示-是不是太难了换一个</template> <template #tips>自定义提示拖动下方滑块完成拼图</template> <!-- <template #question>自定义提示</template> --> <!-- vue3 --> </slider-captcha> </view> </template> <script> import SliderCaptcha from '@/components/kkokk-slider-captcha/slider-captcha.vue' export default { components:{SliderCaptcha}, data(){ return { visible: false, loading: false, options: {} } }, methods: { // 打开触发 open() { this.visible = true this.getSliderOptions() }, // 验证 check(sliderKey, data, done, error) { const sendParam = { id: sliderKey, data: data }; // 这里是验证是否成功的接口 this.loading = true uni.request({ url: '/wxminiCheck', header: { // 'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/json' //自定义请求头信息 }, data: sendParam, method:'POST',//请求方式,必须为大写 success: (res) => { this.loading = false done() }, fail: () => { this.loading = false error() } }) }, // 关闭触发 close() { }, // 获取滑块验证参数 getSliderOptions() { this.loading = true uni.request({ url: '/wxminiCaptcha', header: { // 'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/json' //自定义请求头信息 }, method:'GET',//请求方式,必须为大写 success: (res) => { const {backgroundImage, templateImage ,backgroundImageWidth,backgroundImageHeight,templateImageWidth ,templateImageHeight,key, y} = res.data.data.captcha const seqId = res.data.data.id this.options = { sliderImg: backgroundImage, rotateImg: templateImage, bgImageWidth: backgroundImageWidth, bgImageHeight: backgroundImageHeight, templateImageWidth: templateImageWidth, templateImageHeight: templateImageHeight, sliderKey: seqId, sliderY: y } this.loading = false } }) } } } </script>3.最终效果图

完成前端对接tianai-captcha滑块验证码处理参考
https://ext.dcloud.net.cn/plugin?id=15780
更多推荐
所有评论(0)