微信小程序聊天室 前后端源码附效果图和数据库结构图

 

 

正文:

<!-- <button bindtap='close'>关闭</button><button bindtap='open'>打开</button> -->
<view wx:if='{
  {login}}' class='login_zz'></view>
<button wx:if='{
  {login}}' class='login' bindgetuserinfo='userinfo' open-type="getUserInfo">登录</button>
<view class='page_bg' wx:if='{
  {block}}' bindtap='hide_bg' />
<view class='btn_bg' wx:if='{
  {block}}'>
  <view wx:for="{
  {link_list}}" wx:key='index'>
    <button class="sp_tit" id='{
  {index}}' bindtap='list_item'>查看详情 {
  {item}} </button>
  </view>
</view>
<scroll-view class="history" scroll-y="true" scroll-with-animation scroll-top="{
  {scrollTop}}">
  <block wx:key="{
  {index}}" wx:for="{
  {allContentList}}">
    <block wx:if="{
  {item.is_my}}">
      <view class='my_right new_txt'>
        <view class='time' wx:if='{
  {item.messageTime&&item.messageTime!=0}}'> {
  {item.messageTime}} </view>
        <view class='p_r page_r' style='margin-right: 25rpx;' wx:if='{
  {item.text}}'>
          <view class='new_txt'>
            <view class='new_txt_my'>
              <view class='arrow'>
                <em></em>
                <span></span>
              </view>
              <text decode="true">{
  {item.text}}</text> </view>
          </view>
          <image class='new_img' src='{
  {item.avatarUrl}}'></image>
        </view>
        <view class='p_r page_r' style='margin-right: 25rpx;' wx:if='{
  {item.audio}}' bindtap='my_audio_click' data-id='{
  {index}}'>
          <view class='new_txt_my_2' style=' width:{
  {item.length}}px'>
            <image class='my_audio' src='/images/yuyin_icon.png'></image>
          </view>
          <span class='_span'></span>
          <open-data class='new_img' type="userAvatarUrl"></open-data>
        </view>
      </view>
    </block>
    <!-- <view class='you_left' id='id_{
  {allContentList.length}}'> -->
    <block wx:if="{
  {item.is_ai&&item.is_ai!=''}}">
      <view class='you_left' style='width:100%;' id='id_{
  {allContentList.length}}' wx:key="{
  {index}}">
        <view class='time' wx:if='{
  {item.messageTime}}'> {
  {item.messageTime}} </view>
        <view class='p_r' style='margin-left: 20rpx;'>
          <image class='new_img' src='{
  {item.avatarUrl}}'></image>
          <view class='new_txt'>
            <view class='new_txt_ai'>
              <view class='arrow'>
                <em></em>
                <span></span>
              </view>
              <view class='ai_content'>
                <!-- <text wx:if='{
  {item.type=="1"}}' decode="true">{
  {item.text}}</text> -->
                <text decode="true">{
  {item.text}}</text>
                <!-- <image wx:if='{
  {item.type=="2"}}' style='width:160rpx;height:160rpx;' src='{
  {item.src}}'></image> -->
              </view>
              <view class='yes_problem_log' wx:if="{
  {item.yse_problem&&item.solve_show}}" style=''>感谢您的反馈,我们会再接再厉!</view>
              <view class='yes_problem_log' style='color:#32CF3C' wx:if="{
  {item.no_problem&&item.solve_show}}" bindtap='phone_click'>拨打人工客服</view>
            </view>
          </view>
        </view>
      </view>
    </block>
  </block>
</scroll-view>
<!-- 遮罩 -->
<view class='zezhao' wx:if='{
  {cross}}' bindtap='add_icon_click' id='2'></view>
