2025-06-30 09:38:03 +08:00

272 lines
6.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="swipe-item-v">
<view class="list">
<view v-for="(item, index) in list" :key="index" class="list-item" @click="clickItem(item)">
<view class="swipe-container">
<view class="content-wrapper" :style="{ transform: `translateX(${item.offsetX}px)` }"
@touchstart="!disabled && handleTouchStart($event, index)"
@touchmove="!disabled && handleTouchMove($event, index)"
@touchend="!disabled && handleTouchEnd(index)">
<view class="item-content">
{{ item.title }}
</view>
</view>
<view class="action-buttons">
<view v-for="(btn, btnIndex) in buttons" :key="btnIndex" class="btn" :style="{
background: btn.backgroundColor,
opacity: disabled ? 0.5 : 1
}" @tap="!disabled && handleButtonClick(btn.action, index)">
<text class="btn-text">{{ btn.text }}</text>
<text class="iconfont" :class="btn.icon"></text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
disabled: false, // 添加禁用状态控制
actionWidth: 160, // 操作按钮总宽度
list: [{
id: 1,
title: '列表项 1',
offsetX: 0,
startX: 0,
startY: 0,
isHorizontal: false
},
{
id: 2,
title: '列表项 2',
offsetX: 0,
startX: 0,
startY: 0,
isHorizontal: false
},
{
id: 3,
title: '列表项 3',
offsetX: 0,
startX: 0,
startY: 0,
isHorizontal: false
},
],
buttons: [{
text: '编辑',
icon: 'icon-edit',
action: 'edit',
backgroundColor: '#007aff' // 添加背景色配置
}, {
text: '删除此项内容',
icon: 'icon-delete',
action: 'delete',
backgroundColor: '#55ff00' // 添加背景色配置
}],
currentOpenIndex: -1 // 当前打开的item索引
}
},
watch: {
// 监听按钮数据变化,重新计算宽度
buttons: {
handler() {
this.calculateActionWidth();
},
deep: true
}
},
onLoad() {
// 组件创建时计算操作按钮总宽度
this.calculateActionWidth();
},
methods: {
// 添加禁用/启用方法
setDisabled(status) {
this.disabled = status;
// 如果禁用,关闭所有已打开的滑动
if (status && this.currentOpenIndex !== -1) {
this.list[this.currentOpenIndex].offsetX = 0;
this.currentOpenIndex = -1;
}
},
// 计算操作按钮总宽度
calculateActionWidth() {
// 根据按钮数量动态计算总宽度
const buttonWidth = 160; // 每个按钮宽度
this.actionWidth = this.buttons.length * buttonWidth / 2;
},
// 统一的按钮点击处理方法
handleButtonClick(action, index) {
if (this.disabled) return;
switch (action) {
case 'edit':
this.handleEdit(index);
break;
case 'delete':
this.handleDelete(index);
break;
default:
console.log('未知操作类型');
}
},
clickItem(item) {
console.log(item);
},
// 触摸开始
handleTouchStart(e, index) {
if (this.disabled) return;
const item = this.list[index]
item.startX = e.touches[0].clientX
item.startY = e.touches[0].clientY
item.isHorizontal = false
// 如果点击的不是当前打开的item则关闭已打开的item
if (this.currentOpenIndex !== -1 && this.currentOpenIndex !== index) {
this.list[this.currentOpenIndex].offsetX = 0
this.currentOpenIndex = -1
}
},
// 触摸移动
handleTouchMove(e, index) {
if (this.disabled) return;
const item = this.list[index]
const deltaX = e.touches[0].clientX - item.startX
const deltaY = Math.abs(e.touches[0].clientY - item.startY)
// 方向锁定:优先识别水平滑动
if (!item.isHorizontal) {
if (deltaY > 5) return // 垂直滑动超过5px则放弃处理
if (Math.abs(deltaX) > 5) item.isHorizontal = true
}
if (item.isHorizontal) {
// 只允许左滑(负值)
const validDeltaX = Math.min(0, deltaX)
const maxOffset = -this.actionWidth
item.offsetX = Math.max(maxOffset, validDeltaX)
e.preventDefault()
}
},
// 触摸结束
handleTouchEnd(index) {
if (this.disabled) return;
const item = this.list[index]
const threshold = this.actionWidth * 0.3 // 滑动30%宽度触发
if (item.offsetX <= -threshold) {
item.offsetX = -this.actionWidth
this.currentOpenIndex = index
} else {
item.offsetX = 0
this.currentOpenIndex = -1
}
},
// 编辑按钮点击事件
handleEdit(index) {
uni.showToast({
title: `编辑第${index + 1}`,
icon: 'none'
})
// 操作完成后收起
this.list[index].offsetX = 0
this.currentOpenIndex = -1
},
// 删除按钮点击事件
handleDelete(index) {
uni.showModal({
title: '提示',
content: '确定要删除吗?',
success: (res) => {
if (res.confirm) {
this.list.splice(index, 1)
}
}
})
}
}
}
</script>
<style scoped lang="scss">
.swipe-item-v {
background: #f5f5f5;
min-height: 100vh;
.list {
padding: 20rpx;
.list-item {
margin-bottom: 20rpx;
.swipe-container {
position: relative;
overflow: hidden;
background: #fff;
border-radius: 8rpx;
.content-wrapper {
position: relative;
z-index: 2;
background: inherit;
transition: transform 0.3s ease;
.item-content {
padding: 40rpx;
background: #fff;
}
}
.action-buttons {
position: absolute;
top: 0;
right: 0;
bottom: 0;
display: flex;
width: 320rpx;
/* 增加宽度 */
z-index: 1;
.btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 0 20rpx;
gap: 10rpx;
transition: opacity 0.3s ease;
&.disabled {
opacity: 0.5;
cursor: not-allowed;
}
.btn-text {
color: #fff;
font-size: 28rpx;
text-align: center;
word-break: break-all;
display: -webkit-box;
line-height: 1.3;
}
.iconfont {
color: #fff;
font-size: 32rpx;
}
}
}
}
}
}
}
</style>