ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

微信小程序中聊天室的构建

2022-01-18 11:33:02  阅读:149  来源: 互联网

标签:box 聊天室 url 微信 content 构建 data options wx


html书写如下:

<!--pages/chatroomDetail/chatroomDetail.wxml-->

<view class="bgc"></view>
<view wx:if="{{loadingSocket}}">
  聊天室连接中...
</view>
<!-- 可以滚动的视图 -->
<scroll-view class="chat-container" scroll-y scroll-into-view="{{'k'+list[list.length-1].id}}">
<!-- 每一条消息 -->
  <view class="chat-item {{userName == item.from ? 'my-msg' : ''}}" wx:for="{{list}}" id="{{'k'+item.id}}">
    <view class="avatar">
      <image src="{{item.avatar}}">
      </image>
    </view>
    <view class="msg-box">
      <view class="nickname" wx:if="{{userName !== item.from}}">
        {{item.nickName}}
      </view>
      <view wx:if="{{item.type == 1}}" class="content-box">
        {{item.content}}
      </view>
      <view wx:elif="{{item.type==2}}" class="img-content" >
        <image src="{{item.content}}" mode="widthFix">
        </image>
      </view>
    </view>
  </view>
</scroll-view>

<view class="send-msg-container">
<!-- 做简易双向绑定  -->
    <input class="input" type="text" model:value="{{value}}" />
  <view class="action-box">
    <van-icon name="smile-o" class="icon" bind:tap="sendImg" />
    <van-button class="send-btn" square type="primary" bind:tap="sendMsg">发送</van-button>
  </view>
</view>

css书写如下:

/* pages/chatroomDetail/chatroomDetail.wxss */
/* pages/chat/index.wxss */
.bgc {
  background-color: #E1E0E5;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
}
/* *****************消息区域***************** */
.chat-container {
  padding-bottom: 110rpx;
  height: 100vh;
  box-sizing: border-box;
}


.chat-item{
  display: flex;
  padding: 20rpx 0;
}

.avatar{
  width: 120rpx;
  flex-shrink: 0;
  display: flex;
  justify-content: center;  
}

.avatar image {
  width: 90rpx;
  height: 90rpx;
  border-radius: 10rpx;
}

.msg-box{
  padding: 0 10rpx;
}

.content-box{
  background-color: #fff;
  padding: 15rpx 20rpx;
  border-radius: 5rpx;
  margin-top: 10rpx;
  position: relative;
  max-width: 400rpx;
}

.content-box::before {
  content: " ";
  background-color: white;
  height: 25rpx;
  width: 25rpx;
  position: absolute;
  left: -8rpx;
  top: 22rpx;
  transform: rotate(45deg);
}


.img-content{
}

.img-content image {
  max-width: 400rpx;
  border-radius: 10rpx;
}

/* *****************消息区域***************** */


/* *****************发送消息区域***************** */
.send-msg-container {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  display: flex;
  background-color: #F7F7F7;
  /* background-color: hotpink; */
  height: 110rpx;
  align-items: center;
  box-sizing: border-box;
  padding: 0 10rpx;
}

.input {
  background-color: #FFFFFF;
  flex-grow: 1;
  margin: 0 10rpx;
  height: 68rpx;
  border-radius: 10rpx;
  padding: 0 15rpx;
  box-sizing: border-box;
}

.action-box{
  display: flex;
  width: 200rpx;
  flex-shrink: 0;
}

.action-box .icon {
  font-size: 55rpx;
  color: #282828;
}

.action-box .send-btn .van-button {
  height: 60rpx;
  margin-left: 14rpx;
}


/* *****************发送消息区域***************** */



/* *****************我发送的消息***************** */
.my-msg {
  flex-direction: row-reverse;
}
view{
  word-break: break-all;
}

.my-msg .content-box::before {
  left: auto;
  right: -8rpx;
}
/* *****************我发送的消息***************** */

js书写如下:

// pages/chatroomDetail/chatroomDetail.js
import {
  uploadFile
} from "../../utils/request"

const app = getApp()

