uniapp(vue3)+Node(express)即时通讯

首先我们考虑即时通讯,肯定是双人或者多人聊天,如果你要做单一的,比如当用户下单,立即通知商家(当然有的商家做完商品之后也会通知用户),以下是我探讨的几个点。

  1. uniapp中构建ws
  2. Node中构建ws

uniapp中构建ws

1.构建ws,通常我们都会把他赋给一个值
***我需要特别说一下这个接口的后面/1是什么意思,他表示唯一的,也就是说,如果你想让别人给你发送消息,那别人就会通过这个唯一id值来给你发送。***后续在我们发送的时候我们还需要传递一个发给谁的id
uni.connectSocket({ url: 'ws://localhost:8080/1', complete: () => {} });

2.ws中的一些事件

  1. onOpen :ws已连接
  2. onMessage : 接收消息
  3. onError :打开失败
  4. onClose :已关闭

3.当我们需要发送消息的时候
我们解析以下方法

  1. 其中data表示传递给接收者的信息,其中包括这个接收者id,也就是我们上面提到的/1
  2. success表示发送成功
  3. fail表示发送消息失败
  webSocketTask.value.send({
      data: messageData,
      success: () => {
        console.log('消息发送成功');
		messages.push({isMine:true,content:inputMessage.value})
        inputMessage.value = ''; // 清空输入框
      },
      fail: () => {
        console.error('消息发送失败');
      },
    });
    

完整的uniapp代码

<template>
  <view class="chat-container">
    <scroll-view 
      class="message-list" 
      scroll-y="true" 
      ref="messageList">
      <view class="message" v-for="(message, index) in messages" :key="index">
        <view class="message-content" :class="{ 'my-message': message.isMine }">
			<image src="../../static/icon/我的.png" mode=""></image>
			<text>{{ message.content }}</text>
		</view>
      </view>
    </scroll-view>
    <view class="input-area">
      <input type="text" v-model="inputMessage" placeholder="输入消息" />
      <button @click="sendMessage">发送</button>
    </view>
  </view>
</template>

<script setup>
import { ref, reactive,watch,nextTick } from 'vue';
import { onLoad } from "@dcloudio/uni-app";
const messageList = ref(null);
const messages = reactive([]);
const inputMessage = ref('');
const webSocketTask = ref(null);
const merChantId = ref('')
// 在onLoad生命周期钩子中连接WebSocket
onLoad((option)=>{
	// 默认当前用户的id是1
	
	// 获取商家id
	merChantId.value=option.merchantid
		webSocketTask.value=uni.connectSocket({
				url: 'ws://localhost:8080/1',
				complete: () => {}
			});
	    
	    // 监听WebSocket连接打开事件
	   webSocketTask.value.onOpen((res) => {
	        console.log('WebSocket连接已打开!');
	    });
	    
	    webSocketTask.value.onMessage((message) => {
			console.log(message);
			let data = JSON.parse(message.data)
			messages.push({isMine:false,content:data.text})
	       // const textMessage = JSON.parse(message.data);
	       // messages.value.push({ id: messages.value.length, text: textMessage.text });
	     });
	   
	     webSocketTask.value.onError((err) => {
	       console.error('WebSocket连接打开失败,请检查!', err);
	     });
	   
	     webSocketTask.value.onClose(() => {
	       console.log('WebSocket 已关闭!');
	     });
})
const sendMessage = () => {
   if (inputMessage.value.trim() === '') return;
    const messageData = JSON.stringify({
      text: inputMessage.value,
      to: merChantId._value, // 接收者的用户ID
    });
    webSocketTask.value.send({
      data: messageData,
      success: () => {
        console.log('消息发送成功');
		messages.push({isMine:true,content:inputMessage.value})
        inputMessage.value = ''; // 清空输入框
      },
      fail: () => {
        console.error('消息发送失败');
      },
    });
  // 清空输入框
  // 滚动到底部
};

// 用于确保消息列表在新消息到来时自动滚动到底部

</script>

<style scoped lang="scss">
.chat-container {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.message-list {
  flex-grow: 1;
  padding: 10px;
  background-color: #f2f2f2;
  overflow-y: scroll;
}

.message {
  margin-bottom: 10px;
}

.message-content {
  padding: 8px;
  background-color: #ffffff;
  border-radius: 4px;
  image{
  	  width: 50rpx;
  	  height: 50rpx;
  	  border-radius: 50%;
  }
}

.my-message {
	display: flex;
	    flex-direction: row-reverse;
	
  margin-left: auto; /* 居右显示 */
  background-color: #dcf8c6; /* 自己的消息使用不同颜色 */
  
}

.input-area {
	position: fixed;
	bottom: 0;
	left: 0;
	width: 100%;
  display: flex;
  padding: 10px;
  background-color: #ffffff;
}

input[type="text"] {
  flex-grow: 1;
  margin-right: 10px;
  padding: 10px;
  border: 1px solid #cccccc;
  border-radius: 4px;
}

button {
  white-space: nowrap;
  padding: 10px;
  background-color: #007aff;
  color: white;
  border: none;
  border-radius: 4px;
}
</style>

2.Node中的ws

  1. 首先在node中需要安装一下npm i ws
  2. 在Node中使用
const WebSocket = require('ws');
const http = require('http');

// 创建HTTP服务器
const server = http.createServer((req, res) => {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('WebSocket Server\n');
});

// 创建WebSocket服务器
const wss = new WebSocket.Server({ server });

// 用户列表,用于存储用户连接和相关信息
const users = {};

wss.on('connection', (ws, req) => {
  const userId = req.url.substring(1); // 假设用户ID通过URL传递,如 ws://example.com/userId
  users[userId] = ws;

  ws.on('message', (message) => {
    console.log(`Received message from ${userId}: ${message}`);
    
    // 这里可以根据消息格式进行解析,找到接收方的ID
    // 假设消息是一个JSON字符串,包含发送者和接收者ID以及实际消息内容
    const msg = JSON.parse(message);
    const recipientId = msg.to;

    if (users[recipientId]) {
        if (Buffer.isBuffer(message)) {
            // 处理二进制数据
            const text = message.toString('utf8');
            console.log('Received binary data:', text);
  
            users[recipientId].send(text);

  
          } else {
            console.log('Received message:', message);
            // 处理文本消息
            users[recipientId].send(message);

  
          }     
      // 如果接收者在线,则直接发送消息
    } else {
      // 如果接收者不在线,可以在这里处理离线消息逻辑
      // ...
    }
  });

  ws.on('close', () => {
    console.log(`Connection with ${userId} closed`);
    delete users[userId];
  });
});

server.listen(8080, () => {
  console.log('WebSocket server started on ws://localhost:8080');
});

需要注意的几个点const wss = new WebSocket.Server({ port: 8082 }); 这里的port是端口号。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值