Files
client-web/src/modules/overseas-warehouse/components/TransferPaneDivider.vue
T
2026-10-20 11:54:44 +08:00

53 lines
2.5 KiB
Vue

<script setup lang="ts">
const props = defineProps<{ modelValue: number }>()
const emit = defineEmits<{ 'update:modelValue': [value: number] }>()
let drag: { pointerId: number; startX: number; startValue: number; width: number } | null = null
function resize(value: number) {
emit('update:modelValue', Math.min(65, Math.max(35, value)))
}
function startDrag(event: PointerEvent) {
if (event.button !== 0 || !event.isPrimary) return
const handle = event.currentTarget as HTMLElement
const width = (handle.parentElement?.getBoundingClientRect().width ?? 0) - 16
if (width <= 0) return
event.preventDefault()
handle.focus()
drag = { pointerId: event.pointerId, startX: event.clientX, startValue: props.modelValue, width }
handle.setPointerCapture(event.pointerId)
}
function moveDrag(event: PointerEvent) {
if (!drag || drag.pointerId !== event.pointerId) return
resize(drag.startValue + (event.clientX - drag.startX) / drag.width * 100)
}
function endDrag(event: PointerEvent) {
if (drag?.pointerId !== event.pointerId) return
drag = null
const handle = event.currentTarget as HTMLElement
if (handle.hasPointerCapture(event.pointerId)) handle.releasePointerCapture(event.pointerId)
}
function keyResize(event: KeyboardEvent) {
const value = { ArrowLeft: props.modelValue - 2, ArrowRight: props.modelValue + 2, Home: 35, End: 65, Enter: 43 }[event.key]
if (value === undefined) return
event.preventDefault()
resize(value)
}
</script>
<template>
<div class="transfer-pane-divider" role="separator" tabindex="0" aria-label="调整转运信息和换标申请宽度"
aria-orientation="vertical" :aria-valuenow="Math.round(modelValue)" :aria-valuemin="35" :aria-valuemax="65"
aria-controls="transfer-main-pane transfer-relabel-pane" title="左右拖动调整宽度,双击恢复"
@pointerdown="startDrag" @pointermove="moveDrag" @pointerup="endDrag" @pointercancel="endDrag"
@lostpointercapture="drag = null" @keydown="keyResize" @dblclick="resize(43)">
<span aria-hidden="true" />
</div>
</template>
<style scoped>
.transfer-pane-divider { display:flex; width:16px; align-items:center; justify-content:center; align-self:stretch; cursor:col-resize; touch-action:none; user-select:none; outline:none; }
.transfer-pane-divider span { width:4px; height:64px; border-radius:4px; background:#c5d1e1; transition:background .15s; }
.transfer-pane-divider:hover, .transfer-pane-divider:focus-visible { background:#e9f1ff; border-radius:6px; }
.transfer-pane-divider:hover span, .transfer-pane-divider:focus-visible span { background:#3478c8; }
</style>