<!-- 输入框 -->
<view class='{
  {cross?"in_voice_icon":""}}'>
  <view class="sendmessage" style='bottom:{
  {input_bottom}}px'>
    <input type="text" style='{
  {focus?"border-bottom: 1px solid #88DD4B;":""}}' adjust-position='{
  {false}}' cursor-spacing='5' bindinput="bindKeyInput" value='{
  {inputValue}}' focus='{
  {focus}}' bindblur='no_focus' bindfocus="focus" confirm-type="done" placeholder="请输入您要咨询的问题"
    />
    <button wx:if='{
  {if_send&&inputValue!=""}}' bindtap="submitTo" class='user_input_text'>发送</button>
    <image class='add_icon' bindtap='add_icon_click' id='1' wx:if='{
  {add&&!if_send&&inputValue==""}}' src='/images/jia_img.png'></image>
    <image class='add_icon' bindtap='add_icon_click' id='2' wx:if='{
  {cross}}' src='/images/audio/cross37.png'></image>
  </view>
  <view wx:if='{
  {cross}}' class='item' bindtap='phone_click'>
    <image class='img' src='/images/yuyin_icon.png'></image>
    <view class='text'>人工客服</view>
  </view>
</view>
<!-- <view class='zezhao' wx:if='{
  {add_icon_click}}' bindtap='add_icon_click'></view> -->
<!-- <view class='in_voice_icon'>
  <view class="sendmessage_2">
    <input type="text" bindinput="bindKeyInput" adjust-position='{
  {false}}' value='{
  {inputValue}}' focus='{
  {focus}}' bindfocus="focus" confirm-type="done" placeholder="" />
    <image class='add_icon' bindtap='add_icon_click' src='/images/audio/cross37.png'></image>
  </view>
  <view class='item' bindtap='phone_click'>
    <image class='img' src='/images/yuyin_icon.png'></image>
    <view class='text'>人工客服</view>
  </view>
</view> -->
page {
  background-color: #f2f2f2;
  height: 100%;
  padding: 0 auto;
  margin: 0 auto;
}

.login {
  z-index: 999;
  position: fixed;
  top: 300rpx;
  height: 100rpx;
  text-align: center;
  line-height: 100rpx;
  width: 400rpx;
  left: 50%;
  margin-left: -200rpx;
  background: white;
}

.Phone {
  top: 500rpx;
  width: 400rpx;
}

.login_zz {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 998;
  background-color: rgba(0, 0, 0, 0.5);
}

swiper {
  height: 180rpx;
}

swiper swiper-item .slide-image {
  width: 100%;
  height: 180rpx;
}

.jia_img {
  height: 80rpx;
  width: 90rpx;
}

.time {
  text-align: center;
  padding: 5rpx 20rpx 5rpx 20rpx;
  border-radius: 10rpx;
  display: block;
  height: 38rpx;
  line-height: 38rpx;
  position: relative;
  margin: 0 auto;
  margin-bottom: 20rpx;
  width: 90rpx;
  color: white;
  font-size: 26rpx;
  background-color: #dedede;
}

.tab {
  bottom: 120rpx;
}

.tab_1 {
  position: fixed;
  bottom: 50rpx;
  width: 200rpx;
  font-size: 26rpx;
  left: 50%;
  margin-left: -45rpx;
  height: 100rpx;
}

.tab_2 {
  right: 30rpx;
  position: fixed;
}

/* 聊天 */

.my_right {
  float: right;
  margin-top: 30rpx;
  position: relative;
}

.my_audio {
  height: 60rpx;
  width: 60rpx;
  z-index: 2;
  position: relative;
  top: 10rpx;
  left: 20rpx;
}

.you_left {
  margin-top: 30rpx;
  float: left;
  position: relative;
  padding-left: 5rpx;
}

.new_img {
  width: 85rpx;
  height: 85rpx;
  overflow: hidden;
}

.page_r {
  float: right;
}

.new_txt {
  min-width: 380rpx;
  width: 460rpx;
  word-break: break-all;
}

.new_txt_my {
  border-radius: 7rpx;
  background: #9fe75a;
  position: relative;
  right: 30rpx;
  padding: 17rpx 30rpx 17rpx 30rpx;
  float: right;
  border: 1px solid #d0d0d0;
}

.new_txt_my .arrow {
  position: absolute;
  z-index: 2;
  width: 40rpx;
  right: -38rpx;
}

.new_txt_my .arrow em {
  position: absolute;
  border-style: solid;
  border-width: 15rpx;
  border-color: transparent transparent transparent #d0d0d0;
  top: 1rpx;
}

