小程序 h5 使用 webSocket 实现实时对话

<div class="dialogBox">
    <div class="dialogCont" :style="{ height: height }" ref="mainScrollRef" @scroll="scrollEvent">
      <van-loading class="showTime" v-if="request.loading" type="circular" size="16">{{ request.loadText }}</van-loading>
      <div class="itemBox" v-for="(item, index) in dialogList" :key="index" :id="`msg-${item.id}`">
        <text class="showTime">{{ item.currentTimeIntervalString }}</text>
        <div class="cont_item_l" v-if="item.fromUserId !== userId || item.other">
          <img class="avatar" :src="getAvatar('fromUserAvatar')" />
          <text class="word" v-if="item.content && item.type === 0"> {{ item.content }}</text>
          <van-image width="50%" :src="getImgMessage(item.content?.fileKey || item.fileKey)" v-if="item.type === 1" />
        </div>
        <div class="cont_item_r" v-else>
          <van-image width="50%" :src="getImgMessage(item.fileKey)" v-if="item.type === 1" />
          <text class="word" v-if="item.content && item.type === 0">{{ item.content }}</text>
          <img class="avatar" :src="getAvatar('toUserAvatar')" />
        </div>
      </div>
    </div>
    <div class="fool_input">
          <van-cell-group inset class="input">
            <van-field v-model="newsInput" rows="1" autofocus maxlength="200" @focus="headerShow" @blur="inputBlur"
              :autosize="{ maxHeight: 100 }" ref="field" type="textarea" />
          </van-cell-group>
          <van-icon name="add-o" v-if="!showFunction" color="#5E5F66" size="22" />
          <van-icon name="close" v-else color="#5E5F66" size="22"  />
        </div>
        <van-button v-if="newsInput" type="success" size="mini" @click="sendMsg(newsInput, 0)">发送</van-button>
      </div>
      <van-grid v-if="showFunction" :border="false" class="grid_list">
        <van-grid-item>
          <div class="item">
            <van-uploader :before-read="beforeRead" :after-read="afterRead" :max-size="isOverSize">
              <img src="./images/album.png" alt="album">
            </van-uploader>
            <text>相册</text>
          </div>
        </van-grid-item>
 </div>


<script setup lang="ts">

const userId = '123456'  //发起人id
const token = '154665464454354'
const toUserId = '1666666'
const sessionId = '6666' //会话id

//创建webSocket 会话
const initWebSocket = (userId, sessionId) => {
  console.log(userId, "userId", token)
  websock.value = new WebSocket(`${webSocketUrl}/${userId}?Authorization=${token}`)
  websock.value.onopen = websocketonopen
  websock.value.onerror = websocketonerror
  websock.value.onmessage = websocketonmessage
  websock.value.onclose = websocketclose
  console.log('创建会话开始')
}
//websocket连接成功
const websocketonopen = () => {
  console.log('WebSocket连接成功')
}
//websocket连接失败 
let cont = 0
const websocketonerror = e => {
  console.log('WebSocket连接发生错误', e)
  if (userId != null && cont <= 16) {
    if (sessionId != null) {
      initWebSocket(userId, sessionId)
      cont++
    }
  }
}
//websocket关闭
const websocketclose = e => {
  console.log('断开连接', e);
}
//websocket发送消息接收
const websocketonmessage = (e) => {
  let data = JSON.parse(e?.data) 
  dialogList.value.push(data)
  console.log(dialogList.value, "实时接收的聊天内容--") 
  setPageScrollTo()//
   
}
// 输入框消息发送
const field = ref()
const sendMsg = (message, type) => {
  if (!message.replace(/\n/g, '').trim()) {
    newsInput.value = ''
    Toast('不能发送空白消息')
    return
  }
  let params = {
    id: `${new Date().getTime()}`,
    fromUserId: userId,
    message,
    toUserId: toUserId,
    type
  }
  dialogList.value.push({ params})
  websock.value.send(params)
  type === 0 && (newsInput.value = '') //清空输入框
  getHight('.fool_input')
  setPageScrollTo()
  field.value.focus()
}


//图片上传成功后
const fileObj = ref({})
const afterRead = async (file) => {
  const formData = new FormData()
  formData.append('file', file.file)
  // const { fileKey } = await uploadFile(formData)
  fileObj.value = await uploadFile(formData)
  sendMsg(fileObj.value.fileKey, 1)
}
// 动态获取高度
const getHight = (val?) => {
  let view = document.querySelector(val ? val : '.cont_fool') as HTMLElement
  height.value = `calc(100vh - ${view.getBoundingClientRect().height}px)`
}
// 设置页面滚动位置
const setPageScrollTo = (selector?) => {
  if (!selector) {
    nextTick(() => {
      mainScrollRef.value.scrollTo({ top: mainScrollRef.value.scrollHeight }) 
    })
    return
  }
  let view = document.querySelector(selector) as HTMLElement
  nextTick(() => {
    const selectorPosition = view.getBoundingClientRect().top
    const scrollEl = unref(mainScrollRef)
    // -30 为多显示出大半个消息的高度,示意上面还有信息。
    scrollEl.scrollTo({ top: selectorPosition - 30 })
  })
}
//  监听滚动
const scrollEvent = (e) => {
  //  滚动到顶部
  if (e.srcElement.scrollTop < 5) {
    getHistoryMessage()
  }
}


//  监听滚动
const scrollEvent = (e) => {
  //  滚动到顶部
  if (e.srcElement.scrollTop < 5) {
    getHistoryMessage()
  }
} 
onMounted(() => { 
  //页面首次进来 就开始创建会话
  initWebSocket(userId, sessionId) 
})

onUnmounted(() => {
  //离开页面 断开会话
  unref(websock)?.close() 
})
</script>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值