一、效果
【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)
},
},
})
|