|
@@ -1,235 +0,0 @@
|
|
|
-<script lang="ts" setup>
|
|
|
|
|
-//滑动图片验证码部分
|
|
|
|
|
-import Img01 from '../image/verification-img-1.png'
|
|
|
|
|
-import Img02 from '../image/verification-img-2.png'
|
|
|
|
|
-import Img03 from '../image/verification-img-3.png'
|
|
|
|
|
-import Img04 from '../image/verification-img-4.png'
|
|
|
|
|
-import { ref } from 'vue'
|
|
|
|
|
-//引入'vue3-puzzle-vcode'插件
|
|
|
|
|
-import Vcode from 'vue3-puzzle-vcode'
|
|
|
|
|
-
|
|
|
|
|
-const openDialog = () => {
|
|
|
|
|
- isShow.value = true
|
|
|
|
|
- nextTick(() => {
|
|
|
|
|
- addElement()
|
|
|
|
|
- onSuccess()
|
|
|
|
|
- updateSliderBackground('success')
|
|
|
|
|
- })
|
|
|
|
|
-}
|
|
|
|
|
-// 添加自定义元素
|
|
|
|
|
-const addElement = () => {
|
|
|
|
|
- addTipsNode()
|
|
|
|
|
- addSliderBtnNode('start')
|
|
|
|
|
- updateRefreshImg()
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const updateRefreshImg = () => {
|
|
|
|
|
- const targetNode: any = document.querySelector('img.reset_')
|
|
|
|
|
- if (targetNode) {
|
|
|
|
|
- // 使用 import.meta.url 结合 new URL 获取图片的正确路径
|
|
|
|
|
- targetNode.src = new URL('../image/icon_refresh_bold_b.png', import.meta.url).href
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-const addTipsNode = () => {
|
|
|
|
|
- const childNode = document.createElement('div')
|
|
|
|
|
- childNode.className = 'tips'
|
|
|
|
|
- childNode.innerHTML = `
|
|
|
|
|
- <p>Please drag the slider below to complete the</p>
|
|
|
|
|
- <p>verification to ensure normal access</p>
|
|
|
|
|
- `
|
|
|
|
|
- const parentNode = document.querySelector('.vue-auth-box_')
|
|
|
|
|
- if (parentNode.firstChild) {
|
|
|
|
|
- parentNode.insertBefore(childNode, parentNode.firstChild)
|
|
|
|
|
- } else {
|
|
|
|
|
- parentNode.appendChild(childNode)
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const styleMap = {
|
|
|
|
|
- start: {
|
|
|
|
|
- thumbColor: 'var(--color-neutral-1)',
|
|
|
|
|
- thumbIcon: 'icon-icon_drag__line_b',
|
|
|
|
|
- trackBackground: 'var(--color-success)'
|
|
|
|
|
- },
|
|
|
|
|
- success: {
|
|
|
|
|
- thumbColor: '#fff',
|
|
|
|
|
- thumbIcon: 'icon-icon_confirm_b',
|
|
|
|
|
- trackBackground: 'var(--color-success)'
|
|
|
|
|
- },
|
|
|
|
|
- error: {
|
|
|
|
|
- thumbColor: '#fff',
|
|
|
|
|
- thumbIcon: 'icon-icon_reject_b',
|
|
|
|
|
- trackBackground: '#c7353f'
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const addSliderBtnNode = (state: string) => {
|
|
|
|
|
- const parentNode = document.querySelector('.range-btn')
|
|
|
|
|
- if (state === 'start') {
|
|
|
|
|
- parentNode.innerHTML = `
|
|
|
|
|
- <span style="color: ${styleMap[state].thumbColor}" class="font_family ${styleMap[state].thumbIcon}"></span>
|
|
|
|
|
- `
|
|
|
|
|
- } else {
|
|
|
|
|
- parentNode.innerHTML = `
|
|
|
|
|
- <div class="icon-border" style="background: ${styleMap[state].trackBackground}">
|
|
|
|
|
- <span style="color: ${styleMap[state].thumbColor}" class="font_family ${styleMap[state].thumbIcon}"></span>
|
|
|
|
|
- </div>
|
|
|
|
|
- `
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const isShow = ref(false)
|
|
|
|
|
-
|
|
|
|
|
-// 根据不同的状态,设置已滑动区域的背景颜色
|
|
|
|
|
-const updateSliderBackground = (state: string) => {
|
|
|
|
|
- const targetNode: any = document.querySelector('.range-slider')
|
|
|
|
|
- targetNode.style.background = styleMap[state].trackBackground
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const emit = defineEmits<{
|
|
|
|
|
- close: []
|
|
|
|
|
-}>()
|
|
|
|
|
-// 监听验证成功事件,因为这里库中的成功事件有0.8秒的延迟,所以这里手动监听验证成功事件
|
|
|
|
|
-const onSuccess = () => {
|
|
|
|
|
- // 选择要监听的目标元素
|
|
|
|
|
- const targetNode = document.querySelector('.info-box_') // 将此选择器替换为你的实际目标
|
|
|
|
|
- if (targetNode) {
|
|
|
|
|
- const observer = new MutationObserver((mutationsList) => {
|
|
|
|
|
- mutationsList.forEach((mutation) => {
|
|
|
|
|
- if (mutation.type === 'childList') {
|
|
|
|
|
- if ((mutation.target as any).innerHTML === 'Verification successful') {
|
|
|
|
|
- updateSliderBackground('success')
|
|
|
|
|
- addSliderBtnNode('success')
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- emit('close')
|
|
|
|
|
- isShow.value = false
|
|
|
|
|
- }, 500)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- // 配置 MutationObserver,监听子节点的变化
|
|
|
|
|
- const config = { childList: true, subtree: true }
|
|
|
|
|
-
|
|
|
|
|
- // 启动监听
|
|
|
|
|
- observer.observe(targetNode, config)
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-const close = () => {
|
|
|
|
|
- isShow.value = true
|
|
|
|
|
-}
|
|
|
|
|
-const fail = () => {
|
|
|
|
|
- updateSliderBackground('error')
|
|
|
|
|
- addSliderBtnNode('error')
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- updateSliderBackground('start')
|
|
|
|
|
- addSliderBtnNode('start')
|
|
|
|
|
- }, 800)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-defineExpose({
|
|
|
|
|
- openDialog
|
|
|
|
|
-})
|
|
|
|
|
-</script>
|
|
|
|
|
-<template>
|
|
|
|
|
- <Vcode
|
|
|
|
|
- :show="isShow"
|
|
|
|
|
- @close="close"
|
|
|
|
|
- @fail="fail"
|
|
|
|
|
- :canvasWidth="320"
|
|
|
|
|
- :canvasHeight="180"
|
|
|
|
|
- sliderText="Swipe to verify"
|
|
|
|
|
- :sliderSize="38"
|
|
|
|
|
- successText="Verification successful"
|
|
|
|
|
- failText="Verification failed"
|
|
|
|
|
- :range="5"
|
|
|
|
|
- :imgs="[Img01, Img02, Img03, Img04]"
|
|
|
|
|
- ></Vcode>
|
|
|
|
|
-</template>
|
|
|
|
|
-<style lang="scss" scoped>
|
|
|
|
|
-.slider-verification {
|
|
|
|
|
- width: 400px;
|
|
|
|
|
- height: 373px;
|
|
|
|
|
- padding: 40px;
|
|
|
|
|
- .tips {
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|
|
|
-<style lang="scss">
|
|
|
|
|
-// 整体框架
|
|
|
|
|
-.vue-auth-box_ {
|
|
|
|
|
- width: 400px;
|
|
|
|
|
- height: 373px;
|
|
|
|
|
- padding: 40px;
|
|
|
|
|
- .tips {
|
|
|
|
|
- margin-bottom: 16px;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- }
|
|
|
|
|
- .icon-border {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- width: 16px !important;
|
|
|
|
|
- height: 16px !important;
|
|
|
|
|
- border-radius: 50%;
|
|
|
|
|
- border: none !important;
|
|
|
|
|
- span {
|
|
|
|
|
- font-size: 14px !important;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-div.vue-puzzle-vcode {
|
|
|
|
|
- background-color: rgba(43, 47, 54, 0.7);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.vue-auth-box_ .auth-control_ div.range-box {
|
|
|
|
|
- background-color: #87909e;
|
|
|
|
|
- box-shadow: none;
|
|
|
|
|
-}
|
|
|
|
|
-.vue-auth-box_ div.auth-body_ {
|
|
|
|
|
- border-radius: 6px;
|
|
|
|
|
-}
|
|
|
|
|
-// 已滑动区域的样式
|
|
|
|
|
-.vue-auth-box_ .auth-control_ .range-box div.range-slider {
|
|
|
|
|
- background-color: var(--color-success);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.vue-auth-box_ .auth-body_ div.loading-box_.hide_ {
|
|
|
|
|
- display: none;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 成功的提示
|
|
|
|
|
-.vue-auth-box_ .auth-body_ div.info-box_ {
|
|
|
|
|
- background: var(--color-success);
|
|
|
|
|
-}
|
|
|
|
|
-// 失败的提示
|
|
|
|
|
-.vue-auth-box_ .auth-body_ div.info-box_.fail {
|
|
|
|
|
- background: #c7353f;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.vue-auth-box_ .auth-control_ .range-box .range-slider {
|
|
|
|
|
- border-radius: 6px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.vue-auth-box_ .auth-control_ div.range-box {
|
|
|
|
|
- border-radius: 6px;
|
|
|
|
|
-}
|
|
|
|
|
-// 滑块
|
|
|
|
|
-.vue-auth-box_ .auth-control_ .range-box .range-slider .range-btn {
|
|
|
|
|
- border-radius: 6px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.vue-auth-box_ .auth-body_ .reset_ {
|
|
|
|
|
- width: 20px;
|
|
|
|
|
- height: 20px;
|
|
|
|
|
- top: 10px;
|
|
|
|
|
- right: 10px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.vue-auth-box_ .auth-control_ .range-box .range-text {
|
|
|
|
|
- color: #fff;
|
|
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|