|
|
@@ -1,222 +0,0 @@
|
|
|
-<script lang="ts" setup>
|
|
|
-const dialogVisible = ref(false)
|
|
|
-
|
|
|
-const openDialog = () => {
|
|
|
- dialogVisible.value = true
|
|
|
-}
|
|
|
-
|
|
|
-const position = ref(0)
|
|
|
-const isDragging = ref(false)
|
|
|
-const verifyText = ref('Swipe right to verify')
|
|
|
-const sliderState = ref<'start' | 'success' | 'error' | 'dragging'>('start')
|
|
|
-const styleMap = {
|
|
|
- start: {
|
|
|
- thumbColor: 'var(--color-neutral-1)',
|
|
|
- thumbIcon: 'icon-icon_drag__line_b',
|
|
|
- trackBackground: '#87909e'
|
|
|
- },
|
|
|
- dragging: {
|
|
|
- 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 trackRef = ref<HTMLElement | null>(null)
|
|
|
-
|
|
|
-const getTrackBackground = () => {
|
|
|
- const trackWidth = trackRef.value?.offsetWidth || 320
|
|
|
- const progress = (position.value / (trackWidth - 40)) * 100 // 百分比
|
|
|
- if (sliderState.value === 'start') {
|
|
|
- return styleMap.start.trackBackground // 初始时灰色
|
|
|
- } else if (sliderState.value === 'dragging') {
|
|
|
- return `linear-gradient(90deg, ${styleMap.success.trackBackground} ${progress}%, ${styleMap.start.trackBackground} ${progress}%)`
|
|
|
- } else if (sliderState.value === 'error') {
|
|
|
- return `linear-gradient(90deg, ${styleMap.error.trackBackground} ${progress}%, ${styleMap.start.trackBackground} ${progress}%)`
|
|
|
- }
|
|
|
- return styleMap.success.trackBackground // 成功时整条绿色
|
|
|
-}
|
|
|
-
|
|
|
-const startDrag = () => {
|
|
|
- if (sliderState.value === 'success') {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- isDragging.value = true
|
|
|
- document.addEventListener('mousemove', onDrag)
|
|
|
- document.addEventListener('mouseup', stopDrag)
|
|
|
-}
|
|
|
-
|
|
|
-const onDrag = (event: MouseEvent) => {
|
|
|
- if (isDragging.value) {
|
|
|
- if (trackRef.value) {
|
|
|
- sliderState.value = 'dragging'
|
|
|
- verifyText.value = 'Swipe right to verify'
|
|
|
- const rect = trackRef.value.getBoundingClientRect()
|
|
|
- const offsetX = event.clientX - rect.left
|
|
|
- position.value = Math.min(Math.max(offsetX, 0), rect.width - 40) // 40是滑块的宽度
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const emit = defineEmits<{
|
|
|
- verifySuccess: []
|
|
|
-}>()
|
|
|
-const stopDrag = () => {
|
|
|
- isDragging.value = false
|
|
|
- document.removeEventListener('mousemove', onDrag)
|
|
|
- document.removeEventListener('mouseup', stopDrag)
|
|
|
-
|
|
|
- if (trackRef.value) {
|
|
|
- const trackWidth = trackRef.value.offsetWidth
|
|
|
- if (position.value >= trackWidth - 40) {
|
|
|
- sliderState.value = 'success'
|
|
|
- verifyText.value = 'Verification successful'
|
|
|
- setTimeout(() => {
|
|
|
- dialogVisible.value = false
|
|
|
- emit('verifySuccess')
|
|
|
- }, 500)
|
|
|
- } else {
|
|
|
- sliderState.value = 'error'
|
|
|
- verifyText.value = 'Verification failed'
|
|
|
- setTimeout(() => {
|
|
|
- sliderState.value = 'start'
|
|
|
- verifyText.value = 'Swipe right to verify'
|
|
|
- position.value = 0
|
|
|
- }, 3000)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const moveSlider = (event: MouseEvent) => {
|
|
|
- if (sliderState.value !== 'success') {
|
|
|
- onDrag(event)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const clearData = () => {
|
|
|
- sliderState.value = 'start'
|
|
|
- verifyText.value = 'Swipe right to verify'
|
|
|
- position.value = 0
|
|
|
-}
|
|
|
-defineExpose({
|
|
|
- openDialog
|
|
|
-})
|
|
|
-</script>
|
|
|
-
|
|
|
-<template>
|
|
|
- <el-dialog
|
|
|
- top="30vh"
|
|
|
- destroy-on-close
|
|
|
- :close-on-click-modal="false"
|
|
|
- :close-on-press-escape="false"
|
|
|
- @closed="clearData"
|
|
|
- v-model="dialogVisible"
|
|
|
- width="400"
|
|
|
- class="slide-verify-dialog"
|
|
|
- >
|
|
|
- <div class="content">
|
|
|
- <p>Please drag the slider below to complete the</p>
|
|
|
- <p>verification to ensure normal access</p>
|
|
|
- <div class="slider-container">
|
|
|
- <div
|
|
|
- class="slider-track"
|
|
|
- :style="{ background: getTrackBackground() }"
|
|
|
- @click="moveSlider"
|
|
|
- ref="trackRef"
|
|
|
- >
|
|
|
- {{ verifyText }}
|
|
|
- <div
|
|
|
- class="slider-thumb"
|
|
|
- :style="{ left: `${position}px`, borderColor: styleMap[sliderState].trackBackground }"
|
|
|
- @mousedown="startDrag"
|
|
|
- >
|
|
|
- <span
|
|
|
- v-if="sliderState === 'start' || sliderState === 'dragging'"
|
|
|
- class="font_family"
|
|
|
- :style="{ color: styleMap[sliderState].thumbColor }"
|
|
|
- :class="[styleMap[sliderState].thumbIcon]"
|
|
|
- ></span>
|
|
|
- <span
|
|
|
- v-else
|
|
|
- class="font_family other-state"
|
|
|
- :style="{
|
|
|
- color: styleMap[sliderState].thumbColor,
|
|
|
- backgroundColor: styleMap[sliderState].trackBackground
|
|
|
- }"
|
|
|
- :class="[styleMap[sliderState].thumbIcon]"
|
|
|
- ></span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </el-dialog>
|
|
|
-</template>
|
|
|
-
|
|
|
-<style lang="scss" scoped>
|
|
|
-.content {
|
|
|
- padding: 40px 0;
|
|
|
- text-align: center;
|
|
|
- & > p {
|
|
|
- line-height: 21px;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.slider-container {
|
|
|
- width: 320px;
|
|
|
- margin: 16px auto 0;
|
|
|
- text-align: center;
|
|
|
- user-select: none;
|
|
|
-}
|
|
|
-.slider-track {
|
|
|
- position: relative;
|
|
|
- width: 100%;
|
|
|
- height: 40px;
|
|
|
- padding: 1px;
|
|
|
- background: #868f9d;
|
|
|
- border-radius: 6px;
|
|
|
- line-height: 38px;
|
|
|
- color: #fff;
|
|
|
-}
|
|
|
-.slider-thumb {
|
|
|
- position: absolute;
|
|
|
- top: 0px;
|
|
|
- left: 10px;
|
|
|
- width: 40px;
|
|
|
- height: 40px;
|
|
|
- background: #fff;
|
|
|
- cursor: pointer;
|
|
|
- border-radius: 6px;
|
|
|
- border: 1px solid #868f9d;
|
|
|
- .font_family {
|
|
|
- font-size: 14px;
|
|
|
- &.other-state {
|
|
|
- height: 16px;
|
|
|
- width: 16px;
|
|
|
- padding: 1px;
|
|
|
- border-radius: 50%;
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|
|
|
-
|
|
|
-<style lang="scss">
|
|
|
-.slide-verify-dialog {
|
|
|
- .el-dialog__header {
|
|
|
- display: none;
|
|
|
- }
|
|
|
- .el-dialog__body {
|
|
|
- padding: 0;
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|