• 微信小程序| 用小程序复刻微信Wechat


    📌个人主页个人主页
    ​🧀 推荐专栏小程序开发成神之路 --【这是一个为想要入门和进阶小程序开发专门开启的精品专栏!从个人到商业的全套开发教程,实打实的干货分享,确定不来看看? 😻😻】
    📝作者简介从web开发,再到大数据算法,踩过了无数的坑,用心总结经验教训,助你在技术生涯一臂之力!若想获取更多精彩内容,敬请订阅专栏或者关注😁😂🤣😃😆😉😊😋😍😘🥰
    ⭐️您的小小关注是我持续输出的动力!⭐️


    干货内容推荐

    🥇入门和进阶小程序开发,不可错误的精彩内容🥇 :



    效果预览

    在这里插入图片描述


    一、需求背景

    微信作为熟人社交领域类的顶流。其中有非常多的功能值得借鉴和推敲。其中的用户聊天界面联系人界面特别是朋友圈界面妥妥是进行社交类应用开发的参考和借鉴的典范!

    特此,本文整理了基于vue 2.0语法,结合uniapp框架,从而实现了可覆盖到移动全端的功能。同时使用了小程序端优秀的UI组件库uVIew进行构建,使得开发的成本更低,效果更好。


    二、功能剖析

    2.1 聊天列表

    2.1.1 效果展示

    在这里插入图片描述

    2.1.2 源码解析
    • 在联系人聊天记录条中,使用了uView中的u-swipe-action组件,使得消息具备了滑动展示菜单操作的功能。
    <u-swipe-action :show="item.show" :index="index" v-for="(item, index) in list" btn-width="160" :key="item.id" @click="click" @open="open" :options="options">
    			<view class="item" :class="item.isTop ? 'bg_view' : ''" hover-class="message-hover-class" @tap="linkTo(item)">
    				<image mode="aspectFill" :src="item.images" />
    				
    				<view class="right u-border-bottom title-wrap">
    					<view class="right_top">
    						<view class="right_top_name u-line-1">{{ item.name }}view>
    						<view class="right_top_time ">{{ item.updateTime }}view>
    					view>
    					<view class="right_btm ">
    						<view class="u-line-1">-view>
    						<view class="">view>
    					view>
    				view>
    			view>
    		u-swipe-action>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.2 聊天列表

    2.2.1 效果展示

    在这里插入图片描述

    2.2.2 源码解析
    • 在该聊天界面中,集成进了语音聊天功能,其中通过监听录音设备和用户点击录音按钮的时间长短来动态生成录音内容的大小,并将其转为mp3文件数据进行传输。
    //处理录音文件
    		handleRecorder({ tempFilePath,duration }) {
    			let contentDuration;
    			// #ifdef MP-WEIXIN
    			this.voiceTime = 0;
    			if (duration < 600) {
    				this.voiceIconText="说话时间过短";
    				setTimeout(()=>{
    					this.recording = false;
    				},200)
    				return;
    			} 
    			contentDuration = duration/1000;
    			// #endif
    			
    			// #ifdef APP-PLUS
    			contentDuration = this.voiceTime +1;
    			this.voiceTime = 0;
    			if(contentDuration <= 0) {
    				this.voiceIconText="说话时间过短";
    				setTimeout(()=>{
    					this.recording = false;
    				},200)
    				return;
    			};
    			// #endif
    			
    			this.recording = false;
    			const params = {
    				contentType: 2,
    				content: tempFilePath,
    				contentDuration: Math.ceil(contentDuration)
    			};
    			this.canSend && this.sendMsg(params);
    		},
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    2.3 朋友圈界面

    2.3.1 效果展示

    在这里插入图片描述

    2.3.2 源码解析
    • 针对用户所发的朋友圈信息,根据信息的类型:图片或者文字信息,需要根据类型进行不同的排版。针对点赞的列表需要根据用户的点赞时间进行按需排列。
    <template>
    	<view class="content" id="content">
    		
    		<u-navbar title=" " :background="{ background: '#f8f8f8' }" :border-bottom="false">
    			<view class="slot-wrap" slot="right"><u-icon name="camera-fill" size="36" @click="linkToRelease">u-icon>view>
    		u-navbar>
    		
    		<view class="content-imgbox">
    			<image class="bgimg" :src="_user_info.pictureBanner" mode="scaleToFill" @tap="showSheet">image>
    			<image class="headimg" :src="_user_info.headImg" @tap="linkToBusinessCard(_user_info.id)">image>
    			<text class="nickname">{{ _user_info.userName }}text>
    		view>
    		<view class="signature">
    			<view class="">{{ _user_info.signature }}view>
    		view>
    
    		
    		<view class="content-circle">
    			<view class="content-circle-box" v-for="(item, index) in circleData" :key="item.circleMegId">
    				<view class="headimg"><image class="img" :src="item.userHeadImg" @tap="linkToBusinessCard(item.userId)">image>view>
    				<view class="content">
    					<view class="content-name" @tap="linkToBusinessCard(item.userId)">{{ item.userName }}view>
    					<view class="content-desc">{{ item.content }}view>
    					<view class="content-img" v-if="item.imageList.length">
    						
    						<view v-if="item.imageList.length == 1"><image class="img-1" :src="item.imageList[0]" mode="widthFix" @tap="previewImg(0, item.imageList)">image>view>
    						
    						<view v-else-if="item.imageList.length > 1">
    							<view class="content-img-more">
    								<image
    									class="img-more"
    									v-for="(src, index) in item.imageList"
    									:key="index"
    									:class="index % 3 == 0 && 'img-3'"
    									:src="src"
    									mode="aspectFill"
    									@tap="previewImg(index, item.imageList)"
    								>image>
    							view>
    						view>
    					view>
    					
    					<view class="relavivetime" :id="`comment-${'null'}-${index}`">
    						<view class="time">{{ item.createTime }}view>
    						<view class="icon-box">
    							<view @tap="clickThumb(item)">
    								<image class="img icon-box-item thumb" :src="item.isPraise ? require('@/static/like-fill.png') : require('@/static/like.png')" mode="">image>
    							view>
    							<view @tap="handleComment(item.circleMegId, null, index)">
    								<image class="img icon-box-item" :src="require('@/static/comment.png')" mode="">image>
    							view>
    						view>
    					view>
    					
    					<view class="msg-box">
    						<view class="thumbinfo" v-if="item.praise.length">
    							<image class="thumbinfo-icon" :src="require('@/static/like.png')">image>
    							<text class="thumbinfo-name" v-for="(userInfo, index) in item.praise" :key="userInfo.id" @tap="linkToBusinessCard(userInfo.id)">
    								{{ userInfo.userName }}{{ index != item.praise.length - 1 ? ',' : '' }}
    							text>
    						view>
    						<view class="comment" v-if="item.comment.length">
    							<view
    								class="comment-box"
    								v-for="(comment, index) in item.comment"
    								:key="index"
    								hover-class="comment-hover-class"
    								:id="`comment-${item.circleMegId}-${index}`"
    								@tap="handleComment(item.circleMegId, comment, index)"
    							>
    								<text class="comment-box-name" v-if="!comment.replyUserId" @tap.stop="linkToBusinessCard(comment.userId)">{{ comment.userName }}:text>
    								<text class="comment-box-name" v-if="comment.replyUserId" @tap.stop="linkToBusinessCard(comment.userId)">
    									{{ comment.userName }}
    									<text class="callback">回复text>
    								text>
    								<text v-if="comment.replyUserId" class="comment-box-name" @tap.stop="linkToBusinessCard(comment.replyUserId)">{{ comment.replyUserName }}:text>
    								<text class="comment-box-content">{{ comment.content }}text>
    							view>
    						view>
    					view>
    				view>
    			view>
    			
    			<view :style="{ height: showInput ? '100rpx' : 0 }">view>
    			
    			
    			<view v-show="showInput" :style="{ height: viewOffsetBottom + 'px' }">view>
    			
    		view>
    
    		
    		
    		<view class="input-box" v-if="showInput" id="input-box" :style="{ bottom: inputOffsetBottom > 0 ? inputOffsetBottom + 'px' : '0' }">
    		
    		
    		<view class="input-box" v-show="showInput" id="input-box" :style="{ bottom: inputOffsetBottom > 0 ? inputOffsetBottom + 'px' : '0' }">
    		
    			<view class="input-box-flex">
    				<view class="input-box-flex-grow">
    					<input
    						type="text"
    						class="content"
    						id="input"
    						v-model="content"
    						:adjust-position="false"
    						:confirm-type="'send'"
    						:confirm-hold="true"
    						placeholder-style="color:#DDD;"
    						:cursor-spacing="6"
    						:placeholder="placeholder"
    						:focus="showInput"
    						@blur="blurInput"
    						@confirm="sendMsg"
    					/>
    				view>
    				<button class="btn" type="primary" size="mini" @touchend.prevent="sendMsg">发送button>
    			view>
    		view>
    
    		<u-action-sheet :list="list" v-model="show" border-radius="25" safe-area-inset-bottom @click="clickAction">u-action-sheet>
    	view>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122

    三、完整源码

    在这里插入图片描述

    完整源码下载地址

    觉得好用的话就给个好评吧😁🤩🥰😘😄😗😛

  • 相关阅读:
    golang开发_goroutine在项目中的使用姿势
    【Java系列】一篇文章快速了解Java语言概述
    为什么说星越L Hi·P是一款全能的增程电动SUV?
    深入理解 Spring 事务:入门、使用、原理
    Rust 基础(六)
    系统提示缺少或找不到msvcp140.dll文件的解决方法
    深度相机辅助导航避障(三):地面点云滤除
    Emgu CV4图像处理之轮廓查找与绘制15(C#)
    Kubernetes安装nginx-controller作为统一网关
    鸿蒙开发接口媒体:【@ohos.multimedia.medialibrary (媒体库管理)】
  • 原文地址:https://blog.csdn.net/weixin_37797592/article/details/127957087