From a9866d71e8e73af686fea9b0b52e92c119fbde3d Mon Sep 17 00:00:00 2001 From: zy <82248909@qq.com> Date: Mon, 30 Mar 2026 16:27:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=AE=A1=E7=90=86=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E7=8A=B6=E6=80=81=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 7 +- .env.production | 5 + package.json | 11 +- pnpm-lock.yaml | 257 +++++++++++++++ src/components/mqtt/useMqtt.ts | 312 ++++++++++++++++++ src/components/mqtt/usePageMqtt.ts | 203 ++++++++++++ src/config/mqtt.ts | 34 ++ .../appmana/deploy/SurvDeviceDeployList.vue | 278 +++++++++------- .../deploy/components/ControlModal.vue | 194 ++++++++++- .../deploy/components/RelayGroup.data.ts | 2 +- .../deploy/components/RelayGroupList.vue | 2 +- .../appmana/deploy/components/RunGroup.api.ts | 121 +++++++ .../deploy/components/RunGroup.data.ts | 234 +++++++++++++ .../deploy/components/RunGroupList.vue | 132 ++++++++ .../deploy/components/RunGroupModal.vue | 64 ++++ .../appmana/deploy/components/SetupRun.api.ts | 127 +++++++ .../deploy/components/SetupRun.data.ts | 288 ++++++++++++++++ .../deploy/components/SetupRunList.vue | 132 ++++++++ .../deploy/components/SetupRunModal.vue | 64 ++++ 19 files changed, 2315 insertions(+), 152 deletions(-) create mode 100644 src/components/mqtt/useMqtt.ts create mode 100644 src/components/mqtt/usePageMqtt.ts create mode 100644 src/config/mqtt.ts create mode 100644 src/views/appmana/deploy/components/RunGroup.api.ts create mode 100644 src/views/appmana/deploy/components/RunGroup.data.ts create mode 100644 src/views/appmana/deploy/components/RunGroupList.vue create mode 100644 src/views/appmana/deploy/components/RunGroupModal.vue create mode 100644 src/views/appmana/deploy/components/SetupRun.api.ts create mode 100644 src/views/appmana/deploy/components/SetupRun.data.ts create mode 100644 src/views/appmana/deploy/components/SetupRunList.vue create mode 100644 src/views/appmana/deploy/components/SetupRunModal.vue diff --git a/.env.development b/.env.development index a60c312..b0855a0 100644 --- a/.env.development +++ b/.env.development @@ -6,7 +6,7 @@ VITE_PUBLIC_PATH = / # 跨域代理,您可以配置多个 ,请注意,没有换行符 VITE_PROXY = [["/jeecgboot","http://192.168.2.110:9999"],["/upload","http://192.168.2.110:3300/upload"]] -VITE_PROXY = [["/jeecgboot","https://fxnsp.sxcooh.com/lh-api/"],["/upload","http://192.168.2.111:3300/upload"]] +#VITE_PROXY = [["/jeecgboot","https://fxnsp.sxcooh.com/lh-api/"],["/upload","http://192.168.2.111:3300/upload"]] # 控制台不输出 VITE_DROP_CONSOLE = false @@ -23,3 +23,8 @@ VITE_GLOB_API_URL_PREFIX= #微前端qiankun应用,命名必须以VITE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径 VITE_APP_SUB_jeecg-app-1 = '//localhost:8092' + +# mqtt +VITE_MQTT_BROKER_URL=ws://mqtt.ilhzn.cn:80/mqtt +VITE_MQTT_USERNAME=lhzn.mqtt +VITE_MQTT_PASSWORD=lhzn.2025 diff --git a/.env.production b/.env.production index 698f9f4..a216c58 100644 --- a/.env.production +++ b/.env.production @@ -36,3 +36,8 @@ VITE_USE_PWA = false # 是否兼容旧浏览器 VITE_LEGACY = false + +# mqtt +VITE_MQTT_BROKER_URL=ws://mqtt.ilhzn.cn:80/mqtt +VITE_MQTT_USERNAME=lhzn.mqtt +VITE_MQTT_PASSWORD=lhzn.2025 diff --git a/package.json b/package.json index 2076ca9..84a5345 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ "@vueuse/shared": "^8.3.0", "@zxcvbn-ts/core": "^2.0.1", "ant-design-vue": "^3.2.12", - "html2canvas": "1.4.1", "axios": "^0.26.1", "china-area-data": "^5.0.1", "clipboard": "^2.0.8", @@ -62,11 +61,13 @@ "emoji-mart-vue-fast": "^11.1.1", "enquire.js": "^2.1.6", "ezuikit-js": "^7.6.8", + "html2canvas": "1.4.1", "intro.js": "^5.1.0", "lodash-es": "^4.17.21", "lodash.get": "^4.4.2", "md5": "^2.3.0", "mockjs": "^1.1.0", + "mqtt": "^5.15.1", "nprogress": "^0.2.0", "path-to-regexp": "^6.2.0", "pinia": "2.0.12", @@ -80,6 +81,9 @@ "sortablejs": "^1.15.0", "tinymce": "^5.10.3", "vditor": "^3.8.13", + "video.js": "^8.21.1", + "videojs-contrib-hls": "^5.15.0", + "videojs-vtt.js": "^0.15.5", "vue": "^3.2.33", "vue-cropper": "^0.5.6", "vue-cropperjs": "^5.0.0", @@ -93,10 +97,7 @@ "vxe-table": "4.1.0", "vxe-table-plugin-antd": "3.0.5", "xe-utils": "^3.3.1", - "xss": "^1.0.13", - "video.js": "^8.21.1", - "videojs-contrib-hls": "^5.15.0", - "videojs-vtt.js": "^0.15.5" + "xss": "^1.0.13" }, "devDependencies": { "@commitlint/cli": "^16.2.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 517a026..e148e38 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -114,6 +114,9 @@ importers: mockjs: specifier: ^1.1.0 version: 1.1.0 + mqtt: + specifier: ^5.15.1 + version: 5.15.1 nprogress: specifier: ^0.2.0 version: 0.2.0 @@ -1061,6 +1064,10 @@ packages: resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + '@babel/standalone@7.28.5': resolution: {integrity: sha512-1DViPYJpRU50irpGMfLBQ9B4kyfQuL6X7SS7pwTeWeZX0mNkjzPi0XFqxCjSdddZXUQy4AhnQnnesA/ZHnvAdw==} engines: {node: '>=6.9.0'} @@ -1899,6 +1906,9 @@ packages: '@types/raf@3.4.3': resolution: {integrity: sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==} + '@types/readable-stream@4.0.23': + resolution: {integrity: sha512-wwXrtQvbMHxCbBgjHaMGEmImFTQxxpfMOR/ZoQnXxB1woqkUbdLGFDgauo00Py9IudiaqSeiBiulSV9i6XIPig==} + '@types/resolve@1.17.1': resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} @@ -1932,6 +1942,9 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} @@ -2254,6 +2267,10 @@ packages: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} deprecated: Use your platform's native atob() and btoa() methods instead + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + acorn-globals@6.0.0: resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} @@ -2600,6 +2617,9 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + bl@6.1.6: + resolution: {integrity: sha512-jLsPgN/YSvPUg9UX0Kd73CXpm2Psg9FxMeCSXnk3WBO3CMT10JMwijubhGfHCnFu6TPn1ei3b975dxv7K2pWVg==} + bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} @@ -2620,6 +2640,9 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + broker-factory@3.1.14: + resolution: {integrity: sha512-L45k5HMbPIrMid0nTOZ/UPXG/c0aRuQKVrSDFIb1zOkvfiyHgYmIjc3cSiN1KwQIvRDOtKE0tfb3I9EZ3CmpQQ==} + browser-process-hrtime@1.0.0: resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} @@ -2658,6 +2681,9 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -2917,6 +2943,9 @@ packages: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} engines: {node: ^12.20.0 || >=14} + commist@3.2.0: + resolution: {integrity: sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==} + commitizen@4.2.4: resolution: {integrity: sha512-LlZChbDzg3Ir3O2S7jSo/cgWp5/QwylQVr59K4xayVq8S4/RdKzSyJkghAiZZHfhh5t4pxunUoyeg0ml1q/7aw==} engines: {node: '>= 10'} @@ -2938,6 +2967,10 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concat-stream@2.0.0: + resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} + engines: {'0': node >= 6.0} + config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} @@ -3854,9 +3887,17 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + exec-buffer@3.2.0: resolution: {integrity: sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==} engines: {node: '>=4'} @@ -3948,6 +3989,10 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-unique-numbers@9.0.27: + resolution: {integrity: sha512-nDA9ADeINN8SA2u2wCtU+siWFTTDqQR37XvgPIDDmboWQeExz7X0mImxuaN+kJddliIqy2FpVRmnvRZ+j8i1/A==} + engines: {node: '>=18.2.0'} + fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} @@ -4416,6 +4461,9 @@ packages: header-case@2.0.4: resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==} + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + homedir-polyfill@1.0.3: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} @@ -4618,6 +4666,10 @@ packages: intro.js@5.1.0: resolution: {integrity: sha512-zwWl/duTh00eeNcZRU4o4/xxloNYPFKs4n4lMRDNx59jZr+qRI0jSOnzqYMOuVftD4beGrmxBHz4k8qp9/dCMA==} + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} + is-accessor-descriptor@1.0.1: resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} engines: {node: '>= 0.10'} @@ -5112,6 +5164,9 @@ packages: js-base64@2.6.4: resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + js-sdsl@4.3.0: + resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -5368,6 +5423,9 @@ packages: engines: {node: '>=0.10.0'} hasBin: true + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} @@ -5573,6 +5631,14 @@ packages: resolution: {integrity: sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==} hasBin: true + mqtt-packet@9.0.2: + resolution: {integrity: sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==} + + mqtt@5.15.1: + resolution: {integrity: sha512-V1WnkGuJh3ec9QXzy5Iylw8OOBK+Xu1WhxcQ9mMpLThG+/JZIMV1PgLNRgIiqXhZnvnVLsuyxHl5A/3bHHbcAA==} + engines: {node: '>=16.0.0'} + hasBin: true + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -5693,6 +5759,9 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + number-allocator@1.0.14: + resolution: {integrity: sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==} + nwsapi@2.2.22: resolution: {integrity: sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==} @@ -6283,6 +6352,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -6654,6 +6727,10 @@ packages: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} @@ -6669,6 +6746,10 @@ packages: resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} engines: {node: '>=0.10.0'} + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + sort-keys-length@1.0.1: resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} engines: {node: '>=0.10.0'} @@ -6749,6 +6830,10 @@ packages: split2@3.2.2: resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + split@1.0.1: resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} @@ -7262,6 +7347,9 @@ packages: resolution: {integrity: sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==} engines: {node: '>= 0.4'} + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + typescript@4.6.3: resolution: {integrity: sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==} engines: {node: '>=4.2.0'} @@ -7836,6 +7924,18 @@ packages: workbox-window@6.6.0: resolution: {integrity: sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==} + worker-factory@7.0.49: + resolution: {integrity: sha512-lW7tpgy6aUv2dFsQhv1yv+XFzdkCf/leoKRTGMPVK5/die6RrUjqgJHJf556qO+ZfytNG6wPXc17E8zzsOLUDw==} + + worker-timers-broker@8.0.16: + resolution: {integrity: sha512-JyP3AvUGyPGbBGW7XiUewm2+0pN/aYo1QpVf5kdXAfkDZcN3p7NbWrG6XnyDEpDIvfHk/+LCnOW/NsuiU9riYA==} + + worker-timers-worker@9.0.14: + resolution: {integrity: sha512-/qF06C60sXmSLfUl7WglvrDIbspmPOM8UrG63Dnn4bi2x4/DfqHS/+dxF5B+MdHnYO5tVuZYLHdAodrKdabTIg==} + + worker-timers@8.0.31: + resolution: {integrity: sha512-ngkq5S6JuZyztom8tDgBzorLo9byhBMko/sXfgiUD945AuzKGg1GCgDMCC3NaYkicLpGKXutONM36wEX8UbBCA==} + wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -7866,6 +7966,18 @@ packages: utf-8-validate: optional: true + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xe-utils@3.3.1: resolution: {integrity: sha512-OdQgl9WPV9dK3/djneFPrGX8z1M4neX+VOkzra5oONjoNsCKQhwdiut99WlxceNMQ5vXDv4EQ/wKA2fux3Gdug==} @@ -8709,6 +8821,8 @@ snapshots: '@babel/runtime@7.28.4': {} + '@babel/runtime@7.29.2': {} + '@babel/standalone@7.28.5': {} '@babel/template@7.27.2': @@ -9795,6 +9909,10 @@ snapshots: '@types/raf@3.4.3': optional: true + '@types/readable-stream@4.0.23': + dependencies: + '@types/node': 17.0.25 + '@types/resolve@1.17.1': dependencies: '@types/node': 17.0.25 @@ -9827,6 +9945,10 @@ snapshots: '@types/trusted-types@2.0.7': {} + '@types/ws@8.18.1': + dependencies: + '@types/node': 17.0.25 + '@types/yargs-parser@21.0.3': {} '@types/yargs@16.0.11': @@ -10284,6 +10406,10 @@ snapshots: abab@2.0.6: {} + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + acorn-globals@6.0.0: dependencies: acorn: 7.4.1 @@ -10671,6 +10797,13 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 + bl@6.1.6: + dependencies: + '@types/readable-stream': 4.0.23 + buffer: 6.0.3 + inherits: 2.0.4 + readable-stream: 4.7.0 + bluebird@3.7.2: {} boolbase@1.0.0: {} @@ -10703,6 +10836,13 @@ snapshots: dependencies: fill-range: 7.1.1 + broker-factory@3.1.14: + dependencies: + '@babel/runtime': 7.29.2 + fast-unique-numbers: 9.0.27 + tslib: 2.8.1 + worker-factory: 7.0.49 + browser-process-hrtime@1.0.0: {} browserslist@4.28.0: @@ -10741,6 +10881,11 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + builtin-modules@3.3.0: {} builtins@4.1.0: @@ -11034,6 +11179,8 @@ snapshots: commander@9.5.0: {} + commist@3.2.0: {} + commitizen@4.2.4(@types/node@17.0.25)(typescript@4.6.3): dependencies: cachedir: 2.2.0 @@ -11067,6 +11214,13 @@ snapshots: concat-map@0.0.1: {} + concat-stream@2.0.0: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + typedarray: 0.0.6 + config-chain@1.1.13: dependencies: ini: 1.3.8 @@ -12089,8 +12243,12 @@ snapshots: etag@1.8.1: {} + event-target-shim@5.0.1: {} + eventemitter3@4.0.7: {} + events@3.3.0: {} + exec-buffer@3.2.0: dependencies: execa: 0.7.0 @@ -12233,6 +12391,11 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-unique-numbers@9.0.27: + dependencies: + '@babel/runtime': 7.29.2 + tslib: 2.8.1 + fast-uri@3.1.0: {} fast-xml-parser@4.5.3: @@ -12767,6 +12930,8 @@ snapshots: capital-case: 1.0.4 tslib: 2.8.1 + help-me@5.0.0: {} + homedir-polyfill@1.0.3: dependencies: parse-passwd: 1.0.0 @@ -13031,6 +13196,8 @@ snapshots: intro.js@5.1.0: {} + ip-address@10.1.0: {} + is-accessor-descriptor@1.0.1: dependencies: hasown: 2.0.2 @@ -13712,6 +13879,8 @@ snapshots: js-base64@2.6.4: {} + js-sdsl@4.3.0: {} + js-tokens@4.0.0: {} js-yaml@3.14.2: @@ -14002,6 +14171,8 @@ snapshots: longest: 1.0.1 meow: 3.7.0 + lru-cache@10.4.3: {} + lru-cache@4.1.5: dependencies: pseudomap: 1.0.2 @@ -14233,6 +14404,37 @@ snapshots: '@xmldom/xmldom': 0.8.11 global: 4.4.0 + mqtt-packet@9.0.2: + dependencies: + bl: 6.1.6 + debug: 4.4.3(supports-color@9.4.0) + process-nextick-args: 2.0.1 + transitivePeerDependencies: + - supports-color + + mqtt@5.15.1: + dependencies: + '@types/readable-stream': 4.0.23 + '@types/ws': 8.18.1 + commist: 3.2.0 + concat-stream: 2.0.0 + debug: 4.4.3(supports-color@9.4.0) + help-me: 5.0.0 + lru-cache: 10.4.3 + minimist: 1.2.8 + mqtt-packet: 9.0.2 + number-allocator: 1.0.14 + readable-stream: 4.7.0 + rfdc: 1.4.1 + socks: 2.8.7 + split2: 4.2.0 + worker-timers: 8.0.31 + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + mri@1.2.0: {} ms@2.0.0: {} @@ -14368,6 +14570,13 @@ snapshots: dependencies: boolbase: 1.0.0 + number-allocator@1.0.14: + dependencies: + debug: 4.4.3(supports-color@9.4.0) + js-sdsl: 4.3.0 + transitivePeerDependencies: + - supports-color + nwsapi@2.2.22: {} object-assign@4.1.1: {} @@ -14922,6 +15131,14 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -15305,6 +15522,8 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 4.0.0 + smart-buffer@4.2.0: {} + snake-case@3.0.4: dependencies: dot-case: 3.0.4 @@ -15333,6 +15552,11 @@ snapshots: transitivePeerDependencies: - supports-color + socks@2.8.7: + dependencies: + ip-address: 10.1.0 + smart-buffer: 4.2.0 + sort-keys-length@1.0.1: dependencies: sort-keys: 1.1.2 @@ -15404,6 +15628,8 @@ snapshots: dependencies: readable-stream: 3.6.2 + split2@4.2.0: {} + split@1.0.1: dependencies: through: 2.3.8 @@ -16002,6 +16228,8 @@ snapshots: typed-array-buffer: 1.0.3 typed-array-byte-offset: 1.0.4 + typedarray@0.0.6: {} + typescript@4.6.3: {} uglify-js@3.19.3: @@ -16754,6 +16982,33 @@ snapshots: '@types/trusted-types': 2.0.7 workbox-core: 6.6.0 + worker-factory@7.0.49: + dependencies: + '@babel/runtime': 7.29.2 + fast-unique-numbers: 9.0.27 + tslib: 2.8.1 + + worker-timers-broker@8.0.16: + dependencies: + '@babel/runtime': 7.29.2 + broker-factory: 3.1.14 + fast-unique-numbers: 9.0.27 + tslib: 2.8.1 + worker-timers-worker: 9.0.14 + + worker-timers-worker@9.0.14: + dependencies: + '@babel/runtime': 7.29.2 + tslib: 2.8.1 + worker-factory: 7.0.49 + + worker-timers@8.0.31: + dependencies: + '@babel/runtime': 7.29.2 + tslib: 2.8.1 + worker-timers-broker: 8.0.16 + worker-timers-worker: 9.0.14 + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 @@ -16782,6 +17037,8 @@ snapshots: ws@7.5.10: {} + ws@8.20.0: {} + xe-utils@3.3.1: {} xhr@2.4.0: diff --git a/src/components/mqtt/useMqtt.ts b/src/components/mqtt/useMqtt.ts new file mode 100644 index 0000000..66b25a6 --- /dev/null +++ b/src/components/mqtt/useMqtt.ts @@ -0,0 +1,312 @@ +import { ref, onMounted, onUnmounted } from 'vue'; +import mqtt, { MqttClient, IClientOptions } from 'mqtt'; +import { mqttConfig } from '@/config/mqtt'; + +export function useMqtt() { + // 状态 + const client = ref(null); + const isConnected = ref(false); + const isConnecting = ref(false); + const error = ref(null); + const messages = ref>([]); + + // 消息处理器映射 + const messageHandlers = new Map void>(); + + /** + * 连接 MQTT + */ + const connect = () => { + if (client.value && isConnected.value) { + console.warn('MQTT 已经连接'); + return; + } + + if (isConnecting.value) { + console.warn('MQTT 正在连接中'); + return; + } + + isConnecting.value = true; + error.value = null; + + try { + console.log('开始连接 MQTT...', mqttConfig.brokerUrl); + + // 创建客户端 + client.value = mqtt.connect(mqttConfig.brokerUrl, mqttConfig.options); + + // 连接成功 + client.value.on('connect', () => { + console.log('MQTT 连接成功'); + isConnected.value = true; + isConnecting.value = false; + error.value = null; + + // 订阅主题 + subscribeTopics(); + }); + + // 连接错误 + client.value.on('error', (err) => { + console.error('MQTT 连接错误:', err); + error.value = err.message; + isConnected.value = false; + isConnecting.value = false; + }); + + // 连接关闭 + client.value.on('close', () => { + console.log('MQTT 连接关闭'); + isConnected.value = false; + isConnecting.value = false; + }); + + // 收到消息 + client.value.on('message', (topic, message) => { + const payload = message.toString(); + console.log('收到消息:', topic, payload); + + // 存储消息 + messages.value.unshift({ + topic, + payload, + timestamp: Date.now(), + }); + + // 限制消息数量 + if (messages.value.length > 100) { + messages.value.pop(); + } + + // 调用对应的处理器 + const handler = messageHandlers.get(topic); + if (handler) { + handler(payload, topic); + } + + // 通配符匹配 + for (const [pattern, handler] of messageHandlers.entries()) { + if (pattern.includes('+') || pattern.includes('#')) { + if (matchTopic(pattern, topic)) { + handler(payload, topic); + } + } + } + }); + + // 重连 + client.value.on('reconnect', () => { + console.log('MQTT 正在重连...'); + }); + + // 离线 + client.value.on('offline', () => { + console.log('MQTT 离线'); + isConnected.value = false; + }); + } catch (err: any) { + console.error('创建 MQTT 客户端失败:', err); + error.value = err.message; + isConnecting.value = false; + } + }; + + /** + * 订阅主题 + */ + const subscribeTopics = () => { + if (!client.value || !isConnected.value) { + console.warn('MQTT 未连接,无法订阅'); + return; + } + + mqttConfig.topics.forEach(({ topic, qos }) => { + client.value!.subscribe(topic, { qos }, (err) => { + if (err) { + console.error(`订阅主题失败: ${topic}`, err); + } else { + console.log(`订阅主题成功: ${topic} (QoS: ${qos})`); + } + }); + }); + }; + + /** + * 订阅单个主题 + */ + const subscribe = (topic: string, qos: number = 1): Promise => { + return new Promise((resolve, reject) => { + if (!client.value || !isConnected.value) { + reject(new Error('MQTT 未连接')); + return; + } + + client.value.subscribe(topic, { qos }, (err) => { + if (err) { + console.error(`订阅主题失败: ${topic}`, err); + reject(err); + } else { + console.log(`订阅主题成功: ${topic}`); + resolve(); + } + }); + }); + }; + + /** + * 取消订阅 + */ + const unsubscribe = (topic: string): Promise => { + return new Promise((resolve, reject) => { + if (!client.value || !isConnected.value) { + reject(new Error('MQTT 未连接')); + return; + } + + client.value.unsubscribe(topic, (err) => { + if (err) { + console.error(`取消订阅失败: ${topic}`, err); + reject(err); + } else { + console.log(`取消订阅成功: ${topic}`); + resolve(); + } + }); + }); + }; + + /** + * 发布消息 + */ + const publish = (topic: string, payload: string | object, qos: number = 1, retain: boolean = false): Promise => { + return new Promise((resolve, reject) => { + if (!client.value || !isConnected.value) { + reject(new Error('MQTT 未连接')); + return; + } + + let message: string; + if (typeof payload === 'object') { + message = JSON.stringify(payload); + } else { + message = payload; + } + + client.value.publish(topic, message, { qos, retain }, (err) => { + if (err) { + console.error(`发布消息失败: ${topic}`, err); + reject(err); + } else { + console.log(`发布消息成功: ${topic}`); + resolve(); + } + }); + }); + }; + + /** + * 发送设备控制指令 + */ + const sendDeviceCommand = (deviceId: string, command: string, params?: any): Promise => { + const topic = `lanhai/device/${deviceId}/command`; + const payload = { + command, + params: params || {}, + timestamp: Date.now(), + requestId: generateRequestId(), + }; + return publish(topic, payload, 1, false); + }; + + /** + * 注册消息处理器 + */ + const onMessage = (topic: string, handler: (payload: string, topic: string) => void) => { + messageHandlers.set(topic, handler); + }; + + /** + * 移除消息处理器 + */ + const offMessage = (topic: string) => { + messageHandlers.delete(topic); + }; + + /** + * 清空消息记录 + */ + const clearMessages = () => { + messages.value = []; + }; + + /** + * 断开连接 + */ + const disconnect = () => { + if (client.value) { + client.value.end(); + client.value = null; + isConnected.value = false; + messageHandlers.clear(); + console.log('MQTT 已断开连接'); + } + }; + + /** + * 生成请求ID + */ + const generateRequestId = (): string => { + return `${Date.now()}-${Math.random().toString(36).substring(2, 10)}`; + }; + + /** + * 主题匹配(支持通配符) + */ + const matchTopic = (pattern: string, topic: string): boolean => { + const patternParts = pattern.split('/'); + const topicParts = topic.split('/'); + + if (patternParts.length > topicParts.length && patternParts[patternParts.length - 1] !== '#') { + return false; + } + + for (let i = 0; i < patternParts.length; i++) { + if (patternParts[i] === '+') continue; + if (patternParts[i] === '#') return true; + if (patternParts[i] !== topicParts[i]) return false; + } + + return patternParts.length === topicParts.length; + }; + + // 自动连接 + onMounted(() => { + connect(); + }); + + // 断开连接 + onUnmounted(() => { + disconnect(); + }); + + return { + // 状态 + client, + isConnected, + isConnecting, + error, + messages, + + // 方法 + connect, + disconnect, + publish, + subscribe, + unsubscribe, + sendDeviceCommand, + onMessage, + offMessage, + clearMessages, + }; +} diff --git a/src/components/mqtt/usePageMqtt.ts b/src/components/mqtt/usePageMqtt.ts new file mode 100644 index 0000000..ccf90a2 --- /dev/null +++ b/src/components/mqtt/usePageMqtt.ts @@ -0,0 +1,203 @@ +import { ref, onMounted, onUnmounted, type Ref } from 'vue'; +import mqtt, { MqttClient } from 'mqtt'; + +interface MqttOptions { + brokerUrl: string; + clientId?: string; + username?: string; + password?: string; + keepalive?: number; + reconnectPeriod?: number; +} + +export function usePageMqtt(options: MqttOptions) { + // 状态 + const client = ref(null); + const isConnected = ref(false); + const isConnecting = ref(false); + const error = ref(null); + + // 消息处理器 + let messageHandler: ((payload: string, topic: string) => void) | null = null; + let currentTopic: string | null = null; + + /** + * 连接 MQTT 并订阅主题 + */ + const connectAndSubscribe = (topic: string, handler: (payload: string, topic: string) => void) => { + if (client.value && isConnected.value) { + console.warn('MQTT 已连接,直接订阅'); + subscribeTopic(topic, handler); + return; + } + + if (isConnecting.value) { + console.warn('MQTT 正在连接中'); + return; + } + + currentTopic = topic; + messageHandler = handler; + isConnecting.value = true; + error.value = null; + + try { + // 生成唯一客户端ID + const clientId = options.clientId || `page-${Date.now()}-${Math.random().toString(16).substring(2, 8)}`; + + // 连接配置 + const connectOptions = { + clientId, + username: options.username, + password: options.password, + keepalive: options.keepalive || 60, + clean: true, + reconnectPeriod: options.reconnectPeriod || 5000, + connectTimeout: 30 * 1000, + }; + + console.log('开始连接 MQTT...', options.brokerUrl); + + // 创建客户端 + client.value = mqtt.connect(options.brokerUrl, connectOptions); + + // 连接成功 + client.value.on('connect', () => { + console.log('MQTT 连接成功'); + isConnected.value = true; + isConnecting.value = false; + + // 订阅主题 + if (currentTopic && messageHandler) { + subscribeTopic(currentTopic, messageHandler); + } + }); + + // 连接错误 + client.value.on('error', (err) => { + console.error('MQTT 连接错误:', err); + error.value = err.message; + isConnected.value = false; + isConnecting.value = false; + }); + + // 连接关闭 + client.value.on('close', () => { + console.log('MQTT 连接关闭'); + isConnected.value = false; + }); + + // 收到消息 + client.value.on('message', (topic, message) => { + const payload = message.toString(); + console.log('收到消息:', topic, payload); + + // 调用消息处理器 + if (messageHandler) { + messageHandler(payload, topic); + } + }); + + // 重连 + client.value.on('reconnect', () => { + console.log('MQTT 正在重连...'); + }); + + // 离线 + client.value.on('offline', () => { + console.log('MQTT 离线'); + isConnected.value = false; + }); + } catch (err: any) { + console.error('创建 MQTT 客户端失败:', err); + error.value = err.message; + isConnecting.value = false; + } + }; + + /** + * 订阅主题 + */ + const subscribeTopic = (topic: string, handler: (payload: string, topic: string) => void) => { + if (!client.value || !isConnected.value) { + console.warn('MQTT 未连接,无法订阅'); + return; + } + + messageHandler = handler; + currentTopic = topic; + + client.value.subscribe(topic, { qos: 1 }, (err) => { + if (err) { + console.error(`订阅主题失败: ${topic}`, err); + error.value = `订阅失败: ${err.message}`; + } else { + console.log(`订阅主题成功: ${topic}`); + } + }); + }; + + /** + * 发布消息 + */ + const publish = (topic: string, payload: string | object, qos: number = 1): Promise => { + return new Promise((resolve, reject) => { + if (!client.value || !isConnected.value) { + reject(new Error('MQTT 未连接')); + return; + } + + const message = typeof payload === 'object' ? JSON.stringify(payload) : payload; + + client.value.publish(topic, message, { qos }, (err) => { + if (err) { + console.error(`发布消息失败: ${topic}`, err); + reject(err); + } else { + console.log(`发布消息成功: ${topic}`); + resolve(); + } + }); + }); + }; + + /** + * 断开连接并销毁 + */ + const disconnect = () => { + if (client.value) { + // 取消订阅 + if (currentTopic) { + client.value.unsubscribe(currentTopic, (err) => { + if (err) { + console.error(`取消订阅失败: ${currentTopic}`, err); + } else { + console.log(`取消订阅成功: ${currentTopic}`); + } + }); + } + + // 断开连接 + client.value.end(true, () => { + console.log('MQTT 连接已关闭'); + }); + + client.value = null; + isConnected.value = false; + messageHandler = null; + currentTopic = null; + } + }; + + return { + // 状态 + isConnected, + isConnecting, + error, + + // 方法 + connectAndSubscribe, + publish, + disconnect, + }; +} diff --git a/src/config/mqtt.ts b/src/config/mqtt.ts new file mode 100644 index 0000000..5f9e854 --- /dev/null +++ b/src/config/mqtt.ts @@ -0,0 +1,34 @@ +export const mqttConfig = { + // MQTT 服务器地址 + brokerUrl: 'ws://mqtt.ilhzn.cn:10007', // WebSocket 连接 + // brokerUrl: 'wss://mqtt.example.com:8084/mqtt', // 使用 SSL + + // 连接选项 + options: { + clientId: `vue3-mqtt-${Math.random().toString(16).substring(2, 8)}`, + username: 'lhzn.mqtt', + password: 'lhzn.2025', + keepalive: 60, + clean: true, + reconnectPeriod: 5000, // 自动重连间隔(ms) + connectTimeout: 30 * 1000, + + // SSL 配置(如果使用 wss) + // rejectUnauthorized: false, + + // 遗嘱消息 + will: { + topic: 'app/status', + payload: 'offline', + qos: 1, + retain: true, + }, + }, + + // 订阅主题 + topics: [ + { topic: 'app/receive', qos: 1 }, + { topic: 'app/status', qos: 0 }, + { topic: 'lanhai/device/+/command', qos: 1 }, + ], +}; diff --git a/src/views/appmana/deploy/SurvDeviceDeployList.vue b/src/views/appmana/deploy/SurvDeviceDeployList.vue index 7f847d9..9bea836 100644 --- a/src/views/appmana/deploy/SurvDeviceDeployList.vue +++ b/src/views/appmana/deploy/SurvDeviceDeployList.vue @@ -4,45 +4,44 @@
- - - - - - - - - - - - - + + + + + + + - + 查询 重置 @@ -59,7 +58,7 @@ -