.new_txt_my .arrow span {
  position: absolute;
  top: 5rpx;
  border-style: solid;
  border-width: 15rpx;
  border-color: transparent transparent transparent #9fe75a;
}

.new_txt_my_2 {
  word-break: break-all;
  border-radius: 7rpx;
  background: #9fe75a;
  min-width: 330rpx;
  max-width: 530rpx;
  padding: 17rpx 30rpx 17rpx 30rpx;
  float: right;
}

.new_txt_ai {
  border-radius: 7rpx;
  left: 20rpx;
  background-color: #fff;
  position: relative;
  border: 1px solid #d0d0d0;
  float: left;
}

.new_txt_ai .arrow {
  position: relative;
  width: 40rpx;
  left: -30rpx;
}

.new_txt_ai .arrow em {
  position: absolute;
  border-style: solid;
  border-width: 15rpx;
  top: 20rpx;
  border-color: transparent #d0d0d0 transparent transparent;
}

.new_txt_ai .arrow span {
  position: absolute;
  top: 20rpx;
  border-style: solid;
  border-width: 15rpx;
  border-color: transparent #fff transparent transparent;
  left: 2rpx;
}

.ai_content {
  word-break: break-all;
  padding: 17rpx 30rpx 17rpx 30rpx;
}

.sanjiao {
  top: 25rpx;
  position: relative;
  width: 0px;
  height: 0px;
  border-width: 15rpx;
  border-style: solid;
}

.my {
  border-color: transparent transparent transparent #9fe75a;
}

.you {
  border-color: transparent #fff transparent transparent;
}

._span {
  border-color: #fff transparent transparent;
  top: -17px;
}

.is_ai_btn {
  border-radius: 0 0 7px 7px;
  border-top: 1px solid #d0d0d0;
  background: white;
  position: relative;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 80rpx;
  line-height: 80rpx;
  display: flex;
  flex-direction: row;
  text-align: center;
}

.is_ai_btn view {
  width: 50%;
}

.is_ai_btn image {
  width: 32rpx;
  position: relative;
  top: 4rpx;
  height: 32rpx;
}

.is_ai_btn .two {
  border-left: 1px solid #d0d0d0;
}

.yes_problem_log {
  border-top: 1px solid #d0d0d0;
  height: 80rpx;
  text-align: center;
  line-height: 80rpx;
}

.voice_icon {
  width: 60rpx;
  height: 60rpx;
  margin: 0 auto;
  padding: 10rpx 10rpx 10rpx 10rpx;
}

.add_icon {
  width: 70rpx;
  height: 70rpx;
  margin: 0 auto;
  padding: 20rpx 10rpx 10rpx 15rpx;
}

.voice_ing {
  width: 90%;
  height: 75rpx;
  line-height: 85rpx;
  text-align: center;
  border-radius: 15rpx;
  border: 1px solid #d0d0d0;
}

.zezhao {
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  width: 100%;
  background: rgba(0, 0, 0, 0.5);
}

.in_voice_icon {
  z-index: 3;
  left: 0;
  bottom: 0;
  width: 100%;
  position: absolute;
  height: 500rpx;
  background: #f8f8f8;
}

.in_voice_icon .item {
  position: relative;
  margin-top: 50rpx;
  margin-left: 50rpx;
  text-align: center;
  width: 140rpx;
}

.in_voice_icon .img {
  width: 80rpx;
  height: 80rpx;
  border-radius: 15rpx;
}

.in_voice_icon .text {
  font-size: 32rpx;
  margin-top: 20rpx;
}

.sendmessage {
  width: 100%;
  z-index: 2;
  display: flex;
  position: fixed;
  bottom: 0px;
  background-color: #f8f8f8;
  flex-direction: row;
  height: 100rpx;
}

.sendmessage input {
  width: 78%;
  height: 80rpx;
  line-height: 80rpx;
  font-size: 28rpx;
  margin-top: 10rpx;
  margin-left: 20rpx;
  border-bottom: 1px solid #d0d0d0;
  padding-left: 20rpx;
}

.sendmessage button {
  border: 1px solid white;
  width: 18%;
  height: 80rpx;
  background: #0c0;
  color: white;
  line-height: 80rpx;
  margin-top: 10rpx;
  font-size: 28rpx;
}

