| | |
| | | <template> |
| | | <wd-card> |
| | | <wd-cell-group :border="true"> |
| | | <wd-cell title="单丝编号" :value="data.monofilamentNumber" /> |
| | | <wd-cell title="理论长度" :value="data.amount + ' (m)'" /> |
| | | <wd-cell title="生产长度" :value="data.actuallyLength + ' (m)'" /> |
| | | <wd-cell title="重量" :value="data.actuallyWeight + ' (kg)'" /> |
| | | </wd-cell-group> |
| | | </wd-card> |
| | | <view class="swipe-container"> |
| | | <view |
| | | class="swipe-content" |
| | | :style="{ transform: `translateX(${translateX}px)` }" |
| | | @touchstart="handleTouchStart" |
| | | @touchmove="handleTouchMove" |
| | | @touchend="handleTouchEnd" |
| | | > |
| | | <wd-card> |
| | | <wd-cell-group :border="true"> |
| | | <wd-cell title="单丝编号" :value="data.monofilamentNumber" /> |
| | | <wd-cell title="理论长度" :value="data.amount + ' (m)'" /> |
| | | <wd-cell title="生产长度" :value="data.actuallyLength + ' (m)'" /> |
| | | <wd-cell title="重量" :value="data.actuallyWeight + ' (kg)'" /> |
| | | </wd-cell-group> |
| | | </wd-card> |
| | | </view> |
| | | <view class="swipe-delete" @click="handleDelete"> |
| | | <text class="delete-text">删除</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | defineProps({ |
| | | import { ref } from "vue"; |
| | | |
| | | const props = defineProps({ |
| | | data: { |
| | | type: Object, |
| | | default: () => {}, |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(["delete", "swipe-open"]); |
| | | |
| | | const translateX = ref(0); |
| | | const startX = ref(0); |
| | | const startY = ref(0); |
| | | const currentX = ref(0); |
| | | const isSwipeOpen = ref(false); |
| | | const deleteWidth = 80; // 删除按钮宽度 |
| | | const isHorizontalSwipe = ref(false); |
| | | |
| | | const handleTouchStart = (e: any) => { |
| | | startX.value = e.touches[0].clientX; |
| | | startY.value = e.touches[0].clientY; |
| | | currentX.value = translateX.value; |
| | | isHorizontalSwipe.value = false; |
| | | }; |
| | | |
| | | const handleTouchMove = (e: any) => { |
| | | const moveX = e.touches[0].clientX - startX.value; |
| | | const moveY = e.touches[0].clientY - startY.value; |
| | | |
| | | // 判断是否为水平滑动(水平移动距离大于垂直移动距离) |
| | | if (!isHorizontalSwipe.value && Math.abs(moveX) > Math.abs(moveY) && Math.abs(moveX) > 10) { |
| | | isHorizontalSwipe.value = true; |
| | | } |
| | | |
| | | // 只有水平滑动时才处理删除滑动 |
| | | if (isHorizontalSwipe.value) { |
| | | e.stopPropagation(); |
| | | const newTranslateX = currentX.value + moveX; |
| | | |
| | | // 限制滑动范围:只能向左滑动,最大滑动距离为删除按钮宽度 |
| | | if (newTranslateX <= 0 && newTranslateX >= -deleteWidth) { |
| | | translateX.value = newTranslateX; |
| | | } else if (newTranslateX < -deleteWidth) { |
| | | translateX.value = -deleteWidth; |
| | | } else if (newTranslateX > 0) { |
| | | translateX.value = 0; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleTouchEnd = (e: any) => { |
| | | // 只有水平滑动时才处理结束逻辑 |
| | | if (isHorizontalSwipe.value) { |
| | | e.stopPropagation(); |
| | | // 判断是否应该打开或关闭删除按钮 |
| | | if (translateX.value < -deleteWidth / 2) { |
| | | // 滑动超过一半,打开删除按钮 |
| | | translateX.value = -deleteWidth; |
| | | isSwipeOpen.value = true; |
| | | emit("swipe-open", props.data); |
| | | } else { |
| | | // 滑动不足一半,关闭删除按钮 |
| | | translateX.value = 0; |
| | | isSwipeOpen.value = false; |
| | | } |
| | | } |
| | | isHorizontalSwipe.value = false; |
| | | }; |
| | | |
| | | const handleDelete = () => { |
| | | // 先关闭滑动 |
| | | translateX.value = 0; |
| | | isSwipeOpen.value = false; |
| | | emit("delete", props.data); |
| | | }; |
| | | |
| | | // 关闭滑动的方法,供外部调用 |
| | | const closeSwipe = () => { |
| | | if (isSwipeOpen.value) { |
| | | translateX.value = 0; |
| | | isSwipeOpen.value = false; |
| | | } |
| | | }; |
| | | |
| | | // 暴露方法供父组件调用 |
| | | defineExpose({ |
| | | closeSwipe, |
| | | isSwipeOpen, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| | | <style lang="scss" scoped> |
| | | .swipe-container { |
| | | position: relative; |
| | | overflow: hidden; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .swipe-content { |
| | | position: relative; |
| | | transition: transform 0.3s ease; |
| | | z-index: 2; |
| | | background: #fff; |
| | | touch-action: pan-y; |
| | | } |
| | | |
| | | .swipe-delete { |
| | | position: absolute; |
| | | right: 0; |
| | | top: 12px; |
| | | bottom: 12px; |
| | | width: 80px; |
| | | background: #ff4444; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | z-index: 1; |
| | | border-radius: 4px; |
| | | box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.05); |
| | | |
| | | .delete-text { |
| | | color: #fff; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | </style> |