Compare commits
3 Commits
415267e307
...
4c8e63bd7d
Author | SHA1 | Date | |
---|---|---|---|
|
4c8e63bd7d | ||
|
13bc4f4883 | ||
|
29cf4490e1 |
@ -1,367 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="puzzle-container">
|
|
||||||
<div class="puzzle-box" :style="{ height: boxHeight + 'px' }">
|
|
||||||
<!-- 背景图 -->
|
|
||||||
<img :src="bgImageUrl" style="width: 320px;height: 191px;" ref="bgImage" @load="onImageLoad" @error="handleImageError">
|
|
||||||
<!-- 滑块 -->
|
|
||||||
<img
|
|
||||||
class="slider-block"
|
|
||||||
:src="sliderImageUrl"
|
|
||||||
:style="{
|
|
||||||
top: `${blockY}px`,
|
|
||||||
left: `${moveX}px`,
|
|
||||||
visibility: loaded ? 'visible' : 'hidden',
|
|
||||||
width: '50px',
|
|
||||||
height: '50px'
|
|
||||||
}"
|
|
||||||
></img>
|
|
||||||
<div v-if="verifySuccess || verifyError" :class="`text-#fff ${verifySuccess?'bg-#52C41A':'bg-#FF4D4F'} h-24px w-100% text-14px absolute left-0 bottom-0 text-center leading-24px`">{{ verifyTip }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 滑动条 -->
|
|
||||||
<div class="slider-container">
|
|
||||||
<div class="slider-track">
|
|
||||||
<div
|
|
||||||
class="slider-bar"
|
|
||||||
:style="{ width: `${moveX}px` }"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
class="slider-button"
|
|
||||||
:style="{ left: `${moveX}px` }"
|
|
||||||
@mousedown="handleMouseDown"
|
|
||||||
@touchstart="handleTouchStart"
|
|
||||||
>
|
|
||||||
<div class="slider-icon"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
show: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
blockY: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
bgImageUrl: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
sliderImageUrl: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['leave'])
|
|
||||||
|
|
||||||
// 响应式状态
|
|
||||||
const moveX = ref(0)
|
|
||||||
const startX = ref(0)
|
|
||||||
const oldMoveX = ref(0)
|
|
||||||
const maxMoveX = ref(0)
|
|
||||||
const boxHeight = ref(0)
|
|
||||||
const loaded = ref(false)
|
|
||||||
const isDragging = ref(false)
|
|
||||||
const verifySuccess = ref(false)
|
|
||||||
const verifyError = ref(false)
|
|
||||||
const verifyTip = ref('')
|
|
||||||
|
|
||||||
// 重置方法
|
|
||||||
const reset = () => {
|
|
||||||
moveX.value = 0
|
|
||||||
verifySuccess.value = false
|
|
||||||
verifyError.value = false
|
|
||||||
verifyTip.value = ''
|
|
||||||
isDragging.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOM引用
|
|
||||||
const bgImage = ref(null)
|
|
||||||
|
|
||||||
// 方法
|
|
||||||
const onImageLoad = () => {
|
|
||||||
if (bgImage.value) {
|
|
||||||
try {
|
|
||||||
const img = bgImage.value
|
|
||||||
// 确保图片已经完全加载
|
|
||||||
if (!img.complete) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const scale = img.width / img.naturalWidth // 计算图片缩放比例
|
|
||||||
boxHeight.value = img.height
|
|
||||||
|
|
||||||
// 根据图片实际显示大小调整滑块大小
|
|
||||||
const blockSize = Math.round(50 * scale)
|
|
||||||
document.documentElement.style.setProperty('--block-size', blockSize + 'px')
|
|
||||||
|
|
||||||
maxMoveX.value = img.width - blockSize // 使用实际显示的滑块大小计算最大移动距离
|
|
||||||
loaded.value = true
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Image load error:', error)
|
|
||||||
// 设置默认值以确保组件仍然可用
|
|
||||||
const defaultBlockSize = 50
|
|
||||||
document.documentElement.style.setProperty('--block-size', defaultBlockSize + 'px')
|
|
||||||
maxMoveX.value = 320 - defaultBlockSize // 使用默认容器宽度
|
|
||||||
loaded.value = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加图片错误处理
|
|
||||||
const handleImageError = () => {
|
|
||||||
console.error('Image failed to load')
|
|
||||||
// 设置默认值以确保组件仍然可用
|
|
||||||
const defaultBlockSize = 50
|
|
||||||
document.documentElement.style.setProperty('--block-size', defaultBlockSize + 'px')
|
|
||||||
maxMoveX.value = 320 - defaultBlockSize
|
|
||||||
loaded.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleMouseDown = (event) => {
|
|
||||||
event.preventDefault()
|
|
||||||
startX.value = event.clientX
|
|
||||||
oldMoveX.value = moveX.value
|
|
||||||
isDragging.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleTouchStart = (event) => {
|
|
||||||
event.preventDefault()
|
|
||||||
const touch = event.touches[0]
|
|
||||||
startX.value = touch.clientX
|
|
||||||
oldMoveX.value = moveX.value
|
|
||||||
isDragging.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const move = (clientX) => {
|
|
||||||
let diff = clientX - startX.value
|
|
||||||
let newMoveX = oldMoveX.value + diff
|
|
||||||
|
|
||||||
// 限制移动范围
|
|
||||||
if (newMoveX < 0) newMoveX = 0
|
|
||||||
if (newMoveX > maxMoveX.value) newMoveX = maxMoveX.value
|
|
||||||
|
|
||||||
moveX.value = Math.round(newMoveX) // 取整数避免小数点导致的模糊
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleMouseMove = (event) => {
|
|
||||||
if (!isDragging.value) return
|
|
||||||
move(event.clientX)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleTouchMove = (event) => {
|
|
||||||
if (!isDragging.value) return
|
|
||||||
event.preventDefault() // 防止页面滚动
|
|
||||||
move(event.touches[0].clientX)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleMouseUp = async () => {
|
|
||||||
if (!isDragging.value) return
|
|
||||||
isDragging.value = false
|
|
||||||
|
|
||||||
try {
|
|
||||||
emit('leave', moveX.value, (success) => {
|
|
||||||
if (success) {
|
|
||||||
verifySuccess.value = true
|
|
||||||
verifyError.value = false
|
|
||||||
verifyTip.value = '验证成功'
|
|
||||||
} else {
|
|
||||||
verifySuccess.value = false
|
|
||||||
verifyError.value = true
|
|
||||||
verifyTip.value = '验证失败'
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
verifySuccess.value = false
|
|
||||||
verifyError.value = true
|
|
||||||
verifyTip.value = '验证失败'
|
|
||||||
}finally{
|
|
||||||
setTimeout(() => {
|
|
||||||
reset()
|
|
||||||
}, 2000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleTouchEnd = () => {
|
|
||||||
handleMouseUp()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 预加载图片
|
|
||||||
const preloadImages = () => {
|
|
||||||
const bgImg = new Image()
|
|
||||||
const sliderImg = new Image()
|
|
||||||
|
|
||||||
bgImg.onload = () => {
|
|
||||||
if (bgImage.value) {
|
|
||||||
onImageLoad()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bgImg.src = props.bgImageUrl
|
|
||||||
sliderImg.src = props.sliderImageUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生命周期钩子
|
|
||||||
onMounted(() => {
|
|
||||||
preloadImages()
|
|
||||||
window.addEventListener('mousemove', handleMouseMove)
|
|
||||||
window.addEventListener('mouseup', handleMouseUp)
|
|
||||||
window.addEventListener('touchmove', handleTouchMove)
|
|
||||||
window.addEventListener('touchend', handleTouchEnd)
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
window.removeEventListener('mousemove', handleMouseMove)
|
|
||||||
window.removeEventListener('mouseup', handleMouseUp)
|
|
||||||
window.removeEventListener('touchmove', handleTouchMove)
|
|
||||||
window.removeEventListener('touchend', handleTouchEnd)
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
:root {
|
|
||||||
--block-size: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.puzzle-container {
|
|
||||||
position: relative;
|
|
||||||
margin: 0 auto;
|
|
||||||
background: #fff;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 10px;
|
|
||||||
touch-action: none;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.puzzle-box {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
background: #f8f8f8;
|
|
||||||
border-radius: 8px;
|
|
||||||
touch-action: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-image {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
pointer-events: none;
|
|
||||||
object-fit: contain;
|
|
||||||
max-width: 100%;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider-block {
|
|
||||||
position: absolute;
|
|
||||||
width: var(--block-size);
|
|
||||||
height: var(--block-size);
|
|
||||||
background-size: 100% 100%;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
touch-action: none;
|
|
||||||
will-change: transform;
|
|
||||||
transform: translateZ(0);
|
|
||||||
backface-visibility: hidden;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider-container {
|
|
||||||
position: relative;
|
|
||||||
margin-top: 15px;
|
|
||||||
height: 40px;
|
|
||||||
touch-action: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider-track {
|
|
||||||
position: relative;
|
|
||||||
height: 40px;
|
|
||||||
background: #f5f5f5;
|
|
||||||
border-radius: 20px;
|
|
||||||
touch-action: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider-bar {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: #91d5ff;
|
|
||||||
border-radius: 20px;
|
|
||||||
will-change: transform;
|
|
||||||
transform-origin: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider-button {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
|
||||||
cursor: pointer;
|
|
||||||
will-change: transform;
|
|
||||||
transform: translateZ(0);
|
|
||||||
backface-visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider-icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
background: #1890ff;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verify-result-bar {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 14px;
|
|
||||||
border-radius: 20px;
|
|
||||||
transition: all 0.3s;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verify-result-bar.success {
|
|
||||||
background: #52c41a;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verify-result-bar.error {
|
|
||||||
background: #ff4d4f;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移除旧的提示样式 */
|
|
||||||
.verify-tip {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
195
app/components/puzzleComponent/index.vue
Normal file
195
app/components/puzzleComponent/index.vue
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
<template>
|
||||||
|
<div class="m-auto bg-white p-15px rd-10px touch-none select-none">
|
||||||
|
<div class="relative w-full overflow-hidden bg-#f8f8f8 rd-8px" >
|
||||||
|
<!-- 背景图 -->
|
||||||
|
<img
|
||||||
|
:src="options?.canvasSrc"
|
||||||
|
class="block pointer-events-none object-contain"
|
||||||
|
:style="{ width: `${options?.canvasWidth}px`, height: `${options?.canvasHeight}px` }"
|
||||||
|
ref="bgImage"
|
||||||
|
@load="onImageLoad"
|
||||||
|
@error="onImageError"
|
||||||
|
>
|
||||||
|
<!-- 滑块 -->
|
||||||
|
<img
|
||||||
|
:src="options?.blockSrc"
|
||||||
|
class="absolute cursor-pointer will-change-transform transform-gpu"
|
||||||
|
|
||||||
|
:class="{ 'transition-all duration-300 ease-out': !isDragging }"
|
||||||
|
:style="{
|
||||||
|
top: `${options?.blockY}px`,
|
||||||
|
left: `${moveX}px`,
|
||||||
|
visibility: loaded ? 'visible' : 'hidden',
|
||||||
|
width: `${options?.blockWidth}px`, height: `${options?.blockHeight}px`
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<transition name="fade-slide">
|
||||||
|
<div
|
||||||
|
v-if="verifyStatus.show"
|
||||||
|
class="absolute left-0 bottom-0 w-full h-24px leading-24px text-center text-14px text-white"
|
||||||
|
:class="verifyStatus.type === 'success' ? 'bg-#52c41a' : 'bg-#ff4d4f'"
|
||||||
|
>
|
||||||
|
{{ verifyStatus.message }}
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 滑动条 -->
|
||||||
|
<div class="relative mt-15px h-40px">
|
||||||
|
<div class="relative h-40px bg-#f5f5f5 rd-20px">
|
||||||
|
<div
|
||||||
|
class="absolute h-full bg-#91d5ff rd-20px"
|
||||||
|
:class="{ 'transition-all duration-300 ease-out': !isDragging }"
|
||||||
|
:style="{ width: `${moveX}px` }"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
class="absolute top-0 w-40px h-40px bg-white rd-full shadow-[0_2px_6px_rgba(0,0,0,0.15)] cursor-pointer will-change-transform"
|
||||||
|
:class="{ 'transition-all duration-300 ease-out': !isDragging }"
|
||||||
|
:style="{ left: `${moveX}px` }"
|
||||||
|
@mousedown.prevent="startDrag"
|
||||||
|
@touchstart.prevent="startDrag"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="absolute top-50% left-50% translate--50% w-20px h-20px bg-#1890ff rd-full"
|
||||||
|
:class="{ 'animate-loading': isVerifying }"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
|
||||||
|
|
||||||
|
// Props
|
||||||
|
const props = defineProps({
|
||||||
|
options:Object
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['leave'])
|
||||||
|
|
||||||
|
// 状态管理
|
||||||
|
const moveX = ref(0)
|
||||||
|
|
||||||
|
const loaded = ref(false)
|
||||||
|
const isDragging = ref(false)
|
||||||
|
const isVerifying = ref(false)
|
||||||
|
const maxMoveX = ref(0)
|
||||||
|
const bgImage = ref(null)
|
||||||
|
|
||||||
|
const verifyStatus = reactive({
|
||||||
|
show: false,
|
||||||
|
type: '',
|
||||||
|
message: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const dragState = reactive({
|
||||||
|
startX: 0,
|
||||||
|
oldMoveX: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// 图片加载处理
|
||||||
|
const onImageLoad = () => {
|
||||||
|
if (!bgImage.value?.complete) return
|
||||||
|
|
||||||
|
const img = bgImage.value
|
||||||
|
const scale = img.width / img.naturalWidth
|
||||||
|
const blockSize = Math.round(50 * scale)
|
||||||
|
maxMoveX.value = img.width - blockSize
|
||||||
|
loaded.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const onImageError = () => {
|
||||||
|
console.error('Image failed to load')
|
||||||
|
maxMoveX.value = 270
|
||||||
|
loaded.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拖动处理
|
||||||
|
const startDrag = (e) => {
|
||||||
|
isDragging.value = true
|
||||||
|
dragState.startX = e.touches?.[0].clientX ?? e.clientX
|
||||||
|
dragState.oldMoveX = moveX.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDrag = (e) => {
|
||||||
|
if (!isDragging.value) return
|
||||||
|
|
||||||
|
const clientX = e.touches?.[0].clientX ?? e.clientX
|
||||||
|
let newMoveX = dragState.oldMoveX + (clientX - dragState.startX)
|
||||||
|
|
||||||
|
moveX.value = Math.max(0, Math.min(newMoveX, maxMoveX.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
const endDrag = async () => {
|
||||||
|
if (!isDragging.value) return
|
||||||
|
|
||||||
|
isDragging.value = false
|
||||||
|
isVerifying.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
emit('leave', moveX.value, (success) => {
|
||||||
|
showVerifyResult(success)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
showVerifyResult(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证结果展示
|
||||||
|
const showVerifyResult = (success) => {
|
||||||
|
verifyStatus.show = true
|
||||||
|
verifyStatus.type = success ? 'success' : 'error'
|
||||||
|
verifyStatus.message = success ? '验证成功' : '验证失败'
|
||||||
|
isVerifying.value = false
|
||||||
|
|
||||||
|
if (!success) moveX.value = 0
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
verifyStatus.show = false
|
||||||
|
verifyStatus.message = ''
|
||||||
|
moveX.value = 0
|
||||||
|
}, 1500)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 事件监听
|
||||||
|
onMounted(() => {
|
||||||
|
window.addEventListener('mousemove', onDrag)
|
||||||
|
window.addEventListener('mouseup', endDrag)
|
||||||
|
window.addEventListener('touchmove', onDrag)
|
||||||
|
window.addEventListener('touchend', endDrag)
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('mousemove', onDrag)
|
||||||
|
window.removeEventListener('mouseup', endDrag)
|
||||||
|
window.removeEventListener('touchmove', onDrag)
|
||||||
|
window.removeEventListener('touchend', endDrag)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes loading {
|
||||||
|
from { transform: translate(-50%, -50%) rotate(0deg); }
|
||||||
|
to { transform: translate(-50%, -50%) rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-loading {
|
||||||
|
animation: loading 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 添加过渡动画样式 */
|
||||||
|
.fade-slide-enter-active,
|
||||||
|
.fade-slide-leave-active {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-slide-enter-from,
|
||||||
|
.fade-slide-leave-to {
|
||||||
|
transform: translateY(100%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
@ -8,7 +8,9 @@ import {authStore} from "@/stores/auth/index.js";
|
|||||||
import {message} from '@/components/x-message/useMessage.js'
|
import {message} from '@/components/x-message/useMessage.js'
|
||||||
import {fddCheck} from "~/api/goods/index.js";
|
import {fddCheck} from "~/api/goods/index.js";
|
||||||
import zu6020 from '@/static/images/zu6020@2x.png'
|
import zu6020 from '@/static/images/zu6020@2x.png'
|
||||||
import YourPuzzleComponent from '@/components/YourPuzzleComponent.vue'
|
|
||||||
|
import PuzzleComponent from '@/components/puzzleComponent/index.vue'
|
||||||
|
import { ref } from 'vue';
|
||||||
const {userInfo,token,selectedZone}= authStore()
|
const {userInfo,token,selectedZone}= authStore()
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@ -84,45 +86,30 @@ onMounted(()=>{
|
|||||||
selectedCountry.value=route.query.countryName || defaultCountry.name
|
selectedCountry.value=route.query.countryName || defaultCountry.name
|
||||||
})
|
})
|
||||||
const vanSwipeRef=ref(null)
|
const vanSwipeRef=ref(null)
|
||||||
|
|
||||||
const captcha=ref({
|
const captcha=ref({
|
||||||
"nonceStr": "397b5e08168c31c4",
|
nonceStr: "",
|
||||||
"blockX": 256
|
blockX: 256 ,
|
||||||
|
blockWidth:50,
|
||||||
|
blockHeight:50,
|
||||||
|
canvasWidth:320,
|
||||||
|
canvasHeight:191,
|
||||||
|
place:0,
|
||||||
|
canvasSrc:'',
|
||||||
|
blockSrc:'',
|
||||||
|
blockY:0
|
||||||
})
|
})
|
||||||
const captchaUrl=ref('')
|
|
||||||
const captchaVerifyUrl=ref('')
|
|
||||||
const blockY=ref(0)
|
|
||||||
const getCode =async () => {
|
const getCode =async () => {
|
||||||
loadingRef.value.loading1=true
|
loadingRef.value.loading1=true
|
||||||
const res=await userCaptcha({
|
const res=await userCaptcha(captcha.value)
|
||||||
"canvasWidth": 320, //画布的宽度(canvasWidth大于41并且(canvasWidth-10)/2 - 1> blockWidth)
|
|
||||||
"canvasHeight": 191, //画布的高度(canvasHeight大于26并且 canvasHeight - blockHeight > 11
|
|
||||||
"blockWidth": 50, //块图像的宽度(blockWidth大于14)
|
|
||||||
"blockHeight": 50, //块图像的高度(blockHeight大于14)
|
|
||||||
// "blockRadius": 25, //块图像的圆角半径
|
|
||||||
"place": 0 //图像来源标识,0表示URL下载,1表示本地文件 一般用0
|
|
||||||
})
|
|
||||||
if (res.status===0){
|
if (res.status===0){
|
||||||
captchaUrl.value=`data:image/png;base64,${res.data.canvasSrc}`
|
captcha.value.canvasSrc=`data:image/png;base64,${res.data.canvasSrc}`
|
||||||
captchaVerifyUrl.value=`data:image/png;base64,${res.data.blockSrc}`
|
captcha.value.blockSrc=`data:image/png;base64,${res.data.blockSrc}`
|
||||||
blockY.value=res.data.blockY
|
captcha.value.blockY=res.data.blockY
|
||||||
captcha.value.nonceStr=res.data.nonceStr
|
captcha.value.nonceStr=res.data.nonceStr
|
||||||
isShow.value=true
|
isShow.value=true
|
||||||
loadingRef.value.loading1=false
|
loadingRef.value.loading1=false
|
||||||
}
|
}
|
||||||
// loadingRef.value.loading1=true
|
|
||||||
// const res=await senCode({
|
|
||||||
// telNum:phoneNum.value,
|
|
||||||
// zone:selectedZone.value
|
|
||||||
// })
|
|
||||||
// loadingRef.value.loading1=false
|
|
||||||
// if (res.status===0){
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
// pane.value = 1
|
|
||||||
// vanSwipeRef.value?.swipeTo(pane.value)
|
|
||||||
|
|
||||||
// startCountdown();
|
|
||||||
}
|
}
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
code.value = ''
|
code.value = ''
|
||||||
@ -176,13 +163,7 @@ onUnmounted(() => {
|
|||||||
window.removeEventListener('resize', () => {})
|
window.removeEventListener('resize', () => {})
|
||||||
})
|
})
|
||||||
const isShow=ref(false)
|
const isShow=ref(false)
|
||||||
const onSuccess=()=>{
|
|
||||||
// userCaptchaValidate()
|
|
||||||
isShow.value=false
|
|
||||||
}
|
|
||||||
const onClose=()=>{
|
|
||||||
isShow.value=false
|
|
||||||
}
|
|
||||||
const onLeave =async (moveX, callback) => {
|
const onLeave =async (moveX, callback) => {
|
||||||
loadingRef.value.loading1=true
|
loadingRef.value.loading1=true
|
||||||
const res=await senCode({
|
const res=await senCode({
|
||||||
@ -197,7 +178,7 @@ const onLeave =async (moveX, callback) => {
|
|||||||
if (res.status===408){
|
if (res.status===408){
|
||||||
callback(false)
|
callback(false)
|
||||||
getCode()
|
getCode()
|
||||||
}else{
|
}else if([407,0].includes(res.status)){
|
||||||
callback(true)
|
callback(true)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
pane.value = 1
|
pane.value = 1
|
||||||
@ -286,10 +267,8 @@ const onLeave =async (moveX, callback) => {
|
|||||||
{{ $t('login.agreement') }}<span class="text-#3454AF " @click="$router.push('/privacyPolicy')">{{ $t('login.privacyPolicy') }}</span>
|
{{ $t('login.agreement') }}<span class="text-#3454AF " @click="$router.push('/privacyPolicy')">{{ $t('login.privacyPolicy') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<van-popup v-model:show="isShow" round>
|
<van-popup v-model:show="isShow" round>
|
||||||
<YourPuzzleComponent
|
<PuzzleComponent
|
||||||
:blockY="blockY"
|
:options="captcha"
|
||||||
:bgImageUrl="captchaUrl"
|
|
||||||
:sliderImageUrl="captchaVerifyUrl"
|
|
||||||
@leave="onLeave"
|
@leave="onLeave"
|
||||||
/>
|
/>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
Loading…
Reference in New Issue
Block a user