.hei {
  height: 20rpx;
}

.history {
  height: 88%;
  display: flex;
  font-size: 14px;
  line-height: 50rpx;
  position: relative;
  top: 20rpx;
}

.icno_kf {
  position: fixed;
  bottom: 160rpx;
  margin: 0 auto;
  text-align: center;
  left: 50%;
  margin-left: -40rpx;
  width: 100rpx;
  height: 100rpx;
  border-radius: 50%;
}
// pages/index/to_news/to_news.js 
var app = getApp();
var util = require("../../utils/util.js");
var socketOpen = false;
var uuid = '',
time_ = "1";
var recorder = wx.getRecorderManager();
const innerAudioContext = wx.createInnerAudioContext() //获取播放对象var
frameBuffer_Data, session, SocketTask, string_base64;
Page({
data: {
login: false,
listCustmerServiceBanner: [],
indicatorDots: false,
autoplay: false,
interval: 5000,
duration: 1000,
user_input_text: '', //用户输入文字   
inputValue: '',
time: '',
returnValue: '',
if_send: false,
add: true,
cross: false, // is_my: true, text: '12432'   
allContentList: [{}, {
is_ai: []
}],
num: 0
}, // 页面加载 
onLoad: function(e) {
var that = this;
if (wx, wx.getStorageSync('openid')) {
this.setData({
login: false
})
} else {
this.setData({
login: true
})
}
let url = app.url + '/show.php'
util.request(url, 'post', {}, '正在加载···', function(res) {
for (var i = 0; i < res.data.length; i++) {
console.log(i, res.data[i].iv, wx.getStorageSync('openid'))
if (res.data[i].iv == wx.getStorageSync('openid')) {
res.data[i].is_my = true
} else {
res.data[i].is_ai = true
}
}
that.setData({
allContentList: res.data,
inputValue: ''
})
that.bottom()
})
}, // 获取用户信息并且登录,获取openid  
userinfo: function(e) {
var that = this;
var nickName = JSON.parse(e.detail.rawData).nickName;
var avatarUrl = JSON.parse(e.detail.rawData).avatarUrl;
console.log('nickName:', nickName, 'avatarUrl:', avatarUrl)
wx.setStorageSync('nickName', nickName)
wx.setStorageSync('avatarUrl', avatarUrl)
wx.login({
success: function(res) {
let url = app.url + '/login.php'
if (res.code) {
util.request(url, 'post', {
code: res.code
}, '正在登录···', function(res) {
console.log(res.data)
if (res.data.openid) {
var openid = res.data.openid;
wx.setStorageSync('openid', openid);
if (avatarUrl && openid) {
wx.showToast({
title: '登录成功!',
})
that.setData({
login: false
})
}
}
})
}
}
});
}, // 页面加载完成  
onReady: function() {
var that = this;
this.on_recorder();
this.bottom()
}, // 提交文字  
submitTo: function(e) {
console.log('提交文字')
let that = this;
if (that.data.inputValue == "") {
return;
}
var url = app.url + '/up_text.php'
var data = {
avatarUrl: wx.getStorageSync('avatarUrl'),
iv: wx.getStorageSync('openid'),
inputValue: that.data.inputValue,
time: (new Date()).getTime()
}
console.log('提交文字data:', data)
util.request(url, 'post', data, '', function(res) { // res.data = res.data.reverse();    
for (var i = 0; i < res.data.length; i++) {
console.log(i, res.data[i].iv, wx.getStorageSync('openid'))
if (res.data[i].iv == wx.getStorageSync('openid')) {
res.data[i].is_my = true
} else {
res.data[i].is_ai = true
}
}
that.setData({
allContentList: res.data,
inputValue: ''
})
that.bottom()
}, function(res) {})
}, // 点击加号  
add_icon_click: function(e) {
console.log(e.target.id) // e.target.id == 1 点击加号   ==2  点击 X    
if (e.target.id == 2) {
this.setData({
add: true,
cross: false,
input_bottom: 0
})
} else if (e.target.id == 1) {
this.setData({
add: false,
cross: true,
input_bottom: 240
})
}
}, // 输入框 
bindKeyInput: function(e) {
console.log(e.detail.value)
if (e.detail.value == "") {
this.setData({
if_send: false,
inputValue: e.detail.value
})
} else {
this.setData({
if_send: true,
inputValue: e.detail.value
})
}
}, // 获取到焦点 
focus: function(e) {
var that = this;
console.log(e.detail.height)
this.setData({
focus: true,
add: true,
cross: false,
input_bottom: e.detail.height
})
}, // 失去焦点  
no_focus: function(e) {
if (this.data.cross) {
this.setData({
focus: false,
input_bottom: 240,
})
} else {
this.setData({
focus: false,
input_bottom: 0
})
}
},
onHide: function() {}, // 获取hei的id节点然后屏幕焦点调转到这个节点   
bottom: function() {
var that = this;
this.setData({
scrollTop: 100000
})
},
hide_bg: function() {
this.setData({
block: false
})
}, // 点击录音事件  
my_audio_click: function(e) {
console.log('my_audio_click执行了', e)
var index = e.currentTarget.dataset.id;
console.log('url地址', this.data.allContentList[index].audio);
innerAudioContext.src = this.data.allContentList[index].audio
innerAudioContext.seek(0);
innerAudioContext.play();
}, // 手指点击录音  
voice_ing_start: function() {
var that = this;
this.setData({
voice_ing_start_date: new Date().getTime(), //记录开始点击的时间   
})
const options = {
duration: 10000, //指定录音的时长,单位 ms    
sampleRate: 16000, //采样率    
numberOfChannels: 1, //录音通道数  
encodeBitRate: 24000, //编码码率   
format: 'mp3', //音频格式,有效值 aac/mp3     
frameSize: 12, //指定帧大小,单位 KB   
}
recorder.start(options) //开始录音   
this.animation = wx.createAnimation({
duration: 1200,
}) //播放按钮动画    
that.animation.scale(0.8, 0.8); //还原  
that.setData({
spreakingAnimation: that.animation.export()
})
}, // 录音监听事件 
on_recorder: function() {
recorder.onStart((res) => {
console.log('开始录音');
})
recorder.onStop((res) => {
console.log('停止录音,临时路径', res.tempFilePath); // _tempFilePath = res.tempFilePath;      
var x = new Date().getTime() - this.data.voice_ing_start_date
if (x > 1000) {
that.data.allContentList.push({
is_my: true,
audio: res.tempFilePath,
length: x / 1000 * 30
});
that.setData({
allContentList: that.data.allContentList
})
}
})
recorder.onFrameRecorded((res) => {
var x = new Date().getTime() - this.data.voice_ing_start_date
if (x > 1000) {
console.log('onFrameRecorded  res.frameBuffer', res.frameBuffer);
string_base64 = wx.arrayBufferToBase64(res.frameBuffer) // console.log('string_base64--', wx.arrayBufferToBase64(string_base64))    
if (res.isLastFrame) {
var data = {
audioType: 3,
cmd: 1,
type: 2,
signType: 'BASE64',
session: session,
body: string_base64,
}
console.log('that.data.allContentList', that.data.allContentList) // 进行下一步操作     
} else {
var data = {
cmd: 1,
audioType: 2,
type: 2,
signType: 'BASE64',
session: session,
body: string_base64
}
console.log('录音上传的data:', data)
}
}
})
}, // 手指松开录音 
voice_ing_end: function() {
var that = this;
that.setData({
voice_icon_click: false,
animationData: {}
})
this.animation = "";
var x = new Date().getTime() - this.data.voice_ing_start_date
if (x < 1000) {
console.log('录音停止,说话小于1秒!')
wx.showModal({
title: '提示',
content: '说话要大于1秒!',
})
recorder.stop();
} else { // 录音停止,开始上传   
recorder.stop();
}
}, // 点击语音图片  
voice_icon_click: function() {
this.setData({
voice_icon_click: !this.data.voice_icon_click
})
},
})

 

本文地址:https://blog.csdn.net/qq_41241504/article/details/85987506

(0)
上一篇 2022年3月22日
下一篇 2022年3月22日

相关推荐