实现IM系统与PC端一致的WebSocket连接,优化聊天功能,支持多端消息同步,更新联系人和会话列表接口,增强用户体验。
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import { randomString } from './uitls'
|
||||
import md5 from 'md5'
|
||||
import { useUserStore } from '@/store/user'
|
||||
|
||||
const baseUrl = import.meta.env.VITE_SERVER_BASEURL
|
||||
@@ -8,66 +8,81 @@ class socket {
|
||||
constructor() {
|
||||
this.socketUrl = baseUrl
|
||||
this.socketStart = false
|
||||
this.socketType = ''
|
||||
this.socketType = 'websocket'
|
||||
this._heartbeatTimer = null
|
||||
this.monitorSocketError()
|
||||
this.monitorSocketClose()
|
||||
this.socketReceive()
|
||||
}
|
||||
|
||||
//update-begin---author:xsl ---date:2026-07-20 for:【APP对接真实IM】系统 WebSocket 地址与 PC 一致-----------
|
||||
/** 构建系统 WebSocket 地址:/websocket/{userId}_{md5(token)} */
|
||||
buildSystemWebSocketUrl() {
|
||||
const userStore = useUserStore()
|
||||
const userId = userStore.userInfo.userid
|
||||
const token = userStore.userInfo.token || ''
|
||||
if (!userId || !this.socketUrl) {
|
||||
return ''
|
||||
}
|
||||
const wsClientId = md5(token)
|
||||
const base = this.socketUrl.replace('https://', 'wss://').replace('http://', 'ws://').replace(/\/$/, '')
|
||||
return `${base}/websocket/${userId}_${wsClientId}`
|
||||
}
|
||||
//update-end---author:xsl ---date:2026-07-20 for:【APP对接真实IM】系统 WebSocket 地址与 PC 一致-----------
|
||||
|
||||
init(socket_type, callback?) {
|
||||
const userStore = useUserStore()
|
||||
if (baseUrl) {
|
||||
if (this.socketStart) {
|
||||
console.log('webSocket已经启动了')
|
||||
} else {
|
||||
this.socketType = socket_type
|
||||
let url =
|
||||
this.socketUrl.replace('https://', 'wss://').replace('http://', 'ws://') +
|
||||
'/' +
|
||||
socket_type +
|
||||
'/' +
|
||||
userStore.userInfo.userid +
|
||||
'_app'
|
||||
if (socket_type == 'eoaNewChatSocket') {
|
||||
let randomMessageId = randomString(6)
|
||||
url =
|
||||
this.socketUrl.replace('https://', 'wss://').replace('http://', 'ws://') +
|
||||
'/eoaNewChatSocket/' +
|
||||
userStore.userInfo.userid +
|
||||
'/' +
|
||||
randomMessageId
|
||||
}
|
||||
console.log('启动this.socketUrl连接地址:', url)
|
||||
// update-begin-author:taoyan date:20220422 for:v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
|
||||
|
||||
let token = userStore.userInfo.token
|
||||
uni.connectSocket({
|
||||
url: url,
|
||||
method: 'GET',
|
||||
protocols: [token],
|
||||
})
|
||||
// update-end-author:taoyan date:20220422 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
|
||||
uni.onSocketOpen((res) => {
|
||||
this.socketStart = true
|
||||
callback && callback()
|
||||
console.log('WebSocket连接已打开!')
|
||||
})
|
||||
/* setTimeout(() => {
|
||||
this.getHeartbeat();
|
||||
}, 5000); */
|
||||
}
|
||||
} else {
|
||||
if (!baseUrl) {
|
||||
console.log('config/baseUrl socketUrl为空')
|
||||
return
|
||||
}
|
||||
if (this.socketStart) {
|
||||
console.log('webSocket已经启动了')
|
||||
callback && callback()
|
||||
return
|
||||
}
|
||||
this.socketType = socket_type || 'websocket'
|
||||
//update-begin---author:xsl ---date:2026-07-20 for:【APP对接真实IM】连接原生 /websocket-----------
|
||||
let url = this.buildSystemWebSocketUrl()
|
||||
if (this.socketType !== 'websocket') {
|
||||
// 兼容旧路径(如历史业务仍传入自定义 type)
|
||||
url =
|
||||
this.socketUrl.replace('https://', 'wss://').replace('http://', 'ws://') +
|
||||
'/' +
|
||||
this.socketType +
|
||||
'/' +
|
||||
userStore.userInfo.userid +
|
||||
'_app'
|
||||
}
|
||||
//update-end---author:xsl ---date:2026-07-20 for:【APP对接真实IM】连接原生 /websocket-----------
|
||||
if (!url) {
|
||||
console.log('WebSocket url 为空,跳过连接')
|
||||
return
|
||||
}
|
||||
console.log('启动this.socketUrl连接地址:', url)
|
||||
const token = userStore.userInfo.token
|
||||
uni.connectSocket({
|
||||
url: url,
|
||||
method: 'GET',
|
||||
protocols: [token],
|
||||
})
|
||||
uni.onSocketOpen((res) => {
|
||||
this.socketStart = true
|
||||
callback && callback()
|
||||
console.log('WebSocket连接已打开!')
|
||||
this.startHeartbeat()
|
||||
})
|
||||
}
|
||||
|
||||
// Socket给服务器发送消息
|
||||
send(data, callback) {
|
||||
const userStore = useUserStore()
|
||||
if (userStore.userInfo.userid) {
|
||||
if (userStore.userInfo.userid && typeof data === 'object' && data !== null) {
|
||||
data.userUid = userStore.userInfo.userid
|
||||
}
|
||||
console.log(data)
|
||||
const payload = typeof data === 'string' ? data : JSON.stringify(data)
|
||||
uni.sendSocketMessage({
|
||||
data: JSON.stringify(data),
|
||||
data: payload,
|
||||
success: () => {
|
||||
callback && callback(true)
|
||||
},
|
||||
@@ -76,61 +91,76 @@ class socket {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
acceptMessage(msg) {
|
||||
console.log(msg)
|
||||
}
|
||||
|
||||
// Socket接收服务器发送过来的消息
|
||||
socketReceive() {
|
||||
uni.onSocketMessage((res) => {
|
||||
console.log('APP:--》收到服务器内容:')
|
||||
let data = JSON.parse(res.data)
|
||||
// console.log('收到服务器内容:', data);
|
||||
//update-begin---author:xsl ---date:2026-07-20 for:【APP对接真实IM】忽略心跳并解析 JSON-----------
|
||||
if (res.data === 'ping' || res.data === 'pong') {
|
||||
return
|
||||
}
|
||||
let data
|
||||
try {
|
||||
data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data
|
||||
} catch (e) {
|
||||
console.log('WebSocket 非 JSON 消息:', res.data)
|
||||
return
|
||||
}
|
||||
//update-end---author:xsl ---date:2026-07-20 for:【APP对接真实IM】忽略心跳并解析 JSON-----------
|
||||
this.acceptMessage && this.acceptMessage(data)
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭Socket
|
||||
closeSocket() {
|
||||
this.stopHeartbeat()
|
||||
uni.closeSocket()
|
||||
this.socketStart = false
|
||||
}
|
||||
|
||||
// 监听Socket关闭
|
||||
monitorSocketClose() {
|
||||
uni.onSocketClose((res) => {
|
||||
console.log('WebSocket 已关闭!')
|
||||
this.socketStart = false
|
||||
this.stopHeartbeat()
|
||||
setTimeout(() => {
|
||||
this.init(this.socketType)
|
||||
}, 3000)
|
||||
})
|
||||
}
|
||||
|
||||
// 监听Socket错误
|
||||
monitorSocketError() {
|
||||
uni.onSocketError(function (res) {
|
||||
uni.onSocketError((res) => {
|
||||
this.socketStart = false
|
||||
console.log('WebSocket连接打开失败,请检查!')
|
||||
})
|
||||
}
|
||||
// 心跳
|
||||
getHeartbeat() {
|
||||
const userStore = useUserStore()
|
||||
this.send(
|
||||
{
|
||||
type: '心跳',
|
||||
userUid: userStore.userInfo.userid,
|
||||
},
|
||||
(val) => {
|
||||
setTimeout(() => {
|
||||
if (val) {
|
||||
// this.getHeartbeat();
|
||||
} else {
|
||||
if (!this.socketStart) {
|
||||
// this.init();
|
||||
}
|
||||
}
|
||||
}, 10000)
|
||||
},
|
||||
)
|
||||
|
||||
//update-begin---author:xsl ---date:2026-07-20 for:【APP对接真实IM】心跳 ping-----------
|
||||
startHeartbeat() {
|
||||
this.stopHeartbeat()
|
||||
this._heartbeatTimer = setInterval(() => {
|
||||
if (!this.socketStart) {
|
||||
return
|
||||
}
|
||||
this.send('ping')
|
||||
}, 55000)
|
||||
}
|
||||
|
||||
stopHeartbeat() {
|
||||
if (this._heartbeatTimer) {
|
||||
clearInterval(this._heartbeatTimer)
|
||||
this._heartbeatTimer = null
|
||||
}
|
||||
}
|
||||
//update-end---author:xsl ---date:2026-07-20 for:【APP对接真实IM】心跳 ping-----------
|
||||
}
|
||||
|
||||
const mySocket = new socket()
|
||||
export default mySocket
|
||||
|
||||
Reference in New Issue
Block a user