uniapp:聊天消息列表(好友列表+私人单聊)支持App、H5、小程序

  

  

🎬 江城开朗的豌豆:个人主页

 🔥 个人专栏 :《 VUE 》 《 javaScript 》

 📝 个人网站 :《 江城开朗的豌豆🫛 》 

⛺️ 生活的理想,就是为了理想的生活 !

在这里插入图片描述

目录

 ⭐  文章简介(效果图展示)        

  📟 插件传送门:聊天消息列表

 📘  文章背景

  📘 平台兼容性

 📘  功能实现

废话不说直接上代码

 📟 用户列表完整代码

 📟 单人对话框 完整代码 

🔥 文章总结

📟 隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:


 ⭐  文章简介(效果图展示)

      在现代社交互动中,聊天消息列表是应用程序中的关键组成部分。它不仅仅是一种通信工具,更是人们日常生活中连接感情、分享信息的重要方式之一。随着移动互联网的发展,用户在不同平台上(如App、H5、小程序等)进行聊天的需求也愈发增加。因此,设计并实现一个支持多平台、多种形式的聊天消息列表成为了开发者们的挑战之一。

        

    📟 插件传送门:聊天消息列表

 📘  文章背景

        

       最近我专注于优化我们聊天消息列表的交互体验。现在,我们的消息列表页面上有多个标签,每个标签对应着不同的聊天会话。当用户点击某个标签时,页面会流畅地滚动到相应的聊天记录位置,这样用户就可以更方便地查看他们感兴趣的对话内容。

      今天下午,我花了些时间在消息列表的交互功能上进行调整和改进。经过一番努力,我成功地实现了这一功能!在这个过程中,我逐步解决了各种技术挑战,体验着一个个问题被一一击破的成就感。这种改进用户体验的过程真是让人感到无比满足!

  📘 平台兼容性

Vue2Vue3
App快应用微信小程序支付宝小程序百度小程序字节小程序QQ小程序
HBuilderX 3.6.11 app-vue app-nvue
钉钉小程序快手小程序飞书小程序京东小程序
H5-SafariAndroid Browser微信浏览器(Android)QQ浏览器(Android)ChromeIEEdgeFirefoxPC-Safari

 📘  功能实现

废话不说直接上代码

 📟 用户列表完整代码

