spring
2025-11-19 af4f45eaa2703ecf991bd10f07f6df179f2677d9
src/pages/production/twist/components/MonofilCard.vue
@@ -1,21 +1,153 @@
<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>