微信小程序怎么实现聊天功能
发表于:2025-01-16 作者:千家信息网编辑
千家信息网最后更新 2025年01月16日,这篇文章将为大家详细讲解有关微信小程序怎么实现聊天功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。初始化滚动条高度var keyHeight = 0;数据格式co
千家信息网最后更新 2025年01月16日微信小程序怎么实现聊天功能
这篇文章将为大家详细讲解有关微信小程序怎么实现聊天功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
初始化滚动条高度
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对话框
{{item.content}} {{item.duration}}s {{item.duration}}" {{item.content}}
wxml底部输入框
按住请说话 {{toastTitle}}
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({}) }})
关于"微信小程序怎么实现聊天功能"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
页面
用户
头像
时间
函数
监听
数据
高度
事件
周期
周期函数
生命
表情
处理
篇文章
功能
程序
动作
更多
语音
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
英语网络安全小作文
淮安进口刀片服务器哪家好
海南屿山互联网科技
虹口区专业性软件开发收费标准
kyland串口服务器
服务器端开发书籍
从事软件开发要求
qq密码数据库在线查询
数据库审计和日志审计
重庆web前端软件开发要多少钱
梦幻西游结婚后可以转回服务器吗
数据库如何解析sql
使命召唤服务器
网络安全工程师再升职是啥
网站数据库主机填写
黑客技术拿数据库
服务器无故崩溃
电脑连接服务器的管理口
怎么查看别人数据库
运城展厅多媒体软件开发
大数据库模板
东莞钜讯网络技术
网络安全云课堂观后感
英雄联盟重新连接服务器失败
厦门龟龟网络技术有限
域名服务器可以关机吗
服务器哪些股票值得投资
vpn无法访问内网服务器
pc浏览器dns服务器未响应
对象存储oss和服务器的区别