<template>	<view class="page">		<view class="list-item" v-for="(item,index) in users" :key="index" @click="connect(item)">			<view class="avatar">				<text class="round" v-if="item.read"></text>				<image :src="item.avatar" mode="widthFix"></image>			</view>			<view class="content">				<view class="title">					<text class="name">{{ item.name }}</text>					<text class="time">{{ item.time }}</text>				</view>				<view class="txt">{{ item.msg }}</view>			</view>		</view>	</view></template><script>	export default {		data() {			return {				options: [{					text: '取消',					style: {						backgroundColor: '#007aff'					}				}, {					text: '确认',					style: {						backgroundColor: '#dd524d'					}				}],				users: [{						avatar: '/static/avatar/avatar1.png',						name: '杨涛',						read: 1,						time: '23:59',						msg: '没有消息就是最好的消息'					},					{						avatar: '/static/avatar/avatar2.jpg',						name: '雨中漫步',						read: 1,						time: '23:59',						msg: '没有消息就是最好的消息'					},					{						avatar: '/static/avatar/avatar3.jpeg',						name: '糖果梦境',						read: 1,						time: '23:59',						msg: '没有消息就是最好的消息'					},					{						avatar: '/static/avatar/avatar4.png',						name: '海上日落',						read: 1,						time: '23:59',						msg: '没有消息就是最好的消息'					},					{						avatar: '/static/avatar/avatar6.png',						name: '男朋友',						read: 1,						time: '23:59',						msg: '没有消息就是最好的消息'					},					{						avatar: '/static/avatar/avatar8.png',						name: '女朋友',						read: 1,						time: '23:59',						msg: '没有消息就是最好的消息'					},					{						avatar: '/static/avatar/avatar5.jpeg',						name: '静谧之夜',						read: 1,						time: '23:59',						msg: '没有消息就是最好的消息'					},					{						avatar: '/static/avatar/avatar1.png',						name: '风吹麦浪',						read: 0,						time: '23:59',						msg: '没有消息就是最好的消息'					},					{						avatar: '/static/avatar/avatar1.png',						name: '路过岁月',						read: 0,						time: '23:59',						msg: '没有消息就是最好的消息'					},					{						avatar: '/static/avatar/avatar1.png',						name: '繁星点点',						read: 0,						time: '23:59',						msg: '没有消息就是最好的消息'					}				]			};		},		methods: {			onClick(e) {				console.log('点击了' + (e.position === 'left' ? '左侧' : '右侧') + e.content.text + '按钮')			},			swipeChange(e, index) {				console.log('当前状态:' + e + ',下标:' + index)			},			connect(item) {				uni.navigateTo({					url: `/pages/message/message?name=${item.name}&avatar=${item.avatar}`				})			}		}	}</script><style lang="scss" scoped>	.page {		padding: 0 32rpx;		color: #333;	}	.list-item {		display: flex;		padding: 30rpx 0;		border-bottom: 1px solid #ccced3;		.avatar {			width: 90rpx;			height: 90rpx;			border-radius: 10rpx;			margin-right: 20rpx;			position: relative;			.round {				position: absolute;				width: 14rpx;				height: 14rpx;				border-radius: 50%;				background: #ef5656;				top: -4rpx;				right: -4rpx;				z-index: 1;			}			image {				width: 100%;				height: 100%;				border-radius: 10rpx;			}		}		.content {			flex: 1;			.title {				display: flex;				justify-content: space-between;				.name {					font-weight: bold;				}				.time {					color: #999;					font-size: 24rpx;				}			}			.txt {				margin-top: 10rpx;				overflow: hidden;				text-overflow: ellipsis;				display: -webkit-box;				-webkit-line-clamp: 1;				-webkit-box-orient: vertical;				text-align: left;				color: #999;				font-size: 26rpx;			}		}	}</style>
 📟 单人对话框 完整代码

<template>	<view class="page">		<scroll-view class="scroll-view" scroll-y scroll-with-animation :scroll-top="top">			<view style="padding: 30rpx 30rpx 240rpx;">				<view class="message" :class="[item.userType]" v-for="(item,index) in list" :key="index">					<image :src="item.avatar" v-if="item.userType === 'friend'" class="avatar" mode="widthFix"></image>					<view class="content" v-if="item.messageType === 'image'">						<image :src="item.content" mode="widthFix"></image>					</view>					<view class="content" v-else>						{{ item.content }}					</view>					<image :src="item.avatar" v-if="item.userType === 'self'" class="avatar" mode="widthFix"></image>				</view>			</view>		</scroll-view>		<view class="tool">			<input type="text" v-model="content" class="input" @confirm="send" />			<image src="/static/photo.png" mode="widthFix" class="thumb" @click="chooseImage"></image>		</view>	</view></template><script>	export default {		data() {			return {				content: '',				list: [],				top: 0			};		},		onLoad(options) {			uni.setNavigationBarTitle({				title: options.name			})			this._friendAvatar = options.avatar			this._selfAvatar = '/static/avatar/avatar5.jpeg'			this.list = [				{					content: '对方历史回复消息',					userType: 'friend',					avatar: this._friendAvatar				},				{					content: '历史消息',					userType: 'self',					avatar: this._selfAvatar				}			]		},		methods: {			send() {				this.list.push({					content: this.content,					userType: 'self',					avatar: this._selfAvatar				})				this.content = ''				this.scrollToBottom()				// 模拟对方回复				setTimeout(()=>{					this.list.push({						content: '周末什么安排',						userType: 'friend',						avatar: this._friendAvatar					})					this.scrollToBottom()				}, 1500)			},			chooseImage() {				uni.chooseImage({					// sourceType: 'album',					success: (res) => {						this.list.push({							content: res.tempFilePaths[0],							userType: 'self',							messageType: 'image',							avatar: this._selfAvatar						})						this.scrollToBottom()						// 模拟对方回复						setTimeout(()=>{							this.list.push({								content: '你好呀,朋友~',								userType: 'friend',								avatar: this._friendAvatar							})							this.scrollToBottom()						}, 1500)					}				})			},			scrollToBottom() {				this.top = this.list.length * 1000			}		}	}</script><style lang="scss" scoped>	.scroll-view {		/* #ifdef H5 */		height: calc(100vh - 44px);		/* #endif */		/* #ifndef H5 */		height: 100vh;		/* #endif */		background: #eee;		box-sizing: border-box;	}	.message {		display: flex;		align-items: flex-start;		margin-bottom: 30rpx;				.avatar {			width: 80rpx;			height: 80rpx;			border-radius: 10rpx;			margin-right: 30rpx;		}		.content {			min-height: 80rpx;			max-width: 60vw;			box-sizing: border-box;			font-size: 28rpx;			line-height: 1.3;			padding: 20rpx;			border-radius: 10rpx;			background: #fff;			image {				width: 200rpx;			}		}		&.self {			justify-content: flex-end;			.avatar {				margin: 0 0 0 30rpx;			}			.content {				position: relative;				&::after {					position: absolute;					content: '';					width: 0;					height: 0;					border: 16rpx solid transparent;					border-left: 16rpx solid #fff;					right: -28rpx;					top: 24rpx;				}			}		}		&.friend {			.content {				position: relative;				&::after {					position: absolute;					content: '';					width: 0;					height: 0;					border: 16rpx solid transparent;					border-right: 16rpx solid #fff;					left: -28rpx;					top: 24rpx;				}			}		}	}	.tool {		position: fixed;		width: 100%;		min-height: 120rpx;		left: 0;		bottom: 0;		background: #fff;		display: flex;		align-items: flex-start;		box-sizing: border-box;		padding: 20rpx 24rpx 20rpx 40rpx;		padding-bottom: calc(20rpx + constant(safe-area-inset-bottom)/2) !important;		padding-bottom: calc(20rpx + env(safe-area-inset-bottom)/2) !important;		.input {			background: #eee;			border-radius: 10rpx;			height: 70rpx;			margin-right: 30rpx;			flex: 1;			padding: 0 20rpx;			box-sizing: border-box;			font-size: 28rpx;		}		.thumb {			width: 64rpx;		}	}</style>

 

🔥 文章总结

📟 隐私、权限声明

         如说明表达还不够清楚,不清楚怎么使用可导入完整示例项目运行体验和希望对大家有帮助!

1. 本插件需要申请的系统权限列表:

无,开箱即用

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

没有任何广告,纯分享,方便自己,同时也方便其他能用的的前端好朋友

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

使用插件有任何问题欢迎加入QQ讨论群:

作者QQ群:906392632(未满)

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!



来源:春哥技术博客,欢迎分享,转载请注明出处。(欢迎加春哥团队客服微信号:taike668)

本文地址:https://www.cgtblog.com/cgymlt/11236.html
上一篇:农场管理小程序|基于微信小程序的农场      下一篇:跑腿小程序|基于微信小程序的跑腿平台