@gct-paas/core 0.1.4-dev.11 → 0.1.4-dev.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/dist/index.esm.min.js +21679 -0
  2. package/es/constants/core.mjs +5 -4
  3. package/es/constants/default-date-type/default-date-type.mjs +73 -21
  4. package/es/constants/editor-register/editor-register.mjs +17 -5
  5. package/es/constants/expression-type/BuiltOperators.mjs +152 -147
  6. package/es/constants/expression-type/FunctionKeys.mjs +75 -79
  7. package/es/constants/expression-type/editor.mjs +10 -3
  8. package/es/constants/expression-type/function.mjs +602 -613
  9. package/es/constants/expression-type/index.mjs +111 -113
  10. package/es/constants/expression-type/modeCfg.mjs +256 -263
  11. package/es/constants/expression-type/variable.mjs +43 -39
  12. package/es/constants/form-container-type/form-container-type.mjs +17 -5
  13. package/es/constants/index.mjs +30 -10
  14. package/es/constants/page-designer/model.mjs +15 -5
  15. package/es/create-app-vue.mjs +15 -9
  16. package/es/enums/app-designer/index.d.ts +19 -0
  17. package/es/enums/app-designer/index.mjs +131 -63
  18. package/es/enums/appEnum.mjs +681 -360
  19. package/es/enums/appStateEnum.mjs +17 -10
  20. package/es/enums/authActionEnum.mjs +63 -51
  21. package/es/enums/breakpointEnum.mjs +27 -26
  22. package/es/enums/cacheEnum.mjs +22 -21
  23. package/es/enums/designEnum.mjs +110 -71
  24. package/es/enums/developer-center/integration.mjs +7 -6
  25. package/es/enums/exceptionEnum.mjs +21 -17
  26. package/es/enums/expressionEnum.d.ts +1 -1
  27. package/es/enums/expressionEnum.mjs +81 -74
  28. package/es/enums/globalEnum.mjs +59 -36
  29. package/es/enums/httpEnum.mjs +71 -61
  30. package/es/enums/index.mjs +43 -14
  31. package/es/enums/menuEnum.mjs +42 -38
  32. package/es/enums/page-designer/designer.mjs +403 -407
  33. package/es/enums/page-designer/index.mjs +4 -0
  34. package/es/enums/page-designer/panel.mjs +341 -213
  35. package/es/enums/page-designer/toolkit.mjs +13 -12
  36. package/es/enums/page-designer/widget.mjs +425 -338
  37. package/es/enums/pageEnum.mjs +14 -13
  38. package/es/enums/plugin-enum.mjs +23 -7
  39. package/es/enums/processEnum.mjs +95 -60
  40. package/es/enums/roleEnum.mjs +7 -6
  41. package/es/enums/sizeEnum.d.ts +18 -0
  42. package/es/enums/sizeEnum.mjs +28 -8
  43. package/es/global/gct/gct.mjs +84 -96
  44. package/es/global/index.mjs +1 -0
  45. package/es/hooks/index.mjs +4 -0
  46. package/es/hooks/use-app-inst/use-app-inst.mjs +11 -5
  47. package/es/hooks/use-modal/use-modal.mjs +16 -10
  48. package/es/hooks/use-sub-app-utils/use-sub-app-utils.mjs +43 -23
  49. package/es/hooks/useCopyToClipboard.mjs +50 -50
  50. package/es/index.mjs +122 -114
  51. package/es/locale/index.mjs +43 -57
  52. package/es/modules/env-manager/env-manager.const.mjs +16 -8
  53. package/es/modules/env-manager/env-manager.interface.mjs +14 -7
  54. package/es/modules/env-manager/env-manager.mjs +104 -107
  55. package/es/modules/error-handler/error-handler.const.mjs +11 -16
  56. package/es/modules/error-handler/error-strategy.mjs +199 -175
  57. package/es/modules/error-handler/index.mjs +120 -106
  58. package/es/modules/mqtt/constants/mqtt.const.mjs +21 -24
  59. package/es/modules/mqtt/enums/mqtt-status.enum.mjs +23 -9
  60. package/es/modules/mqtt/index.mjs +4 -0
  61. package/es/modules/mqtt/mqtt-client.mjs +228 -261
  62. package/es/modules/mqtt/mqtt-manager.mjs +117 -77
  63. package/es/modules/platform-config/constants/index.mjs +4 -0
  64. package/es/modules/platform-config/constants/login.const.mjs +48 -45
  65. package/es/modules/platform-config/constants/org.const.mjs +57 -52
  66. package/es/modules/platform-config/constants/theme.const.mjs +11 -4
  67. package/es/modules/platform-config/constants/watermark.const.mjs +17 -12
  68. package/es/modules/platform-config/enums/deploy.enum.mjs +13 -6
  69. package/es/modules/platform-config/enums/login.enum.mjs +29 -15
  70. package/es/modules/platform-config/enums/platform.enum.mjs +16 -13
  71. package/es/modules/platform-config/index.mjs +9 -0
  72. package/es/modules/platform-config/store.mjs +68 -79
  73. package/es/modules/platform-config/useBasicSetting.mjs +47 -35
  74. package/es/modules/platform-config/useDeploySetting.mjs +29 -21
  75. package/es/modules/platform-config/useLoginSetting.mjs +151 -173
  76. package/es/modules/platform-config/useOrgSetting.mjs +63 -62
  77. package/es/modules/platform-config/useProjectSetting.mjs +14 -6
  78. package/es/modules/platform-config/useSecuritySetting.mjs +68 -56
  79. package/es/modules/platform-config/useThemeSetting.mjs +78 -59
  80. package/es/modules/platform-config/useWatermarkSetting.mjs +37 -23
  81. package/es/modules/user-stores/index.mjs +3 -0
  82. package/es/modules/user-stores/store/permission.store.mjs +27 -36
  83. package/es/modules/user-stores/store/tenant.store.mjs +20 -22
  84. package/es/modules/user-stores/store/user.store.mjs +94 -117
  85. package/es/router/index.mjs +25 -28
  86. package/es/setup-app.mjs +23 -39
  87. package/es/state/global-pinia-state/global-pinia-state.mjs +49 -71
  88. package/es/state/index.mjs +1 -0
  89. package/es/store/global-store.mjs +50 -72
  90. package/es/store/index.mjs +25 -19
  91. package/es/types/index.d.ts +7 -0
  92. package/es/utils/axios/interceptors.mjs +21 -17
  93. package/es/utils/cache-adapter/cache-adapter.mjs +61 -56
  94. package/es/utils/design/design.mjs +18 -12
  95. package/es/utils/deviceFingerprint.mjs +74 -63
  96. package/es/utils/dictionary/dictionary.mjs +142 -145
  97. package/es/utils/file/base64Conver.mjs +35 -30
  98. package/es/utils/file/download.mjs +94 -98
  99. package/es/utils/file/parser.d.ts +3 -0
  100. package/es/utils/file/parser.mjs +29 -0
  101. package/es/utils/i18n/index.mjs +14 -3
  102. package/es/utils/index.d.ts +1 -0
  103. package/es/utils/index.mjs +31 -0
  104. package/es/utils/is-sort-filed/is-sort-filed.mjs +42 -37
  105. package/es/utils/linked-list/linked-list.mjs +115 -118
  106. package/es/utils/linked-node/linked-node.mjs +41 -31
  107. package/es/utils/lowcode/utils.mjs +13 -18
  108. package/es/utils/lowcode/validate.mjs +20 -26
  109. package/es/utils/mitt/mitt.mjs +4 -4
  110. package/es/utils/model-loader/model-loader.mjs +280 -325
  111. package/es/utils/namespace/namespace.mjs +178 -164
  112. package/es/utils/openUtil/index.mjs +2 -0
  113. package/es/utils/openUtil/modal/modal.mjs +72 -79
  114. package/es/utils/openUtil/overlay-container/overlay-container.mjs +144 -138
  115. package/es/utils/permission.mjs +33 -37
  116. package/es/utils/plugin-static-resource/plugin-static-resource.mjs +46 -42
  117. package/es/utils/style/index.mjs +94 -138
  118. package/es/utils/tools/tools.mjs +86 -54
  119. package/es/utils/treeHelper/treeHelper.mjs +205 -233
  120. package/es/utils/uploader/uploader.mjs +81 -115
  121. package/es/utils/useUUid.mjs +79 -87
  122. package/es/utils/util.mjs +55 -35
  123. package/es/utils/uuid/uuid.d.ts +1 -0
  124. package/es/utils/uuid/uuid.mjs +36 -43
  125. package/es/utils/validate.mjs +15 -19
  126. package/es/utils/value-helper/value-helper.mjs +113 -98
  127. package/package.json +12 -13
  128. package/dist/index.esm.min.mjs +0 -18322
  129. package/dist/index.min.cjs +0 -393
  130. package/dist/index.system.min.js +0 -393
