1
0
forked from dyf/APP
# Conflicts:
#	pages.json
#	unpackage/dist/dev/app-plus/app-config-service.js
#	unpackage/dist/dev/app-plus/app-service.js
#	unpackage/dist/dev/app-plus/app-view.js
#	unpackage/dist/dev/app-plus/manifest.json
#	utils/request.js
This commit is contained in:
liub
2025-08-11 15:21:37 +08:00
126 changed files with 3977 additions and 727 deletions

View File

@ -1,5 +1,5 @@
// 兼容性补丁:为 Paho MQTT 提供 uni-app 环境下的 WebSocket 实现
(function (root) {
(function(root) {
// 如果未能找到全局对象,则无法应用补丁。
if (!root) {
console.error("MQTT Polyfill: 未能找到全局对象 (global/window/self 均未定义)。");
@ -10,7 +10,7 @@
if (typeof root.WebSocket !== 'undefined') {
return;
}
console.log("MQTT Polyfill: 正在为 uni-app 应用 WebSocket 兼容性补丁。");
class WebSocket {
@ -26,8 +26,11 @@
const errText = JSON.stringify(err) || "Empty error object";
console.error(`uni.connectSocket 失败: ${errText}`);
if (this.onerror) {
const errorMessage = (err && err.errMsg) ? err.errMsg : "uni.connectSocket call failed";
this.onerror({ message: errorMessage });
const errorMessage = (err && err.errMsg) ? err.errMsg :
"uni.connectSocket call failed";
this.onerror({
message: errorMessage
});
}
}
});
@ -53,22 +56,29 @@
console.error(`WebSocket polyfill 错误: ${errText}`);
if (this.onerror) {
// Paho expects an object that can be stringified, not a real Error object.
const errorMessage = (err && err.errMsg) ? err.errMsg : "WebSocket connection failed in uni-app";
this.onerror({ message: errorMessage });
const errorMessage = (err && err.errMsg) ? err.errMsg :
"WebSocket connection failed in uni-app";
this.onerror({
message: errorMessage
});
}
});
socketTask.onMessage((res) => {
if (this.onmessage) {
// Paho 期望事件对象有一个 'data' 属性
this.onmessage({ data: res.data });
this.onmessage({
data: res.data
});
}
});
}
send(data) {
if (this.readyState === WebSocket.OPEN) {
this._socketTask.send({ data: data });
this._socketTask.send({
data: data
});
} else {
console.error('WebSocket polyfill: send() 在非 OPEN 状态下被调用。');
throw new Error('WebSocket is not open');
@ -109,7 +119,7 @@ import Paho from 'paho-mqtt';
import allConfigs from '../config/index.js';
// 根据环境选择正确的配置
const env = 'development';//production //开发of线上 改这里就行
const env = 'production'; //production //开发of线上 改这里就行
const config = allConfigs[env];
class MqttClient {
@ -123,88 +133,147 @@ class MqttClient {
password: config.MQTT_PASSWORD,
};
this.onConnectCallback = null;
this.messageCallbacks = new Map(); // 使用 Map 存储不同主题的回调
this.messageCallbacks = new Map();
this.isReconnecting = false;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 10;
this.reconnectTimeoutId = null;
this.manualDisconnect = false;
this.client = new Paho.Client(
this.options.host,
Number(this.options.port),
"/mqtt",
this.options.clientId
);
this.setCallbacks();
}
setCallbacks() {
this.client.onConnectionLost = (responseObject) => {
if (responseObject.errorCode !== 0) {
console.log("MQTT连接丢失: " + responseObject.errorMessage);
uni.$emit('mqttConnectionLost', {
error: responseObject.errorMessage,
timestamp: Date.now()
});
if (!this.manualDisconnect) {
this.startReconnecting();
}
}
};
this.client.onMessageArrived = (message) => {
const topic = message.destinationName;
const payload = message.payloadString;
console.log(`收到消息, 主题: ${topic}, 内容: ${payload}`);
const potentialJsons = payload.replace(/}\s*{/g, '}|{').split('|');
potentialJsons.forEach(jsonString => {
if (jsonString.trim() === '') return;
if (this.messageCallbacks.has(topic)) {
this.messageCallbacks.get(topic)(jsonString);
}
});
};
}
/**
* 连接到 MQTT Broker
* @param {Function} onConnectCallback - 连接成功后的回调函数
*/
connect(onConnectCallback) {
const brokerUrl = this.options.host;
const brokerPort = this.options.port;
console.log(`正在连接MQTT: ${brokerUrl}:${brokerPort}/mqtt`);
if (this.client && this.client.isConnected()) {
console.log('MQTT客户端已连接。');
if (onConnectCallback) onConnectCallback();
return;
}
this.manualDisconnect = false;
this.onConnectCallback = onConnectCallback;
console.log(`正在连接MQTT: ${this.options.host}:${this.options.port}/mqtt`);
try {
// Paho-MQTT 的客户端需要 host, port, path, clientId
this.client = new Paho.Client(brokerUrl, Number(brokerPort), "/mqtt", this.options.clientId);
this.onConnectCallback = onConnectCallback;
// 设置回调
this.client.onConnectionLost = (responseObject) => {
if (responseObject.errorCode !== 0) {
console.log("MQTT连接丢失: " + responseObject.errorMessage);
// 可以在此添加重连逻辑
}
};
this.client.onMessageArrived = (message) => {
const topic = message.destinationName;
const payload = message.payloadString;
console.log(`收到消息, 主题: ${topic}, 内容: ${payload}`);
if (this.messageCallbacks.has(topic)) {
// 调用该主题对应的回调
this.messageCallbacks.get(topic)(payload);
}
};
const connectOptions = {
timeout: 4,
timeout: 10, // 增加连接超时时间,应对网络波动
keepAliveInterval: 30, // 明确设置心跳间隔为30秒
userName: this.options.username,
password: this.options.password,
useSSL: false, // 如果是 wss, 需要设置为 true
useSSL: false,
cleanSession: true,
onSuccess: () => {
console.log('MQTT连接成功');
this.reconnectAttempts = 0;
this.isReconnecting = false;
clearTimeout(this.reconnectTimeoutId);
this.resubscribe();
if (this.onConnectCallback) {
this.onConnectCallback();
}
},
onFailure: (message) => {
console.error('MQTT连接失败:', message.errorMessage);
this.disconnect();
if (!this.manualDisconnect) {
this.startReconnecting();
}
}
};
this.client.connect(connectOptions);
} catch (error) {
console.error('MQTT客户端初始化失败:', error);
console.error('MQTT客户端连接时发生异常:', error);
if (!this.manualDisconnect) {
this.startReconnecting();
}
}
}
startReconnecting() {
if (this.isReconnecting || this.manualDisconnect) {
return;
}
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
console.error('MQTT: 达到最大重连次数,已放弃。');
this.isReconnecting = false;
this.reconnectAttempts = 0;
return;
}
this.isReconnecting = true;
this.reconnectAttempts++;
const delay = 1000 * Math.pow(2, this.reconnectAttempts - 1);
console.log(`MQTT: 第 ${this.reconnectAttempts} 次重连将在 ${delay / 1000}s 后开始...`);
this.reconnectTimeoutId = setTimeout(() => {
if (!this.manualDisconnect) {
this.connect(this.onConnectCallback);
}
}, delay);
}
resubscribe() {
if (!this.client || !this.client.isConnected()) {
return;
}
console.log('MQTT: 重新订阅所有主题...');
for (const [topic] of this.messageCallbacks) {
console.log(`重新订阅: ${topic}`);
this.client.subscribe(topic, {
qos: 1
});
}
}
/**
* 订阅主题
* @param {String} topic - 需要订阅的主题
* @param {Function} onMessageCallback - 收到该主题消息后的回调函数
*/
subscribe(topic, onMessageCallback) {
this.messageCallbacks.set(topic, onMessageCallback);
if (this.client && this.client.isConnected()) {
console.log(`尝试订阅主题: ${topic}`);
this.client.subscribe(topic, { qos: 1 });
// 存储该主题的回调函数
this.messageCallbacks.set(topic, onMessageCallback);
this.client.subscribe(topic, {
qos: 1
});
} else {
console.error('MQTT未连接无法订阅');
console.error('MQTT未连接订阅请求已缓存,连接后将自动订阅');
}
}
/**
* 发布消息
* @param {String} topic - 需要发布的主题
* @param {String} message - 需要发布的消息
*/
publish(topic, message) {
if (this.client && this.client.isConnected()) {
const mqttMessage = new Paho.Message(message);
@ -216,34 +285,29 @@ class MqttClient {
console.error('MQTT未连接无法发布');
}
}
/**
* 取消订阅
* @param {String} topic - 需要取消订阅的主题
*/
unsubscribe(topic) {
if (this.messageCallbacks.has(topic)) {
this.messageCallbacks.delete(topic);
}
if (this.client && this.client.isConnected()) {
this.client.unsubscribe(topic);
// 从回调Map中移除
if (this.messageCallbacks.has(topic)) {
this.messageCallbacks.delete(topic);
}
console.log(`成功取消订阅: ${topic}`);
} else {
console.error('MQTT未连接无法取消订阅');
console.error('MQTT未连接或已断开,无法取消订阅');
}
}
/**
* 断开连接
*/
disconnect() {
this.manualDisconnect = true;
clearTimeout(this.reconnectTimeoutId);
if (this.client && this.client.isConnected()) {
this.client.disconnect();
}
this.client = null;
this.isReconnecting = false;
this.reconnectAttempts = 0;
console.log('MQTT连接已断开');
}
}
export default MqttClient;
export default MqttClient;