// pages/chat/index.js
Page({
  /**
   * 页面的初始数据
   */
  data: {
    loadingSocket: true,  //websocket是否连接成功 
    value: "", //输入框的内容
    list: [],//聊天室的消息
    userName: ""// 当前用户的名字
  },

  /**
   * 生命周期函数--监听页面加载
   */
  // 场景1:进入聊天室 需要先向服务器查询历史消息
  onl oad: function (options) {
    // 首先做了是否登录判断
    // 执行完第一步.then时在执行下面的程序
    app.globalData.loginPromise.then(()=>{
      console.log(app.globalData);
      if (app.globalData.isLogin) {
        // 这时已经确定登录成功了 
        const userInfo = app.globalData.user
        // 准备数据
        console.log(this)
        // 在构造器中创建userName , 下次使用就直接使用this.userName
        this.userName = userInfo.loginName;
        // 修改data里面的值,并且将渲染层也修改点 
        this.setData({
          userName: this.userName
        })
        // 随便输入
        // courseId 分组id 通过这个courseId来标识不同的聊天室
        this.groupId = "web16" + options.id
        // nickName 昵称
        this.nickName = userInfo.userName
        // 头像
        this.avatar = userInfo.avatar
        //  建立联系完毕
        // 去建立联系; 
        this.connectSocket();
  
        // 监听链接打开
        this.onSocketOpen()
  
        // 接受服务器消息
        this.onSocketMessage()
  
      } else {
        // 未登录 
        wx.reLaunch({
          url: '../mine/mine',
        })
      }
    })
  },

  connectSocket() {
    // const url = `ws://10.9.0.51:13000?username=${this.userName}&password=123&courseId=${this.groupId}&nickName=${this.nickName}&avatar=${this.avatar}`
    const url = `wss://showme2.myhope365.com/websocketChat?username=${this.userName}&password=123&courseId=${this.groupId}&nickName=${this.nickName}&avatar=${this.avatar}`
    // 1.建立链接第一步建立联系
    wx.connectSocket({
      // 要链接的socket服务器的地址
      url,
    })
  },

  onSocketOpen() {
    // 监听链接建立成功
    wx.onSocketOpen((result) => {
      // 当我们socket链接打开之后执行
      // 需要保证的时候,我们在发送消息之前一定要先链接成功
      console.log("socket链接已经打开了");
      // 控制聊天室连接中...显示与否
      this.setData({
        loadingSocket: false
      })
      // 链接打开之后加载历史消息
      this.getHistory()
      // 添加心跳检测  心跳机制是每隔一段时间会向服务器发送一个数据包,
      // 告诉服务器自己还活着,同时客户端会确认服务器端是否还活着,如果还活着的话,就会回传一个数据包给客户端来确定服务器端也还活着,
      // 否则的话,有可能是网络断开连接了。需要重连~
      this.intervalId = setInterval(() => {
        wx.sendSocketMessage({
          data: JSON.stringify({
            "cmd":13, // 固定参数 与后端人员规定的
            "hbbyte":"-127" // 固定参数 
          }),
        })
      }, 5000);
    })
  },

  onSocketMessage() {
    // 接受服务端的消息
    // 服务端每发送一次消息 都会进入回调函数
    wx.onSocketMessage((result) => { 
      // 服务器会返回一个字符串 
      const data = JSON.parse(result.data)
      console.log(data)
      // 针对不同类型的消息进行一些处理
      // 如果comand为11的话 就证明是新消息; 
      if (data.command === 11) {
        // 有新消息
        this.data.list.push(data.data)
        this.setData({
          list: this.data.list
        })
        //  
      } else if (data.command === 20 && data.code === 10018) {
        // 服务端返回了历史消息
        this.setData({
          list: data.data.groups[this.groupId]
        })
      }
    })
  },

  getHistory() {
    const historyBody = {
      cmd: 19, // 命令 和后端规定好的规则 19为查看历史消息
      type: 1, // 类型 固定值 1为查看文本消息
      groupId: this.groupId, //  分组的id
      userId: this.userName  // 用户id(这里可以用loginName)
    }
// 接受字符串类型
// 发送给服务端
    wx.sendSocketMessage({
      data: JSON.stringify(historyBody), //将对象转成字符串. 
    })
  },
// 发送消息
  sendSocketMsg(content, type) {
    console.log(new Date().getTime())
    const msgBody = {
      from: this.userName, // 发送人,当前用户的用户名
      createTime: new Date().getTime(), // 发送时间 getTime 为获取时间戳
      cmd: 11, // 命令固定内容  11为与后端规定为发送消息
      group_id: this.groupId, // 分组id。  想要发送到哪个组里
      chatType: 1, //  聊天类型 固定内容
      msgType: 0, // 消息类型 固定内容
      content:content, // 消息内容,自己设计结构,比如你想发送图片(图片上传的接口)
      nickName: this.nickName, // 用户昵称
      avatar: this.avatar, // 用户头像
      type// 消息类型。 你可以自己设计,发送过去是什么,返回的就是什么(1: 普通文本 2: 图片 3:点赞 4, 送花)
    }
    wx.sendSocketMessage({
      data: JSON.stringify(msgBody),
    })
  },
  // 点击发送按钮触发 
  sendMsg() {
    if (!this.data.value) {
      wx.showToast({
        title: '请输入消息内容',
        icon: "none"
      })
      return
    }

    this.sendSocketMsg(this.data.value, "1")

    this.setData({
      value: ""
    })
  },
  sendImg() {
    // 图片上传发送
    uploadFile('https://showme2.myhope365.com/api/nos/upload/image', "file", {
      'fileUseForEnum': 'DEFAULT'
    }).then(res => {
      this.sendSocketMsg(res.url, "2")
    })
  },

  onUnload(){
    // 进行卸载操作
    wx.closeSocket({
      code: 1000,
    })
    console.log(1)
    // 清除计时器
    clearInterval(this.intervalId)
  }
})

 在untils中写request.js,代码如下:

