fix:完成数据查看模块
258
package-lock.json
generated
@ -21,6 +21,7 @@
|
||||
"maptalks": "^1.1.3",
|
||||
"markdown-it": "^14.1.0",
|
||||
"mitt": "^3.0.1",
|
||||
"ol": "^10.6.1",
|
||||
"serialport": "^12.0.0",
|
||||
"vue": "^3.3.4",
|
||||
"vue-drag-resize": "^2.0.3",
|
||||
@ -687,6 +688,12 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@petamoriken/float16": {
|
||||
"version": "3.9.2",
|
||||
"resolved": "https://r.cnpmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz",
|
||||
"integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
@ -1412,6 +1419,12 @@
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/rbush": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://r.cnpmjs.org/@types/rbush/-/rbush-4.0.0.tgz",
|
||||
"integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/web-bluetooth": {
|
||||
"version": "0.0.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
|
||||
@ -1983,6 +1996,12 @@
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/earcut": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://r.cnpmjs.org/earcut/-/earcut-3.0.2.tgz",
|
||||
"integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/echart": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/echart/-/echart-0.1.3.tgz",
|
||||
@ -2289,6 +2308,25 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/geotiff": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://r.cnpmjs.org/geotiff/-/geotiff-2.1.3.tgz",
|
||||
"integrity": "sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@petamoriken/float16": "^3.4.7",
|
||||
"lerc": "^3.0.0",
|
||||
"pako": "^2.0.4",
|
||||
"parse-headers": "^2.0.2",
|
||||
"quick-lru": "^6.1.1",
|
||||
"web-worker": "^1.2.0",
|
||||
"xml-utils": "^1.0.2",
|
||||
"zstddec": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
@ -2651,6 +2689,12 @@
|
||||
"any-promise": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lerc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://r2.cnpmjs.org/lerc/-/lerc-3.0.0.tgz",
|
||||
"integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/less": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz",
|
||||
@ -2985,6 +3029,38 @@
|
||||
"integrity": "sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ol": {
|
||||
"version": "10.6.1",
|
||||
"resolved": "https://r.cnpmjs.org/ol/-/ol-10.6.1.tgz",
|
||||
"integrity": "sha512-xp174YOwPeLj7c7/8TCIEHQ4d41tgTDDhdv6SqNdySsql5/MaFJEJkjlsYcvOPt7xA6vrum/QG4UdJ0iCGT1cg==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@types/rbush": "4.0.0",
|
||||
"earcut": "^3.0.0",
|
||||
"geotiff": "^2.1.3",
|
||||
"pbf": "4.0.1",
|
||||
"rbush": "^4.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/openlayers"
|
||||
}
|
||||
},
|
||||
"node_modules/ol/node_modules/quickselect": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://r.cnpmjs.org/quickselect/-/quickselect-3.0.0.tgz",
|
||||
"integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ol/node_modules/rbush": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://r.cnpmjs.org/rbush/-/rbush-4.0.1.tgz",
|
||||
"integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"quickselect": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/on-finished": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||
@ -3001,6 +3077,18 @@
|
||||
"resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
|
||||
"integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ=="
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://r.cnpmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/parse-headers": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://r.cnpmjs.org/parse-headers/-/parse-headers-2.0.6.tgz",
|
||||
"integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/parse-node-version": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
|
||||
@ -3038,6 +3126,18 @@
|
||||
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/pbf": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://r.cnpmjs.org/pbf/-/pbf-4.0.1.tgz",
|
||||
"integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"resolve-protobuf-schema": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"pbf": "bin/pbf"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
@ -3109,6 +3209,12 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/protocol-buffers-schema": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://r2.cnpmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
|
||||
"integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/prr": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||
@ -3152,6 +3258,18 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/quick-lru": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://r.cnpmjs.org/quick-lru/-/quick-lru-6.1.2.tgz",
|
||||
"integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/quickselect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz",
|
||||
@ -3202,6 +3320,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-protobuf-schema": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://r2.cnpmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
|
||||
"integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"protocol-buffers-schema": "^3.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/reusify": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||
@ -3817,6 +3944,12 @@
|
||||
"resolved": "https://registry.npmjs.org/vue3-konami-code/-/vue3-konami-code-1.0.0.tgz",
|
||||
"integrity": "sha512-fhHAPFZA1jsgDHlYz5dnG52RmY9+vtfMthBaY1S5VBxNLdU4EWTbnJO0nfL8Uybw5uHsDqCGtTbGaX7nIvQ9Qw=="
|
||||
},
|
||||
"node_modules/web-worker": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://r.cnpmjs.org/web-worker/-/web-worker-1.5.0.tgz",
|
||||
"integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/webpack-sources": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||
@ -3832,6 +3965,12 @@
|
||||
"integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/xml-utils": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://r.cnpmjs.org/xml-utils/-/xml-utils-1.10.2.tgz",
|
||||
"integrity": "sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==",
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/ylru": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ylru/-/ylru-1.4.0.tgz",
|
||||
@ -3847,6 +3986,12 @@
|
||||
"dependencies": {
|
||||
"tslib": "2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/zstddec": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://r.cnpmjs.org/zstddec/-/zstddec-0.1.0.tgz",
|
||||
"integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==",
|
||||
"license": "MIT AND BSD-3-Clause"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
@ -4181,6 +4326,11 @@
|
||||
"fastq": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@petamoriken/float16": {
|
||||
"version": "3.9.2",
|
||||
"resolved": "https://r.cnpmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz",
|
||||
"integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog=="
|
||||
},
|
||||
"@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
@ -4555,6 +4705,11 @@
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"@types/rbush": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://r.cnpmjs.org/@types/rbush/-/rbush-4.0.0.tgz",
|
||||
"integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ=="
|
||||
},
|
||||
"@types/web-bluetooth": {
|
||||
"version": "0.0.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
|
||||
@ -4977,6 +5132,11 @@
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
|
||||
},
|
||||
"earcut": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://r.cnpmjs.org/earcut/-/earcut-3.0.2.tgz",
|
||||
"integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ=="
|
||||
},
|
||||
"echart": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/echart/-/echart-0.1.3.tgz",
|
||||
@ -5195,6 +5355,21 @@
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true
|
||||
},
|
||||
"geotiff": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://r.cnpmjs.org/geotiff/-/geotiff-2.1.3.tgz",
|
||||
"integrity": "sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==",
|
||||
"requires": {
|
||||
"@petamoriken/float16": "^3.4.7",
|
||||
"lerc": "^3.0.0",
|
||||
"pako": "^2.0.4",
|
||||
"parse-headers": "^2.0.2",
|
||||
"quick-lru": "^6.1.1",
|
||||
"web-worker": "^1.2.0",
|
||||
"xml-utils": "^1.0.2",
|
||||
"zstddec": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
@ -5483,6 +5658,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"lerc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://r2.cnpmjs.org/lerc/-/lerc-3.0.0.tgz",
|
||||
"integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww=="
|
||||
},
|
||||
"less": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz",
|
||||
@ -5724,6 +5904,33 @@
|
||||
"integrity": "sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ol": {
|
||||
"version": "10.6.1",
|
||||
"resolved": "https://r.cnpmjs.org/ol/-/ol-10.6.1.tgz",
|
||||
"integrity": "sha512-xp174YOwPeLj7c7/8TCIEHQ4d41tgTDDhdv6SqNdySsql5/MaFJEJkjlsYcvOPt7xA6vrum/QG4UdJ0iCGT1cg==",
|
||||
"requires": {
|
||||
"@types/rbush": "4.0.0",
|
||||
"earcut": "^3.0.0",
|
||||
"geotiff": "^2.1.3",
|
||||
"pbf": "4.0.1",
|
||||
"rbush": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"quickselect": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://r.cnpmjs.org/quickselect/-/quickselect-3.0.0.tgz",
|
||||
"integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g=="
|
||||
},
|
||||
"rbush": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://r.cnpmjs.org/rbush/-/rbush-4.0.1.tgz",
|
||||
"integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==",
|
||||
"requires": {
|
||||
"quickselect": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||
@ -5737,6 +5944,16 @@
|
||||
"resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
|
||||
"integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ=="
|
||||
},
|
||||
"pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://r.cnpmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
|
||||
},
|
||||
"parse-headers": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://r.cnpmjs.org/parse-headers/-/parse-headers-2.0.6.tgz",
|
||||
"integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A=="
|
||||
},
|
||||
"parse-node-version": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
|
||||
@ -5767,6 +5984,14 @@
|
||||
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
|
||||
"dev": true
|
||||
},
|
||||
"pbf": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://r.cnpmjs.org/pbf/-/pbf-4.0.1.tgz",
|
||||
"integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==",
|
||||
"requires": {
|
||||
"resolve-protobuf-schema": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
@ -5810,6 +6035,11 @@
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"protocol-buffers-schema": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://r2.cnpmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
|
||||
"integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="
|
||||
},
|
||||
"prr": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||
@ -5832,6 +6062,11 @@
|
||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||
"dev": true
|
||||
},
|
||||
"quick-lru": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://r.cnpmjs.org/quick-lru/-/quick-lru-6.1.2.tgz",
|
||||
"integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ=="
|
||||
},
|
||||
"quickselect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz",
|
||||
@ -5871,6 +6106,14 @@
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"resolve-protobuf-schema": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://r2.cnpmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
|
||||
"integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
|
||||
"requires": {
|
||||
"protocol-buffers-schema": "^3.3.1"
|
||||
}
|
||||
},
|
||||
"reusify": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||
@ -6259,6 +6502,11 @@
|
||||
"resolved": "https://registry.npmjs.org/vue3-konami-code/-/vue3-konami-code-1.0.0.tgz",
|
||||
"integrity": "sha512-fhHAPFZA1jsgDHlYz5dnG52RmY9+vtfMthBaY1S5VBxNLdU4EWTbnJO0nfL8Uybw5uHsDqCGtTbGaX7nIvQ9Qw=="
|
||||
},
|
||||
"web-worker": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://r.cnpmjs.org/web-worker/-/web-worker-1.5.0.tgz",
|
||||
"integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw=="
|
||||
},
|
||||
"webpack-sources": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||
@ -6271,6 +6519,11 @@
|
||||
"integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==",
|
||||
"dev": true
|
||||
},
|
||||
"xml-utils": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://r.cnpmjs.org/xml-utils/-/xml-utils-1.10.2.tgz",
|
||||
"integrity": "sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA=="
|
||||
},
|
||||
"ylru": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ylru/-/ylru-1.4.0.tgz",
|
||||
@ -6283,6 +6536,11 @@
|
||||
"requires": {
|
||||
"tslib": "2.3.0"
|
||||
}
|
||||
},
|
||||
"zstddec": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://r.cnpmjs.org/zstddec/-/zstddec-0.1.0.tgz",
|
||||
"integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
"maptalks": "^1.1.3",
|
||||
"markdown-it": "^14.1.0",
|
||||
"mitt": "^3.0.1",
|
||||
"ol": "^10.6.1",
|
||||
"serialport": "^12.0.0",
|
||||
"vue": "^3.3.4",
|
||||
"vue-drag-resize": "^2.0.3",
|
||||
|
@ -1 +1 @@
|
||||
{"pathofsave":"C:\\Program Files\\lucamtool","Filename":"testaa","caijiavgNumber":"1","useSG":false,"usehighpass":false,"Dispatcher":{"isenable":true,"begin":"06:25","end":"23:59"},"sensor_typeforset":"IS3"}
|
||||
{"pathofsave":null,"Filename":"testaa","caijiavgNumber":"1","useSG":false,"usehighpass":false,"Dispatcher":{"isenable":true,"begin":"06:25","end":"23:59"},"sensor_typeforset":"IRIS-IS11"}
|
BIN
src-tauri/data46.iris
Normal file
23
src/App.vue
@ -1,6 +1,4 @@
|
||||
<script>
|
||||
// This starter template is using Vue 3 <script setup> SFCs
|
||||
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
||||
import Greet from "./components/Greet.vue";
|
||||
import AppHyperSpectral from "./AppHyperSpectral.vue";
|
||||
import APPDataview from "./DataView/APPDataview.vue";
|
||||
@ -13,34 +11,35 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modalcomponent: 'AppHyperSpectral',
|
||||
compomentlist: ['AppHyperSpectral', 'APPDataview'],
|
||||
currentView: 'AppHyperSpectral', // 当前显示的视图
|
||||
viewList: ['AppHyperSpectral', 'APPDataview'],
|
||||
indexofcomponent: 0,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
EventBus.on('changemainvue', this.onchangemainvue);
|
||||
console.log(window.__TAURI__);
|
||||
|
||||
},
|
||||
methods: {
|
||||
onchangemainvue(){
|
||||
// 切换到下一个视图
|
||||
this.indexofcomponent++;
|
||||
if (this.indexofcomponent >= this.compomentlist.length) {
|
||||
if (this.indexofcomponent >= this.viewList.length) {
|
||||
this.indexofcomponent = 0;
|
||||
}
|
||||
this.modalcomponent = this.compomentlist[this.indexofcomponent];
|
||||
|
||||
|
||||
this.currentView = this.viewList[this.indexofcomponent];
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="modalcomponent" ref="Commancompent" style="user-select: none;"></component>
|
||||
|
||||
<keep-alive>
|
||||
<component
|
||||
:is="currentView"
|
||||
style="user-select: none; width: 100vw; height: 100vh;"
|
||||
/>
|
||||
</keep-alive>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
@ -1,47 +1,56 @@
|
||||
<template>
|
||||
|
||||
|
||||
|
||||
<a-layout style="height: 100vh; width: 100vw;">
|
||||
<a-layout-header>
|
||||
<menubardatavue></menubardatavue>
|
||||
</a-layout-header>
|
||||
<a-layout>
|
||||
<a-layout-sider :resize-directions="['right']" style=" min-width: 200px;max-width: 50vw;">
|
||||
<a-layout-sider :resize-directions="['right']" style=" min-width: 20vw;max-width: 50vw;">
|
||||
<a-dropdown trigger="contextMenu" alignPoint :style="{ display: 'block' }">
|
||||
<GuiLeftSider class="lefttree" v-on:NodeClicked="ononeFilechoese"></GuiLeftSider>
|
||||
<GuiLeftSider class="lefttree" v-on:NodeClicked="ononeFilechoese"
|
||||
v-on:NodeDblClicked="onFileDblClick" v-on:FilesSelected="onFilesSelected"
|
||||
v-on:FolderClicked="onFolderClicked" v-on:FolderDblClicked="onFolderDblClick"
|
||||
v-on:SaveFilesRequested="onSaveFilesRequested" v-on:reset="resetTreeData">
|
||||
</GuiLeftSider>
|
||||
<template #content>
|
||||
<a-doption>Option 1</a-doption>
|
||||
<a-doption>Option 2</a-doption>
|
||||
<a-doption>Option 3</a-doption>
|
||||
<a-doption @click="onShowCurvesClick">显示曲线</a-doption>
|
||||
<!-- <a-doption>Option 2</a-doption> -->
|
||||
<!-- <a-doption>Option 3</a-doption> -->
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-layout-sider>
|
||||
<a-layout-content class="right">
|
||||
<GuiForDataShow ref="GuiForDataShow"></GuiForDataShow>
|
||||
|
||||
</a-layout-content>
|
||||
</a-layout>
|
||||
<a-layout-footer>Footer</a-layout-footer>
|
||||
</a-layout>
|
||||
<!-- <a-layout-footer>Footer</a-layout-footer> -->
|
||||
|
||||
<!-- 保存文件弹窗 -->
|
||||
<SaveFileDialog v-model:visible="showSaveDialog" :files="filesToSave" @save="handleSaveFiles"
|
||||
@cancel="handleCancelSave" />
|
||||
</a-layout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import menubardatavue from './menuvue/menubar.vue';
|
||||
import GuiForDataShow from './vuecomponents/GuiForDataShow.vue';
|
||||
import GuiLeftSider from './vuecomponents/GuiLeftSider.vue';
|
||||
import SaveFileDialog from './vuecomponents/SaveFileDialog.vue';
|
||||
import { fs } from '@tauri-apps/api';
|
||||
|
||||
export default {
|
||||
name: 'APPDataview',
|
||||
components: {
|
||||
menubardatavue,
|
||||
GuiForDataShow,
|
||||
GuiLeftSider
|
||||
GuiLeftSider,
|
||||
SaveFileDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 初始化数据
|
||||
message: '欢迎使用 Vue!',
|
||||
selectedFilePath: null, // 存储当前选中的文件路径
|
||||
selectedFilePaths: [], // 存储多选的文件路径
|
||||
treeData: [
|
||||
{
|
||||
title: 'Trunk 0-0',
|
||||
@ -73,13 +82,113 @@ export default {
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
],
|
||||
showSaveDialog: false,
|
||||
filesToSave: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 方法定义
|
||||
}
|
||||
// 处理单个文件选择(单击)
|
||||
async ononeFilechoese(filePath) {
|
||||
// console.log('选中文件路径:', filePath);
|
||||
// 只记录选中的文件路径,不立即加载数据
|
||||
this.selectedFilePath = filePath;
|
||||
},
|
||||
|
||||
// 处理文件双击事件
|
||||
async onFileDblClick(filePath) {
|
||||
// console.log('双击文件路径:', filePath);
|
||||
// 双击时加载数据
|
||||
this.$refs.GuiForDataShow.onloaddata([filePath]);
|
||||
},
|
||||
|
||||
// 处理多个文件选择(当使用Shift或Ctrl多选时)
|
||||
async onFilesSelected(filePaths) {
|
||||
// console.log('多选文件路径:', filePaths);
|
||||
// 存储多选的文件路径
|
||||
this.selectedFilePaths = filePaths;
|
||||
// 多选时,可以选择不自动加载数据,等待用户进一步操作
|
||||
if (filePaths && filePaths.length > 0) {
|
||||
this.selectedFilePath = filePaths[0];
|
||||
}
|
||||
},
|
||||
|
||||
// 处理文件夹点击事件
|
||||
async onFolderClicked(folderPath, childFilePaths) {
|
||||
// console.log('选中文件夹:', folderPath);
|
||||
// console.log('文件夹下的文件:', childFilePaths);
|
||||
// 存储文件夹下的文件路径
|
||||
this.selectedFilePaths = childFilePaths;
|
||||
},
|
||||
|
||||
// 处理文件夹双击事件
|
||||
async onFolderDblClick(folderPath, childFilePaths) {
|
||||
// console.log('双击文件夹:', folderPath);
|
||||
// console.log('文件夹下的文件:', childFilePaths);
|
||||
|
||||
// 如果文件夹下有文件,则加载所有文件
|
||||
if (childFilePaths && childFilePaths.length > 0) {
|
||||
// 将所有文件路径传递给 GuiForDataShow 组件
|
||||
this.$refs.GuiForDataShow.onloaddata(childFilePaths);
|
||||
}
|
||||
},
|
||||
|
||||
// 处理"显示曲线"菜单项点击事件
|
||||
async onShowCurvesClick() {
|
||||
// console.log('点击显示曲线菜单项');
|
||||
// 如果有多选文件,则加载所有选中的文件
|
||||
if (this.selectedFilePaths && this.selectedFilePaths.length > 0) {
|
||||
// console.log('加载多选文件:', this.selectedFilePaths);
|
||||
this.$refs.GuiForDataShow.onloaddata(this.selectedFilePaths);
|
||||
} else if (this.selectedFilePath) {
|
||||
// 如果只有单选文件,则加载单个文件
|
||||
// console.log('加载单选文件:', this.selectedFilePath);
|
||||
this.$refs.GuiForDataShow.onloaddata(this.selectedFilePath);
|
||||
}
|
||||
},
|
||||
|
||||
resetTreeData() {
|
||||
this.selectedFilePaths = []
|
||||
this.$refs.GuiForDataShow.onloaddata(this.selectedFilePaths);
|
||||
},
|
||||
|
||||
// 处理保存文件请求
|
||||
onSaveFilesRequested(selectedFiles) {
|
||||
this.filesToSave = selectedFiles
|
||||
this.showSaveDialog = true
|
||||
},
|
||||
// 处理保存文件
|
||||
async handleSaveFiles(saveData) {
|
||||
try {
|
||||
const { files, location } = saveData
|
||||
|
||||
for (const file of files) {
|
||||
// 构建目标文件路径
|
||||
const fileName = file.label
|
||||
const targetPath = `${location}/${fileName}`
|
||||
|
||||
// 复制文件
|
||||
await fs.copyFile(file.path, targetPath)
|
||||
}
|
||||
|
||||
this.$message.success(`成功保存 ${files.length} 个文件到 ${location}`)
|
||||
} catch (error) {
|
||||
console.error('保存文件失败:', error)
|
||||
alert('保存文件失败: ' + error.message)
|
||||
}
|
||||
},
|
||||
|
||||
// 取消保存
|
||||
handleCancelSave() {
|
||||
this.showSaveDialog = false
|
||||
this.filesToSave = []
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -87,12 +196,12 @@ export default {
|
||||
h1 {
|
||||
color: #42b983;
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
background-color: #f3f5fa;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
BIN
src/DataView/assets/保存曲线-未点击.png
Normal file
After Width: | Height: | Size: 449 B |
BIN
src/DataView/assets/保存曲线-点击.png
Normal file
After Width: | Height: | Size: 629 B |
BIN
src/DataView/assets/图例设置-未点击.png
Normal file
After Width: | Height: | Size: 763 B |
BIN
src/DataView/assets/图例设置-点击.png
Normal file
After Width: | Height: | Size: 978 B |
BIN
src/DataView/assets/图钉.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
src/DataView/assets/文件图标-线.png
Normal file
After Width: | Height: | Size: 350 B |
BIN
src/DataView/assets/文件图标-面.png
Normal file
After Width: | Height: | Size: 673 B |
BIN
src/DataView/assets/文件夹图标.png
Normal file
After Width: | Height: | Size: 471 B |
BIN
src/DataView/assets/重置视图-未点击.png
Normal file
After Width: | Height: | Size: 489 B |
BIN
src/DataView/assets/重置视图-点击.png
Normal file
After Width: | Height: | Size: 662 B |
@ -1,7 +1,7 @@
|
||||
<script >
|
||||
import { BDropdownItem,BDropdown,BDropdownDivider,BButtonGroup,BButton,BModal,BNavbar,BNavbarBrand,BNavbarNav,BNavItem,BNavItemDropdown,BToast,useToast } from 'bootstrap-vue-next';
|
||||
<script>
|
||||
import { BDropdownItem, BDropdown, BDropdownDivider, BButtonGroup, BButton, BModal, BNavbar, BNavbarBrand, BNavbarNav, BNavItem, BNavItemDropdown, BToast, useToast } from 'bootstrap-vue-next';
|
||||
|
||||
import { ref,Teleport} from 'vue';
|
||||
import { ref, Teleport } from 'vue';
|
||||
|
||||
import EventBus from "../../eventBus.js";
|
||||
|
||||
@ -26,13 +26,13 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
msg: 'Welcome to Your Vue.js App',
|
||||
modal:false,
|
||||
DCbutton:{
|
||||
state:"init",
|
||||
modal: false,
|
||||
DCbutton: {
|
||||
state: "init",
|
||||
|
||||
},
|
||||
WRbutton:{
|
||||
state:"init",
|
||||
WRbutton: {
|
||||
state: "init",
|
||||
|
||||
}
|
||||
|
||||
@ -45,26 +45,26 @@ export default {
|
||||
|
||||
|
||||
|
||||
return {active}
|
||||
return { active }
|
||||
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener("keydown",this.handlekeydown)
|
||||
EventBus.on('SetMenubutton',this.setbutton);
|
||||
window.addEventListener("keydown", this.handlekeydown)
|
||||
EventBus.on('SetMenubutton', this.setbutton);
|
||||
},
|
||||
methods: {
|
||||
setbutton(command){
|
||||
if (command.name == "DC"){
|
||||
setbutton(command) {
|
||||
if (command.name == "DC") {
|
||||
this.DCbutton.state = command.state;
|
||||
}
|
||||
if (command.name == "WR"){
|
||||
if (command.name == "WR") {
|
||||
this.WRbutton.state = command.state;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
showbox(){
|
||||
EventBus.emit('showbox',"hello","提示11")
|
||||
|
||||
showbox() {
|
||||
EventBus.emit('showbox', "hello", "提示11")
|
||||
},
|
||||
changemainvue() {
|
||||
EventBus.emit('changemainvue');
|
||||
@ -100,7 +100,15 @@ export default {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
openFolder() {
|
||||
EventBus.emit('triggerOpenFolder');
|
||||
},
|
||||
|
||||
saveFiles() {
|
||||
EventBus.emit('triggerSaveFiles');
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -122,17 +130,17 @@ export default {
|
||||
|
||||
<BNavbarNav>
|
||||
<BNavItemDropdown text="文件" right>
|
||||
<BDropdownItem href="#">新建</BDropdownItem>
|
||||
<BDropdownItem href="#" >打开</BDropdownItem>
|
||||
<BDropdownItem href="#">保存</BDropdownItem>
|
||||
<BDropdownItem href="#">新建</BDropdownItem>
|
||||
<BDropdownItem href="#" @click="openFolder">打开</BDropdownItem>
|
||||
<BDropdownItem href="#" @click="saveFiles">保存</BDropdownItem>
|
||||
<BDropdownItem href="#">另存为</BDropdownItem>
|
||||
<BDropdownDivider></BDropdownDivider>
|
||||
<BDropdownItem href="#">退出</BDropdownItem>
|
||||
<BDropdownItem href="#" @click="onmenuclick('File','Advance')">高级</BDropdownItem>
|
||||
<BDropdownItem @click="onmenuclick('info','help')">帮助</BDropdownItem>
|
||||
<BDropdownItem href="#" @click="onmenuclick('File', 'Advance')">高级</BDropdownItem>
|
||||
<BDropdownItem @click="onmenuclick('info', 'help')">帮助</BDropdownItem>
|
||||
</BNavItemDropdown>
|
||||
|
||||
<!-- <!– Navbar dropdowns –>-->
|
||||
<!-- <!– Navbar dropdowns –>-->
|
||||
|
||||
|
||||
<BNavItemDropdown text="设置" right>
|
||||
@ -145,31 +153,31 @@ export default {
|
||||
</BNavItemDropdown>
|
||||
|
||||
<BNavItemDropdown text="窗口" right>
|
||||
|
||||
|
||||
<BDropdownItem @click="changemainvue()">数据采集</BDropdownItem>
|
||||
<!-- <BDropdownItem >ES</BDropdownItem>-->
|
||||
<!-- <BDropdownItem href="#">RU</BDropdownItem>-->
|
||||
<!-- <BDropdownItem href="#">FA</BDropdownItem>-->
|
||||
</BNavItemDropdown>
|
||||
|
||||
<BDropdownItem @click="changemainvue()">数据采集</BDropdownItem>
|
||||
<!-- <BDropdownItem >ES</BDropdownItem>-->
|
||||
<!-- <BDropdownItem href="#">RU</BDropdownItem>-->
|
||||
<!-- <BDropdownItem href="#">FA</BDropdownItem>-->
|
||||
</BNavItemDropdown>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- <Teleport to="body">-->
|
||||
<!-- <div class="toast-container position-fixed " style="top:0px;right: 0px;width: 300px" >-->
|
||||
<!-- <BToast v-model="active" variant="info" interval="10" value="100" progress-props="{-->
|
||||
<!-- variant: 'danger',-->
|
||||
<!-- },">-->
|
||||
<!-- <template #title>-->
|
||||
<!-- Title-->
|
||||
<!-- </template>-->
|
||||
<!-- 你好-->
|
||||
<!-- </BToast>-->
|
||||
<!-- </div>-->
|
||||
<!-- </Teleport>-->
|
||||
<!-- <BButton @click="active = !active">Toggle</BButton>-->
|
||||
<!-- <Teleport to="body">-->
|
||||
<!-- <div class="toast-container position-fixed " style="top:0px;right: 0px;width: 300px" >-->
|
||||
<!-- <BToast v-model="active" variant="info" interval="10" value="100" progress-props="{-->
|
||||
<!-- variant: 'danger',-->
|
||||
<!-- },">-->
|
||||
<!-- <template #title>-->
|
||||
<!-- Title-->
|
||||
<!-- </template>-->
|
||||
<!-- 你好-->
|
||||
<!-- </BToast>-->
|
||||
<!-- </div>-->
|
||||
<!-- </Teleport>-->
|
||||
<!-- <BButton @click="active = !active">Toggle</BButton>-->
|
||||
</BNavbarNav>
|
||||
<!-- <div class="btgroup">
|
||||
<b-button variant="secondary" pill class="siglebt" @click="onmenuclick('Work','OPT')">OPT</b-button>
|
||||
@ -188,11 +196,13 @@ export default {
|
||||
background-color: #f8f9fa;
|
||||
width: 100vw;
|
||||
}
|
||||
.btgroup{
|
||||
|
||||
.btgroup {
|
||||
position: absolute;
|
||||
right: 15%;
|
||||
}
|
||||
.siglebt{
|
||||
|
||||
.siglebt {
|
||||
radio: 50%;
|
||||
font-size: 10px;
|
||||
height: 40px;
|
||||
|
@ -1,73 +1,172 @@
|
||||
<template>
|
||||
<el-main style="height: 100%; width: 100%; overflow: auto;">
|
||||
<el-row class="secondhang">
|
||||
<GuiForPlotShow ref="ASDPlotShow" class="plotcontainer"></GuiForPlotShow>
|
||||
</el-row>
|
||||
<el-row class="firsthang">
|
||||
<el-col :span="10" class="diveinfo">
|
||||
设备信息
|
||||
<GuiForDivesInfo ref="GuiForDivesInforef"></GuiForDivesInfo>
|
||||
</el-col>
|
||||
<el-col :span="14">
|
||||
地图
|
||||
<!-- <MapContainer></MapContainer> -->
|
||||
<a-image
|
||||
width="200"
|
||||
src="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a8c8cdb109cb051163646151a4a5083b.png~tplv-uwbnlip3yd-webp.webp"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-main style="height: 100%; width: 100%; overflow: auto;display: flex
|
||||
;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;">
|
||||
<el-row class="secondhang">
|
||||
<GuiForPlotShow @onComBox1="onComBox1" @onComBox2="onComBox2" @legendselectchanged="legendselectchanged"
|
||||
ref="ASDPlotShow" class="plotcontainer">
|
||||
</GuiForPlotShow>
|
||||
</el-row>
|
||||
<el-row class="firsthang">
|
||||
<el-col :span="8" class="diveinfo">
|
||||
<GuiForDivesInfo ref="GuiForDivesInforef"></GuiForDivesInfo>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<PictureDisplayInterface ref="PictureDisplayInterfaceRef"></PictureDisplayInterface>
|
||||
<!-- <div class="imageAndMap">
|
||||
|
||||
</el-main>
|
||||
</div>
|
||||
地图 -->
|
||||
<!-- <MapContainer></MapContainer> -->
|
||||
<!-- <a-image v-if="imgeList.length > 0" width="200" :src="imgeList[0].url" /> -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import GuiForPlotShow from "./GuiForPlotShow.vue";
|
||||
import MapContainer from "./MapContainer.vue";
|
||||
import GuiForDivesInfo from "./GuiForDivesInfo.vue";
|
||||
import {invoke} from "@tauri-apps/api/tauri";
|
||||
export default {
|
||||
name: "GuiForDataShow",
|
||||
components: {
|
||||
GuiForPlotShow,
|
||||
MapContainer,
|
||||
GuiForDivesInfo
|
||||
},
|
||||
methods: {
|
||||
async onloaddata(data){
|
||||
// console.log(data);
|
||||
let jsonfiletem = await this.$MyGetJsonData(data);
|
||||
this.$refs.ASDPlotShow.onloaddata(jsonfiletem);
|
||||
this.$refs.GuiForDivesInforef.onloaddata(jsonfiletem["ASDInfo"]);
|
||||
import GuiForDivesInfo from "./GuiForDivesInfo.vue";
|
||||
import PictureDisplayInterface from "./PictureDisplayInterface.vue";
|
||||
import { ref } from 'vue';
|
||||
import { spectralTypeList } from '../../utils/irisDataDispose';
|
||||
import { SpectralDataService } from '../../utils/spectralDataService';
|
||||
|
||||
}
|
||||
},
|
||||
async mounted(){
|
||||
let aaa=await invoke("getoneirisfile",{path:"iris_data_example.iris"});
|
||||
console.log(aaa);
|
||||
defineOptions({
|
||||
name: "GuiForDataShow"
|
||||
});
|
||||
|
||||
const fromData = ref({
|
||||
comBox1: spectralTypeList[0].value,
|
||||
comBox2: '',
|
||||
});
|
||||
|
||||
const ASDPlotShow = ref(null);
|
||||
const GuiForDivesInforef = ref(null);
|
||||
const PictureDisplayInterfaceRef = ref(null);
|
||||
const spectralDataList = ref([]);
|
||||
const imgeList = ref([]);
|
||||
const fileData = ref([]);
|
||||
|
||||
async function onloaddata(data) {
|
||||
// 重置数据
|
||||
spectralDataList.value = [];
|
||||
imgeList.value = [];
|
||||
fileData.value = [];
|
||||
|
||||
if (!data || data.length === 0) {
|
||||
updateChildComponents([], [], []);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 加载文件数据
|
||||
fileData.value = await SpectralDataService.loadFileData(data);
|
||||
|
||||
// 处理数据
|
||||
await processSpectralData();
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error);
|
||||
updateChildComponents([], [], []);
|
||||
}
|
||||
}
|
||||
|
||||
async function processSpectralData() {
|
||||
try {
|
||||
const result = SpectralDataService.processSpectralData(
|
||||
fileData.value,
|
||||
fromData.value.comBox1,
|
||||
fromData.value.comBox2
|
||||
);
|
||||
|
||||
spectralDataList.value = result.spectralDataList;
|
||||
imgeList.value = result.imageList;
|
||||
|
||||
updateChildComponents(
|
||||
result.processedData,
|
||||
result.spectralDataList,
|
||||
result.imageList
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('处理光谱数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function updateChildComponents(processedData, spectralData, imageData) {
|
||||
ASDPlotShow.value?.onloaddata(processedData, fileData.value);
|
||||
GuiForDivesInforef.value?.onloaddata(spectralData);
|
||||
PictureDisplayInterfaceRef.value?.onloaddata(imageData, spectralData);
|
||||
}
|
||||
|
||||
const onComBox1 = (e) => {
|
||||
fromData.value.comBox1 = e;
|
||||
processSpectralData();
|
||||
};
|
||||
|
||||
const onComBox2 = (val) => {
|
||||
fromData.value.comBox2 = val;
|
||||
if (fromData.value.comBox1) {
|
||||
processSpectralData();
|
||||
}
|
||||
};
|
||||
|
||||
const legendselectchanged = (nameTable) => {
|
||||
if (nameTable) {
|
||||
const filteredImages = imgeList.value.filter(element => {
|
||||
if (!element || element.length === 0) return false;
|
||||
return element.some(item => {
|
||||
const str = item.name.split('.')[0];
|
||||
return nameTable.includes(str);
|
||||
});
|
||||
});
|
||||
|
||||
const selectedSpectral = spectralDataList.value.filter(e =>
|
||||
nameTable.includes(e.name)
|
||||
);
|
||||
|
||||
if (selectedSpectral.length > 0) {
|
||||
GuiForDivesInforef.value?.onloaddata(selectedSpectral);
|
||||
PictureDisplayInterfaceRef.value?.onloaddata(filteredImages, selectedSpectral);
|
||||
}
|
||||
} else {
|
||||
GuiForDivesInforef.value?.onloaddata(spectralDataList.value);
|
||||
PictureDisplayInterfaceRef.value?.onloaddata(imgeList.value, spectralDataList.value);
|
||||
}
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
onloaddata
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.plotcontainer{
|
||||
.plotcontainer {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.firsthang{
|
||||
height: 30%;
|
||||
|
||||
.firsthang {
|
||||
height: 42%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.secondhang{
|
||||
height: 70%;
|
||||
|
||||
.secondhang {
|
||||
height: 56%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.diveinfo{
|
||||
|
||||
.imageAndMap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #FDFDFD;
|
||||
border-radius: 4px;
|
||||
margin-left: 24px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
@ -1,74 +1,264 @@
|
||||
<template>
|
||||
<div class="maincontemer">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-card>
|
||||
<div slot="header" class="clearfix">
|
||||
<span>设备信息</span>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
style="width: 100%">
|
||||
<el-table-column
|
||||
prop="name"
|
||||
<div class="maincontainer">
|
||||
<div class="container_item">
|
||||
<!-- 文件名显示 -->
|
||||
<div class="filename_display">
|
||||
<img src="../assets/文件图标-面.png">
|
||||
{{ currentItem?.environmentData?.fileName || '暂无文件' }}
|
||||
</div>
|
||||
|
||||
width="100px">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="Value"
|
||||
<!-- 轮播内容区域 -->
|
||||
<div class="carousel-container">
|
||||
<!-- 左侧导航按钮 -->
|
||||
<button class="nav-button left" @click="prevItem">
|
||||
<svg t="1754038374827" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="5034" width="200" height="200">
|
||||
<path
|
||||
d="M481.233 904c8.189 0 16.379-3.124 22.628-9.372 12.496-12.497 12.496-32.759 0-45.256L166.488 512l337.373-337.373c12.496-12.497 12.496-32.758 0-45.255-12.498-12.497-32.758-12.497-45.256 0l-360 360c-12.496 12.497-12.496 32.758 0 45.255l360 360c6.249 6.249 14.439 9.373 22.628 9.373z"
|
||||
p-id="5035"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
width="100px">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 主要内容展示 -->
|
||||
<div class="contemer_content">
|
||||
<ul style="width:175px">
|
||||
<li>时间:</li>
|
||||
<li>温度:</li>
|
||||
<li>湿度:</li>
|
||||
<li>距离:</li>
|
||||
</ul>
|
||||
<ul style="flex:1">
|
||||
<li>{{ currentItem?.environmentData?.date || '--' }}</li>
|
||||
<li>{{ currentItem?.environmentData?.temperature || '--' }}</li>
|
||||
<li>{{ currentItem?.environmentData?.humidity || '--' }}</li>
|
||||
<li>{{ currentItem?.environmentData?.height == 0 ? 0 : currentItem?.environmentData?.height || '--' }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 右侧导航按钮 -->
|
||||
<button class="nav-button right" @click="nextItem">
|
||||
<svg style="transform: rotateZ(180deg);left: 10px;" t="1754038374827" class="icon" viewBox="0 0 1024 1024"
|
||||
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5034" width="200" height="200">
|
||||
<path
|
||||
d="M481.233 904c8.189 0 16.379-3.124 22.628-9.372 12.496-12.497 12.496-32.759 0-45.256L166.488 512l337.373-337.373c12.496-12.497 12.496-32.758 0-45.255-12.498-12.497-32.758-12.497-45.256 0l-360 360c-12.496 12.497-12.496 32.758 0 45.255l360 360c6.249 6.249 14.439 9.373 22.628 9.373z"
|
||||
p-id="5035"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 轮播指示器 -->
|
||||
<!-- <div class="carousel-indicators" v-if="tableData.length > 1">
|
||||
<span
|
||||
v-for="(item, index) in tableData"
|
||||
:key="index"
|
||||
:class="{ active: currentIndex === index }"
|
||||
@click="goToItem(index)"
|
||||
></span>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "GuiForDivesInfo",
|
||||
data(){
|
||||
return {
|
||||
tableData: [{
|
||||
name: '设备名称',
|
||||
Value: 'ARS'
|
||||
} ]
|
||||
}
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
},
|
||||
methods: {
|
||||
onloaddata(jsondata){
|
||||
//if (jsondata.isObject){
|
||||
this.tableData=[];
|
||||
this.tableData.push(...convertObjectToArray(jsondata));
|
||||
// }
|
||||
const tableData = ref([])
|
||||
const currentIndex = ref(0)
|
||||
|
||||
}
|
||||
// 计算当前显示的项目
|
||||
const currentItem = computed(() => {
|
||||
return tableData.value[currentIndex.value] || {}
|
||||
})
|
||||
|
||||
// 加载数据方法
|
||||
const onloaddata = (jsondata) => {
|
||||
tableData.value = jsondata
|
||||
currentIndex.value = 0 // 重置到第一项
|
||||
}
|
||||
|
||||
// 上一项
|
||||
const prevItem = () => {
|
||||
if (tableData.value.length <= 1) return
|
||||
currentIndex.value = (currentIndex.value - 1 + tableData.value.length) % tableData.value.length
|
||||
}
|
||||
|
||||
// 下一项
|
||||
const nextItem = () => {
|
||||
if (tableData.value.length <= 1) return
|
||||
currentIndex.value = (currentIndex.value + 1) % tableData.value.length
|
||||
}
|
||||
|
||||
// 跳转到指定项
|
||||
const goToItem = (index) => {
|
||||
if (index >= 0 && index < tableData.value.length) {
|
||||
currentIndex.value = index
|
||||
}
|
||||
}
|
||||
|
||||
function convertObjectToArray(jsonObject) {
|
||||
const jsonArray = [];
|
||||
|
||||
for (const key in jsonObject) {
|
||||
if (jsonObject.hasOwnProperty(key)) {
|
||||
const keyValueObject = {
|
||||
name: key,
|
||||
Value: jsonObject[key]
|
||||
};
|
||||
jsonArray.push(keyValueObject);
|
||||
}
|
||||
}
|
||||
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
onloaddata
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.maincontemer{
|
||||
height: 100px;
|
||||
<style scoped lang="less">
|
||||
.maincontainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #FDFDFD;
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
|
||||
.container_item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.filename_display {
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
font-size: 20px;
|
||||
color: #434959;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&>img {
|
||||
width: 16px;
|
||||
height: 20px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.carousel-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: calc(100% - 100px);
|
||||
position: relative;
|
||||
|
||||
|
||||
|
||||
.contemer_content {
|
||||
flex: 1;
|
||||
padding: 0 20px;
|
||||
font-size: 16px;
|
||||
color: #6B7181;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding-top: 20px;
|
||||
|
||||
&>ul {
|
||||
|
||||
&>li {
|
||||
text-align: right;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&>ul:nth-child(2) {
|
||||
&>li {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
ul,
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
div {
|
||||
margin: 10px 0;
|
||||
|
||||
&>span {
|
||||
color: #434959;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-button {
|
||||
width: 60px;
|
||||
height: 90px;
|
||||
background: rgba(243, 245, 250, 1);
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
justify-content: center;
|
||||
color: #6B7181;
|
||||
box-shadow: none;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
|
||||
&>svg {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
left: 20px;
|
||||
|
||||
&>path {
|
||||
fill: rgba(107, 113, 129, 1);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background: rgba(66, 113, 238, 0.10);
|
||||
border: 1.4px solid #4271EE;
|
||||
|
||||
&>svg {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
left: 20px;
|
||||
|
||||
&>path {
|
||||
fill: rgba(66, 113, 238, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
&.right {
|
||||
right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.carousel-indicators {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: #ccc;
|
||||
margin: 0 5px;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
background: #434959;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
@ -1,78 +1,447 @@
|
||||
<template>
|
||||
<div class="el-treecontain">
|
||||
<el-tree :data="data" :props="defaultProps" class="el-treemain" @node-click="handleNodeClick"/>
|
||||
<div class="GuiLeftSider">
|
||||
<p class="nameList">文件列表</p>
|
||||
<div class="el-treecontain" v-if="data && data.length > 0">
|
||||
<el-tree ref="treeRef" :data="data" :props="defaultProps" class="el-treemain" highlight-current
|
||||
:expand-on-click-node="false" :default-expanded-keys="defaultExpandedKeys" @node-click="handleNodeClick"
|
||||
node-key="id">
|
||||
<template #default="{ node, data }">
|
||||
<div class="fileitem1" v-if="data.isFolder">
|
||||
<img src="../assets/文件夹图标.png">
|
||||
{{ node.label }}
|
||||
</div>
|
||||
<div class="fileitem2" v-else-if="data.isLeaf">
|
||||
<img src="../assets/文件图标-线.png">
|
||||
{{ node.label }}
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</div>
|
||||
<!-- <div class="defaultList" v-else>
|
||||
<button @click="onopendata">选择文件夹</button>
|
||||
</div> -->
|
||||
</div>
|
||||
<button @click="onopendata">click</button>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EventBus from "../../eventBus.js"
|
||||
|
||||
export default {
|
||||
name: "GuiLeftSider",
|
||||
|
||||
data() {
|
||||
return {
|
||||
data: [{
|
||||
label: '请选择',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
},
|
||||
DefualtPath: "\\ARS_data"
|
||||
DefualtPath: "",
|
||||
showButton: true,
|
||||
ctrlKeyPressed: false,
|
||||
shiftKeyPressed: false,
|
||||
shiftKeyField: [],
|
||||
selectNodes: [],
|
||||
includeChildren: true,
|
||||
allFiles: [], // 存储所有解析出的文件
|
||||
lastClickedNode: null, // 记录最后点击的节点
|
||||
lastClickTime: 0, // 记录最后点击时间
|
||||
defaultExpandedKeys: [],
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
//if(this.$isElectron()) {
|
||||
this.DefualtPath="";
|
||||
return
|
||||
|
||||
// };
|
||||
await this.onopendata();
|
||||
window.addEventListener("keydown", this.handleKeyDown);
|
||||
window.addEventListener("keyup", this.handleKeyUp);
|
||||
EventBus.on('triggerOpenFolder', this.onopendata);
|
||||
EventBus.on('triggerSaveFiles', this.handleSaveFiles);
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener("keydown", this.handleKeyDown);
|
||||
window.removeEventListener("keyup", this.handleKeyUp);
|
||||
EventBus.off('triggerOpenFolder', this.onopendata);
|
||||
EventBus.off('triggerSaveFiles', this.handleSaveFiles);
|
||||
},
|
||||
methods: {
|
||||
handleNodeClick(data) {
|
||||
if (data.isLeaf)
|
||||
// console.log(getParentPath(data));
|
||||
this.$emit("NodeClicked", this.DefualtPath+getParentPath(data));
|
||||
|
||||
handleKeyDown(event) {
|
||||
if (event.key == "Control") {
|
||||
this.ctrlKeyPressed = true;
|
||||
}
|
||||
if (event.key == "Shift") {
|
||||
this.shiftKeyPressed = true;
|
||||
}
|
||||
},
|
||||
handleKeyUp(event) {
|
||||
if (event.key == "Control") {
|
||||
this.ctrlKeyPressed = false;
|
||||
}
|
||||
if (event.key == "Shift") {
|
||||
this.shiftKeyPressed = false;
|
||||
}
|
||||
},
|
||||
collectAllFiles(node) {
|
||||
const files = [];
|
||||
|
||||
if (node.isLeaf) {
|
||||
files.push({
|
||||
id: node.id,
|
||||
path: node.path,
|
||||
label: node.label
|
||||
});
|
||||
return files;
|
||||
}
|
||||
|
||||
if (node.children && node.children.length > 0) {
|
||||
for (const child of node.children) {
|
||||
const childFiles = this.collectAllFiles(child);
|
||||
files.push(...childFiles);
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
},
|
||||
isFolder(nodeData) {
|
||||
return nodeData.isFolder === true || (nodeData.children && Array.isArray(nodeData.children));
|
||||
},
|
||||
|
||||
// 添加双击事件处理
|
||||
handleNodeDblClick(nodeData, node) {
|
||||
if (nodeData.isLeaf && !this.isFolder(nodeData)) {
|
||||
// 双击文件时,发送NodeDblClicked事件
|
||||
this.$emit("NodeDblClicked", nodeData.path);
|
||||
} else if (this.isFolder(nodeData)) {
|
||||
// 双击文件夹时,收集所有文件并发送FolderDblClicked事件
|
||||
this.allFiles = this.collectAllFiles(nodeData);
|
||||
const allPaths = this.allFiles.map(file => file.path);
|
||||
this.$emit("FolderDblClicked", nodeData.path, allPaths);
|
||||
}
|
||||
},
|
||||
// 节点点击事件处理
|
||||
handleNodeClick(nodeData, node) {
|
||||
const treeRef = this.$refs.treeRef;
|
||||
if (!treeRef) return;
|
||||
|
||||
const nodes = treeRef.store._getAllNodes(); // 所有node节点
|
||||
const ishas = this.selectNodes.includes(node.id);
|
||||
const isSameLevel = (node1, node2) => node1.parent === node2.parent;
|
||||
const isNodeFolder = this.isFolder(nodeData);
|
||||
|
||||
// 实现双击检测
|
||||
const now = new Date().getTime();
|
||||
const isDoubleClick = this.lastClickedNode === nodeData.path && (now - this.lastClickTime) < 300; // 300ms内的点击视为双击
|
||||
|
||||
// 更新最后点击的节点和时间
|
||||
this.lastClickedNode = nodeData.path;
|
||||
this.lastClickTime = now;
|
||||
|
||||
// 如果是双击,则发送双击事件
|
||||
if (isDoubleClick) {
|
||||
if (nodeData.isLeaf && !isNodeFolder) {
|
||||
this.$emit("NodeDblClicked", nodeData.path);
|
||||
return; // 双击时不执行单击逻辑
|
||||
} else if (isNodeFolder) {
|
||||
// 双击文件夹时,收集所有文件并发送FolderDblClicked事件
|
||||
this.allFiles = this.collectAllFiles(nodeData);
|
||||
const allPaths = this.allFiles.map(file => file.path);
|
||||
this.$emit("FolderDblClicked", nodeData.path, allPaths);
|
||||
return; // 双击时不执行单击逻辑
|
||||
}
|
||||
}
|
||||
|
||||
// 单选模式
|
||||
if (!this.ctrlKeyPressed && !this.shiftKeyPressed) {
|
||||
// 清空之前的选择
|
||||
this.shiftKeyField = [];
|
||||
this.selectNodes = [];
|
||||
|
||||
// 如果是文件,直接选中
|
||||
if (nodeData.isLeaf && !isNodeFolder) {
|
||||
this.selectNodes = [node.id];
|
||||
this.$emit("NodeClicked", nodeData.path);
|
||||
}
|
||||
// 如果是文件夹,解析所有子文件
|
||||
else if (isNodeFolder) {
|
||||
this.selectNodes = [node.id];
|
||||
// 收集文件夹下所有文件
|
||||
this.allFiles = this.collectAllFiles(nodeData);
|
||||
// console.log('文件夹下所有文件:', this.allFiles);
|
||||
// 可以发送所有文件路径给父组件
|
||||
const allPaths = this.allFiles.map(file => file.path);
|
||||
this.$emit("FolderClicked", nodeData.path, allPaths);
|
||||
}
|
||||
}
|
||||
// Shift多选模式
|
||||
else if (this.shiftKeyPressed) {
|
||||
if (isNodeFolder) {
|
||||
this.shiftKeyField = [];
|
||||
this.selectNodes = [];
|
||||
|
||||
for (const item of nodes) {
|
||||
item.isCurrent = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果selectNodes有值但shiftKeyField为空,说明是从单选模式切换到Shift多选模式
|
||||
// 需要将已选中的节点ID添加到shiftKeyField中
|
||||
if (this.selectNodes.length > 0 && this.shiftKeyField.length === 0) {
|
||||
const firstSelectedNodeId = this.selectNodes[0];
|
||||
this.shiftKeyField.push(firstSelectedNodeId);
|
||||
}
|
||||
|
||||
if (this.selectNodes.length > 0) {
|
||||
const firstSelectedNodeId = this.selectNodes[0];
|
||||
const firstSelectedNode = nodes.find(x => x.id == firstSelectedNodeId);
|
||||
|
||||
if (firstSelectedNode && !isSameLevel(firstSelectedNode, node)) {
|
||||
this.shiftKeyField = [];
|
||||
this.selectNodes = [];
|
||||
|
||||
for (const item of nodes) {
|
||||
item.isCurrent = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.shiftKeyField.push(node.id);
|
||||
|
||||
if (this.shiftKeyField.length > 1) {
|
||||
const firstNodeId = this.shiftKeyField[0];
|
||||
const firstNode = nodes.find(x => x.id == firstNodeId);
|
||||
|
||||
if (!isSameLevel(firstNode, node)) {
|
||||
this.shiftKeyField = [];
|
||||
this.selectNodes = [];
|
||||
|
||||
for (const item of nodes) {
|
||||
item.isCurrent = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const sIndex = nodes.findIndex(x => x.id == this.shiftKeyField[0]);
|
||||
const eIndex = nodes.findIndex(x => x.id == this.shiftKeyField[this.shiftKeyField.length - 1]);
|
||||
const s = sIndex < eIndex ? sIndex : eIndex; // 取小值当开头索引
|
||||
const e = sIndex < eIndex ? eIndex : sIndex; // 取大值当结尾索引
|
||||
|
||||
for (let i = s; i <= e; i++) {
|
||||
const currentNode = nodes[i];
|
||||
if (!this.isFolder(currentNode.data) && isSameLevel(currentNode, firstNode)) {
|
||||
if (!this.selectNodes.includes(currentNode.id)) {
|
||||
this.selectNodes.push(currentNode.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!isNodeFolder) {
|
||||
if (!this.selectNodes.includes(node.id)) {
|
||||
this.selectNodes.push(node.id);
|
||||
}
|
||||
} else {
|
||||
this.shiftKeyField = [];
|
||||
this.selectNodes = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
// ctrl多选模式
|
||||
else if (this.ctrlKeyPressed) {
|
||||
if (isNodeFolder) {
|
||||
this.shiftKeyField = [];
|
||||
this.selectNodes = [];
|
||||
|
||||
for (const item of nodes) {
|
||||
item.isCurrent = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ishas) {
|
||||
const index = this.selectNodes.findIndex(x => x == node.id);
|
||||
this.selectNodes.splice(index, 1);
|
||||
} else {
|
||||
this.selectNodes.push(node.id);
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of nodes) {
|
||||
if (this.selectNodes.includes(item.id)) {
|
||||
item.isCurrent = true;
|
||||
} else {
|
||||
item.isCurrent = false;
|
||||
}
|
||||
}
|
||||
|
||||
const selectedNodesInfo = nodes
|
||||
.filter(item => this.selectNodes.includes(item.id))
|
||||
.map(item => ({
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
path: item.data.path || '',
|
||||
isFolder: this.isFolder(item.data)
|
||||
}));
|
||||
|
||||
const selectedFiles = selectedNodesInfo.filter(item => !item.isFolder);
|
||||
if (selectedFiles.length > 0) {
|
||||
const filePaths = selectedFiles.map(file => file.path);
|
||||
this.$emit("FilesSelected", filePaths);
|
||||
}
|
||||
},
|
||||
|
||||
async onopendata() {
|
||||
let cfiles = await this.$MyGetFolderlist(this.DefualtPath);
|
||||
this.data = [];
|
||||
this.data.push(cfiles);
|
||||
try {
|
||||
// 获取文件夹列表
|
||||
this.$emit("reset");
|
||||
this.data = []
|
||||
const folderTree = await this.$tauriApi.getFolderList(this.DefualtPath);
|
||||
// 添加唯一ID
|
||||
let idCounter = 1;
|
||||
const addUniqueIdsAndFilter = (node) => {
|
||||
node.id = idCounter++;
|
||||
if (node.isFolder) {
|
||||
if (Array.isArray(node.children) && node.children.length) {
|
||||
node.children = node.children.filter(child => {
|
||||
if (child.isFolder) return true;
|
||||
if (child.isLeaf && typeof child.label === 'string') {
|
||||
return child.label.endsWith('.iris');
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
node.children.forEach(child => addUniqueIdsAndFilter(child));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
};
|
||||
addUniqueIdsAndFilter(folderTree);
|
||||
if (folderTree && folderTree.label != "请选择") {
|
||||
this.data = [folderTree];
|
||||
}
|
||||
// 收集所有id用于默认展开
|
||||
const expandedKeys = [];
|
||||
this.collectAllNodeIds(folderTree, expandedKeys);
|
||||
this.defaultExpandedKeys = expandedKeys;
|
||||
} catch (error) {
|
||||
console.error("打开文件夹失败:", error);
|
||||
}
|
||||
},
|
||||
|
||||
// 整合所有节点id,默认显示使用
|
||||
collectAllNodeIds(node, arr) {
|
||||
arr.push(node.id);
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children.forEach(child => this.collectAllNodeIds(child, arr));
|
||||
}
|
||||
},
|
||||
// 处理保存文件事件
|
||||
handleSaveFiles() {
|
||||
const selectedFiles = this.getSelectedFiles();
|
||||
if (selectedFiles.length === 0) {
|
||||
alert('请先打开文件后再保存')
|
||||
return;
|
||||
}
|
||||
// 触发保存文件请求事件,传递选中的文件
|
||||
this.$emit('SaveFilesRequested', selectedFiles);
|
||||
},
|
||||
|
||||
// 获取文件
|
||||
getSelectedFiles() {
|
||||
const treeRef = this.$refs.treeRef;
|
||||
if (!treeRef) return [];
|
||||
const nodes = treeRef.store._getAllNodes();
|
||||
const allFiles = [];
|
||||
|
||||
// 遍历所有节点,收集所有文件
|
||||
nodes.forEach(node => {
|
||||
if (node.data && node.data.isLeaf && !node.data.isFolder) {
|
||||
allFiles.push({
|
||||
id: node.id,
|
||||
label: node.data.label,
|
||||
path: node.data.path,
|
||||
name: node.data.label
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return allFiles;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function getParentPath(node) {
|
||||
if (!node) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (node.parent) {
|
||||
return getParentPath(node.parent) + '\\' + node.label;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
el-tree{
|
||||
<style scoped lang="less">
|
||||
el-tree {
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.el-treemain {
|
||||
min-width: 100%;
|
||||
white-space: nowrap; /* 不换行,使树节点水平排列 */
|
||||
display: inline-block; /* 横向排列 */
|
||||
white-space: nowrap;
|
||||
/* 不换行,使树节点水平排列 */
|
||||
display: inline-block;
|
||||
/* 横向排列 */
|
||||
text-align: left;
|
||||
}
|
||||
.el-treecontain{
|
||||
|
||||
.el-treecontain {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
max-height: 96vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
.fileitem1 {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&>img {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.fileitem2 {
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&>img {
|
||||
margin-right: 5px;
|
||||
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.fileitem:nth-child(2) {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
.GuiLeftSider {
|
||||
padding: 17px 24px;
|
||||
}
|
||||
|
||||
.GuiLeftSider p {
|
||||
font-size: 18px;
|
||||
color: #434959;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.defaultList button {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
border-radius: 4px;
|
||||
border: 1.4px solid #4271EE;
|
||||
box-shadow: none;
|
||||
font-size: 16px;
|
||||
color: #4271EE;
|
||||
}
|
||||
</style>
|
@ -1,78 +1,236 @@
|
||||
<template>
|
||||
<div ref="mapContainer" id="map" style="width: 100%; height: 400px;"></div>
|
||||
<div ref="mapContainer" class="ol-map-wrapper">
|
||||
<div class="ol-map" ref="olMap"></div>
|
||||
<button class="fullscreen-btn" @click="toggleFullScreen">
|
||||
{{ isFullscreen ? '退出全屏' : '全屏显示' }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import "maptalks/dist/maptalks.css";
|
||||
import * as maptalks from "maptalks";
|
||||
|
||||
export default {
|
||||
name: "MapContainer",
|
||||
data() {
|
||||
return {
|
||||
map: null,
|
||||
layer: null
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
addpointtomap(lon,lat){
|
||||
var marker1 = new maptalks.Marker(
|
||||
[116.255535,40.204654],
|
||||
{
|
||||
'symbol': {
|
||||
'markerType': 'ellipse',
|
||||
'markerFill': 'rgb(135,196,240)',
|
||||
'markerFillOpacity': 1,
|
||||
'markerLineColor': '#34495e',
|
||||
'markerLineWidth': 3,
|
||||
'markerLineOpacity': 1,
|
||||
'markerLineDasharray': [],
|
||||
'markerWidth': 40,
|
||||
'markerHeight': 40,
|
||||
'markerDx': 0,
|
||||
'markerDy': 0,
|
||||
'markerOpacity': 1
|
||||
}
|
||||
}
|
||||
)
|
||||
marker1.addTo(this.layer);
|
||||
|
||||
},
|
||||
initializeMap() {
|
||||
this.map = new maptalks.Map('map', {
|
||||
center: [-0.113049,51.498568],
|
||||
zoom: 14,
|
||||
compassControl: {
|
||||
position: 'top-left',
|
||||
},
|
||||
<script setup>
|
||||
import { ref, onMounted, onBeforeUnmount, defineProps, watch } from 'vue';
|
||||
import 'ol/ol.css';
|
||||
import { Map, View } from 'ol';
|
||||
import TileLayer from 'ol/layer/Tile';
|
||||
import XYZ from 'ol/source/XYZ';
|
||||
import { Feature } from 'ol';
|
||||
import Point from 'ol/geom/Point';
|
||||
import VectorSource from 'ol/source/Vector';
|
||||
import VectorLayer from 'ol/layer/Vector';
|
||||
import { Icon, Style, Text, Fill, Stroke } from 'ol/style';
|
||||
import { fromLonLat } from 'ol/proj';
|
||||
import pinIcon from '../assets/图钉.png';
|
||||
import { boundingExtent } from 'ol/extent';
|
||||
|
||||
baseLayer: new maptalks.TileLayer('base', {
|
||||
urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
|
||||
subdomains: ['a','b','c','d'],
|
||||
attribution: '© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>'
|
||||
})
|
||||
const props = defineProps({
|
||||
dataListMap: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
const mapContainer = ref(null);
|
||||
const olMap = ref(null)
|
||||
const map = ref(null);
|
||||
const vectorLayer = ref(null);
|
||||
const isMapReady = ref(false);
|
||||
const isFullscreen = ref(false);
|
||||
|
||||
|
||||
const initializeMap = () => {
|
||||
const center = fromLonLat([116.255535, 40.204654]);
|
||||
|
||||
const view = new View({
|
||||
center,
|
||||
zoom: 14
|
||||
});
|
||||
|
||||
const tiandituKey = 'a155b662f47ceee8d82a67bfbb3a0825';
|
||||
|
||||
const tileLayers = [
|
||||
new TileLayer({
|
||||
source: new XYZ({
|
||||
url: `http://t{0-7}.tianditu.gov.cn/DataServer/wmts?T=img_w&x={x}&y={y}&l={z}&tk=${tiandituKey}`
|
||||
}),
|
||||
isBaseLayer: true
|
||||
}),
|
||||
new TileLayer({
|
||||
source: new XYZ({
|
||||
url: `http://t{0-7}.tianditu.gov.cn/DataServer/wmts?T=cia_w&x={x}&y={y}&l={z}&tk=${tiandituKey}`
|
||||
}),
|
||||
isBaseLayer: true
|
||||
})
|
||||
];
|
||||
|
||||
const vectorSource = new VectorSource();
|
||||
vectorLayer.value = new VectorLayer({
|
||||
source: vectorSource
|
||||
});
|
||||
|
||||
map.value = new Map({
|
||||
target: olMap.value,
|
||||
layers: [...tileLayers, vectorLayer.value],
|
||||
view
|
||||
});
|
||||
|
||||
isMapReady.value = true;
|
||||
};
|
||||
|
||||
const getRandomCoordinateInBeijing = () => {
|
||||
const minLon = 115.7;
|
||||
const maxLon = 117.4;
|
||||
const minLat = 40.2;
|
||||
const maxLat = 40.5;
|
||||
|
||||
const lon = Math.random() * (maxLon - minLon) + minLon;
|
||||
const lat = Math.random() * (maxLat - minLat) + minLat;
|
||||
|
||||
return {
|
||||
longitude: parseFloat(lon.toFixed(6)),
|
||||
latitude: parseFloat(lat.toFixed(6))
|
||||
};
|
||||
};
|
||||
|
||||
const handleTagging = (data) => {
|
||||
if (!isMapReady.value || !Array.isArray(data)) return;
|
||||
|
||||
const features = [];
|
||||
const coords = [];
|
||||
|
||||
data.forEach(item => {
|
||||
const { longitude, latitude } = getRandomCoordinateInBeijing(); // 模拟
|
||||
if (longitude && latitude) {
|
||||
const feature = new Feature({
|
||||
geometry: new Point(fromLonLat([longitude, latitude])),
|
||||
name: item.environmentData.fileName || ''
|
||||
});
|
||||
this.map.setCenter([116.255535,40.204654]);
|
||||
this.layer=new maptalks.VectorLayer('vector').addTo(this.map);
|
||||
this.addpointtomap(0,0)
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.initializeMap();
|
||||
// const mapOptions = {
|
||||
// center: [0, 0],
|
||||
// zoom: 10
|
||||
// };
|
||||
//
|
||||
// const map = new Map(this.$refs.mapContainer, mapOptions);
|
||||
feature.setStyle(
|
||||
new Style({
|
||||
image: new Icon({
|
||||
src: pinIcon,
|
||||
anchor: [0.5, 1],
|
||||
scale: 1
|
||||
}),
|
||||
text: new Text({
|
||||
text: item.environmentData.fileName || '',
|
||||
offsetY: 14,
|
||||
font: '300 14px sans-serif',
|
||||
fill: new Fill({
|
||||
color: '#fff'
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
color: '#fff',
|
||||
width: 0
|
||||
}),
|
||||
textAlign: 'center',
|
||||
backgroundFill: new Fill({
|
||||
color: 'rgba(0, 0, 0, 0.5)'
|
||||
}),
|
||||
backgroundStroke: new Stroke({
|
||||
color: 'rgba(0, 0, 0, 0.5)',
|
||||
width: 0
|
||||
}),
|
||||
padding: [1, 10, 1, 10],
|
||||
radius: 4
|
||||
})
|
||||
})
|
||||
);
|
||||
|
||||
features.push(feature);
|
||||
coords.push(fromLonLat([longitude, latitude]));
|
||||
}
|
||||
});
|
||||
|
||||
if (features.length > 0) {
|
||||
vectorLayer.value.getSource().clear();
|
||||
vectorLayer.value.getSource().addFeatures(features);
|
||||
|
||||
const extent = boundingExtent(coords);
|
||||
map.value.getView().fit(extent, {
|
||||
padding: [50, 50, 50, 50],
|
||||
maxZoom: 16,
|
||||
duration: 1000
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const toggleFullScreen = () => {
|
||||
const container = mapContainer.value;
|
||||
|
||||
if (!document.fullscreenElement) {
|
||||
container?.requestFullscreen?.();
|
||||
} else {
|
||||
document.exitFullscreen?.();
|
||||
}
|
||||
};
|
||||
|
||||
const fullscreenChangeHandler = () => {
|
||||
isFullscreen.value = !!document.fullscreenElement;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.dataListMap,
|
||||
(newVal) => {
|
||||
if (!Array.isArray(newVal) || newVal.length === 0) return;
|
||||
|
||||
const tryAdd = () => {
|
||||
if (isMapReady.value) {
|
||||
handleTagging(newVal);
|
||||
} else {
|
||||
setTimeout(tryAdd, 100);
|
||||
}
|
||||
};
|
||||
|
||||
tryAdd();
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
try {
|
||||
initializeMap();
|
||||
} catch (error) {
|
||||
alert('初始化地图出错,', error)
|
||||
}
|
||||
document.addEventListener('fullscreenchange', fullscreenChangeHandler);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('fullscreenchange', fullscreenChangeHandler);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.ol-map-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ol-map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.fullscreen-btn {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 1000;
|
||||
padding: 6px 12px;
|
||||
font-size: 14px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
|
240
src/DataView/vuecomponents/PictureDisplayInterface.vue
Normal file
@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<div class="maincontainer">
|
||||
<div class="container_item">
|
||||
<!-- 文件名显示 -->
|
||||
<div class="filename_display" v-if="!isLastPage && currentItem?.url">
|
||||
<img src="../assets/文件图标-面.png">
|
||||
{{ currentItem?.name || '暂无文件' }}
|
||||
</div>
|
||||
<div class="filename_display" v-else>
|
||||
地图
|
||||
</div>
|
||||
|
||||
<!-- 轮播内容区域 -->
|
||||
<div class="carousel-container">
|
||||
<!-- 左侧导航按钮 -->
|
||||
<button class="nav-button left" @click="prevItem">
|
||||
<svg t="1754038374827" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="5034" width="200" height="200">
|
||||
<path
|
||||
d="M481.233 904c8.189 0 16.379-3.124 22.628-9.372 12.496-12.497 12.496-32.759 0-45.256L166.488 512l337.373-337.373c12.496-12.497 12.496-32.758 0-45.255-12.498-12.497-32.758-12.497-45.256 0l-360 360c-12.496 12.497-12.496 32.758 0 45.255l360 360c6.249 6.249 14.439 9.373 22.628 9.373z"
|
||||
p-id="5035"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="contemer_content">
|
||||
<img v-if="!isLastPage && currentItem?.url" :src="currentItem.url" />
|
||||
<div v-else class="last-page-box">
|
||||
<MapContainer :dataListMap="dataListMap"></MapContainer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧导航按钮 -->
|
||||
<button class="nav-button right" @click="nextItem">
|
||||
<svg style="transform: rotateZ(180deg);left: 10px;" t="1754038374827" class="icon"
|
||||
viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5034" width="200"
|
||||
height="200">
|
||||
<path
|
||||
d="M481.233 904c8.189 0 16.379-3.124 22.628-9.372 12.496-12.497 12.496-32.759 0-45.256L166.488 512l337.373-337.373c12.496-12.497 12.496-32.758 0-45.255-12.498-12.497-32.758-12.497-45.256 0l-360 360c-12.496 12.497-12.496 32.758 0 45.255l360 360c6.249 6.249 14.439 9.373 22.628 9.373z"
|
||||
p-id="5035"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import MapContainer from "./MapContainer.vue";
|
||||
|
||||
const imgeList = ref([])
|
||||
const currentIndex = ref(0)
|
||||
const dataListMap = ref([])
|
||||
const isLastPage = computed(() => currentIndex.value === imgeList.value.length)
|
||||
|
||||
const currentItem = computed(() => {
|
||||
if (isLastPage.value) {
|
||||
return null
|
||||
}
|
||||
return imgeList.value[currentIndex.value] || {}
|
||||
})
|
||||
|
||||
|
||||
const onloaddata = async (jsondata, dataList) => {
|
||||
if (jsondata && jsondata.length > 0 && dataList && dataList.length > 0) {
|
||||
dataListMap.value = dataList
|
||||
imgeList.value = jsondata.flat()
|
||||
currentIndex.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 上一项
|
||||
const prevItem = () => {
|
||||
if (imgeList.value.length === 0) return
|
||||
currentIndex.value =
|
||||
(currentIndex.value - 1 + (imgeList.value.length + 1)) %
|
||||
(imgeList.value.length + 1)
|
||||
}
|
||||
|
||||
// 下一项
|
||||
const nextItem = () => {
|
||||
if (imgeList.value.length === 0) return
|
||||
currentIndex.value = (currentIndex.value + 1) % (imgeList.value.length + 1)
|
||||
}
|
||||
|
||||
// 跳转到指定项
|
||||
const goToItem = (index) => {
|
||||
if (index >= 0 && index < imgeList.value.length) {
|
||||
currentIndex.value = index
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
onloaddata
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.maincontainer {
|
||||
width: 97.5%;
|
||||
height: 100%;
|
||||
background: #FDFDFD;
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
float: right;
|
||||
|
||||
.container_item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.filename_display {
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
font-size: 20px;
|
||||
color: #434959;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&>img {
|
||||
width: 16px;
|
||||
height: 20px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.carousel-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: calc(100% - 100px);
|
||||
position: relative;
|
||||
|
||||
|
||||
|
||||
.contemer_content {
|
||||
flex: 1;
|
||||
padding: 0 20px;
|
||||
font-size: 18px;
|
||||
color: #6B7181;
|
||||
width: 100%;
|
||||
height: 30vh;
|
||||
display: flex;
|
||||
padding-top: 20px;
|
||||
|
||||
&>img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
&>.last-page-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.nav-button {
|
||||
width: 60px;
|
||||
height: 90px;
|
||||
background: rgba(243, 245, 250, 1);
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
justify-content: center;
|
||||
color: #6B7181;
|
||||
box-shadow: none;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
&>svg {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
left: 20px;
|
||||
|
||||
&>path {
|
||||
fill: rgba(107, 113, 129, 1);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background: rgba(66, 113, 238, 0.10);
|
||||
border: 1.4px solid #4271EE;
|
||||
|
||||
&>svg {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
left: 20px;
|
||||
|
||||
&>path {
|
||||
fill: rgba(66, 113, 238, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&.left {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
&.right {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.carousel-indicators {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: #ccc;
|
||||
margin: 0 5px;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
background: #434959;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
301
src/DataView/vuecomponents/SaveFileDialog.vue
Normal file
@ -0,0 +1,301 @@
|
||||
<template>
|
||||
<el-dialog style="padding: 0 ; border-radius: 12px; overflow: hidden; min-width:600px; max-width:800px"
|
||||
class="legend_my_el_dialog" v-model="showModal" width="24%" @close="handleCancel">
|
||||
<template #title>
|
||||
<div class="legend-dialog-title">保存文件</div>
|
||||
</template>
|
||||
<div class="save-dialog-content">
|
||||
<div class="file-selection-section">
|
||||
<div class="select-all-section">
|
||||
<h6>选择要保存的文件</h6>
|
||||
<el-checkbox class="my_save_checkbox select-all-checkbox" v-model="selectAll"
|
||||
:indeterminate="isIndeterminate" @change="handleSelectAll">
|
||||
全选
|
||||
</el-checkbox>
|
||||
</div>
|
||||
<div class="file-list">
|
||||
<div>
|
||||
<div v-for="file in selectedFiles" :key="file.path" class="file-item">
|
||||
<el-checkbox class="my_save_checkbox" v-model="file.selected" :label="file.label"
|
||||
@change="handleFileSelect">
|
||||
{{ file.label }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="save-location-section">
|
||||
<h6>保存位置</h6>
|
||||
<div class="location-input">
|
||||
<el-input v-model="saveLocation" placeholder="请选择保存位置">
|
||||
</el-input>
|
||||
<el-button @click="selectSaveLocation" class="input-group-button">浏览</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="save-actions">
|
||||
<el-button type="primary" @click="handleSave" class="input-group-button-primary">保存</el-button>
|
||||
<el-button @click="handleCancel" class="input-group-button">取消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { dialog } from '@tauri-apps/api'
|
||||
|
||||
export default {
|
||||
name: 'SaveFileDialog',
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
files: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
emits: ['update:visible', 'save', 'cancel'],
|
||||
data() {
|
||||
return {
|
||||
saveLocation: '',
|
||||
selectedFiles: [],
|
||||
selectAll: false,
|
||||
isIndeterminate: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showModal: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('update:visible', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
files: {
|
||||
handler(newFiles) {
|
||||
this.selectedFiles = newFiles.map(file => ({
|
||||
...file,
|
||||
selected: true
|
||||
}))
|
||||
this.updateSelectAllState()
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async selectSaveLocation() {
|
||||
try {
|
||||
const selected = await dialog.open({
|
||||
directory: true,
|
||||
title: '选择保存位置'
|
||||
})
|
||||
if (selected) {
|
||||
this.saveLocation = selected
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('选择保存位置失败:', error)
|
||||
}
|
||||
},
|
||||
|
||||
handleSave() {
|
||||
const filesToSave = this.selectedFiles.filter(file => file.selected)
|
||||
if (filesToSave.length === 0) {
|
||||
// this.$message.warning('请至少选择一个文件')
|
||||
alert('请至少选择一个文件')
|
||||
return
|
||||
}
|
||||
if (!this.saveLocation) {
|
||||
alert('请选择保存位置')
|
||||
// this.$message.warning('请选择保存位置')
|
||||
return
|
||||
}
|
||||
|
||||
this.$emit('save', {
|
||||
files: filesToSave,
|
||||
location: this.saveLocation
|
||||
})
|
||||
this.showModal = false
|
||||
},
|
||||
|
||||
handleCancel() {
|
||||
this.$emit('cancel')
|
||||
this.showModal = false
|
||||
},
|
||||
|
||||
handleSelectAll(value) {
|
||||
this.selectedFiles.forEach(file => {
|
||||
file.selected = value
|
||||
})
|
||||
this.updateSelectAllState()
|
||||
},
|
||||
|
||||
handleFileSelect() {
|
||||
this.updateSelectAllState()
|
||||
},
|
||||
|
||||
updateSelectAllState() {
|
||||
const selectedCount = this.selectedFiles.filter(file => file.selected).length
|
||||
const totalCount = this.selectedFiles.length
|
||||
|
||||
if (selectedCount === 0) {
|
||||
this.selectAll = false
|
||||
this.isIndeterminate = false
|
||||
} else if (selectedCount === totalCount) {
|
||||
this.selectAll = true
|
||||
this.isIndeterminate = false
|
||||
} else {
|
||||
this.selectAll = false
|
||||
this.isIndeterminate = true
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.file-selection-section,
|
||||
.save-location-section {
|
||||
margin-bottom: 20px;
|
||||
|
||||
h6 {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.select-all-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.file-list {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
margin-bottom: 8px;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
text-align: left;
|
||||
|
||||
}
|
||||
|
||||
.file-item:hover {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.file-path {
|
||||
color: #606266;
|
||||
font-size: 12px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.no-files-message {
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.location-input {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.legend_my_el_dialog {
|
||||
.el-dialog__header.show-close {
|
||||
padding: 0 !important;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
|
||||
.el-dialog__headerbtn {
|
||||
box-shadow: none;
|
||||
top: 4px;
|
||||
right: 14px;
|
||||
font-size: 24px;
|
||||
color: #000;
|
||||
|
||||
.el-icon {
|
||||
fill: #000;
|
||||
|
||||
path {
|
||||
fill: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.legend-dialog-title {
|
||||
text-align: left;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
background: #F3F5FA;
|
||||
border-radius: 12px 12px 0px 0px;
|
||||
padding: 0;
|
||||
font-weight: 600;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.save-dialog-content {
|
||||
padding: 20px 0;
|
||||
|
||||
.my_save_checkbox {
|
||||
.el-checkbox__input.is-checked+.el-checkbox__label {
|
||||
color: #4271EE;
|
||||
}
|
||||
|
||||
.el-checkbox__input.is-checked .el-checkbox__inner {
|
||||
border-color: #4271EE;
|
||||
background-color: #4271EE;
|
||||
}
|
||||
|
||||
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
|
||||
background-color: #4271EE;
|
||||
border-color: #4271EE;
|
||||
}
|
||||
}
|
||||
|
||||
.el-input__wrapper.is-focus {
|
||||
box-shadow: 0 0 0 1px #dcdfe6;
|
||||
}
|
||||
|
||||
|
||||
.input-group-button {
|
||||
margin-left: 10px;
|
||||
box-shadow: none;
|
||||
background-color: #EDF1FB;
|
||||
color: #6B7181;
|
||||
border: 1px solid #D3D8E3;
|
||||
}
|
||||
|
||||
.input-group-button-primary {
|
||||
box-shadow: none;
|
||||
color: #fff;
|
||||
background-color: #4271EE;
|
||||
}
|
||||
|
||||
.el-button:hover {
|
||||
color: #6B7181;
|
||||
border-color: #aaabad;
|
||||
}
|
||||
|
||||
.input-group-button-primary:hover {
|
||||
color: #fff;
|
||||
border-color: #4271EE;
|
||||
}
|
||||
}
|
||||
</style>
|
74
src/main.js
@ -2,54 +2,64 @@ import { createApp } from "vue";
|
||||
import "./styles.css";
|
||||
//import App from "./AppHyperSpectral.vue";
|
||||
import App from "./App.vue";
|
||||
import { appWindow } from '@tauri-apps/api/window';
|
||||
import { LogicalSize } from '@tauri-apps/api/window';
|
||||
import ElementPlus from 'element-plus';
|
||||
import 'element-plus/dist/index.css'
|
||||
import {createBootstrap} from 'bootstrap-vue-next'
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { LogicalSize } from "@tauri-apps/api/window";
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/dist/index.css";
|
||||
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
|
||||
import { createBootstrap } from "bootstrap-vue-next";
|
||||
|
||||
//
|
||||
// // Add the necessary CSS
|
||||
import 'bootstrap/dist/css/bootstrap.css'
|
||||
import 'bootstrap-vue-next/dist/bootstrap-vue-next.css'
|
||||
import ArcoVue from '@arco-design/web-vue';
|
||||
import "bootstrap/dist/css/bootstrap.css";
|
||||
import "bootstrap-vue-next/dist/bootstrap-vue-next.css";
|
||||
import ArcoVue from "@arco-design/web-vue";
|
||||
|
||||
import '@arco-design/web-vue/dist/arco.css';
|
||||
import { Draggable,DraggablePlugin, DraggableDirective } from '@braks/revue-draggable';
|
||||
import KonamiCode from 'vue3-konami-code';
|
||||
import "@arco-design/web-vue/dist/arco.css";
|
||||
import {
|
||||
Draggable,
|
||||
DraggablePlugin,
|
||||
DraggableDirective,
|
||||
} from "@braks/revue-draggable";
|
||||
import KonamiCode from "vue3-konami-code";
|
||||
import EventBus from "./eventBus.js";
|
||||
import tauriApi from "./utils/tauriApi.js";
|
||||
|
||||
async function setWindowSize() {
|
||||
// const primaryMonitor = await screen.primaryMonitor();
|
||||
// const screenSize = primaryMonitor.size;
|
||||
// const primaryMonitor = await screen.primaryMonitor();
|
||||
// const screenSize = primaryMonitor.size;
|
||||
|
||||
const newSize = new LogicalSize(800, 600);
|
||||
await appWindow.setSize(newSize);
|
||||
// appWindow.setSize(new Size(1000, 1000));
|
||||
const newSize = new LogicalSize(800, 600);
|
||||
await appWindow.setSize(newSize);
|
||||
// appWindow.setSize(new Size(1000, 1000));
|
||||
}
|
||||
var app = createApp(App);
|
||||
app.use(ElementPlus);
|
||||
app.use(createBootstrap( {components: true, directives: true,plugins:true,icons: true,}));
|
||||
app.use(ElementPlus, {
|
||||
locale: zhCn,
|
||||
});
|
||||
app.use(
|
||||
createBootstrap({
|
||||
components: true,
|
||||
directives: true,
|
||||
plugins: true,
|
||||
icons: true,
|
||||
})
|
||||
);
|
||||
app.use(ArcoVue);
|
||||
app.use(DraggablePlugin);
|
||||
app.use(KonamiCode, {
|
||||
onKonamiCodeEntered: () => {
|
||||
// 用户输入Konami Code后执行的代码
|
||||
console.log('Konami Code 已输入!');
|
||||
EventBus.emit('konamiactive');
|
||||
}
|
||||
onKonamiCodeEntered: () => {
|
||||
// 用户输入Konami Code后执行的代码
|
||||
console.log("Konami Code 已输入!");
|
||||
EventBus.emit("konamiactive");
|
||||
},
|
||||
});
|
||||
// or
|
||||
app.directive('draggable', DraggableDirective)
|
||||
app.component('Draggable', Draggable);
|
||||
|
||||
|
||||
|
||||
app.directive("draggable", DraggableDirective);
|
||||
app.component("Draggable", Draggable);
|
||||
|
||||
// 注册全局 API
|
||||
app.config.globalProperties.$tauriApi = tauriApi;
|
||||
|
||||
// app.use(BootstrapVueIcons);
|
||||
app.mount("#app");
|
||||
|
||||
|
||||
|
||||
|
||||
|
112
src/utils/hyperspectralParser.js
Normal file
@ -0,0 +1,112 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
export function useHyperspectralDataParser() {
|
||||
const parsedData = ref(null);
|
||||
const error = ref(null);
|
||||
|
||||
// 解析时间结构
|
||||
const parseTimeStruct = (timeData) => {
|
||||
if (!timeData) return null;
|
||||
return {
|
||||
timezone: timeData.time_zone || 0,
|
||||
year: timeData.year || 0,
|
||||
month: timeData.month || 0,
|
||||
day: timeData.day || 0,
|
||||
hour: timeData.hour || 0,
|
||||
minute: timeData.minute || 0,
|
||||
second: timeData.second || 0,
|
||||
millisecond: timeData.millisecond || 0
|
||||
};
|
||||
};
|
||||
|
||||
// 解析设备元数据
|
||||
const parseDeviceInfo = (metaData) => {
|
||||
if (!metaData || metaData.info_type !== "devinfo") {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
infoType: metaData.info_type,
|
||||
sensorId: metaData.sensor_id || '',
|
||||
bandNum: metaData.bandnum || 0,
|
||||
waveCoeff: {
|
||||
a1: metaData.wave_coeff?.a1 || 0,
|
||||
a2: metaData.wave_coeff?.a2 || 0,
|
||||
a3: metaData.wave_coeff?.a3 || 0,
|
||||
a4: metaData.wave_coeff?.a4 || 0
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// 解析光谱数据
|
||||
const parseSpectralData = (uint8Array, bands, dataType) => {
|
||||
try {
|
||||
switch (dataType) {
|
||||
case 0x20: // float32
|
||||
return new Float32Array(uint8Array.buffer, 0, bands);
|
||||
case 0x21: // float64
|
||||
return new Float64Array(uint8Array.buffer, 0, bands);
|
||||
case 0x10: // uint8
|
||||
return new Uint8Array(uint8Array.buffer, 0, bands);
|
||||
case 0x11: // int16
|
||||
return new Int16Array(uint8Array.buffer, 0, bands);
|
||||
case 0x12: // uint16
|
||||
return new Uint16Array(uint8Array.buffer, 0, bands);
|
||||
case 0x13: // int32
|
||||
return new Int32Array(uint8Array.buffer, 0, bands);
|
||||
case 0x14: // uint32
|
||||
return new Uint32Array(uint8Array.buffer, 0, bands);
|
||||
default:
|
||||
throw new Error(`Unsupported data type: 0x${dataType.toString(16)}`);
|
||||
}
|
||||
} catch (e) {
|
||||
error.value = `Failed to parse spectral data: ${e.message}`;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// 主解析函数
|
||||
const parseHyperspectralData = (rawData, metaData) => {
|
||||
try {
|
||||
if (!rawData || !rawData.spectral_data || !rawData.bands) {
|
||||
throw new Error('Invalid data format: missing required fields');
|
||||
}
|
||||
const uint8Array = new Uint8Array(rawData.spectral_data);
|
||||
const deviceInfo = metaData ? parseDeviceInfo(metaData) : null;
|
||||
const result = {
|
||||
deviceInfo,
|
||||
dataInfo: {
|
||||
name: rawData.name || '',
|
||||
sensorId: rawData.sensor_id || '',
|
||||
fiberId: rawData.fiber_id || 0,
|
||||
collectionTime: rawData.collection_time ? parseTimeStruct(rawData.collection_time) : null,
|
||||
exposure: rawData.exposure || 0,
|
||||
gain: rawData.gain || 0,
|
||||
dataType: rawData.data_type || 0,
|
||||
pixelSize: rawData.pixel_size || 0,
|
||||
groundType: rawData.ground_type || 0,
|
||||
validFlag: rawData.valid_flag || 0,
|
||||
bands: rawData.bands || 0
|
||||
},
|
||||
spectralData: parseSpectralData(uint8Array, rawData.bands, rawData.data_type)
|
||||
};
|
||||
parsedData.value = result;
|
||||
return result;
|
||||
} catch (e) {
|
||||
error.value = `Data parsing error: ${e.message}`;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// 重置状态
|
||||
const reset = () => {
|
||||
parsedData.value = null;
|
||||
error.value = null;
|
||||
};
|
||||
|
||||
return {
|
||||
parsedData,
|
||||
error,
|
||||
parseHyperspectralData,
|
||||
reset
|
||||
};
|
||||
}
|
455
src/utils/irisDataDispose.js
Normal file
@ -0,0 +1,455 @@
|
||||
class getIrisDataDispose {
|
||||
spectralName;
|
||||
irisData;
|
||||
spectralInfoData;
|
||||
spectral_data;
|
||||
image_info;
|
||||
devinfoData;
|
||||
environmentData;
|
||||
|
||||
constructor(irisData, spectralName) {
|
||||
this.irisData = irisData;
|
||||
this.spectralName = spectralName;
|
||||
this.spectral_data = irisData.spectral_data_section;
|
||||
this.image_info = irisData.image_info_section;
|
||||
|
||||
for (const element of irisData.spectral_info_section) {
|
||||
if (element.info_type == "devinfo") {
|
||||
this.devinfoData = element;
|
||||
} else if (element.info_type == "environment") {
|
||||
this.environmentData = element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initData() {
|
||||
const basicTypes = ["ground_dn", "flat_dn", "dark_dn", "gain"];
|
||||
const specialTypes = [
|
||||
"flat_ref",
|
||||
"radiance_ground",
|
||||
"radiance_flat",
|
||||
"refrad",
|
||||
];
|
||||
|
||||
if (basicTypes.includes(this.spectralName)) {
|
||||
return this.getFileSpectralData();
|
||||
} else if (specialTypes.includes(this.spectralName)) {
|
||||
return this.getSpecialFileSpectralData();
|
||||
}
|
||||
}
|
||||
|
||||
//获取一般后端直接返回的类型
|
||||
getFileSpectralData() {
|
||||
for (const element of this.spectral_data) {
|
||||
const typedArray = manageSpectralData(element, this.devinfoData);
|
||||
const normalArray = Array.from(typedArray);
|
||||
if (element.name.toLowerCase().includes(this.spectralName)) {
|
||||
return { ...element, normalArray };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//获取需要计算的类型
|
||||
getSpecialFileSpectralData() {
|
||||
let spectralDataMap = new Map([
|
||||
["ground_dn", null],
|
||||
["flat_dn", null],
|
||||
["dark_dn", null],
|
||||
["flat_ref", null],
|
||||
["gain", null],
|
||||
["radiance_ground", null],
|
||||
["radiance_flat", null],
|
||||
["refrad", null],
|
||||
]);
|
||||
for (const element of this.spectral_data) {
|
||||
const typedArray = manageSpectralData(element, this.devinfoData);
|
||||
const normalArray = Array.from(typedArray);
|
||||
if (element.name.toLowerCase().includes("ground_dn")) {
|
||||
spectralDataMap.set("ground_dn", { ...element, normalArray });
|
||||
} else if (element.name.toLowerCase().includes("flat_dn")) {
|
||||
spectralDataMap.set("flat_dn", { ...element, normalArray });
|
||||
} else if (element.name.toLowerCase().includes("dark_dn")) {
|
||||
spectralDataMap.set("dark_dn", { ...element, normalArray });
|
||||
} else if (element.name.toLowerCase().includes("gain")) {
|
||||
spectralDataMap.set("gain", { ...element, normalArray });
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
spectralDataMap.get("ground_dn") &&
|
||||
spectralDataMap.get("flat_dn") &&
|
||||
spectralDataMap.get("dark_dn") &&
|
||||
spectralDataMap.get("gain")
|
||||
) {
|
||||
const obj1 = {
|
||||
ground_dn: spectralDataMap.get("ground_dn").normalArray,
|
||||
flat_dn: spectralDataMap.get("flat_dn").normalArray,
|
||||
dark_dn: spectralDataMap.get("dark_dn").normalArray,
|
||||
gain: spectralDataMap.get("gain").normalArray,
|
||||
};
|
||||
|
||||
const arrAll = mergeObjectArrays(obj1);
|
||||
const name = spectralDataMap.get("ground_dn").name.split("_")[0];
|
||||
|
||||
// 通用的数值验证函数
|
||||
const validateAndPush = (array, value, type, invalidCount) => {
|
||||
if (isFinite(value) && !isNaN(value)) {
|
||||
array.push(value);
|
||||
return true;
|
||||
} else {
|
||||
invalidCount.invalidResult++;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 通用的除零检查函数
|
||||
const checkDivision = (numerator, denominator, type, invalidCount) => {
|
||||
if (Math.abs(denominator) < 1e-10) {
|
||||
invalidCount.zeroDiv++;
|
||||
return null;
|
||||
}
|
||||
return numerator / denominator;
|
||||
};
|
||||
|
||||
// 通用的结果验证和返回函数
|
||||
const validateResult = (array, name, type) => {
|
||||
if (array.length === 0) {
|
||||
console.error(`${type}计算错误: 没有有效的数据点,无法生成图表`);
|
||||
return { normalArray: [], name: name };
|
||||
}
|
||||
return { normalArray: array, name: name };
|
||||
};
|
||||
|
||||
if (this.spectralName == "radiance_ground") {
|
||||
const radiance_ground = [];
|
||||
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
|
||||
|
||||
for (const element of arrAll) {
|
||||
const gainExposure = spectralDataMap.get("gain").exposure;
|
||||
const groundExposure = spectralDataMap.get("ground_dn").exposure;
|
||||
|
||||
// 检查曝光时间除零 - 改为补充0值
|
||||
if (Math.abs(groundExposure) < 1e-10) {
|
||||
invalidCount.zeroDiv++;
|
||||
radiance_ground.push(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
const exposureRatio = gainExposure / groundExposure;
|
||||
const dnDiff = element.ground_dn - element.dark_dn;
|
||||
const a = exposureRatio * (element.gain * dnDiff);
|
||||
|
||||
// 验证结果,无效时补充0值
|
||||
if (isFinite(a) && !isNaN(a)) {
|
||||
radiance_ground.push(a);
|
||||
} else {
|
||||
invalidCount.invalidResult++;
|
||||
radiance_ground.push(0);
|
||||
}
|
||||
}
|
||||
// 记录统计信息
|
||||
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
|
||||
console.warn(`radiance_ground计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${radiance_ground.length} 个`);
|
||||
}
|
||||
|
||||
return validateResult(radiance_ground, name + "_radiance_ground", 'radiance_ground');
|
||||
|
||||
} else if (this.spectralName == "radiance_flat") {
|
||||
const radiance_flat = [];
|
||||
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
|
||||
|
||||
for (const element of arrAll) {
|
||||
const gainExposure = spectralDataMap.get("gain").exposure;
|
||||
const flatExposure = spectralDataMap.get("flat_dn").exposure;
|
||||
|
||||
// 检查曝光时间除零 - 改为补充0值
|
||||
if (Math.abs(flatExposure) < 1e-10) {
|
||||
invalidCount.zeroDiv++;
|
||||
radiance_flat.push(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
const exposureRatio = gainExposure / flatExposure;
|
||||
const dnDiff = element.flat_dn - element.dark_dn;
|
||||
const b = exposureRatio * (element.gain * dnDiff);
|
||||
|
||||
// 验证结果,无效时补充0值
|
||||
if (isFinite(b) && !isNaN(b)) {
|
||||
radiance_flat.push(b);
|
||||
} else {
|
||||
invalidCount.invalidResult++;
|
||||
radiance_flat.push(0);
|
||||
}
|
||||
}
|
||||
// 记录统计信息
|
||||
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
|
||||
console.warn(`radiance_flat计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${radiance_flat.length} 个`);
|
||||
}
|
||||
|
||||
return validateResult(radiance_flat, name + "_radiance_flat", 'radiance_flat');
|
||||
|
||||
} else if (this.spectralName == "refrad") {
|
||||
const refrad = [];
|
||||
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
|
||||
|
||||
for (const element of arrAll) {
|
||||
const gainExposure = spectralDataMap.get("gain").exposure;
|
||||
const groundExposure = spectralDataMap.get("ground_dn").exposure;
|
||||
const flatExposure = spectralDataMap.get("flat_dn").exposure;
|
||||
|
||||
// 检查曝光时间除零 - 改为补充0值
|
||||
if (Math.abs(groundExposure) < 1e-10 || Math.abs(flatExposure) < 1e-10) {
|
||||
invalidCount.zeroDiv++;
|
||||
refrad.push(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
const groundRatio = gainExposure / groundExposure;
|
||||
const flatRatio = gainExposure / flatExposure;
|
||||
|
||||
const groundDnDiff = element.ground_dn - element.dark_dn;
|
||||
const flatDnDiff = element.flat_dn - element.dark_dn;
|
||||
|
||||
const a = groundRatio * (element.gain * groundDnDiff);
|
||||
const b = flatRatio * (element.gain * flatDnDiff);
|
||||
|
||||
// 检查分母b是否为零 - 改为补充0值
|
||||
if (Math.abs(b) < 1e-10) {
|
||||
invalidCount.zeroDiv++;
|
||||
refrad.push(0);
|
||||
} else {
|
||||
const c = a / b;
|
||||
if (isFinite(c) && !isNaN(c)) {
|
||||
refrad.push(c);
|
||||
} else {
|
||||
invalidCount.invalidResult++;
|
||||
refrad.push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 记录统计信息
|
||||
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
|
||||
console.warn(`refrad计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${refrad.length} 个`);
|
||||
}
|
||||
|
||||
return validateResult(refrad, name + "_refrad", 'refrad');
|
||||
|
||||
} else if (this.spectralName == "flat_ref") {
|
||||
const validData = [];
|
||||
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
|
||||
|
||||
for (const element of arrAll) {
|
||||
const denominator = element.flat_dn - element.dark_dn;
|
||||
const numerator = element.ground_dn - element.dark_dn;
|
||||
|
||||
// 检查分母是否为零或接近零 - 改为补充0值
|
||||
if (Math.abs(denominator) < 1e-10) {
|
||||
invalidCount.zeroDiv++;
|
||||
validData.push(0);
|
||||
} else {
|
||||
const b = numerator / denominator;
|
||||
if (isFinite(b) && !isNaN(b)) {
|
||||
validData.push(b);
|
||||
} else {
|
||||
invalidCount.invalidResult++;
|
||||
validData.push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 记录统计信息
|
||||
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
|
||||
console.warn(`flat_ref计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${validData.length} 个`);
|
||||
}
|
||||
return validateResult(validData, name + "_flat_ref", 'flat_ref');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getSpectralInfoData() {
|
||||
let spectralInfoData = [];
|
||||
for (let i = 0; i < this.devinfoData.bandnum; i++) {
|
||||
const a =
|
||||
this.devinfoData.wave_coeff.a1 * i ** 3 +
|
||||
this.devinfoData.wave_coeff.a2 * i * i +
|
||||
this.devinfoData.wave_coeff.a3 * i +
|
||||
this.devinfoData.wave_coeff.a4;
|
||||
spectralInfoData.push(a);
|
||||
}
|
||||
return spectralInfoData;
|
||||
}
|
||||
|
||||
parseImageData(image_info) {
|
||||
if (!image_info || image_info.length === 0) {
|
||||
console.log("No image data found");
|
||||
return [];
|
||||
}
|
||||
const imageInfos = image_info;
|
||||
const images = [];
|
||||
for (const imageInfo of imageInfos) {
|
||||
// 获取图像类型
|
||||
const imageType = imageInfo.info_type;
|
||||
let mimeType;
|
||||
switch (imageType) {
|
||||
case 0:
|
||||
mimeType = "image/jpeg";
|
||||
break;
|
||||
case 1:
|
||||
mimeType = "image/png";
|
||||
break;
|
||||
case 2:
|
||||
mimeType = "image/tiff";
|
||||
break;
|
||||
case 3:
|
||||
mimeType = "application/octet-stream"; // 原始数据
|
||||
break;
|
||||
default:
|
||||
mimeType = "application/octet-stream";
|
||||
}
|
||||
// 创建Blob对象
|
||||
const imageBlob = new Blob([new Uint8Array(imageInfo.image_data)], {
|
||||
type: mimeType,
|
||||
});
|
||||
// 创建URL
|
||||
const imageUrl = URL.createObjectURL(imageBlob);
|
||||
images.push({
|
||||
name: imageInfo.name,
|
||||
type: imageType,
|
||||
url: imageUrl,
|
||||
time: imageInfo.collection_time,
|
||||
});
|
||||
}
|
||||
|
||||
return images;
|
||||
}
|
||||
}
|
||||
|
||||
function mergeObjectArrays(obj) {
|
||||
const keys = Object.keys(obj);
|
||||
const length = obj[keys[0]].length;
|
||||
|
||||
const result = [];
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
const item = {};
|
||||
for (const key of keys) {
|
||||
item[key] = obj[key][i];
|
||||
}
|
||||
result.push(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const manageSpectralData = (rawData, devinfoData) => {
|
||||
const bands = devinfoData.bandnum;
|
||||
const uint8Array = new Uint8Array(rawData.spectral_data);
|
||||
try {
|
||||
switch (rawData.data_type) {
|
||||
case 0x20: // float32
|
||||
return new Float32Array(uint8Array.buffer, 0, bands);
|
||||
case 0x21: // float64
|
||||
return new Float64Array(uint8Array.buffer, 0, bands);
|
||||
case 0x10: // uint8
|
||||
return new Uint8Array(uint8Array.buffer, 0, bands);
|
||||
case 0x11: // int16
|
||||
return new Int16Array(uint8Array.buffer, 0, bands);
|
||||
case 0x12: // uint16
|
||||
return new Uint16Array(uint8Array.buffer, 0, bands);
|
||||
case 0x13: // int32
|
||||
return new Int32Array(uint8Array.buffer, 0, bands);
|
||||
case 0x14: // uint32
|
||||
return new Uint32Array(uint8Array.buffer, 0, bands);
|
||||
default:
|
||||
throw new Error(`Unsupported data type: 0x${dataType.toString(16)}`);
|
||||
}
|
||||
} catch (e) {
|
||||
error.value = `Failed to parse spectral data: ${e.message}`;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const spectralTypeList = [
|
||||
{
|
||||
value: "ground_dn",
|
||||
label: "地物DN",
|
||||
},
|
||||
{
|
||||
value: "flat_dn",
|
||||
label: "参考DN",
|
||||
},
|
||||
{
|
||||
value: "dark_dn",
|
||||
label: "暗噪DN",
|
||||
},
|
||||
{
|
||||
value: "flat_ref",
|
||||
label: "反射率",
|
||||
},
|
||||
{
|
||||
value: "gain",
|
||||
label: "能量校准文件",
|
||||
},
|
||||
{
|
||||
value: "radiance_ground",
|
||||
label: "地物辐射亮度",
|
||||
},
|
||||
{
|
||||
value: "radiance_flat",
|
||||
label: "参考辐射亮度",
|
||||
},
|
||||
{
|
||||
value: "refrad",
|
||||
label: "反射率能量",
|
||||
},
|
||||
{
|
||||
value: "jdfs",
|
||||
label: "绝对反射率",
|
||||
},
|
||||
{
|
||||
value: "ckbzwj",
|
||||
label: "参考校准文件",
|
||||
},
|
||||
{
|
||||
value: "fszd",
|
||||
label: "辐射照度",
|
||||
},
|
||||
];
|
||||
|
||||
const spectralProcessTypeList = [
|
||||
{
|
||||
value: "D1",
|
||||
label: "一阶导数",
|
||||
},
|
||||
{
|
||||
value: "D2",
|
||||
label: "二阶导数",
|
||||
},
|
||||
{
|
||||
value: "MA",
|
||||
label: "移动平均平滑",
|
||||
},
|
||||
];
|
||||
|
||||
function D1(arr) {
|
||||
const result = [];
|
||||
for (let i = 1; i < arr.length; i++) {
|
||||
result.push(arr[i] - arr[i - 1]);
|
||||
}
|
||||
result.push(arr[arr.length - 1]);
|
||||
return result;
|
||||
}
|
||||
|
||||
function D2(arr) {
|
||||
const arr2 = D1(arr);
|
||||
return D1(arr2);
|
||||
}
|
||||
|
||||
export {
|
||||
spectralTypeList,
|
||||
getIrisDataDispose,
|
||||
spectralProcessTypeList,
|
||||
D1,
|
||||
D2,
|
||||
};
|
106
src/utils/spectralDataService.js
Normal file
@ -0,0 +1,106 @@
|
||||
import { getIrisDataDispose, D1, D2 } from '../utils/irisDataDispose';
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
|
||||
/**
|
||||
* 光谱数据处理服务
|
||||
*/
|
||||
export class SpectralDataService {
|
||||
/**
|
||||
* 提取文件名
|
||||
*/
|
||||
static extractFileName(filePath) {
|
||||
const match = filePath.match(/[^\\\/]+$/);
|
||||
return match ? match[0] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载文件数据
|
||||
*/
|
||||
static async loadFileData(filePaths) {
|
||||
const fileData = [];
|
||||
for (const path of filePaths) {
|
||||
try {
|
||||
const src = await invoke("getoneirisfile", { path });
|
||||
const fileName = this.extractFileName(path);
|
||||
fileData.push({ data: src, name: fileName });
|
||||
} catch (error) {
|
||||
console.error(`加载文件失败: ${path}`, error);
|
||||
}
|
||||
}
|
||||
return fileData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理光谱数据
|
||||
*/
|
||||
static processSpectralData(fileData, spectralType, processType = '') {
|
||||
const spectralDataList = [];
|
||||
const imageList = [];
|
||||
|
||||
for (const element of fileData) {
|
||||
if (!element.data) continue;
|
||||
|
||||
try {
|
||||
const dispose = new getIrisDataDispose(element.data, spectralType);
|
||||
const datay = dispose.initData();
|
||||
const datax = dispose.getSpectralInfoData();
|
||||
const environmentData = dispose.environmentData;
|
||||
const img = dispose.parseImageData(element.data.image_info_section);
|
||||
|
||||
if (datay?.normalArray && datax) {
|
||||
spectralDataList.push({
|
||||
name: datay?.name || '',
|
||||
datax: datax,
|
||||
datay: datay.normalArray,
|
||||
environmentData: { ...environmentData, fileName: element.name }
|
||||
});
|
||||
imageList.push(img);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`处理光谱数据失败: ${element.name}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
spectralDataList,
|
||||
imageList,
|
||||
processedData: this.applyProcessing(spectralDataList, processType)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用数据处理(D1/D2等)
|
||||
*/
|
||||
static applyProcessing(spectralDataList, processType) {
|
||||
if (!processType) return spectralDataList;
|
||||
|
||||
switch (processType) {
|
||||
case 'D1':
|
||||
return spectralDataList.map(item => ({
|
||||
name: item.name + '_D1',
|
||||
datax: item.datax,
|
||||
datay: D1(item.datay),
|
||||
environmentData: item.environmentData
|
||||
}));
|
||||
case 'D2':
|
||||
return spectralDataList.map(item => ({
|
||||
name: item.name + '_D2',
|
||||
datax: item.datax,
|
||||
datay: D2(item.datay),
|
||||
environmentData: item.environmentData
|
||||
}));
|
||||
default:
|
||||
return spectralDataList;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量处理选定文件的光谱数据
|
||||
*/
|
||||
static processSelectedFiles(fileData, selectedFileNames, spectralType, processType = '') {
|
||||
const filteredData = fileData.filter(file =>
|
||||
selectedFileNames.includes(file.name)
|
||||
);
|
||||
return this.processSpectralData(filteredData, spectralType, processType);
|
||||
}
|
||||
}
|
118
src/utils/tauriApi.js
Normal file
@ -0,0 +1,118 @@
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { dialog, fs } from "@tauri-apps/api";
|
||||
|
||||
export default {
|
||||
/**
|
||||
* 打开文件夹选择对话框并获取文件夹内容
|
||||
* @param {string} defaultPath 默认路径
|
||||
* @returns {Promise<Object>} 文件夹树形结构
|
||||
*/
|
||||
async getFolderList(defaultPath = "") {
|
||||
try {
|
||||
// 打开文件夹选择对话框
|
||||
const options = {
|
||||
defaultPath: defaultPath || "../",
|
||||
directory: true,
|
||||
title: "请选择文件夹",
|
||||
};
|
||||
|
||||
const selectedPath = await dialog.open(options);
|
||||
|
||||
if (!selectedPath) {
|
||||
return {
|
||||
label: '请选择',
|
||||
children: [],
|
||||
};
|
||||
}
|
||||
|
||||
// 读取文件夹内容并构建树形结构
|
||||
const tree = await this.buildFolderTree(selectedPath);
|
||||
return tree;
|
||||
} catch (error) {
|
||||
console.error("获取文件夹列表失败:", error);
|
||||
return {
|
||||
label: '请选择',
|
||||
children: [],
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 构建文件夹树形结构
|
||||
* @param {string} folderPath 文件夹路径
|
||||
* @returns {Promise<Object>} 树形结构对象
|
||||
*/
|
||||
async buildFolderTree(folderPath) {
|
||||
try {
|
||||
const entries = await fs.readDir(folderPath, { recursive: true });
|
||||
|
||||
// 获取文件夹名称
|
||||
const pathParts = folderPath.split(/[\\\/]/);
|
||||
const folderName = pathParts[pathParts.length - 1] || folderPath;
|
||||
const obj = {
|
||||
name: folderName,
|
||||
path: folderPath,
|
||||
children: entries,
|
||||
isFolder: true,
|
||||
isLeaf: false
|
||||
}
|
||||
const data = this.getTreeData(obj);
|
||||
return data
|
||||
} catch (error) {
|
||||
console.error("构建文件夹树失败:", error);
|
||||
return {
|
||||
label: folderPath,
|
||||
children: [],
|
||||
path: folderPath,
|
||||
isFolder: true,
|
||||
isLeaf: false
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getTreeData(entries) {
|
||||
if (!entries) {
|
||||
return null;
|
||||
}
|
||||
const obj = {
|
||||
label: entries.name,
|
||||
path: entries.path,
|
||||
}
|
||||
if (entries?.children && Array.isArray(entries.children)) {
|
||||
// 处理数组
|
||||
obj.children = entries.children.map((item) => {
|
||||
return this.getTreeData(item);
|
||||
});
|
||||
obj.isFolder = true;
|
||||
obj.isLeaf = false;
|
||||
|
||||
} else {
|
||||
obj.isLeaf = true;
|
||||
obj.isFolder = false;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
function deepTraverse(data) {
|
||||
if (Array.isArray(data)) {
|
||||
// 处理数组
|
||||
data.forEach((item, index) => {
|
||||
console.log(`数组项 ${index}:`, item);
|
||||
deepTraverse(item); // 递归处理数组元素
|
||||
});
|
||||
} else if (typeof data === 'object' && data !== null) {
|
||||
// 处理对象
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
console.log(`属性 ${key}:`, value);
|
||||
deepTraverse(value); // 递归处理对象属性
|
||||
});
|
||||
} else {
|
||||
// 基本类型值
|
||||
console.log('值:', data);
|
||||
}
|
||||
}
|
106
yarn.lock
@ -124,6 +124,11 @@
|
||||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@petamoriken/float16@^3.4.7":
|
||||
version "3.9.2"
|
||||
resolved "https://r.cnpmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz"
|
||||
integrity sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==
|
||||
|
||||
"@popperjs/core@^2.11.8", "@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7":
|
||||
version "2.11.8"
|
||||
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
|
||||
@ -287,6 +292,11 @@
|
||||
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.4.tgz"
|
||||
integrity sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==
|
||||
|
||||
"@types/rbush@4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://r.cnpmjs.org/@types/rbush/-/rbush-4.0.0.tgz"
|
||||
integrity sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==
|
||||
|
||||
"@types/web-bluetooth@^0.0.16":
|
||||
version "0.0.16"
|
||||
resolved "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz"
|
||||
@ -694,6 +704,11 @@ destroy@^1.0.4:
|
||||
resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz"
|
||||
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
|
||||
|
||||
earcut@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://r.cnpmjs.org/earcut/-/earcut-3.0.2.tgz"
|
||||
integrity sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==
|
||||
|
||||
echart@^0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.npmjs.org/echart/-/echart-0.1.3.tgz"
|
||||
@ -854,6 +869,20 @@ function-bind@^1.1.2:
|
||||
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
geotiff@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://r.cnpmjs.org/geotiff/-/geotiff-2.1.3.tgz"
|
||||
integrity sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==
|
||||
dependencies:
|
||||
"@petamoriken/float16" "^3.4.7"
|
||||
lerc "^3.0.0"
|
||||
pako "^2.0.4"
|
||||
parse-headers "^2.0.2"
|
||||
quick-lru "^6.1.1"
|
||||
web-worker "^1.2.0"
|
||||
xml-utils "^1.0.2"
|
||||
zstddec "^0.1.0"
|
||||
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
|
||||
@ -1096,6 +1125,11 @@ koa@^2.2.0:
|
||||
type-is "^1.6.16"
|
||||
vary "^1.1.2"
|
||||
|
||||
lerc@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://r2.cnpmjs.org/lerc/-/lerc-3.0.0.tgz"
|
||||
integrity sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==
|
||||
|
||||
less@*, less@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/less/-/less-4.2.0.tgz"
|
||||
@ -1339,6 +1373,17 @@ number-precision@^1.6.0:
|
||||
resolved "https://registry.npmjs.org/number-precision/-/number-precision-1.6.0.tgz"
|
||||
integrity sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==
|
||||
|
||||
ol@^10.6.1:
|
||||
version "10.6.1"
|
||||
resolved "https://r.cnpmjs.org/ol/-/ol-10.6.1.tgz"
|
||||
integrity sha512-xp174YOwPeLj7c7/8TCIEHQ4d41tgTDDhdv6SqNdySsql5/MaFJEJkjlsYcvOPt7xA6vrum/QG4UdJ0iCGT1cg==
|
||||
dependencies:
|
||||
"@types/rbush" "4.0.0"
|
||||
earcut "^3.0.0"
|
||||
geotiff "^2.1.3"
|
||||
pbf "4.0.1"
|
||||
rbush "^4.0.0"
|
||||
|
||||
on-finished@^2.3.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz"
|
||||
@ -1351,6 +1396,16 @@ only@~0.0.2:
|
||||
resolved "https://registry.npmjs.org/only/-/only-0.0.2.tgz"
|
||||
integrity sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==
|
||||
|
||||
pako@^2.0.4:
|
||||
version "2.1.0"
|
||||
resolved "https://r.cnpmjs.org/pako/-/pako-2.1.0.tgz"
|
||||
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==
|
||||
|
||||
parse-headers@^2.0.2:
|
||||
version "2.0.6"
|
||||
resolved "https://r.cnpmjs.org/parse-headers/-/parse-headers-2.0.6.tgz"
|
||||
integrity sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==
|
||||
|
||||
parse-node-version@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz"
|
||||
@ -1378,6 +1433,13 @@ pathe@^1.1.2:
|
||||
resolved "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz"
|
||||
integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
|
||||
|
||||
pbf@4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://r.cnpmjs.org/pbf/-/pbf-4.0.1.tgz"
|
||||
integrity sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==
|
||||
dependencies:
|
||||
resolve-protobuf-schema "^2.1.0"
|
||||
|
||||
picocolors@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz"
|
||||
@ -1421,6 +1483,11 @@ postcss@^8.4.35, postcss@^8.5.3:
|
||||
picocolors "^1.1.1"
|
||||
source-map-js "^1.2.1"
|
||||
|
||||
protocol-buffers-schema@^3.3.1:
|
||||
version "3.6.0"
|
||||
resolved "https://r2.cnpmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz"
|
||||
integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==
|
||||
|
||||
prr@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz"
|
||||
@ -1441,11 +1508,21 @@ queue-microtask@^1.2.2:
|
||||
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
|
||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||
|
||||
quick-lru@^6.1.1:
|
||||
version "6.1.2"
|
||||
resolved "https://r.cnpmjs.org/quick-lru/-/quick-lru-6.1.2.tgz"
|
||||
integrity sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==
|
||||
|
||||
quickselect@^1.0.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz"
|
||||
integrity sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==
|
||||
|
||||
quickselect@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://r.cnpmjs.org/quickselect/-/quickselect-3.0.0.tgz"
|
||||
integrity sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==
|
||||
|
||||
rbush@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/rbush/-/rbush-2.0.2.tgz"
|
||||
@ -1453,6 +1530,13 @@ rbush@^2.0.2:
|
||||
dependencies:
|
||||
quickselect "^1.0.1"
|
||||
|
||||
rbush@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://r.cnpmjs.org/rbush/-/rbush-4.0.1.tgz"
|
||||
integrity sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==
|
||||
dependencies:
|
||||
quickselect "^3.0.0"
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz"
|
||||
@ -1465,6 +1549,13 @@ resize-observer-polyfill@^1.5.1:
|
||||
resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz"
|
||||
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
||||
|
||||
resolve-protobuf-schema@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://r2.cnpmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz"
|
||||
integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==
|
||||
dependencies:
|
||||
protocol-buffers-schema "^3.3.1"
|
||||
|
||||
resolve@^1.22.8:
|
||||
version "1.22.8"
|
||||
resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz"
|
||||
@ -1789,6 +1880,11 @@ vue3-konami-code@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/vue3-konami-code/-/vue3-konami-code-1.0.0.tgz"
|
||||
integrity sha512-fhHAPFZA1jsgDHlYz5dnG52RmY9+vtfMthBaY1S5VBxNLdU4EWTbnJO0nfL8Uybw5uHsDqCGtTbGaX7nIvQ9Qw==
|
||||
|
||||
web-worker@^1.2.0:
|
||||
version "1.5.0"
|
||||
resolved "https://r.cnpmjs.org/web-worker/-/web-worker-1.5.0.tgz"
|
||||
integrity sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==
|
||||
|
||||
webpack-sources@^3.2.3:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz"
|
||||
@ -1799,6 +1895,11 @@ webpack-virtual-modules@^0.6.1:
|
||||
resolved "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz"
|
||||
integrity sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==
|
||||
|
||||
xml-utils@^1.0.2:
|
||||
version "1.10.2"
|
||||
resolved "https://r.cnpmjs.org/xml-utils/-/xml-utils-1.10.2.tgz"
|
||||
integrity sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==
|
||||
|
||||
ylru@^1.2.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmjs.org/ylru/-/ylru-1.4.0.tgz"
|
||||
@ -1810,3 +1911,8 @@ zrender@5.5.0:
|
||||
integrity sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==
|
||||
dependencies:
|
||||
tslib "2.3.0"
|
||||
|
||||
zstddec@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://r.cnpmjs.org/zstddec/-/zstddec-0.1.0.tgz"
|
||||
integrity sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==
|
||||
|