| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- <template>
- <view class="captcha-verify-container">
- <!-- 滑动验证 -->
- <view class="slide-verify">
- <view class="slide-track">
- <view
- class="slide-thumb"
- :class="{ 'success': verified }"
- :style="{ left: thumbPosition + 'px' }"
- @touchstart="touchStartHandler"
- @touchmove="touchMoveHandler"
- @touchend="touchEndHandler"
- >
- <view class="slide-icon">
- <text v-if="verified">✓</text>
- <text v-else>→</text>
- </view>
- </view>
- <view class="slide-text">{{ verified ? '验证通过' : '向右滑动完成验证' }}</view>
- </view>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'CaptchaVerify',
- data() {
- return {
- // 滑动验证相关
- verified: false,
- thumbPosition: 0,
- startX: 0,
- trackWidth: 0,
- thumbWidth: 0
- }
- },
- mounted() {
- this.initVerify();
- },
- methods: {
- // 初始化验证
- initVerify() {
- this.initSlideVerify();
- },
-
- // 滑动验证初始化
- initSlideVerify() {
- const query = uni.createSelectorQuery().in(this);
- query.select('.slide-track').boundingClientRect(data => {
- this.trackWidth = data.width;
- }).exec();
-
- query.select('.slide-thumb').boundingClientRect(data => {
- this.thumbWidth = data.width;
- }).exec();
-
- this.thumbPosition = 0;
- this.verified = false;
- },
-
- // 滑动开始
- touchStartHandler(e) {
- if (this.verified) return;
- this.startX = e.changedTouches[0].clientX;
- },
-
- // 滑动中
- touchMoveHandler(e) {
- if (this.verified) return;
-
- let currentX = e.changedTouches[0].clientX;
- let moveX = currentX - this.startX;
-
- // 限制滑块在轨道内
- if (moveX < 0) {
- moveX = 0;
- } else if (moveX > this.trackWidth - this.thumbWidth) {
- moveX = this.trackWidth - this.thumbWidth;
- }
-
- this.thumbPosition = moveX;
- },
-
- // 滑动结束
- touchEndHandler() {
- if (this.verified) return;
-
- // 验证是否滑动到末端
- if (this.thumbPosition >= this.trackWidth - this.thumbWidth - 5) {
- this.verified = true;
- this.$emit('verify-success');
- } else {
- // 未滑到末端,复位
- this.thumbPosition = 0;
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .captcha-verify-container {
- width: 75%; /* 减小六分之一 */
- padding: 15rpx;
- box-sizing: border-box;
- margin: 0 auto; /* 水平居中 */
-
- // 滑动验证样式
- .slide-verify {
- width: 100%;
- height: 90rpx; /* 再增高五分之一 */
- position: relative;
-
- .slide-track {
- width: 100%;
- height: 90rpx; /* 增高到90rpx */
- background-color: #E8F1FF; /* 浅蓝色背景 */
- border-radius: 45rpx; /* 更新圆角 */
- position: relative;
- box-shadow: 0 2rpx 8rpx rgba(51, 133, 255, 0.2); /* 添加蓝色阴影 */
- border: 1rpx solid #BBDEFB; /* 添加边框 */
-
- .slide-thumb {
- position: absolute;
- top: 0;
- left: 0;
- width: 90rpx; /* 调整宽度与高度一致 */
- height: 90rpx; /* 增高到90rpx */
- border-radius: 45rpx; /* 更新圆角 */
- background: linear-gradient(90deg, #4285F4, #3385ff); /* 更亮丽的蓝色渐变 */
- z-index: 2;
- display: flex;
- align-items: center;
- justify-content: center;
- transition: background 0.3s;
- box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.2); /* 添加滑块阴影 */
-
- &.success {
- background: linear-gradient(90deg, #5CB85C, #4CAF50); /* 更亮丽的绿色渐变 */
- }
-
- .slide-icon {
- color: #fff;
- font-size: 36rpx; /* 调整字体 */
- }
- }
-
- .slide-text {
- position: absolute;
- width: 100%;
- height: 100%;
- line-height: 90rpx; /* 调整行高 */
- text-align: center;
- color: #5E91E5; /* 蓝色文字 */
- font-size: 28rpx; /* 调整字体大小 */
- z-index: 1;
- font-weight: 500; /* 稍微加粗文字 */
- }
- }
- }
- }
- </style>
|