// 作用:封装接口请求
// 输入: 
// 地址
// 方式
// 请求头
// 请求体
// ...
// 返回请求到的数据res
// 返回一个Promise,通过Promise对象拿到请求的结果
function request(options) {
  // 请求拦截器
  //  ...
  // 1. 加一些统一的参数,或者配置
  if (!options.url.startsWith("https://") && !options.url.startsWith("http://")) {
    options.url = "https://showme2.myhope365.com" + options.url
  }

  let header = {
    "content-type": "application/x-www-form-urlencoded",
    "cookie": wx.getStorageSync("cookie") || ""
  };
  if (options.header) {
    header = {
      ...header,
      ...options.header
    }
  }

  return new Promise((reslove, reject) => {
    // 调用接口
    wx.request({
      // 默认的配置
      // 加载传入的配置
      ...options,
      header,
      success(res) {
        // 响应拦截器,所有接口获取数据之前,都会先执行这里
        //  1. 统一的错误处理
        if (res.statusCode != 200) {
          wx.showToast({
            title: '服务器异常,请联系管理员',
          })
        }

        reslove(res)
      },
      fail(err) {
        reject(err)
      }
    })
  })
}

export function get(url, options = {}) {
  return request({
    url,
    ...options
  })
}

export function post(url, data, options = {}) {
  return request({
    url,
    data,
    method: "POST",
    ...options
  })
}


export function uploadFile(url, name = "file", formData = {}, options = {}) {
  return new Promise((reslove, reject) => {
    // 图片上传发送
    wx.chooseImage({
      success: res => {
        const tempFilePaths = res.tempFilePaths
        wx.uploadFile({
          //仅为示例,非真实的接口地址
          url,
          filePath: tempFilePaths[0],
          // 上传文件对应的key值,这个值在接口文档里找
          name,
          // 除了文件之外额外的参数
          formData,
          header: {
            "cookie": wx.getStorageSync("cookie") || ""
          },
          ...options,
          success: res => {
            // 请求成功的回调
            const data = JSON.parse(res.data)
            console.log(data)
            reslove(data)
          }
        })
      }
    })
  })
}

 

 

标签:box,聊天室,url,微信,content,构建,data,options,wx
来源: https://blog.csdn.net/Insideo/article/details/122556151

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有