[小程序]- 列表左滑置顶删除功能

一、效果

【wxml】

 <view wx:if="{{msgGroup.length > 0}}">
      <message-box pType="im" data="{{item}}" wx:for="{{msgGroup}}" wx:key="{{item.groupID}}" bind:touchS="touchS" bind:touchE="touchE" bind:touchM="touchM" leftRange="{{leftRange}}" startX="{{startX}}" moveX="{{moveX}}" InfoId="{{InfoId}}" />
    </view>

<view class="msg-container">
  <view class="msg-item" bind:tap="onClick" data-path="{{data.uri}}" style="margin-left: {{InfoId == data.conversationID ? '-'+ leftRange +'rpx': '' }}" data-item="{{data}}" bindtouchstart="onClickS" bindtouchmove="onClickM" bindtouchend="onClickE">
    <image class="left-img" src="{{data.image || data.avatar}}" />
    <view class="right-con">
      <view class="top-con">
        <view class="title">{{data.title || data.name}}</view>
        <view class="time" wx:if="{{isShowTime && data.message_time != 0}}">
          {{data.message_time}}
        </view>
        <image class="topStatus" wx:if="{{isShowTime && isPinned}}" src="https://staticscdn.zgzpsjz.com/miniprogram/images/wyl/yupao_mini_icon_up_masa_13x.png" />
      </view>
      <view class="down-con">
        <view class="dtop">{{data.desc}}</view>
        <view class="ddown {{data.show_number > 9 ? 'ddown-more' : ''}}" wx:if="{{pTyoe == 'im' ? isShowTime && data.show_number > 0 && data.groupProfile.selfInfo.messageRemindType != 'discard' : isShowTime && data.show_number > 0}}">
          <text>{{data.show_number > 99 ? '99+' : data.show_number}}</text>
        </view>
        <image class="discardImg" wx:if="{{data.groupProfile.selfInfo.messageRemindType == 'discard'}}" src="https://staticscdn.zgzpsjz.com/miniprogram/images/wyl/yupao_mini_icon_x85rtrx.png" />
      </view>
    </view>
  </view>
  <!-- 这里是左滑按钮部分----start -->
  <view class='isMove' wx:if="{{isShowTime && leftRange && InfoId == data.conversationID}}" bindtap="moveItem" hidden='{{!data.isMove}}'>
    <view class="commonBanner operateTop" catchtap="top">
      <image class="contentImg operateTopImg" src="https://staticscdn.zgzpsjz.com/miniprogram/images/wyl/yupao_mini_icon_xx_sc9trtrx.png" />
      <text class="contentText operateTopText">置顶</text>
    </view>
    <view class="commonBanner operateDel" catchtap="del">
      <image class="contentImg operateDelImg" src="https://staticscdn.zgzpsjz.com/miniprogram/images/wyl/yupao_mini_icon_xx_sc3trtrx.png" />
      <text class="contentText operateDelText">删除聊天</text>
    </view>
  </view>
  <!-- 这里是左滑按钮部分----end -->
</view>

 【less】

.msg-container {
  display: flex;
  flex-direction: row;
  .msg-item {
    width: 750rpx;
    height: 144rpx;
    background-color: #FFF;
    border: 0;
    box-sizing: border-box;
    padding: 24rpx 32rpx;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .left-img {
      display: block;
      width: 96rpx;
      height: 96rpx;
      border-radius: 16rpx;
      object-fit: cover;
    }
    .right-con {
      flex:1;
      height: 96rpx;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      align-items: center;
      margin-left: 24rpx;
      .top-con {
        width: 100%;
        display: flex;
        justify-content: space-between;
        align-items: center;
        position: relative;
        .title {
          flex:1;
          height: 48rpx;
          max-width: 448rpx;
          line-height: 48rpx;
          font-size: 32rpx;
          color: rgba(0, 0, 0, 0.85);
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
          font-weight: bold;
        }
        .time {
          width: 188rpx;
          height: 40rpx;
          line-height: 40rpx;
          font-size: 24rpx;
          color: rgba(0, 0, 0, 0.45);
          text-align: right;
        }
        .topStatus {
          z-index: 99;
          position: absolute;
          right:-32rpx;
          top:-24rpx;
          width: 40rpx;
          height: 40rpx;
        }
      }
      .down-con {
        width: 100%;
        display: flex;
        justify-content: space-between;
        align-items: center;
        .dtop {
          flex:1;
          max-width: 448rpx;
          height: 44rpx;
          line-height: 44rpx;
          font-size: 28rpx;
          color: rgba(0, 0, 0, 0.45);
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
          font-weight: bold;
        }
        .ddown {
          min-width: 30rpx;
          height: 30rpx;
          line-height: 30rpx;
          font-size: 20rpx;
          background-color: #F74742;
          text-align: center;
          border-radius: 50%;
          color: #FFF;
          font-weight: bold;
          margin-right: 4rpx;
        }
        .ddown-more {
          border-radius: 30rpx;
          padding: 0rpx 8rpx;
        }
        .discardImg {
          width: 48rpx;
          height: 48rpx;
        }
      }
    }
  }
  .isMove {
    max-width: 288rpx;
    height: 144rpx;
    display: flex;
    justify-content: flex-start;
    .commonBanner {
      position: relative;
      width: 144rpx;
      height: 100%;
      background-color: #0092FF;
      color: rgba(255, 255, 255, 0.95);
      .contentImg {
        position: absolute;
        top: 32rpx;
        left: 48rpx;
        width: 48rpx;
        height: 48rpx;
      }
      .contentText {
        position: absolute;
        bottom: 14rpx;
        left: 0rpx;
        font-size: 24rpx;
        height: 40rpx;
        line-height: 40rx;
        width: 144rpx ;
        text-align: center;
      }
    }
    .operateTop {
      background-color: #0092FF;
    }
    .operatehaveTop {
      background-color: #8796A2;
    }
    .operateDel {
      background-color: #F74742;
    }
  }
}

