溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

微信小程序怎么實現聊天功能

發布時間:2021-09-28 13:52:51 來源:億速云 閱讀:765 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關微信小程序怎么實現聊天功能,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

初始化滾動條高度

var keyHeight = 0;

數據格式

const CHAT_DATA=[ {  type:0,//0客服1用戶  content:'歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎歡迎',  headImg:'../../assets/common/images/headHortrait.jpeg',//頭像  creatTime:'2019-01-01',//創建時間  contentType:'text' }, {  type: 0,//0客服1用戶  content: '1111111',  headImg: '../../assets/common/images/headHortrait.jpeg',//頭像  creatTime: '2019-01-01',//創建時間  contentType: 'text' }, {  type: 1,//0客服1用戶  content: '222222',  headImg: '../../assets/common/images/headHortrait.jpeg',//頭像  creatTime: '2019-01-01',//創建時間  contentType: 'text' }, {  type: 0,//0客服1用戶  content: '333333',  headImg: '../../assets/common/images/headHortrait.jpeg',//頭像  creatTime: '2019-01-01',//創建時間  contentType: 'text' }, {  type: 1,//0客服1用戶  content: '4444444',  headImg: '../../assets/common/images/headHortrait.jpeg',//頭像  creatTime: '2019-01-01',//創建時間  contentType: 'text', }, {  type: 0,//0客服1用戶  content: 'http://tmp/wxc79c66d8b0ed19a8.o6zAJs6QE8L8FKq645ts4e3LoKzI.pGakaVHKmbQ3160aa57e2bf33cb576fbabf691cd890b.durationTime=3706.aac',  headImg: '../../assets/common/images/headHortrait.jpeg',//頭像  creatTime: '2019-01-01',//創建時間  contentType: 'voice',  duration: '3706', },{  type: 1,//0客服1用戶  content: 'http://tmp/wxc79c66d8b0ed19a8.o6zAJs6QE8L8FKq645ts4e3LoKzI.pGakaVHKmbQ3160aa57e2bf33cb576fbabf691cd890b.durationTime=3706.aac',  headImg: '../../assets/common/images/headHortrait.jpeg',//頭像  creatTime: '2019-01-01',//創建時間  contentType: 'voice',  duration:'3706' }, {  type: 1,//0客服1用戶  content: 'https://cache.yisu.com/upload/information/20201210/269/44185.jpg',  headImg: '../../assets/common/images/headHortrait.jpeg',//頭像  creatTime: '2019-01-01',//創建時間  contentType: 'img' }, {  type: 1,//0客服1用戶  content: 'https://cache.yisu.com/upload/information/20201210/269/44185.jpg',  headImg: '../../assets/common/images/headHortrait.jpeg',//頭像  creatTime: '2019-01-01',//創建時間  contentType: 'img' }];

wxml對話框

<block wx:key wx:for='{{chatData}}' wx:for-index="index">   <!-- 單個消息1 客服發出(左) -->   <view wx:if='{{item.type==0}}' id='msg-{{index}}' class="contentLeft" style=''>    <view class="head">      <image class="headImg" src='{{item.headImg}}' mode='widthFix'></image>    </view>    <view class='leftMsg' wx:if="{{item.contentType==='text'}}">{{item.content}}</view>    <view class='leftMsg' wx:if="{{item.contentType==='voice'}}" data-duration="{{item.content}}">{{item.duration}}s</view>    <view class='leftMsg img' wx:if="{{item.contentType==='img'}}"><image src="{{item.content}}" data-src="{{item.content}}" mode='widthFix' bindtap="onPreview"/></view>   </view>   <!-- 單個消息2 用戶發出(右) -->   <view wx:else id='msg-{{index}}' class="contentRight">    <view class='rightMsg' wx:if="{{item.contentType==='voice'}}" data-duration="{{item.duration}}" bindtap="playRecord" >{{item.duration}}"<van-icon name="../../../assets/common/icon/voice-r.png"  /></view>    <view class='rightMsg' wx:if="{{item.contentType==='text'}}">{{item.content}}</view>    <view class='rightMsg img' wx:if="{{item.contentType==='img'}}"><image src="{{item.content}}" data-src="{{item.content}}" mode='widthFix' bindtap="onPreview"/></view>     <view>      <image class="headImg" src='{{item.headImg}}' mode='widthFix'></image>    </view>   </view>  </block>

wxml底部輸入框

<view class='inputRoom' style='bottom: {{inputBottom}};height: {{bottomHeight}}'>  <van-row class="bottomRow">   <van-col span="2"wx:if="{{show}}"> <van-icon bindtap="startRecord" class="iconfont icon" class-prefix='icon' size="40rpx" name="yuyin" ></van-icon></van-col>    <van-col span="2" wx:if="{{!show}}"> <van-icon bindtap="startRecord" class="iconfont icon" class-prefix='icon' size="40rpx" name="fabiaowenzhang" ></van-icon></van-col>   <van-col span="18" wx:if="{{show}}"> <input bindconfirm='sendClick'bind:input="inputValue" adjust-position='{{false}}' value='{{inputVal}}' confirm-type='send' bindfocus='focus' bindblur='blur'></input></van-col>   <van-col span="18" wx:if="{{!show}}"> <view class="holdTape" bind:touchstart="startTalk" bind:touchend='stopRecord'>按住請說話</view></van-col>   <van-col span="2"><van-icon class="iconfont icon" class-prefix='icon' size="40rpx" name='biaoqing' bindtap="getEmoji"></van-icon></van-col>   <van-col span="2"><van-uploader use-slot accept='image' bind:after-read="uploadeImg"> <van-icon class="iconfont icon" class-prefix='icon' size="40rpx" name='icon02' ></van-icon></van-uploader></van-col>  </van-row>   <view wx:if="{{showEmoji}}" class="emoji">   <emoji bind:clickEmoji="clickEmoji" data-key="inputVal" value="{{inputVal}}" />  </view> </view></view><view class="recordDailog" wx:if="{{showDailog}}"  ><view class="show"> <image src="../../assets/common/images/record.png"></image> <text>{{toastTitle}}</text></view>

css

#page{ height: 90%;overflow-y: auto;}.content{ background: white;}.inputRoom { width: 100vw; /* height: 16vw; */ border-top: 1px solid #cdcdcd; position: fixed; bottom: 0; display: flex; align-items: center; z-index: 20; background: white; flex-direction: column;}.bottomRow{ width: 100%; height: 16vw;display: flex;align-items: center;flex-direction: row}.bottomRow .van-row{ width: 100%;}.emoji{ height: 30vw;}input {width: 90%;height: 9.33vw;background-color: #EEF4FA;border-radius: 6rpx;font-size: 28rpx;color: #444;padding: 0 3%;margin-left: 2%;}.leftMsg { font-size: 26rpx; color: #333333;line-height: 6vw;padding: 2vw 2.5vw;background-color: #EEF4FA; border-radius: 10rpx; z-index: 10;}.rightMsg { font-size: 26rpx; color: white; line-height: 6vw; padding: 2vw 2.5vw; background-color: #496DFF; border-radius: 10rpx; z-index: 10;}.chatFrame{ background: white; height: 100%}.icon{ line-height: 8vw;}.head{ display: flex; align-items: center}.headImg{ border-radius: 50%; width: 60rpx;height: 60rpx;}.holdTape{ width: 90%;height: 9.33vw;background-color: #EEF4FA;border-radius: 6rpx;padding: 0 3%;margin-left: 2%;display: flex;align-items: center;justify-content: center;}.recordDailog{ -webkit-transition-duration: 300ms;transition-duration: 300ms;z-index: 1000;position: fixed;top: 50%;left: 50%;width: -webkit-fit-content;width: fit-content;-webkit-transform: translate(-50%,-50%);transform: translate(-50%,-50%);max-width: var(--toast-max-width,70%);}.show{width: var(--toast-default-width,90px);min-height: var(--toast-default-min-height,90px);padding: var(--toast-default-padding,16px);display: flex;-webkit-flex-direction: column;flex-direction: column;-webkit-align-items: center;align-items: center;-webkit-justify-content: center;justify-content: center;box-sizing: initial;color: var(--toast-text-color,#fff);font-size: var(--toast-font-size,14px);line-height: var(--toast-line-height,20px);white-space: pre-wrap;word-wrap: break-word;background-color: var(--toast-background-color,rgba(50,50,51,.88));border-radius: var(--toast-border-radius,4px);}.show image{ width: 24px; height: 24px}image{ /* max-width: 88vw;max-height: 400rpx; */width: 100%}.img{background: none;width: 90%}.contentRight{ display: flex; justify-content: flex-end; padding: 2vw 2vw 2vw 11vw;width: 86%;}.contentLeft{ display: flex; padding: 2vw 11vw 2vw 2vw;width: 86%;}

js

// pages/contact/contact.jsconst { pageFunc} = require('../../utils/util.js');const app = getApp();var windowWidth = wx.getSystemInfoSync().windowWidth;var windowHeight = wx.getSystemInfoSync().windowHeight;var keyHeight = 0;const { CHAT_DATA}=require("../../data/customerService.js");import Toast from '../../components/vant/toast/toast';const recorderManager = wx.getRecorderManager();const innerAudioContext = wx.createInnerAudioContext();const db = wx.cloud.database();/** * 初始化數據 *//** * 計算msg總高度 */function calScrollHeight(that, keyHeight) { var query = wx.createSelectorQuery(); query.select('.scrollMsg').boundingClientRect(function(rect) { }).exec();}Page({ /**  * 頁面的初始數據  */ data: {  scrollHeight: '100vh',  inputVal:"",  inputBottom: 0,  chatData:[],  show:true,  showDailog:false,  bottomHeight:"18vw",  sendData:{},  pagination: {   pageSize: 5,   currentPage: 1,   total: 0,  },  showEmoji:false,  toastTitle:"錄音中...." }, /**  * 生命周期函數--監聽頁面加載  */ onLoad: function (options) {  // this.setData({  //  cusHeadIcon: app.globalData.userInfo.avatarUrl,  // });  const {   pagination  } = this.data  this.getData({ param: CHAT_DATA, pagination });   wx.pageScrollTo({    scrollTop: 1000   }) }, getData(params) {  const { chatData } = this.data;  const {   param,   pagination: {    pageSize = 10,    currentPage = 1   },  } = params;  this.setData({   pagination: { pageSize, currentPage }  });  const {   data,   pagination  } = pageFunc(param, currentPage, pageSize);  data.forEach((item) => {   if (item.duration) {    item.duration = Math.ceil(item.duration / 1000)   }  });   this.setData({    'chatData': data.concat(chatData)   }); }, startRecord(){//開始錄音 const {show}=this.data  if (show){   this.setData({    show: false,   })  }else{   this.setData({    show: true,   })  } }, startTalk(e){//開始說話  this.setData({   showDailog:true,  })  const options = {   duration: 60000,   sampleRate: 44100,   numberOfChannels: 1,   encodeBitRate: 192000,   format: 'aac',   frameSize: 50  }  recorderManager.start(options)  recorderManager.onStart((res) => {  }) }, stopRecord(){//停止說話  const that=this  this.setData({   showDailog:false,  })  recorderManager.stop();  recorderManager.onStop((res) => {   const { sendData, chatData } = that.data;   let { tempFilePath, duration, fileSize} = res   sendData.tempFilePathData=res   duration = Math.ceil(duration / 1000)   const data = { content: tempFilePath, duration , fileSize, contentType: 'voice', type: 1};   chatData.push(data);   wx.createSelectorQuery().select('.content').boundingClientRect(function (rect) {    // 使頁面滾動到底部    wx.pageScrollTo({     scrollTop: rect.bottom + 5000    })   }).exec();   that.setData({    'tempFilePath': tempFilePath,    sendData,    chatData,    scrollHeight: (windowHeight - 0) + 'px',    toView: 'msg-' + (chatData.length - 1),    inputBottom: '0px'   })  }) }, playRecord(e){//播放語音  const { currentTarget: { dataset: { duration } }}=e;  const { tempFilePath} = this.data  innerAudioContext.autoplay = true;  innerAudioContext.src = tempFilePath ,   innerAudioContext.onPlay(() => {    this.setData({     toastTitle: "播放中....",     showDailog: true,    })   })  innerAudioContext.onEnded((res) => {   this.setData({    toastTitle: "錄音中....",    showDailog: false,   })  })  innerAudioContext.onError((res) => {  });  innerAudioContext.play() }, uploadeImg(e){  const { file: { path,size:fileSize} } = e.detail;  const { chatData } = this.data;  const data = { content: path, fileSize, contentType: 'img', type: 1 };  chatData.push(data);  wx.createSelectorQuery().select('.content').boundingClientRect(function (rect) {   // 使頁面滾動到底部   wx.pageScrollTo({    scrollTop: rect.bottom + 5000   })  }).exec()  this.setData({   chatData,   scrollHeight: (windowHeight - 0) + 'px',   toView: 'msg-' + (chatData.length - 1),   inputBottom:'0px'  }) }, getEmoji(){//獲取表情包  wx.createSelectorQuery().select('.content').boundingClientRect(function (rect) {   // 使頁面滾動到底部   wx.pageScrollTo({    scrollTop: rect.bottom + 5000   })  }).exec() this.setData({  showEmoji:true,  bottomHeight:"48vw" }) }, clickEmoji: function (e) {//選擇表情包  const {   detail: {    value   },   currentTarget: {    dataset: {     key    }   }  } = e;  this.setData({   [key]: value  }) }, onPreview(e){  const {   currentTarget: {    dataset: {     src    }   }  } = e;  const urls = [src]  wx.previewImage({   current: src,   urls  }) }, /**  * 生命周期函數--監聽頁面顯示  */ onShow: function () { }, /**  * 頁面相關事件處理函數--監聽用戶下拉動作  */ onPullDownRefresh: function () {  let { pagination: { currentPage } } = this.data  this.getData({   param: CHAT_DATA,   pagination: {    pageSize: 5,    currentPage: currentPage + 1,   }  }); }, /**  * 頁面上拉觸底事件的處理函數  */ onReachBottom: function () { }, /**  * 獲取聚焦  */ inputValue(e){  const {detail:{value}}=e  this.setData({   inputVal:value  }) }, focus: function (e) {  const { chatData}=this.data  keyHeight = e.detail.height;  wx.pageScrollTo({   scrollTop: windowHeight - keyHeight  })  this.setData({   toView: 'msg-' + (chatData.length - 1),   inputBottom: keyHeight + 'px',   scrollHeight: (windowHeight - keyHeight) + 'px',   showEmoji:false,   bottomHeight: "18vw"  })  //計算msg高度  // calScrollHeight(this, keyHeight); }, //失去聚焦(軟鍵盤消失) blur: function (e) {  const { chatData } = this.data  this.setData({   scrollHeight: '100vh',   inputBottom: 0  })  this.setData({   toView: 'msg-' + (chatData.length - 1)  }) }, /**  * 發送點擊監聽  */ sendClick: function (e) {  const { chatData, scrollHeight}=this.data;  wx.createSelectorQuery().select('.content').boundingClientRect(function (rect) {   // 使頁面滾動到底部   wx.pageScrollTo({    scrollTop: rect.bottom + 5000   })  }).exec()  chatData.push({   type: 1,   contentType: 'text',   content: e.detail.value,   headImg: '../../assets/common/images/headHortrait.jpeg',  })  this.setData({   chatData,   inputVal:''  }); }, /**  * 退回上一頁  */ toBackClick: function () {  wx.navigateBack({}) }})// pages/contact/contact.jsconst { pageFunc} = require('../../utils/util.js');const app = getApp();var windowWidth = wx.getSystemInfoSync().windowWidth;var windowHeight = wx.getSystemInfoSync().windowHeight;var keyHeight = 0;const { CHAT_DATA}=require("../../data/customerService.js");import Toast from '../../components/vant/toast/toast';const recorderManager = wx.getRecorderManager();const innerAudioContext = wx.createInnerAudioContext();const db = wx.cloud.database();/** * 初始化數據 *//** * 計算msg總高度 */function calScrollHeight(that, keyHeight) { var query = wx.createSelectorQuery(); query.select('.scrollMsg').boundingClientRect(function(rect) { }).exec();}Page({ /**  * 頁面的初始數據  */ data: {  scrollHeight: '100vh',  inputVal:"",  inputBottom: 0,  chatData:[],  show:true,  showDailog:false,  bottomHeight:"18vw",  sendData:{},  pagination: {   pageSize: 5,   currentPage: 1,   total: 0,  },  showEmoji:false,  toastTitle:"錄音中...." }, /**  * 生命周期函數--監聽頁面加載  */ onLoad: function (options) {  // this.setData({  //  cusHeadIcon: app.globalData.userInfo.avatarUrl,  // });  const {   pagination  } = this.data  this.getData({ param: CHAT_DATA, pagination });   wx.pageScrollTo({    scrollTop: 1000   }) }, getData(params) {  const { chatData } = this.data;  const {   param,   pagination: {    pageSize = 10,    currentPage = 1   },  } = params;  this.setData({   pagination: { pageSize, currentPage }  });  const {   data,   pagination  } = pageFunc(param, currentPage, pageSize);  data.forEach((item) => {   if (item.duration) {    item.duration = Math.ceil(item.duration / 1000)   }  });   this.setData({    'chatData': data.concat(chatData)   }); }, startRecord(){//開始錄音 const {show}=this.data  if (show){   this.setData({    show: false,   })  }else{   this.setData({    show: true,   })  } }, startTalk(e){//開始說話  this.setData({   showDailog:true,  })  const options = {   duration: 60000,   sampleRate: 44100,   numberOfChannels: 1,   encodeBitRate: 192000,   format: 'aac',   frameSize: 50  }  recorderManager.start(options)  recorderManager.onStart((res) => {  }) }, stopRecord(){//停止說話  const that=this  this.setData({   showDailog:false,  })  recorderManager.stop();  recorderManager.onStop((res) => {   const { sendData, chatData } = that.data;   let { tempFilePath, duration, fileSize} = res   sendData.tempFilePathData=res   duration = Math.ceil(duration / 1000)   const data = { content: tempFilePath, duration , fileSize, contentType: 'voice', type: 1};   chatData.push(data);   wx.createSelectorQuery().select('.content').boundingClientRect(function (rect) {    // 使頁面滾動到底部    wx.pageScrollTo({     scrollTop: rect.bottom + 5000    })   }).exec();   that.setData({    'tempFilePath': tempFilePath,    sendData,    chatData,    scrollHeight: (windowHeight - 0) + 'px',    toView: 'msg-' + (chatData.length - 1),    inputBottom: '0px'   })  }) }, playRecord(e){//播放語音  const { currentTarget: { dataset: { duration } }}=e;  const { tempFilePath} = this.data  innerAudioContext.autoplay = true;  innerAudioContext.src = tempFilePath ,   innerAudioContext.onPlay(() => {    this.setData({     toastTitle: "播放中....",     showDailog: true,    })   })  innerAudioContext.onEnded((res) => {   this.setData({    toastTitle: "錄音中....",    showDailog: false,   })  })  innerAudioContext.onError((res) => {  });  innerAudioContext.play() }, uploadeImg(e){  const { file: { path,size:fileSize} } = e.detail;  const { chatData } = this.data;  const data = { content: path, fileSize, contentType: 'img', type: 1 };  chatData.push(data);  wx.createSelectorQuery().select('.content').boundingClientRect(function (rect) {   // 使頁面滾動到底部   wx.pageScrollTo({    scrollTop: rect.bottom + 5000   })  }).exec()  this.setData({   chatData,   scrollHeight: (windowHeight - 0) + 'px',   toView: 'msg-' + (chatData.length - 1),   inputBottom:'0px'  }) }, getEmoji(){//獲取表情包  wx.createSelectorQuery().select('.content').boundingClientRect(function (rect) {   // 使頁面滾動到底部   wx.pageScrollTo({    scrollTop: rect.bottom + 5000   })  }).exec() this.setData({  showEmoji:true,  bottomHeight:"48vw" }) }, clickEmoji: function (e) {//選擇表情包  const {   detail: {    value   },   currentTarget: {    dataset: {     key    }   }  } = e;  this.setData({   [key]: value  }) }, onPreview(e){  const {   currentTarget: {    dataset: {     src    }   }  } = e;  const urls = [src]  wx.previewImage({   current: src,   urls  }) }, /**  * 生命周期函數--監聽頁面顯示  */ onShow: function () { }, /**  * 頁面相關事件處理函數--監聽用戶下拉動作  */ onPullDownRefresh: function () {  let { pagination: { currentPage } } = this.data  this.getData({   param: CHAT_DATA,   pagination: {    pageSize: 5,    currentPage: currentPage + 1,   }  }); }, /**  * 頁面上拉觸底事件的處理函數  */ onReachBottom: function () { }, /**  * 獲取聚焦  */ inputValue(e){  const {detail:{value}}=e  this.setData({   inputVal:value  }) }, focus: function (e) {  const { chatData}=this.data  keyHeight = e.detail.height;  wx.pageScrollTo({   scrollTop: windowHeight - keyHeight  })  this.setData({   toView: 'msg-' + (chatData.length - 1),   inputBottom: keyHeight + 'px',   scrollHeight: (windowHeight - keyHeight) + 'px',   showEmoji:false,   bottomHeight: "18vw"  })  //計算msg高度  // calScrollHeight(this, keyHeight); }, //失去聚焦(軟鍵盤消失) blur: function (e) {  const { chatData } = this.data  this.setData({   scrollHeight: '100vh',   inputBottom: 0  })  this.setData({   toView: 'msg-' + (chatData.length - 1)  }) }, /**  * 發送點擊監聽  */ sendClick: function (e) {  const { chatData, scrollHeight}=this.data;  wx.createSelectorQuery().select('.content').boundingClientRect(function (rect) {   // 使頁面滾動到底部   wx.pageScrollTo({    scrollTop: rect.bottom + 5000   })  }).exec()  chatData.push({   type: 1,   contentType: 'text',   content: e.detail.value,   headImg: '../../assets/common/images/headHortrait.jpeg',  })  this.setData({   chatData,   inputVal:''  }); }, /**  * 退回上一頁  */ toBackClick: function () {  wx.navigateBack({}) }})

關于“微信小程序怎么實現聊天功能”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女