20260908223921

This commit is contained in:
oneao committed 2026-09-08 22:39:22 +08:00
1 parent 8734b43a2a
commit ead8e66626
60 files changed
+562 -8502

No files matched your search

@@ -47,9 +47,28 @@ watch(isPassing, (val) => {
/* ================= 拖拽逻辑 ================= */
function getEventPageX(e) {
if ('pageX' in e) return e.pageX
if ('touches' in e && e.touches[0]) return e.touches[0].pageX
return 0
if (typeof e.pageX === 'number') return e.pageX
// touchend 事件没有 touches,需要取 changedTouches,否则会误判为拖到 0 而回退
const touch = e.changedTouches?.[0] || e.touches?.[0]
return touch ? touch.pageX : 0
}
/**
* 拖拽中把 move 事件挂到 document 上:
* 只挂在组件根节点时,鼠标移出组件后收不到 mousemove,滑块会卡在原地。
*/
function bindDragEvents() {
document.addEventListener('mousemove', handleDragMoving)
document.addEventListener('touchmove', handleDragMoving, { passive: false })
document.body.style.userSelect = 'none'
document.body.style.cursor = 'grabbing'
}
function unbindDragEvents() {
document.removeEventListener('mousemove', handleDragMoving)
document.removeEventListener('touchmove', handleDragMoving)
document.body.style.userSelect = ''
document.body.style.cursor = ''
}
function getOffset() {
@@ -64,15 +83,18 @@ function getOffset() {
function handleDragStart(e) {
if (isPassing.value || props.disabled) return
if (e.cancelable && e.type !== 'touchstart') e.preventDefault() // 阻止拖拽时选中文本
moveStartX.value = getEventPageX(e)
const currentLeft = Number.parseInt(actionLeft.value || '0', 10)
moveDistance.value = moveStartX.value - currentLeft
isMoving.value = true
bindDragEvents()
emit('start', e)
}
function handleDragMoving(e) {
if (!isMoving.value || isPassing.value) return
if (e.cancelable) e.preventDefault() // 移动端阻止页面跟随滚动
const action = actionRef.value
const bar = barRef.value
if (!action || !bar) return
@@ -103,6 +125,7 @@ function onDocumentMouseUp(e) {
function handleDragEnd(e) {
if (!isMoving.value || isPassing.value) return
unbindDragEvents()
emit('end', e)
const action = actionRef.value
const bar = barRef.value
@@ -123,12 +146,14 @@ function handleDragEnd(e) {
}
function checkPass() {
unbindDragEvents()
isPassing.value = true
isMoving.value = false
emit('update:modelValue', true)
}
function resume() {
unbindDragEvents()
isMoving.value = false
isPassing.value = false
moveDistance.value = 0
@@ -144,14 +169,23 @@ function resume() {
})
}
// 鼠标在窗口外松开 / 切换窗口时收不到 mouseup,兜底取消拖拽,避免一直跟随鼠标
function onWindowBlur() {
if (!isMoving.value) return
resume()
}
onMounted(() => {
document.addEventListener('mouseup', onDocumentMouseUp)
document.addEventListener('touchend', onDocumentMouseUp)
window.addEventListener('blur', onWindowBlur)
})
onBeforeUnmount(() => {
unbindDragEvents()
document.removeEventListener('mouseup', onDocumentMouseUp)
document.removeEventListener('touchend', onDocumentMouseUp)
window.removeEventListener('blur', onWindowBlur)
})
defineExpose({ resume })
@@ -162,8 +196,6 @@ defineExpose({ resume })
ref="wrapperRef"
class="scaptcha"
:class="{ 'scaptcha--disabled': disabled, 'scaptcha--passed': isPassing }"
@mousemove="handleDragMoving"
@touchmove="handleDragMoving"
>
<!-- 进度条 -->
<div
@@ -271,6 +303,7 @@ defineExpose({ resume })
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
color: var(--fms-text-secondary);
cursor: grab;
touch-action: none; /* 移动端禁止手势接管滑动 */
transition: box-shadow 150ms ease, color 200ms ease;
z-index: 1;
}