Files
lilishop-uniapp/pages/promotion/live/utils/liveMqtt.js
Yer11214 349ffa4f34 refactor: 重构多个组件以支持 Vue 3 语法和功能
- 将多个组件转换为 `<script setup>` 语法,提升可读性和性能
- 优化状态管理和事件处理逻辑,简化代码结构
- 更新样式和布局以适应新组件结构
- 添加新功能和修复已知问题,提升用户体验
2026-07-08 18:37:11 +08:00

241 lines
6.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 直播 MQTT 连接管理(由 saas-uni-v3 useMqtt 迁移)
*/
// #ifndef MP-WEIXIN
import { createMqttClient } from "../mqtt/mqtt.js";
export class LiveMqttService {
constructor(liveId, userId) {
this.liveId = liveId;
this.userId = userId;
this.mqttClient = null;
this.isMqttConnected = false;
this.fallbackMode = false;
this.reconnectAttempts = 0;
this.mqttReconnectTimer = null;
this.lastHeartbeatTime = null;
this.heartbeatCheckTimer = null;
this.maxReconnectAttempts = 60;
this.reconnectInterval = 10000;
this.messageHandlers = {};
}
setMessageHandlers(handlers) {
this.messageHandlers = handlers || {};
}
initMqtt() {
if (this.mqttClient) return;
if (!this.liveId || !this.userId) {
console.warn("直播ID或用户ID不完整跳过MQTT初始化");
this.fallbackMode = true;
return;
}
const clientId = `${this.userId}-${this.liveId}-${Date.now()}`;
try {
const topicList = [
{
topic: `live/goods/${this.liveId}`,
qos: 1,
handler: (msg, topic) => this.messageHandlers.onGoodsMessage?.(msg, topic),
},
{
topic: `live/goods/${this.liveId}/#`,
qos: 1,
handler: (msg, topic) => this.messageHandlers.onGoodsMessage?.(msg, topic),
},
{
topic: `live/coupon/${this.liveId}`,
qos: 1,
handler: (msg, topic) => this.messageHandlers.onCouponMessage?.(msg, topic),
},
{
topic: `live/coupon/${this.liveId}/#`,
qos: 1,
handler: (msg, topic) => this.messageHandlers.onCouponMessage?.(msg, topic),
},
{
topic: `live/live/${this.liveId}`,
qos: 1,
handler: (msg, topic) => this.messageHandlers.onLiveMessage?.(msg, topic),
},
{
topic: `live/blacklist/${this.liveId}/${this.userId}`,
qos: 1,
handler: (msg, topic) => this.messageHandlers.onBlacklistMessage?.(msg, topic),
},
{
topic: "live/keepalive",
qos: 1,
handler: (msg) => this.handleKeepaliveMessage(msg),
},
{
topic: `live/push/${this.liveId}`,
qos: 1,
handler: (msg, topic) => this.messageHandlers.onPushStream?.(msg, topic),
},
];
this.mqttClient = createMqttClient({
clientId,
topicHandlers: topicList,
});
this.mqttClient
.onConnected(() => {
console.log("✅ MQTT连接成功");
this.isMqttConnected = true;
this.fallbackMode = false;
this.stopMqttReconnect();
this.reconnectAttempts = 0;
this.startHeartbeatCheck();
})
.onErrorOccurred((error) => this.handleMqttFailure(error))
.onClosed(() => this.handleMqttFailure())
.onClientOffline(() => this.handleMqttFailure());
this.mqttClient.connect();
} catch (error) {
console.error("❌ MQTT初始化失败:", error);
this.handleMqttFailure(error);
}
}
handleKeepaliveMessage(message) {
console.log("[MQTT keepalive]", message);
this.lastHeartbeatTime = Date.now();
}
handleMqttFailure(error) {
if (error) console.error("MQTT错误:", error);
this.disconnectMqtt(false);
if (!this.fallbackMode) {
console.log("❗MQTT异常启动备用模式和重连机制");
this.fallbackMode = true;
}
this.isMqttConnected = false;
this.startMqttReconnect();
}
disconnectMqtt(resetFallback = true) {
try {
if (this.mqttClient) {
this.mqttClient.disconnect();
this.mqttClient = null;
console.log("🔌 MQTT连接已断开");
}
} catch (error) {
console.error("断开MQTT连接时出错:", error);
}
this.isMqttConnected = false;
this.stopMqttReconnect();
if (resetFallback) {
this.fallbackMode = false;
}
}
startMqttReconnect() {
if (this.mqttReconnectTimer) return;
console.log(`开始MQTT重连机制间隔${this.reconnectInterval}ms`);
this.mqttReconnectTimer = setInterval(() => {
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
console.log(`已达到最大重连次数${this.maxReconnectAttempts},停止重连`);
this.stopMqttReconnect();
return;
}
this.reconnectAttempts++;
console.log(`MQTT重连尝试 ${this.reconnectAttempts}/${this.maxReconnectAttempts}`);
try {
if (this.mqttClient) {
this.mqttClient.disconnect();
this.mqttClient = null;
}
} catch (error) {
console.warn("断开旧MQTT连接失败:", error);
}
this.initMqtt();
}, this.reconnectInterval);
}
stopMqttReconnect() {
if (this.mqttReconnectTimer) {
clearInterval(this.mqttReconnectTimer);
this.mqttReconnectTimer = null;
}
this.reconnectAttempts = 0;
}
startHeartbeatCheck() {
if (this.heartbeatCheckTimer) return;
this.heartbeatCheckTimer = setInterval(() => {
if (!this.isMqttConnected || !this.lastHeartbeatTime) return;
const timeSinceLastHeartbeat = Date.now() - this.lastHeartbeatTime;
if (timeSinceLastHeartbeat > 30000) {
console.warn("⚠️ MQTT心跳超时主动重连");
if (this.mqttClient) {
try {
this.mqttClient.disconnect();
this.mqttClient = null;
} catch (error) {
console.warn("断开假死MQTT连接失败:", error);
}
}
this.isMqttConnected = false;
this.lastHeartbeatTime = null;
this.mqttClient = null;
this.initMqtt();
}
}, 10000);
}
stopHeartbeatCheck() {
if (this.heartbeatCheckTimer) {
clearInterval(this.heartbeatCheckTimer);
this.heartbeatCheckTimer = null;
}
}
isConnected() {
return this.isMqttConnected;
}
cleanup() {
this.stopHeartbeatCheck();
this.stopMqttReconnect();
this.disconnectMqtt();
}
}
// #endif
// #ifdef MP-WEIXIN
export class LiveMqttService {
constructor() {}
set messageHandlers() {}
setMessageHandlers() {}
initMqtt() {}
isConnected() {
return false;
}
get mqttClient() {
return null;
}
cleanup() {}
}
// #endif