<template>
|
<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.diskMaterial || '-'" />
|
<wd-cell title="批次号" :value="data.batchNo || data.batchCode || '-'" />
|
<wd-cell title="规格型号" :value="data.model || '-'" />
|
<wd-cell title="盘号" :value="data.monofilamentNumber || '-'" />
|
<wd-cell title="数量" :value="formatAmount" />
|
<wd-cell title="重量" :value="formatWeight" />
|
<wd-cell title="厂家" :value="data.supplier || '-'" />
|
</wd-cell-group>
|
</wd-card>
|
</view>
|
<view class="swipe-delete" @click="handleDelete">
|
<text class="delete-text">删除</text>
|
</view>
|
</view>
|
</template>
|
|
<script setup lang="ts">
|
import { ref, computed } 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 formatAmount = computed(() => {
|
const val = props.data.amount;
|
if (val === undefined || val === null || val === "") return "-";
|
return `${val} ${props.data.unit || ""}`;
|
});
|
|
const formatWeight = computed(() => {
|
const val = props.data.weight;
|
if (val === undefined || val === null || val === "") return "-";
|
const unit = props.data.weightUnit || "kg";
|
return `${val} ${unit}`;
|
});
|
|
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>
|
.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>
|