@@ -1,262 +1,229 @@
1
- import mqtt from 'mqtt';
2
- import { MqttConnectionStatus } from './enums/mqtt-status.enum.mjs';
3
- import { MQTT_DEFAULT_CONNECT_OPTIONS, MQTT_CLIENT_EVENT } from './constants/mqtt.const.mjs';
4
-
5
- class MqttClient {
6
- /** 客户端唯一标识 */
7
- instanceId;
8
- /** 连接 URL(即 brokerUrl) */
9
- url;
10
- /** 内部 mqtt.js 客户端实例 */
11
- _client = null;
12
- /** 当前连接状态 */
13
- _status = MqttConnectionStatus.DISCONNECTED;
14
- /** topic -> 消息回调集合 */
15
- _subscriptions = /* @__PURE__ */ new Map();
16
- /** 用户注册的连接级事件监听器集合 */
17
- _eventListeners = {
18
- connect: /* @__PURE__ */ new Set(),
19
- disconnect: /* @__PURE__ */ new Set(),
20
- reconnect: /* @__PURE__ */ new Set(),
21
- error: /* @__PURE__ */ new Set()
22
- };
23
- /** 内部保存的连接选项 */
24
- _options;
25
- /**
26
- * 创建 MQTT 客户端实例
27
- *
28
- * @param instanceId 实例唯一标识
29
- * @param options 连接选项
30
- */
31
- constructor(instanceId, url, options) {
32
- if (!instanceId) {
33
- throw new Error("MqttClient: instanceId 不能为空");
34
- }
35
- if (!url) {
36
- throw new Error("MqttClient: url 不能为空");
37
- }
38
- if (!options.clientId) {
39
- throw new Error("MqttClient: options.clientId 不能为空");
40
- }
41
- this.instanceId = instanceId;
42
- this.url = url;
43
- this._options = {
44
- ...options,
45
- keepalive: options.keepalive ?? MQTT_DEFAULT_CONNECT_OPTIONS.keepalive,
46
- connectTimeout: options.connectTimeout ?? MQTT_DEFAULT_CONNECT_OPTIONS.connectTimeout,
47
- reconnectPeriod: options.reconnectPeriod ?? MQTT_DEFAULT_CONNECT_OPTIONS.reconnectPeriod,
48
- clean: options.clean ?? MQTT_DEFAULT_CONNECT_OPTIONS.clean
49
- };
50
- }
51
- /** 获取当前连接状态 */
52
- get status() {
53
- return this._status;
54
- }
55
- /**
56
- * 建立 MQTT 连接
57
- *
58
- * @description 若当前已连接或正在连接中则不重复建链
59
- */
60
- connect() {
61
- if (this._status === MqttConnectionStatus.CONNECTED || this._status === MqttConnectionStatus.CONNECTING) {
62
- return;
63
- }
64
- this._status = MqttConnectionStatus.CONNECTING;
65
- this._client = mqtt.connect(this.url, this._options);
66
- this._bindClientEvents();
67
- }
68
- /**
69
- * 断开 MQTT 连接
70
- *
71
- * @description 主动断开并停止 mqtt.js 内置重连
72
- */
73
- disconnect() {
74
- if (!this._client) {
75
- this._status = MqttConnectionStatus.DISCONNECTED;
76
- return;
77
- }
78
- this._status = MqttConnectionStatus.DISCONNECTING;
79
- this._client.end(false, {}, () => {
80
- this._status = MqttConnectionStatus.DISCONNECTED;
81
- this._emitEvent(MQTT_CLIENT_EVENT.DISCONNECT);
82
- });
83
- }
84
- /**
85
- * 订阅一个或多个主题
86
- *
87
- * @param topics 主题或主题数组
88
- * @param callback 消息回调函数
89
- * @returns 取消订阅函数
90
- */
91
- subscribe(topics, callback) {
92
- const topicList = Array.isArray(topics) ? topics : [topics];
93
- topicList.forEach((topic) => {
94
- if (!this._subscriptions.has(topic)) {
95
- this._subscriptions.set(topic, /* @__PURE__ */ new Set());
96
- if (this._client && this._status === MqttConnectionStatus.CONNECTED) {
97
- this._client.subscribe(topic);
98
- }
99
- }
100
- this._subscriptions.get(topic).add(
101
- callback
102
- );
103
- });
104
- return () => this.unsubscribe(topicList);
105
- }
106
- /**
107
- * 取消订阅一个或多个主题
108
- *
109
- * @param topics 主题或主题数组
110
- */
111
- unsubscribe(topics) {
112
- const topicList = Array.isArray(topics) ? topics : [topics];
113
- topicList.forEach((topic) => {
114
- this._subscriptions.delete(topic);
115
- if (this._client && this._status === MqttConnectionStatus.CONNECTED) {
116
- this._client.unsubscribe(topic);
117
- }
118
- });
119
- }
120
- /**
121
- * 向指定主题发布消息
122
- *
123
- * @param topic 目标主题
124
- * @param payload 消息内容
125
- * @param options 发布选项
126
- * @returns Promise,发布成功后 resolve
127
- */
128
- publish(topic, payload, options) {
129
- return new Promise((resolve, reject) => {
130
- if (!this._client || this._status !== MqttConnectionStatus.CONNECTED) {
131
- reject(
132
- new Error(
133
- `MqttClient [${this.instanceId}]: 尚未建立连接,无法发布消息`
134
- )
135
- );
136
- return;
137
- }
138
- const publishOptions = {
139
- qos: options?.qos ?? 0,
140
- retain: options?.retain ?? false
141
- };
142
- this._client.publish(topic, payload, publishOptions, (err) => {
143
- if (err) {
144
- reject(err);
145
- } else {
146
- resolve();
147
- }
148
- });
149
- });
150
- }
151
- /**
152
- * 监听连接级事件
153
- *
154
- * @param event 事件名
155
- * @param listener 监听函数
156
- */
157
- on(event, listener) {
158
- this._eventListeners[event].add(listener);
159
- }
160
- /**
161
- * 取消监听连接级事件
162
- *
163
- * @param event 事件名
164
- * @param listener 监听函数
165
- */
166
- off(event, listener) {
167
- this._eventListeners[event].delete(
168
- listener
169
- );
170
- }
171
- // ─────────────────────────────────────────────
172
- // 私有方法
173
- // ─────────────────────────────────────────────
174
- /**
175
- * 绑定 mqtt.js 内部事件
176
- *
177
- * @private
178
- */
179
- _bindClientEvents() {
180
- if (!this._client) return;
181
- this._client.on("connect", (_connack) => {
182
- this._status = MqttConnectionStatus.CONNECTED;
183
- this._emitEvent(MQTT_CLIENT_EVENT.CONNECT);
184
- });
185
- this._client.on("reconnect", () => {
186
- this._status = MqttConnectionStatus.RECONNECTING;
187
- this._emitEvent(MQTT_CLIENT_EVENT.RECONNECT);
188
- });
189
- this._client.on("error", (err) => {
190
- this._emitEvent(MQTT_CLIENT_EVENT.ERROR, err);
191
- });
192
- this._client.on("close", () => {
193
- if (this._status !== MqttConnectionStatus.DISCONNECTING) {
194
- this._status = MqttConnectionStatus.DISCONNECTED;
195
- }
196
- });
197
- this._client.on("message", (topic, payload) => {
198
- this._dispatchMessage(topic, payload);
199
- });
200
- }
201
- /**
202
- * 向所有已订阅该 topic 的回调函数分发消息
203
- *
204
- * @private
205
- * @param topic 消息主题
206
- * @param payload 消息内容
207
- */
208
- _dispatchMessage(topic, payload) {
209
- const callbacks = this._subscriptions.get(topic);
210
- if (callbacks) {
211
- callbacks.forEach((cb) => cb(topic, payload));
212
- }
213
- this._subscriptions.forEach((cbSet, pattern) => {
214
- if (pattern !== topic && this._matchTopic(pattern, topic)) {
215
- cbSet.forEach((cb) => cb(topic, payload));
216
- }
217
- });
218
- }
219
- /**
220
- * MQTT 通配符主题匹配
221
- *
222
- * @private
223
- * @param pattern 订阅时使用的通配符 pattern(支持 + #)
224
- * @param topic 实际消息的主题
225
- */
226
- _matchTopic(pattern, topic) {
227
- const patternSegments = pattern.split("/");
228
- const topicSegments = topic.split("/");
229
- for (let i = 0; i < patternSegments.length; i++) {
230
- const p = patternSegments[i];
231
- if (p === "#") {
232
- return true;
233
- }
234
- if (p !== "+" && p !== topicSegments[i]) {
235
- return false;
236
- }
237
- }
238
- return patternSegments.length === topicSegments.length;
239
- }
240
- /**
241
- * 触发连接级事件
242
- *
243
- * @private
244
- * @param event 事件名
245
- * @param arg 可选参数(如 Error)
246
- */
247
- _emitEvent(event, arg) {
248
- if (event === MQTT_CLIENT_EVENT.ERROR && arg) {
249
- this._eventListeners.error.forEach(
250
- (fn) => fn(arg)
251
- );
252
- } else if (event === MQTT_CLIENT_EVENT.CONNECT) {
253
- this._eventListeners.connect.forEach((fn) => fn());
254
- } else if (event === MQTT_CLIENT_EVENT.DISCONNECT) {
255
- this._eventListeners.disconnect.forEach((fn) => fn());
256
- } else if (event === MQTT_CLIENT_EVENT.RECONNECT) {
257
- this._eventListeners.reconnect.forEach((fn) => fn());
258
- }
259
- }
260
- }
261
-
1
+ import { MQTT_CLIENT_EVENT, MQTT_DEFAULT_CONNECT_OPTIONS } from "./constants/mqtt.const.mjs";
2
+ import { MqttConnectionStatus } from "./enums/mqtt-status.enum.mjs";
3
+ import mqtt from "mqtt";
4
+ //#region src/modules/mqtt/mqtt-client.ts
5
+ /**
6
+ * MQTT 客户端
7
+ *
8
+ * @description 封装单个 MQTT 连接,提供连接、断连、订阅、取消订阅、发布等功能。
9
+ * 重连逻辑完全委托给 mqtt.js 内置机制(reconnectPeriod),本类仅负责
10
+ * 状态同步、消息分发与事件转发。
11
+ *
12
+ * @export
13
+ * @class MqttClient
14
+ * @implements {IMqttClient}
15
+ */
16
+ var MqttClient = class {
17
+ /** 客户端唯一标识 */
18
+ instanceId;
19
+ /** 连接 URL(即 brokerUrl) */
20
+ url;
21
+ /** 内部 mqtt.js 客户端实例 */
22
+ _client = null;
23
+ /** 当前连接状态 */
24
+ _status = MqttConnectionStatus.DISCONNECTED;
25
+ /** topic -> 消息回调集合 */
26
+ _subscriptions = /* @__PURE__ */ new Map();
27
+ /** 用户注册的连接级事件监听器集合 */
28
+ _eventListeners = {
29
+ connect: /* @__PURE__ */ new Set(),
30
+ disconnect: /* @__PURE__ */ new Set(),
31
+ reconnect: /* @__PURE__ */ new Set(),
32
+ error: /* @__PURE__ */ new Set()
33
+ };
34
+ /** 内部保存的连接选项 */
35
+ _options;
36
+ /**
37
+ * 创建 MQTT 客户端实例
38
+ *
39
+ * @param instanceId 实例唯一标识
40
+ * @param options 连接选项
41
+ */
42
+ constructor(instanceId, url, options) {
43
+ if (!instanceId) throw new Error("MqttClient: instanceId 不能为空");
44
+ if (!url) throw new Error("MqttClient: url 不能为空");
45
+ if (!options.clientId) throw new Error("MqttClient: options.clientId 不能为空");
46
+ this.instanceId = instanceId;
47
+ this.url = url;
48
+ this._options = {
49
+ ...options,
50
+ keepalive: options.keepalive ?? MQTT_DEFAULT_CONNECT_OPTIONS.keepalive,
51
+ connectTimeout: options.connectTimeout ?? MQTT_DEFAULT_CONNECT_OPTIONS.connectTimeout,
52
+ reconnectPeriod: options.reconnectPeriod ?? MQTT_DEFAULT_CONNECT_OPTIONS.reconnectPeriod,
53
+ clean: options.clean ?? MQTT_DEFAULT_CONNECT_OPTIONS.clean
54
+ };
55
+ }
56
+ /** 获取当前连接状态 */
57
+ get status() {
58
+ return this._status;
59
+ }
60
+ /**
61
+ * 建立 MQTT 连接
62
+ *
63
+ * @description 若当前已连接或正在连接中则不重复建链
64
+ */
65
+ connect() {
66
+ if (this._status === MqttConnectionStatus.CONNECTED || this._status === MqttConnectionStatus.CONNECTING) return;
67
+ this._status = MqttConnectionStatus.CONNECTING;
68
+ this._client = mqtt.connect(this.url, this._options);
69
+ this._bindClientEvents();
70
+ }
71
+ /**
72
+ * 断开 MQTT 连接
73
+ *
74
+ * @description 主动断开并停止 mqtt.js 内置重连
75
+ */
76
+ disconnect() {
77
+ if (!this._client) {
78
+ this._status = MqttConnectionStatus.DISCONNECTED;
79
+ return;
80
+ }
81
+ this._status = MqttConnectionStatus.DISCONNECTING;
82
+ this._client.end(false, {}, () => {
83
+ this._status = MqttConnectionStatus.DISCONNECTED;
84
+ this._emitEvent(MQTT_CLIENT_EVENT.DISCONNECT);
85
+ });
86
+ }
87
+ /**
88
+ * 订阅一个或多个主题
89
+ *
90
+ * @param topics 主题或主题数组
91
+ * @param callback 消息回调函数
92
+ * @returns 取消订阅函数
93
+ */
94
+ subscribe(topics, callback) {
95
+ const topicList = Array.isArray(topics) ? topics : [topics];
96
+ topicList.forEach((topic) => {
97
+ if (!this._subscriptions.has(topic)) {
98
+ this._subscriptions.set(topic, /* @__PURE__ */ new Set());
99
+ if (this._client && this._status === MqttConnectionStatus.CONNECTED) this._client.subscribe(topic);
100
+ }
101
+ this._subscriptions.get(topic).add(callback);
102
+ });
103
+ return () => this.unsubscribe(topicList);
104
+ }
105
+ /**
106
+ * 取消订阅一个或多个主题
107
+ *
108
+ * @param topics 主题或主题数组
109
+ */
110
+ unsubscribe(topics) {
111
+ (Array.isArray(topics) ? topics : [topics]).forEach((topic) => {
112
+ this._subscriptions.delete(topic);
113
+ if (this._client && this._status === MqttConnectionStatus.CONNECTED) this._client.unsubscribe(topic);
114
+ });
115
+ }
116
+ /**
117
+ * 向指定主题发布消息
118
+ *
119
+ * @param topic 目标主题
120
+ * @param payload 消息内容
121
+ * @param options 发布选项
122
+ * @returns Promise,发布成功后 resolve
123
+ */
124
+ publish(topic, payload, options) {
125
+ return new Promise((resolve, reject) => {
126
+ if (!this._client || this._status !== MqttConnectionStatus.CONNECTED) {
127
+ reject(/* @__PURE__ */ new Error(`MqttClient [${this.instanceId}]: 尚未建立连接,无法发布消息`));
128
+ return;
129
+ }
130
+ const publishOptions = {
131
+ qos: options?.qos ?? 0,
132
+ retain: options?.retain ?? false
133
+ };
134
+ this._client.publish(topic, payload, publishOptions, (err) => {
135
+ if (err) reject(err);
136
+ else resolve();
137
+ });
138
+ });
139
+ }
140
+ /**
141
+ * 监听连接级事件
142
+ *
143
+ * @param event 事件名
144
+ * @param listener 监听函数
145
+ */
146
+ on(event, listener) {
147
+ this._eventListeners[event].add(listener);
148
+ }
149
+ /**
150
+ * 取消监听连接级事件
151
+ *
152
+ * @param event 事件名
153
+ * @param listener 监听函数
154
+ */
155
+ off(event, listener) {
156
+ this._eventListeners[event].delete(listener);
157
+ }
158
+ /**
159
+ * 绑定 mqtt.js 内部事件
160
+ *
161
+ * @private
162
+ */
163
+ _bindClientEvents() {
164
+ if (!this._client) return;
165
+ this._client.on("connect", (_connack) => {
166
+ this._status = MqttConnectionStatus.CONNECTED;
167
+ this._emitEvent(MQTT_CLIENT_EVENT.CONNECT);
168
+ });
169
+ this._client.on("reconnect", () => {
170
+ this._status = MqttConnectionStatus.RECONNECTING;
171
+ this._emitEvent(MQTT_CLIENT_EVENT.RECONNECT);
172
+ });
173
+ this._client.on("error", (err) => {
174
+ this._emitEvent(MQTT_CLIENT_EVENT.ERROR, err);
175
+ });
176
+ this._client.on("close", () => {
177
+ if (this._status !== MqttConnectionStatus.DISCONNECTING) this._status = MqttConnectionStatus.DISCONNECTED;
178
+ });
179
+ this._client.on("message", (topic, payload) => {
180
+ this._dispatchMessage(topic, payload);
181
+ });
182
+ }
183
+ /**
184
+ * 向所有已订阅该 topic 的回调函数分发消息
185
+ *
186
+ * @private
187
+ * @param topic 消息主题
188
+ * @param payload 消息内容
189
+ */
190
+ _dispatchMessage(topic, payload) {
191
+ const callbacks = this._subscriptions.get(topic);
192
+ if (callbacks) callbacks.forEach((cb) => cb(topic, payload));
193
+ this._subscriptions.forEach((cbSet, pattern) => {
194
+ if (pattern !== topic && this._matchTopic(pattern, topic)) cbSet.forEach((cb) => cb(topic, payload));
195
+ });
196
+ }
197
+ /**
198
+ * MQTT 通配符主题匹配
199
+ *
200
+ * @private
201
+ * @param pattern 订阅时使用的通配符 pattern(支持 + 和 #)
202
+ * @param topic 实际消息的主题
203
+ */
204
+ _matchTopic(pattern, topic) {
205
+ const patternSegments = pattern.split("/");
206
+ const topicSegments = topic.split("/");
207
+ for (let i = 0; i < patternSegments.length; i++) {
208
+ const p = patternSegments[i];
209
+ if (p === "#") return true;
210
+ if (p !== "+" && p !== topicSegments[i]) return false;
211
+ }
212
+ return patternSegments.length === topicSegments.length;
213
+ }
214
+ /**
215
+ * 触发连接级事件
216
+ *
217
+ * @private
218
+ * @param event 事件名
219
+ * @param arg 可选参数(如 Error)
220
+ */
221
+ _emitEvent(event, arg) {
222
+ if (event === MQTT_CLIENT_EVENT.ERROR && arg) this._eventListeners.error.forEach((fn) => fn(arg));
223
+ else if (event === MQTT_CLIENT_EVENT.CONNECT) this._eventListeners.connect.forEach((fn) => fn());
224
+ else if (event === MQTT_CLIENT_EVENT.DISCONNECT) this._eventListeners.disconnect.forEach((fn) => fn());
225
+ else if (event === MQTT_CLIENT_EVENT.RECONNECT) this._eventListeners.reconnect.forEach((fn) => fn());
226
+ }
227
+ };
228
+ //#endregion
262
229
  export { MqttClient };