2025-12-18 17:36:51 +08:00
|
|
|
|
// let url = "ws://89.40.9.89:2109/mosty-api/mosty-websocket/socket/"; //线上
|
|
|
|
|
|
let url = "ws://155.240.22.30:2109/mosty-api/mosty-websocket/socket/"; //线上
|
2025-12-18 17:18:53 +08:00
|
|
|
|
|
|
|
|
|
|
if(process.env.NODE_ENV === 'development') {
|
|
|
|
|
|
url = "ws://47.108.232.77:9537/mosty-api/mosty-websocket/socket/"; //本地
|
|
|
|
|
|
}
|
2025-04-12 14:54:02 +08:00
|
|
|
|
import {
|
|
|
|
|
|
getItem
|
|
|
|
|
|
} from "@/utils/storage";
|
2025-11-27 14:27:59 +08:00
|
|
|
|
import emitter from "@/utils/eventBus.js"; // 导入事件总线
|
2025-04-12 14:54:02 +08:00
|
|
|
|
class WebSoketClass {
|
2025-11-27 14:27:59 +08:00
|
|
|
|
constructor(props) {
|
|
|
|
|
|
this.ws = null;
|
|
|
|
|
|
this.state = null;
|
|
|
|
|
|
this.reconnectCount = 0;
|
|
|
|
|
|
this.maxReconnectCount = 10;
|
|
|
|
|
|
this.reconnectInterval = 6000;
|
|
|
|
|
|
this.uuid = null; // 保存UUID,用于重连时复用
|
|
|
|
|
|
this.sfzh = null; // 保存身份证号,用于重连时复用
|
|
|
|
|
|
this.fullUrl = null; // 保存完整连接URL,用于重连时复用
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-12 14:54:02 +08:00
|
|
|
|
static getInstance() {
|
2025-11-27 14:27:59 +08:00
|
|
|
|
if (!this.instance) this.instance = new WebSoketClass();
|
|
|
|
|
|
return this.instance;
|
2025-04-12 14:54:02 +08:00
|
|
|
|
}
|
2025-11-27 14:27:59 +08:00
|
|
|
|
|
2025-04-12 14:54:02 +08:00
|
|
|
|
//关闭连接
|
|
|
|
|
|
static close() {
|
2025-11-27 14:27:59 +08:00
|
|
|
|
if (this.instance) {
|
|
|
|
|
|
this.instance.closeConnection();
|
|
|
|
|
|
}
|
2025-04-12 14:54:02 +08:00
|
|
|
|
}
|
2025-11-27 14:27:59 +08:00
|
|
|
|
|
|
|
|
|
|
// 关闭连接的实例方法
|
|
|
|
|
|
closeConnection() {
|
|
|
|
|
|
if (this.ws) {
|
|
|
|
|
|
this.ws.close();
|
|
|
|
|
|
this.ws = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (this.state) {
|
|
|
|
|
|
clearInterval(this.state);
|
|
|
|
|
|
this.state = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
this.reconnectCount = 0;
|
|
|
|
|
|
// 重置UUID,下次连接时生成新的
|
|
|
|
|
|
this.uuid = null;
|
|
|
|
|
|
this.fullUrl = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-12 14:54:02 +08:00
|
|
|
|
// 创建连接
|
|
|
|
|
|
connect(fun) {
|
2025-11-27 14:27:59 +08:00
|
|
|
|
// 首次连接时获取并保存连接参数
|
|
|
|
|
|
if (!this.sfzh) {
|
|
|
|
|
|
this.sfzh = getItem("idEntityCard");
|
|
|
|
|
|
}
|
|
|
|
|
|
// 首次连接时生成并保存UUID
|
|
|
|
|
|
if (!this.uuid) {
|
|
|
|
|
|
this.uuid = this.getUUid();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.sfzh) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 如果还没有完整URL或需要更新,重新构建
|
|
|
|
|
|
if (!this.fullUrl || this.maxReconnectCount == 10) {
|
|
|
|
|
|
this.fullUrl = url + this.sfzh + '/' + this.uuid;
|
|
|
|
|
|
this.reconnectCount = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log('尝试连接WebSocket:', this.fullUrl);
|
|
|
|
|
|
this.ws = new WebSocket(this.fullUrl);
|
|
|
|
|
|
console.log(this.ws);
|
|
|
|
|
|
|
|
|
|
|
|
this.ws.onopen = (e) => {
|
|
|
|
|
|
console.log('WebSocket连接已打开');
|
|
|
|
|
|
// 只有在非重连状态下才重置重连计数
|
|
|
|
|
|
// 避免短暂连接成功后又关闭导致计数重置
|
|
|
|
|
|
if (this.reconnectCount === 0) {
|
|
|
|
|
|
console.log('首次连接成功');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log('重连成功');
|
|
|
|
|
|
// 重连成功后重置计数
|
|
|
|
|
|
// this.reconnectCount = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
this.heartCheck();
|
|
|
|
|
|
this.getMessage();
|
|
|
|
|
|
if (fun) fun(true);
|
|
|
|
|
|
};
|
|
|
|
|
|
this.ws.onclose = (e) => {
|
|
|
|
|
|
console.log(e);
|
|
|
|
|
|
|
|
|
|
|
|
console.log('WebSocket连接已关闭,关闭码:', e.code, '原因:', e.reason);
|
|
|
|
|
|
// 如果是正常关闭(1000)或手动关闭(1001),不进行重连
|
|
|
|
|
|
if (e.code !== 1000 && e.code !== 1001) {
|
|
|
|
|
|
this.handleReconnect(fun);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log('WebSocket正常关闭,不进行重连');
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
this.ws.onerror = (e) => {
|
|
|
|
|
|
console.error('WebSocket连接错误:', e);
|
|
|
|
|
|
this.handleReconnect(fun);
|
|
|
|
|
|
};
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('创建WebSocket连接失败:', error);
|
|
|
|
|
|
this.handleReconnect(fun);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.error('获取用户身份证号失败,无法建立WebSocket连接');
|
|
|
|
|
|
if (fun) fun(false);
|
|
|
|
|
|
}
|
2025-04-12 14:54:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 心跳机制
|
|
|
|
|
|
heartCheck() {
|
2025-11-27 14:27:59 +08:00
|
|
|
|
if (this.state) {
|
|
|
|
|
|
clearInterval(this.state);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-12 14:54:02 +08:00
|
|
|
|
this.state = setInterval(() => {
|
2025-11-27 14:27:59 +08:00
|
|
|
|
try {
|
|
|
|
|
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
|
|
|
|
this.ws.send("/heart");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log('WebSocket未连接,停止心跳');
|
|
|
|
|
|
clearInterval(this.state);
|
|
|
|
|
|
this.state = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('心跳发送失败:', error);
|
|
|
|
|
|
clearInterval(this.state);
|
|
|
|
|
|
this.state = null;
|
2025-04-12 14:54:02 +08:00
|
|
|
|
}
|
2025-11-27 14:27:59 +08:00
|
|
|
|
}, 6000);
|
2025-04-12 14:54:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取uuid
|
|
|
|
|
|
getUUid() {
|
|
|
|
|
|
var s = [];
|
|
|
|
|
|
var hexDigits = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
|
|
|
|
for (var i = 0; i < 32; i++) {
|
|
|
|
|
|
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
s[14] = "4";
|
|
|
|
|
|
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
|
|
|
|
|
|
s[8] = s[13] = s[18] = s[23];
|
|
|
|
|
|
let uuid = s.join("");
|
|
|
|
|
|
return uuid
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-27 14:27:59 +08:00
|
|
|
|
// 处理重连
|
|
|
|
|
|
handleReconnect(fun) {
|
|
|
|
|
|
if (this.reconnectCount >= this.maxReconnectCount) {
|
|
|
|
|
|
console.log('达到最大重连次数,停止重连');
|
|
|
|
|
|
if (fun) fun(false);
|
|
|
|
|
|
return;
|
2025-04-12 14:54:02 +08:00
|
|
|
|
}
|
2025-11-27 14:27:59 +08:00
|
|
|
|
this.reconnectCount++;
|
|
|
|
|
|
console.log(`尝试第${this.reconnectCount}次重连...`);
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
this.connect(fun);
|
|
|
|
|
|
}, this.reconnectInterval);
|
2025-04-12 14:54:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 接收发送消息
|
|
|
|
|
|
getMessage() {
|
|
|
|
|
|
this.ws.onmessage = (e) => {
|
2025-11-27 14:27:59 +08:00
|
|
|
|
console.log(e);
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (e.data) {
|
|
|
|
|
|
let newsDate = JSON.parse(e.data);
|
|
|
|
|
|
// 根据消息类型发射相应的事件
|
|
|
|
|
|
if (newsDate.type === '01') {
|
|
|
|
|
|
// 触发音频播放
|
|
|
|
|
|
console.log('触发音频播放');
|
|
|
|
|
|
emitter.emit('openYp', newsDate.data); // 传递消息数据
|
|
|
|
|
|
}
|
|
|
|
|
|
// else if (newsDate.type === 'ALARM_STOP' || newsDate.type === 'warning_stop') {
|
|
|
|
|
|
// // 触发音频停止
|
|
|
|
|
|
// emitter.emit('closeYp');
|
|
|
|
|
|
// } else if (newsDate.type === 'POSITION_UPDATE') {
|
|
|
|
|
|
// // 位置更新事件
|
|
|
|
|
|
// emitter.emit('positionUpdate', newsDate.data);
|
|
|
|
|
|
// } else if (newsDate.type === 'STATUS_UPDATE') {
|
|
|
|
|
|
// // 状态更新事件
|
|
|
|
|
|
// emitter.emit('statusUpdate', newsDate.data);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// // 通用消息事件
|
|
|
|
|
|
// emitter.emit('webSocketMessage', newsDate);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('处理WebSocket消息失败:', error);
|
|
|
|
|
|
// 如果是心跳响应,不报错
|
|
|
|
|
|
if (e.data !== '/heart') {
|
|
|
|
|
|
console.error('消息内容:', e.data);
|
|
|
|
|
|
}
|
2025-04-12 14:54:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
export default WebSoketClass;
|