【父组件ts】


import { MapStateToData, connectPage } from '@/store/index'
import { dateTransformation, msgTypeTransformation } from './utils'

const mapStateToData: MapStateToData = () => {
  return {}
}

Page(
  connectPage(mapStateToData)({
    /** 页面的初始数据 */
    data: {
      topGroup: [],
      suggestGroup: [],
      systemGroup: [],
      msgGroup: [],
      leftRange: 0, // 移动的范围
      startX: 0, // 首次点击的位置
      moveX: 0, // 滑动时的距离
      InfoId: '',
    },

    /** 初始化获取数据 */
    async initData() {
      const res = await wx.$.fetch['GET/message/message/messageIconList']()
      const topList = res.data?.tops
      let newTopList = []
      if (topList?.length > 0) {
        newTopList = topList.map((item: any) => {
          return { ...item, message_time: dateTransformation(item?.message_time) }
        })
      }

      // 请求IM消息列表的接口
      wx.$.tim
        .getConversationList()
        .then((imResponse) => {
          if (imResponse.data.conversationList) {
            let newConversationList = []
            newConversationList = imResponse.data.conversationList?.map((item: any) => {
              return { ...item, message_time: dateTransformation(item?.lastMessage?.lastTime), desc: msgTypeTransformation(item?.lastMessage) }
            })
            this.setData({
              msgGroup: newConversationList,
            })
            console.log(this.data.msgGroup) // 群组列表
          }
        })
        .catch((imError) => {
          console.warn('getGroupList error:', imError) // 获取群组列表失败的相关信息
        })

      this.setData({
        topGroup: res.data?.lists,
        suggestGroup: res.data?.suggest,
        systemGroup: newTopList,
      })
    },

    /** 生命周期函数--监听页面加载 */
    onLoad() {},

    /** 生命周期函数--监听页面显示 */
    onShow() {
      this.initData()
    },

    // 左滑删除
    touchS(el) {
      const e = el.detail.element
      const { item } = el.detail
      // 更新初始值
      this.setData({
        leftRange: 0,
      })
      // startX记录开始移动的位置
      if (e.touches.length === 1) {
        this.setData({
          startX: e.touches[0].clientX,
        })
      }
      // 移动列表某个 防止v-for循环整体循环
      this.setData({
        InfoId: item.conversationID,
      })
    },
    touchM(el) {
      const e = el.detail
      // 滑动时判断是否为初始值
      if (this.data.leftRange === 375) {
        return
      }
      if (e.touches.length === 1) {
        // 手指移动时水平方向位置
        this.setData({
          moveX: e.touches[0].clientX,
        })
        // 判断移动的距离是变大变小 变大便是右移
        if (this.data.startX < this.data.moveX) {
          // 更改移动时的距离。防止弹出删除按钮
          this.setData({
            moveX: 0,
          })
        } else {
          // 移动的距离 加 20 如需调整 可以调整这里
          this.setData({
            leftRange: 288,
          })
        }
      }
    },
    touchE() {
      // 如果滑动的距离大于45  则直接弹出删除按钮
      if (this.data.moveX > 45) {
        this.setData({
          leftRange: 288,
        })
      }
      // 松开后刷新 滑动的距离
      this.setData({
        moveX: 0,
      })
    },

    
  }),
)

Component({
  properties: {
    /** 组件用途类型 */
    pType: {
      type: String,
      value: 'common',
    },
    /** 父组件传的:文字,图片等 */
    data: {
      type: Object,
    },
    /** 是否显示时间 */
    isShowTime: {
      type: Boolean,
      value: true,
    },
    onClickCon: {
      type: Function,
    },
    /** 移动的距离 */
    leftRange: {
      type: Number,
      value: 0,
    },
    /** 移动的距离 */
    InfoId: {
      type: String || Number,
      value: '',
    },
  },
  methods: {
    onClick(e) {
      this.triggerEvent('click', { path: e.currentTarget.dataset.path })
    },
    onClickS(element) {
      const { item } = element.currentTarget.dataset
      this.triggerEvent('touchS', { element, item })
    },
    onClickM(e) {
      this.triggerEvent('touchM', e)
    },
    onClickE(e) {
      this.triggerEvent('touchE', e)
    },
  },
})

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值