diff --git a/package-lock.json b/package-lock.json
index 1c10203..39f0a78 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -26,18 +26,21 @@
"mqtt": "^5.15.0",
"pinia": "^3.0.4",
"sockjs-client": "^1.6.1",
+ "sortablejs": "^1.15.7",
"stats.js": "^0.17.0",
"three": "^0.182.0",
"vue": "^3.3.4",
"vue-echarts": "^6.6.5",
"vue-router": "^4.2.5",
- "vue3-ace-editor": "^2.2.4"
+ "vue3-ace-editor": "^2.2.4",
+ "vuedraggable": "^4.1.0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node18": "^18.2.2",
"@types/jsdom": "^21.1.3",
"@types/node": "^18.18.5",
+ "@types/sortablejs": "^1.15.9",
"@types/three": "^0.182.0",
"@vitejs/plugin-vue": "^4.4.0",
"@vue/eslint-config-prettier": "^8.0.0",
@@ -157,6 +160,7 @@
"integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.28.6",
"@babel/generator": "^7.28.6",
@@ -1932,8 +1936,7 @@
"resolved": "https://registry.npmmirror.com/@rtsao/scc/-/scc-1.1.0.tgz",
"integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/@rushstack/eslint-patch": {
"version": "1.15.0",
@@ -2138,7 +2141,8 @@
"resolved": "https://registry.npmmirror.com/@types/chai/-/chai-4.3.20.tgz",
"integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/@types/chai-subset": {
"version": "1.3.6",
@@ -2181,8 +2185,7 @@
"resolved": "https://registry.npmmirror.com/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/@types/lodash": {
"version": "4.17.23",
@@ -2195,6 +2198,7 @@
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/lodash": "*"
}
@@ -2230,6 +2234,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/sortablejs": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmmirror.com/@types/sortablejs/-/sortablejs-1.15.9.tgz",
+ "integrity": "sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/stats.js": {
"version": "0.17.4",
"resolved": "https://registry.npmmirror.com/@types/stats.js/-/stats.js-0.17.4.tgz",
@@ -2341,6 +2352,7 @@
"integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
"dev": true,
"license": "BSD-2-Clause",
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "6.21.0",
"@typescript-eslint/types": "6.21.0",
@@ -3196,6 +3208,7 @@
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.26.tgz",
"integrity": "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/reactivity": "3.5.26",
"@vue/shared": "3.5.26"
@@ -3379,7 +3392,8 @@
"version": "1.43.5",
"resolved": "https://registry.npmmirror.com/ace-builds/-/ace-builds-1.43.5.tgz",
"integrity": "sha512-iH5FLBKdB7SVn9GR37UgA/tpQS8OTWIxWAuq3Ofaw+Qbc69FfPXsXd9jeW7KRG2xKpKMqBDnu0tHBrCWY5QI7A==",
- "license": "BSD-3-Clause"
+ "license": "BSD-3-Clause",
+ "peer": true
},
"node_modules/acorn": {
"version": "8.15.0",
@@ -3387,6 +3401,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -3593,7 +3608,6 @@
"integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.4",
@@ -3643,7 +3657,6 @@
"integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.4",
@@ -3666,7 +3679,6 @@
"integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
@@ -3686,7 +3698,6 @@
"integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
@@ -4014,6 +4025,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -5126,6 +5138,7 @@
"resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
"integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"tslib": "2.3.0",
"zrender": "5.6.1"
@@ -5361,7 +5374,6 @@
"integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"hasown": "^2.0.2"
},
@@ -5455,6 +5467,7 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -5511,6 +5524,7 @@
"integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
@@ -5537,7 +5551,6 @@
"integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"debug": "^3.2.7",
"is-core-module": "^2.13.0",
@@ -5550,7 +5563,6 @@
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"ms": "^2.1.1"
}
@@ -5561,7 +5573,6 @@
"integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"debug": "^3.2.7"
},
@@ -5580,7 +5591,6 @@
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"ms": "^2.1.1"
}
@@ -5591,7 +5601,6 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -5626,7 +5635,6 @@
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -5638,7 +5646,6 @@
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"ms": "^2.1.1"
}
@@ -5649,7 +5656,6 @@
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
"dev": true,
"license": "Apache-2.0",
- "peer": true,
"dependencies": {
"esutils": "^2.0.2"
},
@@ -5663,7 +5669,6 @@
"integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==",
"dev": true,
"license": "ISC",
- "peer": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -5677,7 +5682,6 @@
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"license": "ISC",
- "peer": true,
"bin": {
"semver": "bin/semver.js"
}
@@ -5719,6 +5723,7 @@
"integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"globals": "^13.24.0",
@@ -7715,6 +7720,7 @@
"integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"abab": "^2.0.6",
"cssstyle": "^3.0.0",
@@ -7852,6 +7858,7 @@
"integrity": "sha512-UKgI3/KON4u6ngSsnDADsUERqhZknsVZbnuzlRZXLQCmfC/MDld42fTydUE9B+Mla1AL6SJ/Pp6SlEFi/AVGfw==",
"hasInstallScript": true,
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"copy-anything": "^2.0.1",
"parse-node-version": "^1.0.1",
@@ -7953,13 +7960,15 @@
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/lodash-es": {
"version": "4.17.22",
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.22.tgz",
"integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/lodash-unified": {
"version": "1.0.3",
@@ -8797,7 +8806,6 @@
"integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1",
@@ -8817,7 +8825,6 @@
"integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1",
@@ -8856,7 +8863,6 @@
"integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
@@ -9249,6 +9255,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -9366,6 +9373,7 @@
"integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -9857,6 +9865,7 @@
"integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"rollup": "dist/bin/rollup"
},
@@ -10506,6 +10515,12 @@
"npm": ">= 3.0.0"
}
},
+ "node_modules/sortablejs": {
+ "version": "1.15.7",
+ "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.7.tgz",
+ "integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==",
+ "license": "MIT"
+ },
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
@@ -10896,7 +10911,6 @@
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=4"
}
@@ -11587,7 +11601,6 @@
"integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/json5": "^0.0.29",
"json5": "^1.0.2",
@@ -11601,7 +11614,6 @@
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"minimist": "^1.2.0"
},
@@ -11764,6 +11776,7 @@
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"devOptional": true,
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -12074,6 +12087,7 @@
"integrity": "sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"esbuild": "^0.18.10",
"postcss": "^8.4.27",
@@ -12337,6 +12351,7 @@
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.26.tgz",
"integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.26",
"@vue/compiler-sfc": "3.5.26",
@@ -12517,6 +12532,24 @@
"vue": "^3"
}
},
+ "node_modules/vuedraggable": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz",
+ "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==",
+ "license": "MIT",
+ "dependencies": {
+ "sortablejs": "1.14.0"
+ },
+ "peerDependencies": {
+ "vue": "^3.0.1"
+ }
+ },
+ "node_modules/vuedraggable/node_modules/sortablejs": {
+ "version": "1.14.0",
+ "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.14.0.tgz",
+ "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==",
+ "license": "MIT"
+ },
"node_modules/w3c-xmlserializer": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
diff --git a/package.json b/package.json
index 0301a16..a6668d2 100644
--- a/package.json
+++ b/package.json
@@ -47,18 +47,21 @@
"mqtt": "^5.15.0",
"pinia": "^3.0.4",
"sockjs-client": "^1.6.1",
+ "sortablejs": "^1.15.7",
"stats.js": "^0.17.0",
"three": "^0.182.0",
"vue": "^3.3.4",
"vue-echarts": "^6.6.5",
"vue-router": "^4.2.5",
- "vue3-ace-editor": "^2.2.4"
+ "vue3-ace-editor": "^2.2.4",
+ "vuedraggable": "^4.1.0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node18": "^18.2.2",
"@types/jsdom": "^21.1.3",
"@types/node": "^18.18.5",
+ "@types/sortablejs": "^1.15.9",
"@types/three": "^0.182.0",
"@vitejs/plugin-vue": "^4.4.0",
"@vue/eslint-config-prettier": "^8.0.0",
diff --git a/public/models/default/default.glb b/public/models/default/default.glb
new file mode 100644
index 0000000..b48b0b9
Binary files /dev/null and b/public/models/default/default.glb differ
diff --git a/src/App.vue b/src/App.vue
index 5c936e6..b7da8da 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -68,8 +68,13 @@ import VueTableFireHydrant from '@/components/vue-components/vue-table-fire-hydr
import VueTableFireHydrantInfo from '@/components/vue-components/vue-table-fire-hydrant-info.vue';
import VueThreeBuilding from '@/components/three-components/vue-three-building.vue';
import VueExtinguisherTable from '@/components/vue-components/vue-extinguisher-table.vue';
-// F:\vue\workspace\maotu-webtopo\src\components\vue-components\vue-illumination-table.vue
import VueIlluminationTable from '@/components/vue-components/vue-illumination-table.vue';
+import VueStrInfo from '@/components/vue-components/vue-str-info.vue';
+import VueTestController from '@/components/vue-components/vue-test-controller.vue';
+import VueCar from '@/components/vue-components/vue-car.vue';
+import VueBaseInformation from '@/components/vue-components/vue-base-information.vue';
+// F:\vue\workspace\maotu-webtopo\src\components\vue-components\vue-3d-base-information.vue
+import Vue3dBaseInformation from '@/components/vue-components/vue-3d-base-information.vue';
// 图表
import VueGradeGauge from '@/components/vue-components/echarts-grade-gauge.vue';
@@ -127,6 +132,11 @@ instance?.appContext.app.component('vue-my-table-fire-hydrant-info', VueTableFir
instance?.appContext.app.component('vue-my-three-building', VueThreeBuilding);
instance?.appContext.app.component('vue-my-extinguisher-table', VueExtinguisherTable);
instance?.appContext.app.component('vue-my-illumination-table', VueIlluminationTable);
+instance?.appContext.app.component('vue-my-str-info', VueStrInfo);
+instance?.appContext.app.component('vue-my-test-controller', VueTestController);
+instance?.appContext.app.component('vue-my-car', VueCar);
+instance?.appContext.app.component('vue-my-base-information', VueBaseInformation);
+instance?.appContext.app.component('vue-my-3d-base-information', Vue3dBaseInformation);
instance?.appContext.app.component('vue-grade-gauge', VueGradeGauge);
instance?.appContext.app.component('vue-guage-line-chart', VueGuageLineChart);
@@ -322,7 +332,12 @@ leftAsideStore.registerConfig('vue四遥组件', [
showInfo: {
type: 'switch',
val: false,
- title: '显示名称'
+ title: '显示详情'
+ },
+ showText: {
+ type: 'switch',
+ val: false,
+ title: '显示文字'
},
location: {
type: 'select',
@@ -349,6 +364,44 @@ leftAsideStore.registerConfig('vue四遥组件', [
}
}
},
+ {
+ id: 'vue-my-str-info',
+ title: 'vue遥测-模式',
+ type: 'vue',
+ thumbnail: '/svgs/num-info.svg',
+ props: {
+ moduleType: {
+ type: 'inputTypeTag',
+ val: '遥测',
+ title: '四遥类型'
+ },
+ moduleId: {
+ type: 'inputSelectId',
+ val: '--',
+ title: '绑定ID'
+ },
+ showStart: {
+ type: 'switch',
+ val: false,
+ title: '显示状态'
+ },
+ showModel: {
+ type: 'switch',
+ val: true,
+ title: '显示模式'
+ },
+ showVal: {
+ type: 'switch',
+ val: false,
+ title: '显示值'
+ },
+ showText: {
+ type: 'switch',
+ val: false,
+ title: '显示名称'
+ }
+ }
+ },
{
id: 'vue-my-regulator',
title: 'vue遥调',
@@ -366,6 +419,19 @@ leftAsideStore.registerConfig('vue四遥组件', [
title: '绑定ID'
}
}
+ },
+ {
+ id: 'vue-my-test-controller',
+ title: '测试组件',
+ type: 'vue',
+ thumbnail: '/svgs/regulator.svg',
+ props: {
+ moduleId: {
+ type: 'inputSelectId',
+ val: '--',
+ title: '绑定ID'
+ }
+ }
}
]);
@@ -398,8 +464,18 @@ leftAsideStore.registerConfig('vue公共组件', [
},
testColor: {
type: 'color',
- val: '#44B6E7',
+ val: '#ffffff',
title: '文字颜色'
+ },
+ fontSize: {
+ type: 'number',
+ val: 16,
+ title: '字体大小'
+ },
+ fontBold: {
+ type: 'switch',
+ val: false,
+ title: '加粗'
}
}
},
@@ -671,6 +747,97 @@ leftAsideStore.registerConfig('vue公共组件', [
]
}
}
+ },
+ {
+ id: 'vue-my-car',
+ title: 'vue卡片组件',
+ type: 'vue',
+ thumbnail: '/svgs/table-base.svg',
+ props: {
+ fontFamily: {
+ title: '字体',
+ type: 'select',
+ val: 'Segoe UI',
+ options: [
+ {
+ value: 'Segoe UI',
+ label: 'Segoe UI'
+ },
+ {
+ value: '微软雅黑',
+ label: '微软雅黑'
+ },
+ {
+ value: '黑体',
+ label: '黑体'
+ },
+ {
+ value: '宋体',
+ label: '宋体'
+ }
+ ]
+ },
+ testContent: {
+ type: 'input',
+ val: '标题内容',
+ title: '标题内容'
+ },
+ fontSize: {
+ type: 'number',
+ val: 14,
+ title: '标题大小'
+ },
+ testColor: {
+ type: 'color',
+ val: '#ffffff',
+ title: '文字颜色'
+ },
+ skeletonBool: {
+ type: 'switch',
+ val: false,
+ title: '辅助框'
+ },
+ skeletonRows: {
+ type: 'number',
+ val: 3,
+ title: '框数量'
+ }
+ }
+ },
+ {
+ id: 'vue-my-base-information',
+ title: 'vue基本信息',
+ type: 'vue',
+ thumbnail: '/svgs/table-base.svg',
+ props: {
+ dataSource: {
+ title: '数据源',
+ type: 'select',
+ val: '--',
+ options: [
+ {
+ value: 'fireAlarmHost',
+ label: '火灾报警系统主机'
+ },
+ {
+ value: 'host',
+ label: '主机'
+ },
+ {
+ value: 'oilChromatography',
+ label: '2号主变油色谱'
+ },
+ {
+ value: 'partialDischarge',
+ label: '2号主变局放'
+ },
+ {
+ value: 'switchGap',
+ label: '2215开关间隔'
+ }
+ ]
+ }
+ }
}
]);
leftAsideStore.registerConfig('vue3D组件', [
@@ -816,6 +983,54 @@ leftAsideStore.registerConfig('vue3D组件', [
val: '--'
}
}
+ },
+ {
+ id: 'vue-my-3d-base-information',
+ title: '3d-基本信息',
+ type: 'vue',
+ thumbnail: '/svgs/table-only.svg',
+ props: {
+ dataTitle: {
+ title: '标题',
+ type: 'input',
+ val: '单个设备基本信息'
+ },
+ dataSource: {
+ title: '数据源',
+ type: 'select',
+ val: '--',
+ options: [
+ {
+ value: 'smokeSiren',
+ label: '烟感报警器'
+ },
+ {
+ value: 'temperatureFireDetector',
+ label: '温感火灾探测器'
+ },
+ {
+ value: 'fireHydrant',
+ label: '消火栓'
+ },
+ {
+ value: 'fireExtinguisher',
+ label: '灭火器'
+ },
+ {
+ value: 'evacuationSign',
+ label: '疏散指示灯'
+ },
+ {
+ value: 'infraredBeam',
+ label: '红外对射'
+ },
+ {
+ value: 'accessController',
+ label: '门禁控制器'
+ }
+ ]
+ }
+ }
}
]);
leftAsideStore.registerConfig('vue组件', [
diff --git a/src/assets.zip b/src/assets.zip
deleted file mode 100644
index 18eda4d..0000000
Binary files a/src/assets.zip and /dev/null differ
diff --git a/src/components/StompDemo.vue b/src/components/StompDemo.vue
index f88f394..efe58a7 100644
--- a/src/components/StompDemo.vue
+++ b/src/components/StompDemo.vue
@@ -11,8 +11,10 @@
- 连接
- 断开
+
+ {{ isConnected ? 'MQTT 已连接' : 'MQTT 未连接' }}
+
+ 重新连接
@@ -119,17 +121,14 @@ const clearLogs = () => {
};
// 连接 STOMP
-const connect = () => {
- stompService.connect({
- reconnectDelay: 5000
- });
- ElMessage.info('正在连接 STOMP...');
-};
-
-// 断开连接
-const disconnect = () => {
+const reconnect = () => {
stompService.disconnect();
- ElMessage.info('已断开 STOMP 连接');
+ setTimeout(() => {
+ stompService.connect({
+ reconnectDelay: 5000
+ });
+ ElMessage.info('正在重新连接 MQTT...');
+ }, 1000);
};
// 发送消息
@@ -151,17 +150,17 @@ const sendMessage = () => {
// 注册服务
onMounted(() => {
+ // 监听连接状态
stompService.registerService('demoComponent', {
mqttReady() {
- console.log('[Demo] STOMP 已就绪');
+ console.log('[Demo] MQTT 已就绪');
isConnected.value = true;
- ElMessage.success('STOMP 连接成功');
},
onConnectionLost() {
- console.log('[Demo] STOMP 连接丢失');
+ console.log('[Demo] MQTT 连接丢失');
isConnected.value = false;
- ElMessage.warning('STOMP 连接已断开,正在重连...');
+ ElMessage.warning('MQTT 连接已断开,正在重连...');
}
});
@@ -187,8 +186,8 @@ onMounted(() => {
// 组件卸载时清理
onUnmounted(() => {
- // 注意:通常不需要断开连接,除非是最后一个组件
- // stompService.disconnect();
+ // 不需要断开连接,因为 MQTT 是全局连接
+ console.log('[Demo] 组件卸载');
});
diff --git a/src/components/mt-edit/components/layout/header-panel/index.vue b/src/components/mt-edit/components/layout/header-panel/index.vue
index b1a03d2..c02e91b 100644
--- a/src/components/mt-edit/components/layout/header-panel/index.vue
+++ b/src/components/mt-edit/components/layout/header-panel/index.vue
@@ -73,8 +73,8 @@
-
-
+
@@ -332,6 +332,11 @@ const headerPanelProps = withDefaults(defineProps(), {
useThumbnail: false,
selectedItemsId: () => []
});
+
+function leftJustify() {
+ emits('alignSelected', 'left');
+}
+
const emits = defineEmits([
'update:leftAside',
'update:rightAside',
diff --git a/src/components/mt-edit/components/layout/main-panel/index.vue b/src/components/mt-edit/components/layout/main-panel/index.vue
index ec3b031..f7bbfe8 100644
--- a/src/components/mt-edit/components/layout/main-panel/index.vue
+++ b/src/components/mt-edit/components/layout/main-panel/index.vue
@@ -348,6 +348,7 @@ const onRenderCoreMouseDown = (item: IDoneJson, e: MouseEvent) => {
globalStore.refreshSelectedItemsId();
}
};
+
const onMouseDown = (e: MouseEvent) => {
beginListenerKeyDown();
globalStore.cancelAllSelect();
@@ -376,6 +377,7 @@ const onMouseDown = (e: MouseEvent) => {
globalStore.setIntention('beginMulSelect');
selectedAreaRef.value?.onMouseDown(e);
};
+
/**
* 区域选择结束事件 之所以用getBoundingClientRect是为了处理旋转后的坐标
* @param area_binfo 区域选择的边界信息
diff --git a/src/components/mt-edit/components/layout/right-aside/select-item-props-setting.vue b/src/components/mt-edit/components/layout/right-aside/select-item-props-setting.vue
index 60ac584..962da9b 100644
--- a/src/components/mt-edit/components/layout/right-aside/select-item-props-setting.vue
+++ b/src/components/mt-edit/components/layout/right-aside/select-item-props-setting.vue
@@ -108,6 +108,24 @@
height="80%"
width="60%"
>
+
+
+ 分区
+
+
+
+
+ 查询
+
+
+
+
@@ -178,6 +196,7 @@ import {
ElColorPicker,
ElIcon,
ElButton,
+ ElMessage,
type UploadFile
} from 'element-plus';
import { Search } from '@element-plus/icons-vue';
@@ -237,16 +256,22 @@ function setInputTagVal() {
const item = selectItemPropsSettingProps.propsInfo[key];
if (item.type === 'inputTypeTag') {
inputTypeTagValue.value = item.val;
+ console.log('inputTypeTagValue:', inputTypeTagValue.value);
+ break;
}
}
}
let attrItem: any;
const dialogTableVisible = ref(false);
-function handleIconClick(obj: any) {
- assembleList();
+
+async function handleIconClick(obj: any) {
+ console.log('inputTypeTagValue11:', inputTypeTagValue.value);
+ console.log('handleIconClick:', obj);
attrItem = obj;
- dialogTableVisible.value = true;
+ await getAllTree(); // 等待获取树形数据完成
+ assembleList();
+ dialogTableVisible.value = true; // 数据加载完成后再打开弹窗
}
let attrImg: any;
@@ -266,6 +291,22 @@ function bindingImg(obj: any) {
let modelIds = ref([]);
+// 选中的分区数据
+const selectedPartition = ref([]);
+
+// 处理分区选择变化
+const handlePartitionChange = (value: string[]) => {
+ console.log('选中的分区数据:', value);
+ // value 是一个数组,包含选中的层级数据
+ // 例如:['分区 ID', '子分区 ID', ...]
+ // 最后一个值是最后选中的层级
+ if (value && value.length > 0) {
+ const lastValue = value[value.length - 1];
+ console.log('最后选中的值:', lastValue);
+ // 在这里处理你的业务逻辑
+ }
+};
+
function handleEdit(obj: any) {
dialogTableVisible.value = false;
attrItem.val = obj.modeId;
@@ -310,20 +351,36 @@ const filterTag = (value: number, row: any) => {
// 根据搜索条件过滤数据
const filteredData = computed(() => {
+ debugger;
if (!search.value) {
- return gridData;
+ return gridData.value;
}
- return gridData.filter((item) => {
+ return gridData.value.filter((item) => {
return item.name.toLowerCase().includes(search.value.toLowerCase());
});
});
// 获取数据源
function assembleList() {
- // debugger;
+ debugger;
let code: number | undefined;
+ setInputTagVal();
+ // 第一次加载或没有数据时,从 globalDataRaw 加载
+ gridData.value.splice(0, gridData.value.length);
if (inputTypeTagValue.value !== undefined) code = getNameForNode(inputTypeTagValue.value);
- gridData.splice(0, gridData.length);
+
+ // 如果已经有数据,直接筛选,不再重新加载
+ if (gridDataSource.value && gridDataSource.value.length > 0) {
+ if (code === undefined) {
+ // code 未定义时,显示所有数据(已经在上一次加载中填充)
+ return;
+ } else {
+ // code 有值时,筛选出符合的数据
+ gridData.value = gridDataSource.value.filter((item) => item.bType === code);
+ console.log('new_gridData:', gridData.value);
+ return;
+ }
+ }
let globalDataRaw = (window as unknown as ExtendedParentWindow).globalData;
// let globalDataRaw = (window.parent as ExtendedParentWindow).Rec?.service.node.runtimes;
@@ -340,7 +397,7 @@ function assembleList() {
let modeId = key;
let name = data.node.name;
let bType = data.bType;
- gridData.push({ modeId, name, bType });
+ gridData.value.push({ modeId, name, bType });
}
});
} else {
@@ -352,7 +409,7 @@ function assembleList() {
let modeId = key;
let name = data.node.name;
let bType = data.bType;
- gridData.push({ modeId, name, bType });
+ gridData.value.push({ modeId, name, bType });
}
}
}
@@ -365,7 +422,73 @@ interface GridDataItem {
bType: number;
}
-const gridData: GridDataItem[] = [];
+const gridData = ref([]);
+const gridDataSource = ref([]);
+
+const props2 = {
+ multiple: false,
+ checkStrictly: true
+};
+
+async function getDataSource() {
+ debugger;
+ let cls = '-1';
+ if (selectedPartition.value && selectedPartition.value.length > 0)
+ cls = selectedPartition.value[selectedPartition.value.length - 1];
+
+ let response = await modelApi.getNodeByCls_get(cls);
+ if (response.code != 200 || response.data == null) {
+ ElMessage.error(response.message);
+ } else {
+ let code: number | undefined;
+ setInputTagVal();
+ if (inputTypeTagValue.value !== undefined) code = getNameForNode(inputTypeTagValue.value);
+
+ gridDataSource.value.splice(0, gridDataSource.value.length);
+ gridData.value.splice(0, gridData.value.length);
+ response.data.forEach((item: any) => {
+ console.log('item:', item);
+ gridDataSource.value.push({
+ modeId: item.id,
+ name: item.name,
+ bType: item.btype
+ });
+
+ if (code == undefined || code == item.btype) {
+ gridData.value.push({
+ modeId: item.id,
+ name: item.name,
+ bType: item.btype
+ });
+ }
+ });
+
+ ElMessage.success('接口请求成功');
+ console.log('gridData:', gridData.value);
+ }
+}
+
+async function getAllTree() {
+ const response = await modelApi.allTree_get();
+ if (response.code != 200 || response.data == null) {
+ ElMessage.error(response.message);
+ } else {
+ // 转换数据格式,将 id 转换为 value
+ options = convertTreeData(response.data);
+ ElMessage.success('树接口请求成功');
+ }
+}
+
+// 转换树形数据格式
+function convertTreeData(data: any[]): any[] {
+ return data.map((item) => ({
+ value: item.id.toString(), // 将 id 转换为 value
+ label: item.label,
+ children: item.children ? convertTreeData(item.children) : []
+ }));
+}
+
+let options: any[] = [];
diff --git a/src/components/public-compoents/node-list-dialog.vue b/src/components/public-compoents/node-list-dialog.vue
new file mode 100644
index 0000000..4db24d8
--- /dev/null
+++ b/src/components/public-compoents/node-list-dialog.vue
@@ -0,0 +1,262 @@
+
+
+
+
+ 分区
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+
+
+
+ {{ '遥信' }}
+ {{ '遥测' }}
+ {{ '遥控' }}
+ {{ '遥调' }}
+ {{ '其他' }}
+
+
+
+
+
+ {{ '遥信' }}
+ {{ '遥测' }}
+ {{ '遥控' }}
+ {{ '遥调' }}
+
+
+
+
+
+
+
+
+
+
+ 绑定
+
+
+
+
+
+
+
+
+
diff --git a/src/components/vue-components/vue-3d-base-information.vue b/src/components/vue-components/vue-3d-base-information.vue
new file mode 100644
index 0000000..e1a942d
--- /dev/null
+++ b/src/components/vue-components/vue-3d-base-information.vue
@@ -0,0 +1,293 @@
+
+
+ {{ dataTitle }}
+
+
+
+
+
+
+
+
+
+ {{ item.field }}
+ {{ item.value }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/vue-components/vue-base-information.vue b/src/components/vue-components/vue-base-information.vue
new file mode 100644
index 0000000..f48a749
--- /dev/null
+++ b/src/components/vue-components/vue-base-information.vue
@@ -0,0 +1,101 @@
+
+
+ 基本信息
+
+
+
+ {{ item.field }}
+
+ {{ item.value }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/vue-components/vue-car.vue b/src/components/vue-components/vue-car.vue
new file mode 100644
index 0000000..7e38522
--- /dev/null
+++ b/src/components/vue-components/vue-car.vue
@@ -0,0 +1,98 @@
+
+
+
+
+ {{ testContent }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/vue-components/vue-str-info.vue b/src/components/vue-components/vue-str-info.vue
new file mode 100644
index 0000000..4533aa2
--- /dev/null
+++ b/src/components/vue-components/vue-str-info.vue
@@ -0,0 +1,289 @@
+
+
+
+
+
+
+
+
+
+ {{ nodeStatus }}
+
+
+
+
+ {{ nodeModel }}
+
+
+
+
+ {{ nodeValue }}
+
+
+
+
+
+
+
+
+ {{ modeName }}
+
+
+
+
+
+
diff --git a/src/components/vue-components/vue-test-controller.vue b/src/components/vue-components/vue-test-controller.vue
new file mode 100644
index 0000000..8835db7
--- /dev/null
+++ b/src/components/vue-components/vue-test-controller.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Send
+
+
+
+
+
+
+
diff --git a/src/components/vue-xq-test/vue-num-info.vue b/src/components/vue-xq-test/vue-num-info.vue
index d691036..a4707cd 100644
--- a/src/components/vue-xq-test/vue-num-info.vue
+++ b/src/components/vue-xq-test/vue-num-info.vue
@@ -1,7 +1,7 @@
-
+
{{ modeName }}
@@ -11,7 +11,7 @@
-
+
{{ modeName }}
@@ -75,7 +75,7 @@
-
+
{{ modeName }}
@@ -85,7 +85,7 @@
-
+
{{ modeName }}
@@ -132,6 +132,10 @@ const props = defineProps({
showInfo: {
type: Boolean,
default: false
+ },
+ showText: {
+ type: Boolean,
+ default: false
}
});
diff --git a/src/main.ts b/src/main.ts
index 8c12fb0..b12d8cc 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -10,6 +10,7 @@ import { createPinia } from 'pinia';
import 'element-plus/dist/index.css';
import router from './router/newIndex';
import '@/utils/globalUtils';
+import { stompService } from '@/utils/stompService';
// 导入 Element Plus 语言包
// import enLocale from 'element-plus/dist/locale/en.mjs';
@@ -74,4 +75,11 @@ app.component('my-input', MyInput);
app.component('my-button', MyButton);
app.component('custom-demo', CustomDemo);
app.component('pie-charts', PieCharts);
+
+// 项目启动时自动连接 STOMP/MQTT
+stompService.connect({
+ reconnectDelay: 5000 // 5 秒后重连
+});
+console.log('[Main] STOMP/MQTT 服务已启动,正在连接...');
+
app.mount('#app');
diff --git a/src/router/newIndex.ts b/src/router/newIndex.ts
index 3fbd9d7..a08225f 100644
--- a/src/router/newIndex.ts
+++ b/src/router/newIndex.ts
@@ -813,6 +813,59 @@ export const constantRoutes: Readonly = [
}
]
},
+ {
+ path: '/classify', //F:\vue\workspace\maotu-webtopo\src\views\preview\classify\index.vue
+ name: 'classify',
+ component: () => import('@/layout/view_index.vue'),
+ meta: {
+ title: '设备分类项目',
+ hidden: false,
+ treeHidden: false,
+ bottomHidden: false,
+ menuIcon: 'Operation'
+ },
+ children: [
+ {
+ path: '/classify/index',
+ name: 'classifyIndex',
+ component: () => import('@/views/preview/classify/index.vue'),
+ meta: {
+ title: '设备分类',
+ hidden: false,
+ treeHidden: false,
+ bottomHidden: false,
+ menuIcon: 'Setting'
+ }
+ }
+ ]
+ },
+ // F:\vue\workspace\maotu-webtopo\src\views\preview\lightBoard\index.vue
+ {
+ path: '/lightBoard', //F:\vue\workspace\maotu-webtopo\src\views\preview\classify\index.vue
+ name: 'lightBoard',
+ component: () => import('@/layout/view_index.vue'),
+ meta: {
+ title: '光字牌项目',
+ hidden: false,
+ treeHidden: false,
+ bottomHidden: false,
+ menuIcon: 'Operation'
+ },
+ children: [
+ {
+ path: '/lightBoard/index',
+ name: 'lightBoardIndex',
+ component: () => import('@/views/preview/lightBoard/index.vue'),
+ meta: {
+ title: '光字牌',
+ hidden: false,
+ treeHidden: false,
+ bottomHidden: false,
+ menuIcon: 'Setting'
+ }
+ }
+ ]
+ },
{
path: '/test', //F:\vue\workspace\maotu-webtopo\src\views\preview\systemInfo\index.vue
name: 'test',
diff --git a/src/utils/config.ts b/src/utils/config.ts
index 10d54fe..6e02a32 100644
--- a/src/utils/config.ts
+++ b/src/utils/config.ts
@@ -47,6 +47,58 @@ export const getIndex = (num: number) => {
return -1;
}
};
+
+/**
+ * 节点状态
+ * @param num Node里面的sig值
+ * @returns
+ */
+export const getNodeStatus = (sig: number) => {
+ switch (sig) {
+ case -2000:
+ return '未初始化状态';
+ case 0:
+ return '正常';
+ case 1:
+ return '开启';
+ case 5:
+ return '联动关';
+ case 10:
+ return '高联动';
+ case -10:
+ return '低联动';
+ case 20:
+ return '高限告警';
+ case -20:
+ return '低限告警';
+ default:
+ return '未知状态';
+ }
+};
+
+/**
+ * 节点颜色
+ * @param num Node里面的sig值
+ * @returns
+ */
+export const getNodeColor = (sig: number) => {
+ switch (sig) {
+ case -2000:
+ return 'info';
+ case 0:
+ case 1:
+ return 'primary';
+ case 5:
+ case 10:
+ case -10:
+ return 'warning';
+ case 20:
+ case -20:
+ return 'danger';
+ default:
+ return 'info';
+ }
+};
// 四遥基本类型
Rec.Node.TypeBase = [
[1, '遥信'],
@@ -139,7 +191,7 @@ Rec.EnumTypeVal[14] = [
[2, '送风']
];
-Rec.EnumTypeValFun[14] = function (val: any) {
+Rec.EnumTypeValFun[14] = function (val: any, index: number) {
return Rec.trans!(val, Rec.EnumTypeVal![14]);
};
@@ -152,7 +204,7 @@ Rec.EnumTypeVal[11] = [
[4, '送风']
];
-Rec.EnumTypeValFun[11] = function (val: any) {
+Rec.EnumTypeValFun[11] = function (val: any, index: number) {
return Rec.trans!(val, Rec.EnumTypeVal![11]);
};
@@ -175,7 +227,7 @@ Rec.EnumTypeVal[12] = [
[30, '30℃']
];
-Rec.EnumTypeValFun[12] = function (val: any) {
+Rec.EnumTypeValFun[12] = function (val: any, index: number) {
return Rec.trans!(val, Rec.EnumTypeVal![12]);
};
@@ -187,7 +239,7 @@ Rec.EnumTypeVal[13] = [
[3, '高']
];
-Rec.EnumTypeValFun[13] = function (val: any) {
+Rec.EnumTypeValFun[13] = function (val: any, index: number) {
return Rec.trans!(val, Rec.EnumTypeVal![13]);
};
@@ -198,7 +250,7 @@ Rec.EnumTypeVal[21] = [
[2, '制热']
];
-Rec.EnumTypeValFun[21] = function (val: any) {
+Rec.EnumTypeValFun[21] = function (val: any, index: number) {
return Rec.trans!(val, Rec.EnumTypeVal![21]);
};
//
diff --git a/src/utils/globalUtils.ts b/src/utils/globalUtils.ts
index 50872bb..b72c02f 100644
--- a/src/utils/globalUtils.ts
+++ b/src/utils/globalUtils.ts
@@ -85,7 +85,6 @@ async function getData() {
if (data && typeof data === 'object') {
// 判断当前 globalData 类型并相应处理
const currentGlobalData = window.globalData;
- debugger;
currentGlobalData.clear();
Object.entries(data).forEach(([key, value]) => {
diff --git a/src/utils/invariable.ts b/src/utils/invariable.ts
new file mode 100644
index 0000000..d3a6744
--- /dev/null
+++ b/src/utils/invariable.ts
@@ -0,0 +1,162 @@
+export interface Paragraph {
+ field: string;
+ value: string;
+}
+
+export const invariantObjMap: Record = {
+ // 火灾报警系统主机
+ fireAlarmHost: [
+ { field: '名称', value: '火灾报警系统主机' },
+ { field: '产品型号', value: 'JB-QB-GST200' },
+ { field: '厂商', value: '海湾公司' },
+ { field: '运行日期', value: '2023-04-01' },
+ { field: '电源电压', value: '220V AC' },
+ { field: '频率', value: '50Hz' },
+ { field: '输出电压', value: '24V DC' },
+ { field: '输出电流', value: '5A' },
+ { field: '环境温度', value: '-5℃ ~ 45℃' },
+ { field: '相对湿度', value: '5% ~ 95%' },
+ { field: '维护单位', value: '陕西消防科技有限公司' },
+ { field: '联系电话', value: '188*****00' }
+ ],
+ // 主机
+ host: [
+ { field: '名称', value: 'PAVLN排油注氮智能防护系统控制主机' },
+ { field: '型号', value: 'JB-QB-GST200' },
+ { field: '厂家', value: '海湾公司' },
+ { field: '运行日期', value: '2015-10-10' },
+ { field: '电源电压', value: 'DC 220V 5A/AC 220V 5A' },
+ { field: '频率', value: '27~1600MHz' },
+ { field: '输出电压', value: '24V DC' },
+ { field: '输出电流', value: '5A' },
+ { field: '环境温度', value: '-5℃ ~ 45℃' },
+ { field: '相对湿度', value: '5% ~ 95%' },
+ { field: '维护单位', value: '陕西消防科技有限公司' },
+ { field: '联系电话', value: '188*****00' }
+ ],
+ // 2号主变油色谱
+ oilChromatography: [
+ { field: '厂家', value: '宁波理工' },
+ { field: '型号', value: 'MGA2000-6H' },
+ { field: '投运日期', value: '2015年10月27日' },
+ { field: '工作电源', value: 'AC220V,50Hz' },
+ { field: '工作环境温度', value: '-40°C~+80°C' },
+ { field: '工作相对湿度', value: '5%~95%' }
+ ],
+ //2号主变局放
+ partialDischarge: [
+ { field: '厂家', value: '上海思瑞在线监测技术有限公司' },
+ { field: '型号', value: 'MGA2000-6H' },
+ { field: '投运日期', value: '2015年10月16日' },
+ { field: '局放测量通道', value: '3个局放测量通道+1个噪音测量通道' },
+ { field: '局放传感器频宽', value: '300MHZ~2000MHZ' },
+ { field: '工作环境温度', value: '-25°C~+55°C' },
+ { field: '工作相对湿度', value: '5%~95%' }
+ ],
+ //2215开关间隔
+ switchGap: [
+ { field: '厂家', value: '许继电气股份有限公司' },
+ { field: '型号', value: 'DPD-801' },
+ { field: '投运日期', value: '2015年11月17日' },
+ { field: '局放测量通道', value: '3个局放测量通道+1个噪音测量通道' },
+ { field: '工作环境温度', value: '-40°C~+70°C' },
+ { field: '工作相对湿度', value: '5%~95%' }
+ ]
+};
+
+const threeDPath = {
+ smokeSiren: '/models/smokeSiren/smokeSiren.glb',
+ default: '/models/default/default.glb'
+};
+
+export const invariant3DObjMap: Record = {
+ // 烟感报警器
+ smokeSiren: [
+ { field: '3D模型', value: threeDPath.smokeSiren },
+ { field: '厂家', value: '海湾公司' },
+ { field: '型号', value: 'VLP-666-CH标准型' },
+ { field: '投运日期', value: '2014-06-08' },
+ { field: '布设位置', value: '35kV高压室' },
+ { field: '供电电压', value: '18-30VDC' },
+ { field: 'IP等级', value: 'IP30' },
+ { field: '接线方式', value: '两线制(L+、L-)' },
+ { field: '尺寸(长x高x宽)', value: '350mmx225mmx125mm' },
+ { field: '报警灵敏度范围', value: '0.005%至20%obs/m' },
+ { field: '运行条件1', value: '探测器环境(-5°C至45°C)' },
+ { field: '运行条件2', value: '采样空气(-20°C至60°C)' },
+ { field: '运行条件3', value: '湿度(5%至95%RH)' }
+ ],
+ // 温感火灾探测器
+ temperatureFireDetector: [
+ { field: '3D模型', value: threeDPath.default },
+ { field: '厂家', value: '海湾公司' },
+ { field: '型号', value: 'CT1-155X' },
+ { field: '投运日期', value: '2012-08-08' },
+ { field: '使用环境', value: '温度-5°C~45°C' },
+ { field: '火灾响应规模', value: '10mm' },
+ { field: '测量温度精度', value: '≤1°C' },
+ { field: '类型', value: '定温式' },
+ { field: '报警温度', value: '85°C' },
+ { field: '标准', value: 'GB16280-2014' }
+ ],
+ // 消火栓
+ fireHydrant: [
+ { field: '3D模型', value: threeDPath.default },
+ { field: '厂家', value: '宏达消防设备制造有限公司' },
+ { field: '型号', value: 'SN-65' },
+ { field: '投运日期', value: '2016-10-10' },
+ { field: '布设位置', value: '生产综合楼1楼走廊' },
+ { field: '质量保证书类型', value: '型式认证' },
+ { field: '质保证书', value: 'NO2015-2032' },
+ { field: '维保单位', value: '陕西消防科技有限公司' },
+ { field: '联系电话', value: '188*****00' }
+ ],
+ // 灭火器
+ fireExtinguisher: [
+ { field: '3D模型', value: threeDPath.default },
+ { field: '厂家', value: '天河消防厂' },
+ { field: '型号', value: 'MFZ35' },
+ { field: '投运日期', value: '2012-08-08' },
+ { field: '布设位置', value: '生产综合楼1楼35kV高压室' },
+ { field: '名称', value: '推车式干粉灭火器' },
+ { field: '品牌', value: '淮海' },
+ { field: '灭火剂', value: '碳酸铵盐50%、硫酸铵25%、滑石粉25%' },
+ { field: '灭火级别', value: 'ABCD' }
+ ],
+ // 疏散指示灯
+ evacuationSign: [
+ { field: '3D模型', value: threeDPath.default },
+ { field: '厂家', value: 'XXX消防设备有限公司' },
+ { field: '型号', value: 'BSD128F(自带应急照明)' },
+ { field: '投运日期', value: '2013-08-06' },
+ { field: '布设位置', value: '110kV保护室' },
+ { field: '输入电压', value: 'AC220V(+10%)' },
+ { field: '频率', value: '50Hz' },
+ { field: '功率', value: '<3W' },
+ { field: '应急时间', value: '>=90min' },
+ { field: '转换时间', value: '<=10s' },
+ { field: '充电时间', value: '>=24h' },
+ { field: '电池类型', value: 'Ni-Cd 1.2v 800mAh' }
+ ],
+ // 红外对射
+ infraredBeam: [
+ { field: '3D模型', value: threeDPath.default },
+ { field: '厂家', value: 'XX霍尼维尔' },
+ { field: '生产型号', value: 'DT-8041' },
+ { field: '供电电源', value: '9.0-15VDC' },
+ { field: '微波频率', value: '10.525GHz' },
+ { field: '工作温度', value: '-10°C~55°C' },
+ { field: '相对湿度', value: '5至93%' },
+ { field: '探测范围', value: '12m' }
+ ],
+ // 门禁控制器
+ accessController: [
+ { field: '3D模型', value: threeDPath.default },
+ { field: '生产厂家', value: 'Pegasus' },
+ { field: '生产型号', value: 'PP6750V' },
+ { field: '投运日期', value: '2017-05-09' },
+ { field: '电源电压', value: 'DC12V' },
+ { field: '工作电流', value: '100mA' },
+ { field: '管理门数', value: '4' }
+ ]
+};
diff --git a/src/utils/request.ts b/src/utils/request.ts
index 007c9be..392db6b 100644
--- a/src/utils/request.ts
+++ b/src/utils/request.ts
@@ -21,7 +21,102 @@ export const buildApiUrl = (path: string) => {
};
export const modelApi = {
- // http://localhost:8080/monitor/info
+ // http://localhost:8080/data/lightModel/getLightBoardList
+ getLightBoardList_post(endJson: any): Promise {
+ return fetch(buildApiUrl('/data/lightModel/getLightBoardList'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Accept: '*/*'
+ },
+ body: JSON.stringify(endJson)
+ }).then((response) => {
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+ return response.json();
+ });
+ },
+
+ changeNodeClass_post(endJson: any): Promise {
+ return fetch(buildApiUrl('/data/tree/changeNodeClass'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Accept: '*/*'
+ },
+ body: JSON.stringify(endJson)
+ }).then((response) => {
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+ return response.json();
+ });
+ },
+
+ getNodeByCls_get(clsId: string): Promise {
+ return fetch(buildApiUrl(`/data/tree/getNodeByCls?clsId=${clsId}`), {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Accept: '*/*'
+ }
+ }).then((response) => {
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+ return response.json();
+ });
+ },
+ deleteTreeNode_post(endJson: any): Promise {
+ return fetch(buildApiUrl('/data/tree/deleteTreeNode'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Accept: '*/*'
+ },
+ body: JSON.stringify(endJson)
+ }).then((response) => {
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+ return response.json();
+ });
+ },
+
+ changeTreeNode_post(endJson: any): Promise {
+ return fetch(buildApiUrl('/data/tree/changeTreeNode'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Accept: '*/*'
+ },
+ body: JSON.stringify(endJson)
+ }).then((response) => {
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+ return response.json();
+ });
+ },
+
+ addTreeNode_post(endJson: any): Promise {
+ return fetch(buildApiUrl('/data/tree/addTreeNode'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Accept: '*/*'
+ },
+ body: JSON.stringify(endJson)
+ }).then((response) => {
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+ return response.json();
+ });
+ },
+
+ allTree_get(): Promise {
+ return fetch(buildApiUrl('/data/tree/allTree'), {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Accept: '*/*'
+ }
+ }).then((response) => {
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+ return response.json();
+ });
+ },
+
monitor_info_get(): Promise {
return fetch(buildApiUrl('/monitor/info'), {
method: 'GET',
diff --git a/src/utils/stompService.ts b/src/utils/stompService.ts
index 7e157b3..41879f0 100644
--- a/src/utils/stompService.ts
+++ b/src/utils/stompService.ts
@@ -287,7 +287,9 @@ class StompService {
break;
case MqttCmd.Node:
- debugger;
+ console.log('[STOMP] 收到 Node 更新消息:', msgObject.value);
+ window.vueGlobalFunction(msgObject.value);
+
// 单一 Node 更新消息
if (this.services.node) {
this.services.nod;
diff --git a/src/views/preview/classify/index.vue b/src/views/preview/classify/index.vue
new file mode 100644
index 0000000..e8055bf
--- /dev/null
+++ b/src/views/preview/classify/index.vue
@@ -0,0 +1,668 @@
+
+
+
+
+
+ 节点分区
+
+
+
+
+
+
+
+
+
+ 添加
+
+
+ 刷新
+
+
+
+
+
+
+
+ {{ node.label }}
+
+ 添加
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+ 节点列表
+
+
+ 选择树节点:{{ treeNodeName }}
+ 未选择树节点
+
+
+
+
+
+
+
+ {{ '遥信' }}
+ {{ '遥测' }}
+ {{ '遥控' }}
+ {{ '遥调' }}
+ {{ '其他' }}
+
+
+
+
+
+
+
+
+
+ 所有节点
+
+
+
+
+
+
+
+
+
+
+ {{ '遥信' }}
+ {{ '遥测' }}
+ {{ '遥控' }}
+ {{ '遥调' }}
+ {{ '其他' }}
+
+
+
+
+
+ {{ '遥信' }}
+ {{ '遥测' }}
+ {{ '遥控' }}
+ {{ '遥调' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/preview/lightBoard/index.vue b/src/views/preview/lightBoard/index.vue
new file mode 100644
index 0000000..9836ae3
--- /dev/null
+++ b/src/views/preview/lightBoard/index.vue
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 清除
+ 查询
+
+
+
+
+
+
+
+
+
+ 刷新
+
+
+
+
+
+
实际绑定节点:{{ props.row.lightBoardStartNum-1 }}
+
绑定状态
+
+
状态列表
+
+
+
+
+
+ {{
+ scope.row.nodeId
+ }}
+ 无节点ID
+
+
+
+
+
+
+ 无信号
+ 出现信号
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ tag }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+