add
This commit is contained in:
parent
ab89bed57d
commit
dcac2021f5
326
package-lock.json
generated
326
package-lock.json
generated
@ -22,6 +22,7 @@
|
||||
"dayjs": "^1.11.13",
|
||||
"echarts": "^5.5.1",
|
||||
"lodash": "^4.17.21",
|
||||
"maplibre-gl": "^5.0.1",
|
||||
"moment-timezone": "^0.5.46",
|
||||
"normalize.css": "^8.0.1",
|
||||
"pinia": "^2.0.28",
|
||||
@ -4394,6 +4395,113 @@
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@mapbox/geojson-rewind": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmmirror.com/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz",
|
||||
"integrity": "sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"get-stream": "^6.0.1",
|
||||
"minimist": "^1.2.6"
|
||||
},
|
||||
"bin": {
|
||||
"geojson-rewind": "geojson-rewind"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/geojson-rewind/node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/jsonlint-lines-primitives": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz",
|
||||
"integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/point-geometry": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
|
||||
"integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@mapbox/tiny-sdf": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz",
|
||||
"integrity": "sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==",
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/@mapbox/unitbezier": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz",
|
||||
"integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==",
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/@mapbox/vector-tile": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz",
|
||||
"integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@mapbox/point-geometry": "~0.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/whoots-js": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz",
|
||||
"integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@maplibre/maplibre-gl-style-spec": {
|
||||
"version": "23.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-23.1.0.tgz",
|
||||
"integrity": "sha512-R6/ihEuC5KRexmKIYkWqUv84Gm+/QwsOUgHyt1yy2XqCdGdLvlBWVWIIeTZWN4NGdwmY6xDzdSGU2R9oBLNg2w==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@mapbox/jsonlint-lines-primitives": "~2.0.2",
|
||||
"@mapbox/unitbezier": "^0.0.1",
|
||||
"json-stringify-pretty-compact": "^4.0.0",
|
||||
"minimist": "^1.2.8",
|
||||
"quickselect": "^3.0.0",
|
||||
"rw": "^1.3.3",
|
||||
"tinyqueue": "^3.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"gl-style-format": "dist/gl-style-format.mjs",
|
||||
"gl-style-migrate": "dist/gl-style-migrate.mjs",
|
||||
"gl-style-validate": "dist/gl-style-validate.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@maplibre/maplibre-gl-style-spec/node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/@maplibre/maplibre-gl-style-spec/node_modules/quickselect": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/quickselect/-/quickselect-3.0.0.tgz",
|
||||
"integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@maplibre/maplibre-gl-style-spec/node_modules/tinyqueue": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/tinyqueue/-/tinyqueue-3.0.0.tgz",
|
||||
"integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@mars3d/heatmap.js": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmmirror.com/@mars3d/heatmap.js/-/heatmap.js-2.0.7.tgz",
|
||||
@ -7410,6 +7518,15 @@
|
||||
"integrity": "sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/geojson-vt": {
|
||||
"version": "3.2.5",
|
||||
"resolved": "https://registry.npmmirror.com/@types/geojson-vt/-/geojson-vt-3.2.5.tgz",
|
||||
"integrity": "sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/geojson": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
@ -7439,6 +7556,23 @@
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mapbox__point-geometry": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmmirror.com/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz",
|
||||
"integrity": "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/mapbox__vector-tile": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmmirror.com/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.4.tgz",
|
||||
"integrity": "sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/geojson": "*",
|
||||
"@types/mapbox__point-geometry": "*",
|
||||
"@types/pbf": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.19.68",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.68.tgz",
|
||||
@ -7448,6 +7582,12 @@
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/pbf": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/@types/pbf/-/pbf-3.0.5.tgz",
|
||||
"integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.8",
|
||||
"resolved": "https://registry.npmmirror.com/@types/semver/-/semver-7.5.8.tgz",
|
||||
@ -7461,6 +7601,15 @@
|
||||
"integrity": "sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/supercluster": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/@types/supercluster/-/supercluster-7.1.3.tgz",
|
||||
"integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/geojson": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||
@ -10660,6 +10809,12 @@
|
||||
"integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/geojson-vt": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/geojson-vt/-/geojson-vt-4.0.2.tgz",
|
||||
"integrity": "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.6.tgz",
|
||||
@ -10693,6 +10848,18 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz",
|
||||
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/get-symbol-description": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
|
||||
@ -10720,6 +10887,12 @@
|
||||
"js-binary-schema-parser": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/gl-matrix": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/gl-matrix/-/gl-matrix-3.4.3.tgz",
|
||||
"integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
|
||||
@ -10755,6 +10928,44 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/global-prefix": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/global-prefix/-/global-prefix-4.0.0.tgz",
|
||||
"integrity": "sha512-w0Uf9Y9/nyHinEk5vMJKRie+wa4kR5hmDbEhGGds/kG1PwGLLHKRoNMeJOyCQjjBkANlnScqgzcFwGHgmgLkVA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ini": "^4.1.3",
|
||||
"kind-of": "^6.0.3",
|
||||
"which": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/global-prefix/node_modules/isexe": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/isexe/-/isexe-3.1.1.tgz",
|
||||
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/global-prefix/node_modules/which": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/which/-/which-4.0.0.tgz",
|
||||
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/which.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz",
|
||||
@ -11059,6 +11270,15 @@
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/ini/-/ini-4.1.3.tgz",
|
||||
"integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/internal-slot": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/internal-slot/-/internal-slot-1.1.0.tgz",
|
||||
@ -11614,6 +11834,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-stringify-pretty-compact": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz",
|
||||
"integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
|
||||
@ -11652,6 +11878,15 @@
|
||||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz",
|
||||
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/kolorist": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz",
|
||||
@ -11812,6 +12047,65 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/maplibre-gl": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/maplibre-gl/-/maplibre-gl-5.0.1.tgz",
|
||||
"integrity": "sha512-kNvod1Tq0BcZvn43UAciA3DrzaEGmowqMoI6nh3kUo9rf+7m89mFJI9dELxkWzJ/N9Pgnkp7xF1jzTP08PGpCw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@mapbox/geojson-rewind": "^0.5.2",
|
||||
"@mapbox/jsonlint-lines-primitives": "^2.0.2",
|
||||
"@mapbox/point-geometry": "^0.1.0",
|
||||
"@mapbox/tiny-sdf": "^2.0.6",
|
||||
"@mapbox/unitbezier": "^0.0.1",
|
||||
"@mapbox/vector-tile": "^1.3.1",
|
||||
"@mapbox/whoots-js": "^3.1.0",
|
||||
"@maplibre/maplibre-gl-style-spec": "^23.0.0",
|
||||
"@types/geojson": "^7946.0.15",
|
||||
"@types/geojson-vt": "3.2.5",
|
||||
"@types/mapbox__point-geometry": "^0.1.4",
|
||||
"@types/mapbox__vector-tile": "^1.3.4",
|
||||
"@types/pbf": "^3.0.5",
|
||||
"@types/supercluster": "^7.1.3",
|
||||
"earcut": "^3.0.1",
|
||||
"geojson-vt": "^4.0.2",
|
||||
"gl-matrix": "^3.4.3",
|
||||
"global-prefix": "^4.0.0",
|
||||
"kdbush": "^4.0.2",
|
||||
"murmurhash-js": "^1.0.0",
|
||||
"pbf": "^3.3.0",
|
||||
"potpack": "^2.0.0",
|
||||
"quickselect": "^3.0.0",
|
||||
"supercluster": "^8.0.1",
|
||||
"tinyqueue": "^3.0.0",
|
||||
"vt-pbf": "^3.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.14.0",
|
||||
"npm": ">=8.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/maplibre-gl/node_modules/earcut": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/earcut/-/earcut-3.0.1.tgz",
|
||||
"integrity": "sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/maplibre-gl/node_modules/quickselect": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/quickselect/-/quickselect-3.0.0.tgz",
|
||||
"integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/maplibre-gl/node_modules/tinyqueue": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/tinyqueue/-/tinyqueue-3.0.0.tgz",
|
||||
"integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/marchingsquares": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmmirror.com/marchingsquares/-/marchingsquares-1.3.3.tgz",
|
||||
@ -11989,6 +12283,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/murmurhash-js": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz",
|
||||
"integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mz": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz",
|
||||
@ -12971,6 +13271,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/potpack": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/potpack/-/potpack-2.0.0.tgz",
|
||||
"integrity": "sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
@ -14323,6 +14629,15 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/supercluster": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/supercluster/-/supercluster-8.0.1.tgz",
|
||||
"integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"kdbush": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
|
||||
@ -15250,6 +15565,17 @@
|
||||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vt-pbf": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/vt-pbf/-/vt-pbf-3.1.3.tgz",
|
||||
"integrity": "sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mapbox/point-geometry": "0.1.0",
|
||||
"@mapbox/vector-tile": "^1.3.1",
|
||||
"pbf": "^3.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/vue": {
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz",
|
||||
|
@ -25,6 +25,7 @@
|
||||
"dayjs": "^1.11.13",
|
||||
"echarts": "^5.5.1",
|
||||
"lodash": "^4.17.21",
|
||||
"maplibre-gl": "^5.0.1",
|
||||
"moment-timezone": "^0.5.46",
|
||||
"normalize.css": "^8.0.1",
|
||||
"pinia": "^2.0.28",
|
||||
|
@ -6,10 +6,23 @@ window['settings'] = {
|
||||
base: {
|
||||
icon: './images/icons/base/党政首脑机关.png',
|
||||
color: '#ea7354',
|
||||
model: './models/基地.glb',
|
||||
},
|
||||
airport: {
|
||||
icon: './images/icons/base/军用机场.png',
|
||||
color: '#80b1d3',
|
||||
model: './models/机场.glb',
|
||||
},
|
||||
port: {
|
||||
icon: './images/icons/base/军用港口.png',
|
||||
color: '#fcee82',
|
||||
model: './models/港口.glb',
|
||||
},
|
||||
station: {
|
||||
icon: './images/icons/base/民用机场.png',
|
||||
color: '#8dd3c7',
|
||||
model: './models/雷达.glb',
|
||||
},
|
||||
airport: { icon: './images/icons/base/军用机场.png', color: '#80b1d3' },
|
||||
port: { icon: './images/icons/base/军用港口.png', color: '#fcee82' },
|
||||
station: { icon: './images/icons/base/民用机场.png', color: '#8dd3c7' },
|
||||
},
|
||||
mbDict: {
|
||||
甲: {
|
||||
|
BIN
public/models/基地.glb
Normal file
BIN
public/models/基地.glb
Normal file
Binary file not shown.
BIN
public/models/机场.glb
Normal file
BIN
public/models/机场.glb
Normal file
Binary file not shown.
BIN
public/models/港口.glb
Normal file
BIN
public/models/港口.glb
Normal file
Binary file not shown.
BIN
public/models/雷达.glb
Normal file
BIN
public/models/雷达.glb
Normal file
Binary file not shown.
6738
public/style.json
Normal file
6738
public/style.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -15,3 +15,11 @@ export function getHangjing(data = {}) {
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function updateHjStyle(data = {}) {
|
||||
return request({
|
||||
url: `${baseUrl}/hangjing/style`,
|
||||
method: 'put',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
@ -55,9 +55,10 @@
|
||||
#71ffff77
|
||||
);
|
||||
|
||||
--color-bg: #1a222966;
|
||||
/* --color-bg: #1a222966; */
|
||||
--color-bg: #1a222999;
|
||||
|
||||
--gradient-bg-title: linear-gradient(to right, #4fd2dd55, #4b877400);
|
||||
--gradient-bg-title: linear-gradient(to right, #4fd2dd66, #4b877400);
|
||||
--tw-from-opacity: 33%;
|
||||
}
|
||||
|
||||
|
3
src/assets/earth.scss
Normal file
3
src/assets/earth.scss
Normal file
@ -0,0 +1,3 @@
|
||||
.cesium-widget-credits {
|
||||
display: none !important;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
@import './base.css';
|
||||
@import './naiveui.css';
|
||||
@import './detail.scss';
|
||||
@import './earth.scss';
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
|
@ -23,10 +23,10 @@
|
||||
border-image-slice: 2;
|
||||
border-image-repeat: stretch; */
|
||||
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
/* position: relative;
|
||||
margin-bottom: 10px; */
|
||||
/* background: rgba(26, 34, 41, 0.8); */
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
/* background: rgba(0, 0, 0, 0.8); */
|
||||
}
|
||||
/* .n-notification-wrapper {
|
||||
width: 200px;
|
||||
@ -38,14 +38,14 @@
|
||||
} */
|
||||
|
||||
.n-message-wrapper::before {
|
||||
border-radius: 5px;
|
||||
/* border-radius: 5px;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
bottom: -2px;
|
||||
left: -2px;
|
||||
right: -2px;
|
||||
z-index: -1;
|
||||
z-index: -1; */
|
||||
/* background: linear-gradient(
|
||||
45deg,
|
||||
#f7c30b,
|
||||
@ -55,7 +55,7 @@
|
||||
#f49805,
|
||||
#f7c30b
|
||||
); */
|
||||
background: white;
|
||||
/* background: white;
|
||||
background-size: 300% 300%;
|
||||
|
||||
animation: gradientAnimation 3s ease infinite alternate;
|
||||
@ -70,7 +70,7 @@
|
||||
2px 100%,
|
||||
100% 100%,
|
||||
100% 0%
|
||||
);
|
||||
); */
|
||||
}
|
||||
|
||||
@keyframes gradientAnimation {
|
||||
|
@ -11,6 +11,7 @@ export const useEntity = () => {
|
||||
showEntity,
|
||||
getHisTraj,
|
||||
getMBEntityOpt,
|
||||
iconOrModel,
|
||||
changeIconOrModel,
|
||||
}
|
||||
}
|
||||
@ -89,7 +90,7 @@ function getMBEntityOpt({
|
||||
scaleByDistance: new Cesium.NearFarScalar(7000000, 1.0, 18000000, 0.4),
|
||||
},
|
||||
billboard: {
|
||||
show: true,
|
||||
show: !iconOrModel.value,
|
||||
image: mubiaoDict.icon,
|
||||
width: 30,
|
||||
height: 30,
|
||||
@ -97,7 +98,7 @@ function getMBEntityOpt({
|
||||
scaleByDistance: new Cesium.NearFarScalar(7000000, 1.0, 18000000, 0.4),
|
||||
},
|
||||
model: {
|
||||
show: false,
|
||||
show: iconOrModel.value,
|
||||
uri: mubiaoDict.model,
|
||||
scale: 1000,
|
||||
minimumPixelSize: 50,
|
||||
@ -124,8 +125,10 @@ function getMBEntityOpt({
|
||||
}
|
||||
}
|
||||
|
||||
const iconOrModel = ref(false)
|
||||
function changeIconOrModel() {
|
||||
;[...mubiaoMap.values()].forEach(entity => {
|
||||
iconOrModel.value = !iconOrModel.value
|
||||
;[...mubiaoMap.values(), ...baseMap.values()].forEach(entity => {
|
||||
entity.model.show = !entity.model.show._value
|
||||
entity.billboard.show = !entity.billboard.show._value
|
||||
})
|
||||
|
@ -36,6 +36,11 @@ const router = createRouter({
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/placename',
|
||||
name: 'PlaceName',
|
||||
component: () => import('@/views/PlaceName'),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
|
@ -10,7 +10,7 @@ import { useEntity } from '@/hooks/entity'
|
||||
|
||||
const treeData = ref([])
|
||||
|
||||
const { baseMap } = useEntity()
|
||||
const { baseMap, iconOrModel } = useEntity()
|
||||
// const { baseMap } = storeToRefs(entity)
|
||||
|
||||
// const allKeys = computed(() => getAllKeys(treeData))
|
||||
@ -48,10 +48,136 @@ export const useBase = () => {
|
||||
// console.log(nodes, '====')
|
||||
nodes.forEach(({ data, dataId }: TBase) => {
|
||||
const entity = addEntity(data)
|
||||
// console.log(entity)
|
||||
|
||||
addEventSub(dataId, entity, data)
|
||||
baseMap.set(dataId, entity)
|
||||
|
||||
// console.log(entity)
|
||||
// const boundingSphere = entity.computeBoundingSphere()
|
||||
// const radius = boundingSphere.radius
|
||||
|
||||
// // 计算模型的底部位置
|
||||
// const newPosition = Cesium.Cartesian3.subtract(
|
||||
// entity.position.getValue(),
|
||||
// Cesium.Cartesian3.multiplyByScalar(
|
||||
// Cesium.Cartesian3.UNIT_Z,
|
||||
// radius,
|
||||
// new Cesium.Cartesian3()
|
||||
// )
|
||||
// )
|
||||
|
||||
// // 设置模型的新的位置
|
||||
// entity.position = new Cesium.ConstantPositionProperty(newPosition)
|
||||
})
|
||||
|
||||
const modelUrls = Object.values(window.settings.baseMBDict).map(
|
||||
item => item.model
|
||||
)
|
||||
// console.log(viewer.scene.primitives)
|
||||
|
||||
viewer.scene.preRender.addEventListener(() => {
|
||||
viewer.scene.primitives._primitives.forEach(primitive => {
|
||||
if (primitive instanceof Cesium.Model && primitive?._id?._name) {
|
||||
const entity = baseMap.get(primitive._id._name)
|
||||
if (!entity) {
|
||||
return
|
||||
}
|
||||
if (primitive.ready && entity) {
|
||||
// // 获取模型的 BoundingSphere
|
||||
// const boundingSphere = primitive.boundingSphere
|
||||
|
||||
// const entityPos = entity.position._value
|
||||
// // 计算底部高度调整
|
||||
// const center = boundingSphere.center
|
||||
// // const height = Cesium.Cartesian3.distance(center, entityPos)
|
||||
// const radius = boundingSphere.radius
|
||||
// // console.log(center, radius)
|
||||
// const cartographic = Cesium.Cartographic.fromCartesian(
|
||||
// entity.position._value
|
||||
// )
|
||||
// // -(Math.sqrt(3) * radius) / 3
|
||||
// const adjustedHeight = radius * 0.8
|
||||
|
||||
// // + cartographic.height
|
||||
// const newPosition = Cesium.Cartesian3.fromRadians(
|
||||
// cartographic.longitude,
|
||||
// cartographic.latitude,
|
||||
// adjustedHeight
|
||||
// )
|
||||
|
||||
let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||||
entity.position._value
|
||||
)
|
||||
const heightOffset = Cesium.Matrix4.fromTranslation(
|
||||
new Cesium.Cartesian3(
|
||||
0,
|
||||
0,
|
||||
primitive.boundingSphere.radius * 0.8
|
||||
)
|
||||
)
|
||||
modelMatrix = Cesium.Matrix4.multiply(
|
||||
modelMatrix,
|
||||
heightOffset,
|
||||
new Cesium.Matrix4()
|
||||
)
|
||||
primitive.modelMatrix = modelMatrix
|
||||
|
||||
// Cesium.Matrix4.setTranslation(
|
||||
// primitive.modelMatrix,
|
||||
// newPosition,
|
||||
// primitive.modelMatrix
|
||||
// )
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// console.log(viewer.scene.primitives._primitives)
|
||||
// // 获取模型的 Primitive 实例
|
||||
// const primitiveModel = viewer.scene.primitives._primitives.filter(
|
||||
// primitive => {
|
||||
// console.log(primitive, modelUrls)
|
||||
// return modelUrls.includes(primitive?._resource?.url)
|
||||
// }
|
||||
// )
|
||||
// console.log(primitiveModel)
|
||||
// 等待模型加载完成并调整其位置
|
||||
// viewer.scene.preRender.addEventListener(() => {
|
||||
// // 遍历场景中的所有 Primitive
|
||||
// viewer.scene.primitives._primitives.forEach(primitive => {
|
||||
// if (
|
||||
// primitive instanceof Cesium.Model && // 判断是否为 Model 类型
|
||||
// modelUrls.includes(primitive.uri) // 确保是我们需要的模型
|
||||
// ) {
|
||||
// // 获取 BoundingSphere 信息
|
||||
// const boundingSphere = primitive.boundingSphere
|
||||
// if (boundingSphere) {
|
||||
// // 计算模型底部到中心的偏移量
|
||||
// const bottomOffset = boundingSphere.radius
|
||||
|
||||
// // 获取模型当前的 Cartographic 坐标
|
||||
// const cartographic = Cesium.Cartographic.fromCartesian(
|
||||
// modelEntity.position
|
||||
// )
|
||||
|
||||
// // 调整高度,使模型底部贴地
|
||||
// const adjustedHeight = cartographic.height - bottomOffset
|
||||
// const newPosition = Cesium.Cartesian3.fromRadians(
|
||||
// cartographic.longitude,
|
||||
// cartographic.latitude,
|
||||
// adjustedHeight
|
||||
// )
|
||||
|
||||
// // 更新 Entity 的位置
|
||||
// modelEntity.position = newPosition
|
||||
|
||||
// // 删除监听器,防止重复调整
|
||||
// viewer.scene.preRender.removeEventListener(arguments.callee)
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
removeIds.forEach(id => {
|
||||
@ -109,13 +235,13 @@ function getAllKeys(treeData: any) {
|
||||
}
|
||||
|
||||
function addEntity(data: TBaseNode) {
|
||||
const { sheShiName, sheShiType, geom } = data
|
||||
const { id, sheShiName, sheShiType, geom } = data
|
||||
const pos = parseWKT(geom).coordinates
|
||||
const color = Cesium.Color.fromCssColorString(
|
||||
window.settings.baseMBDict[sheShiType].color
|
||||
)
|
||||
const entity = viewer.entities.add({
|
||||
name: sheShiName,
|
||||
name: id,
|
||||
position: Cesium.Cartesian3.fromDegrees(...pos),
|
||||
label: {
|
||||
text: `${sheShiName}`,
|
||||
@ -135,6 +261,7 @@ function addEntity(data: TBaseNode) {
|
||||
scaleByDistance: new Cesium.NearFarScalar(7000000, 1.0, 18000000, 0.4),
|
||||
},
|
||||
billboard: {
|
||||
show: !iconOrModel.value,
|
||||
image: window.settings.baseMBDict[sheShiType].icon,
|
||||
width: 30,
|
||||
height: 30,
|
||||
@ -144,6 +271,13 @@ function addEntity(data: TBaseNode) {
|
||||
|
||||
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
},
|
||||
model: {
|
||||
show: iconOrModel.value,
|
||||
uri: window.settings.baseMBDict[sheShiType].model,
|
||||
scale: 30,
|
||||
minimumPixelSize: 30,
|
||||
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
|
||||
},
|
||||
})
|
||||
return entity
|
||||
}
|
||||
|
@ -19,7 +19,45 @@ export default defineComponent({
|
||||
tilingScheme: new Cesium[baseMapList[mapId].tilingScheme](),
|
||||
})
|
||||
)
|
||||
// modifyMap()
|
||||
}
|
||||
|
||||
function modifyMap() {
|
||||
// 获取地图影像图层
|
||||
let baseLayer = viewer.imageryLayers.get(0)
|
||||
//设置2个变量,用来判断是否进行颜色的翻转和过滤
|
||||
baseLayer.invertColor = true
|
||||
|
||||
baseLayer.filterRGB = [60, 145, 172] //[255,255,255] = > [0,50,100]
|
||||
// 更改底图着色器的代码
|
||||
const baseFragmentShader =
|
||||
viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources
|
||||
// console.log(baseFragmentShader);
|
||||
|
||||
// 循环修改着色器
|
||||
// for (let i = 0; i < baseFragmentShader.length; i++) {
|
||||
// console.log(baseFragmentShader[i]);
|
||||
const strS = 'color = czm_saturation(color, textureSaturation);\n#endif\n'
|
||||
let strT = 'color = czm_saturation(color, textureSaturation);\n#endif\n'
|
||||
if (baseLayer.invertColor) {
|
||||
strT += `
|
||||
color.r = 1.0 - color.r;
|
||||
color.g = 1.0 - color.g;
|
||||
color.b = 1.0 - color.b;
|
||||
`
|
||||
}
|
||||
if (baseLayer.filterRGB) {
|
||||
strT += `
|
||||
color.r = color.r*${baseLayer.filterRGB[0]}.0/255.0;
|
||||
color.g = color.g*${baseLayer.filterRGB[1]}.0/255.0;
|
||||
color.b = color.b*${baseLayer.filterRGB[2]}.0/255.0;
|
||||
`
|
||||
}
|
||||
|
||||
baseFragmentShader[2] = baseFragmentShader[2].replace(strS, strT)
|
||||
// }
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
changeMap(Object.keys(baseMapList)[2])
|
||||
})
|
||||
|
@ -15,6 +15,8 @@ import MultiHisTrajectory from '../Mubiao/components/MultiHisTrajectory/index.vu
|
||||
import YsHangjing from '../YsHangjing/index.vue'
|
||||
|
||||
import TextMessage from '../TextReport/components/Message'
|
||||
|
||||
import Daodan from '../Daodan'
|
||||
// import HeatMap from '../Mubiao/components/HeatMap/index.vue'
|
||||
|
||||
// import TextDetailModal from '../TextReport/components/DetailsModal/index.vue'
|
||||
@ -22,6 +24,7 @@ import { useTextReport } from '../TextReport/hooks/text'
|
||||
import { useHisImage } from '../BaseMB/components/HisImages/hooks/hisImage'
|
||||
import { useMBTrajectory } from '../Mubiao/components/HisTrajectory/hooks/mbTraj'
|
||||
import { useMultiMBTrajectory } from '../Mubiao/components/MultiHisTrajectory/hooks/multiMbTraj'
|
||||
import { useDaodan } from '../Daodan/daodan'
|
||||
// import { useWeather } from '../Weather/hooks/weather'
|
||||
import DetailsModal from './components/DetailsModal/index.vue'
|
||||
|
||||
@ -30,6 +33,7 @@ const { getTextConfigs, initWebSocket } = useTextReport()
|
||||
const { showHisImageCom } = useHisImage()
|
||||
const { showHisTrajCom } = useMBTrajectory()
|
||||
const { showMultiHisTrajCom } = useMultiMBTrajectory()
|
||||
const { showDdConfigCom } = useDaodan()
|
||||
const getConfig = async () => {
|
||||
const res = await getTextConfigs()
|
||||
// console.log(res)
|
||||
@ -122,9 +126,17 @@ const showOrHideTextReport = () => {
|
||||
|
||||
<div class="grid flex-1 grid-cols-[1.5fr_3fr_1.5fr] grid-rows-1 gap-1">
|
||||
<div class="left-panel pl-8">
|
||||
<div class="radio-group absolute -left-4 top-[15%] z-30 flex w-12 translate-y-[-50%] transform flex-col">
|
||||
<div
|
||||
class="radio-group absolute -left-4 top-[15%] z-30 flex w-12 translate-y-[-50%] transform flex-col"
|
||||
>
|
||||
<template v-for="panel in panelList" :key="panel.id">
|
||||
<input type="radio" :id="panel.id" name="selector" v-model="showPanelName" :value="panel.value" />
|
||||
<input
|
||||
type="radio"
|
||||
:id="panel.id"
|
||||
name="selector"
|
||||
v-model="showPanelName"
|
||||
:value="panel.value"
|
||||
/>
|
||||
<label for="wx" @click="hidePanel($event, panel.value)">{{
|
||||
panel.name
|
||||
}}</label>
|
||||
@ -179,10 +191,21 @@ const showOrHideTextReport = () => {
|
||||
</div>
|
||||
<!-- <div class="z-20 grid grid-cols-1 grid-rows-3 gap-1"> -->
|
||||
<div>
|
||||
<div class="btn-transform z-20 w-h-full" :class="showTextReport ? '' : 'btn-transform-pos'">
|
||||
<n-button class="absolute -left-[16px] top-5 z-30 border border-[#29baf1] bg-[var(--color-bg)]" size="tiny"
|
||||
@click="showOrHideTextReport">
|
||||
<n-icon class="btn-transform" :class="showTextReport ? '' : 'icon-transform'"><arrow-right /></n-icon>
|
||||
<div
|
||||
class="btn-transform z-20 w-h-full"
|
||||
:class="showTextReport ? '' : 'btn-transform-pos'"
|
||||
>
|
||||
<n-button
|
||||
class="absolute -left-[16px] top-5 z-30 border border-[#29baf1] bg-[var(--color-bg)]"
|
||||
size="tiny"
|
||||
@click="showOrHideTextReport"
|
||||
>
|
||||
<n-icon
|
||||
class="btn-transform"
|
||||
:class="showTextReport ? '' : 'icon-transform'"
|
||||
>
|
||||
<arrow-right />
|
||||
</n-icon>
|
||||
</n-button>
|
||||
<!-- <transition name="slide2">.slice(0, 3) -->
|
||||
<panel title="文字报"><text-report :tabs="types" /></panel>
|
||||
@ -200,11 +223,23 @@ const showOrHideTextReport = () => {
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute bottom-0 flex h-full w-full flex-col justify-end">
|
||||
<text-message class="absolute z-30 h-[200px]"></text-message>
|
||||
<mubiao-his-trajectory v-if="showHisTrajCom" class="z-30 h-[260px]"></mubiao-his-trajectory>
|
||||
<multi-his-trajectory v-if="showMultiHisTrajCom" class="z-30 h-[260px]"></multi-his-trajectory>
|
||||
<his-images v-if="showHisImageCom" class="z-30 h-[260px]"></his-images>
|
||||
<div
|
||||
class="absolute bottom-0 flex h-full w-full flex-col items-center justify-end"
|
||||
>
|
||||
<text-message class="absolute z-30 h-[200px] w-full"></text-message>
|
||||
<mubiao-his-trajectory
|
||||
v-if="showHisTrajCom"
|
||||
class="z-30 h-[260px] w-full"
|
||||
></mubiao-his-trajectory>
|
||||
<multi-his-trajectory
|
||||
v-if="showMultiHisTrajCom"
|
||||
class="z-30 h-[260px] w-full"
|
||||
></multi-his-trajectory>
|
||||
<his-images
|
||||
v-if="showHisImageCom"
|
||||
class="z-30 h-[260px] w-full"
|
||||
></his-images>
|
||||
<daodan v-show="showDdConfigCom" class="z-30 h-[75%] w-[75%]"></daodan>
|
||||
</div>
|
||||
<details-modal></details-modal>
|
||||
</div>
|
||||
@ -373,4 +408,5 @@ const showOrHideTextReport = () => {
|
||||
// // background: var(--gradient-bg);
|
||||
// // background-clip: text;
|
||||
// }
|
||||
// }</style>
|
||||
// }
|
||||
</style>
|
||||
|
129
src/views/Daodan/components/TrajTable.jsx
Normal file
129
src/views/Daodan/components/TrajTable.jsx
Normal file
@ -0,0 +1,129 @@
|
||||
import {
|
||||
NInputNumber,
|
||||
NDataTable,
|
||||
NButton,
|
||||
NDatePicker,
|
||||
NSwitch,
|
||||
NIcon,
|
||||
} from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TrajTable',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { data: trajData } = toRefs(props)
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '',
|
||||
key: 'name',
|
||||
render(row) {
|
||||
return (
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div>{row.name} </div>
|
||||
<NButton
|
||||
// quaternary
|
||||
// type="primary"
|
||||
size="tiny"
|
||||
v-slots={{
|
||||
icon: () => (
|
||||
<NIcon size="14">
|
||||
<svg
|
||||
t="1737444618400"
|
||||
class="icon"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="2312"
|
||||
width="64"
|
||||
height="64"
|
||||
>
|
||||
<path
|
||||
d="M512 42.688c23.616 0 42.688 19.072 42.688 42.624v31.488c0 32.32 24.32 58.88 55.296 68.16a342.08 342.08 0 0 1 229.12 229.12c9.216 30.912 35.84 55.232 68.096 55.232h31.488a42.688 42.688 0 0 1 0 85.376h-31.488c-32.256 0-58.88 24.32-68.096 55.232a342.08 342.08 0 0 1-229.12 229.12c-30.976 9.28-55.232 35.84-55.296 68.16v31.488a42.688 42.688 0 0 1-85.312 0v-31.488c0-32.256-24.32-58.88-55.296-68.096a342.08 342.08 0 0 1-229.12-229.12c-9.28-30.976-35.84-55.296-68.096-55.296h-31.488a42.688 42.688 0 0 1 0-85.376h31.424c32.32 0 58.88-24.32 68.16-55.232a342.08 342.08 0 0 1 229.12-229.12c30.976-9.28 55.296-35.84 55.296-68.16v-31.424c0-23.616 19.072-42.688 42.624-42.688zM512 256a256 256 0 1 0 0 512 256 256 0 0 0 0-512z m0 170.688a85.312 85.312 0 1 1 0 170.624 85.312 85.312 0 0 1 0-170.624z"
|
||||
p-id="2313"
|
||||
></path>
|
||||
</svg>
|
||||
</NIcon>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '经度',
|
||||
key: 'lon',
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.lon}
|
||||
max={180}
|
||||
min={-180}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '纬度',
|
||||
key: 'lat',
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.lat}
|
||||
max={90}
|
||||
min={-90}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '高度',
|
||||
key: 'alt',
|
||||
render(row) {
|
||||
return <NInputNumber v-model:value={row.alt} min={0}></NInputNumber>
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '时间',
|
||||
key: 'time',
|
||||
render(row) {
|
||||
return (
|
||||
<NDatePicker v-model:value={row.time} type="datetime"></NDatePicker>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '助推器脱落',
|
||||
key: 'detached',
|
||||
render(row, rowIndex) {
|
||||
return rowIndex !== 0 && rowIndex < trajData.value.length - 1 ? (
|
||||
<NSwitch v-model:value={row.detached} type="datetime"></NSwitch>
|
||||
) : (
|
||||
'-'
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
return () => (
|
||||
<>
|
||||
<div class="flex justify-between">
|
||||
<div class="detail-item-title">{props.title}</div>
|
||||
<NButton quaternary type="primary">
|
||||
添加特征点
|
||||
</NButton>
|
||||
</div>
|
||||
<NDataTable data={trajData.value} columns={columns} />
|
||||
</>
|
||||
)
|
||||
},
|
||||
})
|
24
src/views/Daodan/components/TrajUpload.jsx
Normal file
24
src/views/Daodan/components/TrajUpload.jsx
Normal file
@ -0,0 +1,24 @@
|
||||
import { NUpload, NButton } from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TrajUpload',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
return () => (
|
||||
<>
|
||||
<div class="detail-item-title">{props.title}</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-[80px]">STK 文件</div>
|
||||
<NUpload action="https://www.mocky.io/v2/5e4bafc63100007100d8b70f">
|
||||
<NButton>上传文件</NButton>
|
||||
</NUpload>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
},
|
||||
})
|
16
src/views/Daodan/daodan.jsx
Normal file
16
src/views/Daodan/daodan.jsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
const daodanData = ref({})
|
||||
export function useDaodan() {
|
||||
return {
|
||||
showDdConfigCom,
|
||||
showOrHideDdConfig,
|
||||
daodanData,
|
||||
}
|
||||
}
|
||||
|
||||
const showDdConfigCom = ref(false)
|
||||
function showOrHideDdConfig(data) {
|
||||
daodanData.value = data
|
||||
showDdConfigCom.value = !showDdConfigCom.value
|
||||
}
|
87
src/views/Daodan/index.jsx
Normal file
87
src/views/Daodan/index.jsx
Normal file
@ -0,0 +1,87 @@
|
||||
import { NTabs, NTabPane, NButton, NScrollbar } from 'naive-ui'
|
||||
import TrajTable from './components/TrajTable'
|
||||
import TrajUpload from './components/TrajUpload'
|
||||
import Panel from '@/components/Panel/index.vue'
|
||||
import { useDaodan } from './daodan'
|
||||
|
||||
const panels = ['手动配置', 'STK轨迹文件配置']
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const { daodanData, showOrHideDdConfig } = useDaodan()
|
||||
const name = ref('手动配置')
|
||||
|
||||
const data = ref([
|
||||
{
|
||||
name: '起始点',
|
||||
lon: 120,
|
||||
lat: 21,
|
||||
alt: 0,
|
||||
time: 1183135260000,
|
||||
},
|
||||
{
|
||||
name: '中间特征点',
|
||||
lon: 120,
|
||||
lat: 21,
|
||||
alt: 0,
|
||||
time: 1183135260000,
|
||||
detached: false,
|
||||
},
|
||||
{
|
||||
name: '落点',
|
||||
lon: 120,
|
||||
lat: 21,
|
||||
alt: 0,
|
||||
time: 1183135260000,
|
||||
},
|
||||
])
|
||||
const handleClose = () => {}
|
||||
return () => (
|
||||
<div>
|
||||
<Panel title={`${daodanData.value.targetName}配置`}>
|
||||
<div class="flex h-full w-full flex-col gap-2 p-2">
|
||||
<NTabs
|
||||
class="flex h-[calc(100%-42px)] flex-col"
|
||||
v-model:value={name.value}
|
||||
type="card"
|
||||
tab-style="min-width: 80px;"
|
||||
onClose={handleClose}
|
||||
>
|
||||
{panels.map(panel => (
|
||||
<NTabPane
|
||||
class="flex-1 overflow-y-auto rounded-b-[var(--n-tab-border-radius)] border border-[var(--n-tab-border-color)] border-t-transparent"
|
||||
key={panel}
|
||||
tab={panel}
|
||||
name={panel}
|
||||
>
|
||||
<NScrollbar>
|
||||
<div class="px-4 pb-4">
|
||||
<div class="detail-container">
|
||||
{panel === '手动配置' ? (
|
||||
<>
|
||||
<TrajTable title="轨迹点" data={data.value} />
|
||||
<TrajTable title="拦截弹" data={data.value} />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<TrajUpload title="轨迹点" />
|
||||
<TrajUpload title="拦截弹" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</NScrollbar>
|
||||
</NTabPane>
|
||||
))}
|
||||
</NTabs>
|
||||
<div class="flex justify-end gap-2">
|
||||
<NButton type="primary" onClick={() => showOrHideDdConfig({})}>
|
||||
确认
|
||||
</NButton>
|
||||
<NButton onClick={() => showOrHideDdConfig({})}>取消</NButton>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
@ -52,18 +52,18 @@ onMounted(async () => {
|
||||
viewer.scene.postProcessStages.fxaa.enabled = true
|
||||
viewer.scene.skyBox = new Cesium.SkyBox({
|
||||
sources: {
|
||||
// positiveX: 'GV/resources/theme/skyBox/PositiveX.jpg',
|
||||
// negativeX: 'GV/resources/theme/skyBox/NegativeX.jpg',
|
||||
// positiveY: 'GV/resources/theme/skyBox/PositiveY.jpg',
|
||||
// negativeY: 'GV/resources/theme/skyBox/NegativeY.jpg',
|
||||
// positiveZ: 'GV/resources/theme/skyBox/PositiveZ.jpg',
|
||||
// negativeZ: 'GV/resources/theme/skyBox/NegativeZ.jpg',
|
||||
positiveX: './images/skybox/skyCube2k_px.jpg',
|
||||
negativeX: './images/skybox/skyCube2k_mx.jpg',
|
||||
positiveY: './images/skybox/skyCube2k_py.jpg',
|
||||
negativeY: './images/skybox/skyCube2k_my.jpg',
|
||||
positiveZ: './images/skybox/skyCube2k_pz.jpg',
|
||||
negativeZ: './images/skybox/skyCube2k_mz.jpg',
|
||||
positiveX: 'GV/resources/theme/skyBox/PositiveX.jpg',
|
||||
negativeX: 'GV/resources/theme/skyBox/NegativeX.jpg',
|
||||
positiveY: 'GV/resources/theme/skyBox/PositiveY.jpg',
|
||||
negativeY: 'GV/resources/theme/skyBox/NegativeY.jpg',
|
||||
positiveZ: 'GV/resources/theme/skyBox/PositiveZ.jpg',
|
||||
negativeZ: 'GV/resources/theme/skyBox/NegativeZ.jpg',
|
||||
// positiveX: './images/skybox/skyCube2k_px.jpg',
|
||||
// negativeX: './images/skybox/skyCube2k_mx.jpg',
|
||||
// positiveY: './images/skybox/skyCube2k_py.jpg',
|
||||
// negativeY: './images/skybox/skyCube2k_my.jpg',
|
||||
// positiveZ: './images/skybox/skyCube2k_pz.jpg',
|
||||
// negativeZ: './images/skybox/skyCube2k_mz.jpg',
|
||||
},
|
||||
})
|
||||
|
||||
@ -118,9 +118,3 @@ onMounted(async () => {
|
||||
class="absolute bottom-0 left-0 right-0 top-0"
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.cesium-widget-credits {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -2,6 +2,8 @@ import { difference } from 'lodash'
|
||||
import { useWebSocket } from '@vueuse/core'
|
||||
import { useTree } from '@/utils/tree'
|
||||
import { useHjPolygon } from './hangjingPolygon'
|
||||
import { getHangjing } from '@/api/Hangjing'
|
||||
|
||||
interface IPolygonData {
|
||||
id: string
|
||||
position: number[]
|
||||
@ -17,8 +19,8 @@ export const useHangjing = () => {
|
||||
onMounted(() => {
|
||||
initWebSocket()
|
||||
})
|
||||
const addHangjing = (ids, hangjingData) => {
|
||||
addHangjingPolygon(ids, hangjingData)
|
||||
const addHangjing = ids => {
|
||||
addHangjingPolygon(ids, hjTreeData)
|
||||
}
|
||||
|
||||
const removeHangjing = (id: string) => {
|
||||
@ -28,6 +30,15 @@ export const useHangjing = () => {
|
||||
return {
|
||||
addHangjing,
|
||||
removeHangjing,
|
||||
hjTreeData,
|
||||
isLoading,
|
||||
timeRange,
|
||||
searchTitle,
|
||||
type,
|
||||
searchHangjing,
|
||||
clearSelected,
|
||||
getHangjingData,
|
||||
checkedKeys,
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,3 +100,44 @@ const initWebSocket = () => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const hjTreeData = ref([])
|
||||
|
||||
const isLoading = ref(false)
|
||||
async function getHangjingData(params = {}) {
|
||||
isLoading.value = true
|
||||
const { code, data: resData } = await getHangjing(params)
|
||||
|
||||
if (code === '200') {
|
||||
hjTreeData.value = [resData]
|
||||
}
|
||||
isLoading.value = false
|
||||
}
|
||||
const timeRange = ref(null)
|
||||
|
||||
const searchTitle = ref('')
|
||||
|
||||
const type = ref<string>('')
|
||||
|
||||
async function searchHangjing(checked: string[]) {
|
||||
// handleCheck([])
|
||||
await getHangjingData({
|
||||
timeBegin: timeRange.value?.[0],
|
||||
timeEnd: timeRange.value?.[1],
|
||||
// wkt: drawnArea.value,
|
||||
hjType: type.value === '' ? null : type.value,
|
||||
title: searchTitle.value,
|
||||
})
|
||||
if (checked && checked.length > 0) {
|
||||
checkedKeys.value = checked
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelected() {
|
||||
timeRange.value = null
|
||||
type.value = ''
|
||||
searchTitle.value = ''
|
||||
searchHangjing()
|
||||
}
|
||||
|
||||
const checkedKeys = ref<Array<string | number>>([])
|
||||
|
@ -13,7 +13,7 @@ function renderDetailsContent(data) {
|
||||
<div class="detail-item-title">基本信息</div>
|
||||
<div>
|
||||
{Object.keys(data)
|
||||
.filter(key => key !== 'geom')
|
||||
.filter(key => !['geom', 'styleJsonData'].includes(key))
|
||||
.map(key => (
|
||||
<div>
|
||||
{key}:{data[key]}
|
||||
|
@ -4,8 +4,9 @@ import { parseWKT } from '@/utils/parseWKT'
|
||||
import { difference } from 'lodash'
|
||||
import { polygonGradient } from '@/js/polygonGradient'
|
||||
import { polygonMaterial } from '@/js/polygon'
|
||||
import { centerOfMass } from '@turf/turf'
|
||||
import { centerOfMass, midpoint, point } from '@turf/turf'
|
||||
import { useTree } from '@/utils/tree'
|
||||
import { cartesian32LonLat } from '@/utils/pos'
|
||||
|
||||
import { useHangjingPopup } from './hangjingPopup'
|
||||
|
||||
@ -34,12 +35,14 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
||||
params: addIds,
|
||||
paramName: 'dataId',
|
||||
})
|
||||
// console.log(nodes, 'nodes')
|
||||
nodes.forEach(({ data: hjData, dataId: id }) => {
|
||||
// const item = data.find(item => item.id === id)
|
||||
if (hjData) {
|
||||
if (hjData.zoneList.length > 0) {
|
||||
hjData.zoneList.forEach(zone => {
|
||||
addPolygon(zone, id)
|
||||
// console.log(zone, 'zone')
|
||||
addPolygon({ ...zone, styleJsonData: hjData.styleJsonData }, id)
|
||||
})
|
||||
} else {
|
||||
addPolygon(hjData)
|
||||
@ -49,7 +52,7 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
||||
}
|
||||
// 删除
|
||||
if (removeIds.length > 0) {
|
||||
console.log(removeIds, 'removeIds')
|
||||
// console.log(removeIds, 'removeIds')
|
||||
removeIds.forEach(id => {
|
||||
removeEventSub(polygonMap.get(id))
|
||||
removeHangjingPolygon(id)
|
||||
@ -58,13 +61,13 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
||||
}
|
||||
|
||||
function addPolygon(item, parentId: number | null = null) {
|
||||
const { id, geom, title } = item
|
||||
const { id, geom, title, styleJsonData } = item
|
||||
const feature = parseWKT(geom)
|
||||
const position = feature.coordinates[0].map(pos => {
|
||||
return Cesium.Cartesian3.fromDegrees(...pos)
|
||||
})
|
||||
|
||||
const labels = addTextAlongCurve('Cesium中文垂直排列测试', position)
|
||||
// const labels = addTextAlongCurve('Cesium中文垂直排列测试', position)
|
||||
|
||||
// console.log(item, id, position, 'id, position, color')
|
||||
// const randomColor =
|
||||
@ -86,10 +89,13 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
||||
}
|
||||
const color = colors.get(curId)
|
||||
|
||||
const style = JSON.parse(styleJsonData || '{}')
|
||||
const polygon = addPrimitivePolygon({
|
||||
id,
|
||||
title,
|
||||
color: color,
|
||||
position,
|
||||
style,
|
||||
})
|
||||
|
||||
const centerPoint = centerOfMass(feature).geometry.coordinates
|
||||
@ -117,12 +123,21 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
||||
|
||||
function addPolygonCenter(centerPoint: number[]) {
|
||||
return viewer.entities.add({
|
||||
show: false,
|
||||
show: true,
|
||||
position: Cesium.Cartesian3.fromDegrees(...centerPoint),
|
||||
point: {
|
||||
pixelSize: 10,
|
||||
color: Cesium.Color.RED,
|
||||
},
|
||||
label: {
|
||||
text: centerPoint.toString(),
|
||||
font: '14px sans-serif',
|
||||
fillColor: Cesium.Color.RED,
|
||||
outlineColor: Cesium.Color.BLACK,
|
||||
outlineWidth: 2,
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
pixelOffset: new Cesium.Cartesian2(0, -20),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -130,11 +145,24 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
||||
id,
|
||||
position,
|
||||
color,
|
||||
style,
|
||||
title,
|
||||
}: {
|
||||
id: string
|
||||
position: Cesium.Cartesian3[]
|
||||
color: string
|
||||
style: Record<string, string | number>
|
||||
title: string
|
||||
}): Cesium.Primitive {
|
||||
const {
|
||||
fontFamily,
|
||||
fontSize,
|
||||
textColor,
|
||||
polygonColor,
|
||||
lineColor,
|
||||
lineWidth,
|
||||
lineType,
|
||||
} = style
|
||||
// const polygonOptions = {
|
||||
// extrudedHeight: 5000,
|
||||
// polygonHierarchy: new Cesium.PolygonHierarchy(position),
|
||||
@ -156,17 +184,37 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
||||
// }),
|
||||
// })
|
||||
// return viewer.scene.primitives.add(primitive)
|
||||
|
||||
const lineMaterial = Cesium.Color.fromCssColorString(
|
||||
lineColor || 'rgba(255,0,0,1)'
|
||||
)
|
||||
return viewer.entities.add({
|
||||
id,
|
||||
position: findNorthernMostPoint(position),
|
||||
label: {
|
||||
show: true,
|
||||
text: title,
|
||||
font: `${fontSize || 14}px ${fontFamily || '微软雅黑'}`,
|
||||
fillColor: Cesium.Color.fromCssColorString(
|
||||
textColor || 'rgba(255,255,0,1)'
|
||||
),
|
||||
pixelOffset: new Cesium.Cartesian2(0, -10),
|
||||
// outlineColor: Cesium.Color.BLACK,
|
||||
// outlineWidth: 2,
|
||||
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
},
|
||||
polyline: {
|
||||
positions: position,
|
||||
width: 1,
|
||||
material: Cesium.Color.RED,
|
||||
width: lineWidth || 1,
|
||||
material:
|
||||
lineType === 'dashed'
|
||||
? new Cesium.PolylineDashMaterialProperty({ color: lineMaterial })
|
||||
: lineMaterial,
|
||||
},
|
||||
polygon: {
|
||||
hierarchy: new Cesium.PolygonHierarchy(position),
|
||||
material: Cesium.Color.fromCssColorString(color),
|
||||
material: Cesium.Color.fromCssColorString(
|
||||
polygonColor || 'rgba(255,255,255,0.5)'
|
||||
),
|
||||
// material: polygonMaterial(color),
|
||||
// material: polygonGradient(color),
|
||||
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
||||
@ -225,120 +273,27 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
||||
}
|
||||
}
|
||||
|
||||
function addTextAlongCurve(text, polygonPoints) {
|
||||
// 创建 Billboard 集合
|
||||
const billboardCollection = viewer.scene.primitives.add(
|
||||
new Cesium.BillboardCollection()
|
||||
function findNorthernMostPoint(positions) {
|
||||
const cartographicPositions = positions.map(pos =>
|
||||
Cesium.Cartographic.fromCartesian(pos)
|
||||
)
|
||||
|
||||
// 创建文字绘制的辅助函数
|
||||
function createTextTexture(text, angle) {
|
||||
const canvas = document.createElement('canvas')
|
||||
const context = canvas.getContext('2d')
|
||||
|
||||
// 设置 Canvas 大小
|
||||
canvas.width = 20
|
||||
canvas.height = 20
|
||||
|
||||
// 设置文字样式
|
||||
context.font = '20px sans-serif' // 支持中文
|
||||
context.fillStyle = 'blue'
|
||||
context.textAlign = 'center'
|
||||
context.textBaseline = 'middle'
|
||||
|
||||
// 将文字绘制到 Canvas,并进行旋转
|
||||
context.clearRect(0, 0, canvas.width, canvas.height)
|
||||
context.save()
|
||||
|
||||
// 旋转文字
|
||||
context.translate(canvas.width / 2, canvas.height / 2)
|
||||
context.rotate(angle)
|
||||
context.fillText(text, 0, 0)
|
||||
|
||||
context.restore()
|
||||
|
||||
return canvas
|
||||
}
|
||||
|
||||
// 动态生成字符标注
|
||||
function generateLabels(cameraHeight) {
|
||||
billboardCollection.removeAll() // 清除之前的标注
|
||||
|
||||
let charIndex = 0 // 当前字符索引
|
||||
for (let i = 0; i < polygonPoints.length - 1; i++) {
|
||||
const start = polygonPoints[i] // 当前边的起点
|
||||
const end = polygonPoints[i + 1] // 当前边的终点
|
||||
|
||||
// 计算线段的方向向量
|
||||
const direction = Cesium.Cartesian3.subtract(
|
||||
end,
|
||||
start,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
Cesium.Cartesian3.normalize(direction, direction)
|
||||
|
||||
// 计算垂直于线段的方向向量
|
||||
const perpendicular = Cesium.Cartesian3.cross(
|
||||
direction,
|
||||
Cesium.Cartesian3.UNIT_Z, // 使用 Z 轴(垂直地球表面)计算垂直方向
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
Cesium.Cartesian3.normalize(perpendicular, perpendicular)
|
||||
|
||||
// 计算线段的长度
|
||||
const length = Cesium.Cartesian3.distance(start, end)
|
||||
|
||||
// 动态调整字符间隔,基于相机高度
|
||||
const baseSpacing = 50 // 基础字符间隔
|
||||
const charSpacing = Math.max((baseSpacing * cameraHeight) / 5000000, 30)
|
||||
|
||||
// 按字符间隔放置文字
|
||||
let distance = 0
|
||||
while (distance < length && charIndex < text.length) {
|
||||
// 计算字符的位置
|
||||
const fraction = distance / length // 当前字符在边上的位置比例
|
||||
const position = Cesium.Cartesian3.lerp(
|
||||
start,
|
||||
end,
|
||||
fraction,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
|
||||
// 计算旋转角度,使文字垂直于线段
|
||||
const angle = Math.atan2(perpendicular.y, perpendicular.x)
|
||||
|
||||
// 创建带旋转的文字纹理
|
||||
const canvas = createTextTexture(text[charIndex], angle)
|
||||
|
||||
// 添加 Billboard 显示文字
|
||||
billboardCollection.add({
|
||||
position: position,
|
||||
image: canvas, // 使用生成的文字纹理
|
||||
// pixelOffset: new Cesium.Cartesian2(10, 0),
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
})
|
||||
|
||||
// 更新字符索引和距离
|
||||
charIndex++
|
||||
console.log(charSpacing)
|
||||
distance += charSpacing * 2000
|
||||
// distance *= 2
|
||||
console.log(distance)
|
||||
}
|
||||
|
||||
// 如果字符已用完,跳出循环
|
||||
if (charIndex >= text.length) {
|
||||
break
|
||||
}
|
||||
let maxLatitude = -Infinity
|
||||
cartographicPositions.forEach(carto => {
|
||||
if (carto.latitude > maxLatitude) {
|
||||
maxLatitude = carto.latitude
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化标注(根据初始相机高度)
|
||||
generateLabels(viewer.camera.positionCartographic.height)
|
||||
|
||||
// 监听相机变化事件,动态更新字符间隔
|
||||
viewer.camera.changed.addEventListener(() => {
|
||||
const cameraHeight = viewer.camera.positionCartographic.height
|
||||
generateLabels(cameraHeight)
|
||||
})
|
||||
const northernMostPoints = cartographicPositions.filter(
|
||||
carto => carto.latitude.toFixed(15) === maxLatitude.toFixed(15)
|
||||
)
|
||||
const lat = Cesium.Math.toDegrees(northernMostPoints[0].latitude)
|
||||
const startLon = Cesium.Math.toDegrees(northernMostPoints[0].longitude)
|
||||
const endLon = Cesium.Math.toDegrees(
|
||||
northernMostPoints[
|
||||
northernMostPoints.length - (northernMostPoints.length > 2 ? 2 : 1)
|
||||
].longitude
|
||||
)
|
||||
const mid = midpoint(point([startLon, lat]), point([endLon, lat]))
|
||||
return Cesium.Cartesian3.fromDegrees(...mid.geometry.coordinates)
|
||||
}
|
||||
|
@ -7,23 +7,36 @@ import {
|
||||
NInputNumber,
|
||||
NButton,
|
||||
} from 'naive-ui'
|
||||
import { useHangjing } from './hangjing'
|
||||
import { updateHjStyle } from '@/api/hangjing'
|
||||
import { useModal } from '@/views/Content/hooks/modal'
|
||||
const { openDetailsModal } = useModal()
|
||||
|
||||
const styleForm = ref({
|
||||
fontFamily: '微软雅黑',
|
||||
fontSize: 14,
|
||||
textColor: 'rgba(255,255,0,1)',
|
||||
polygonColor: 'rgba(255,0,0,0.3)',
|
||||
lineColor: 'rgba(255,0,0,1)',
|
||||
lineWidth: 1,
|
||||
lineType: 'solid',
|
||||
})
|
||||
const styleForm = ref({})
|
||||
export const useHangjingStyle = () => {
|
||||
return { renderStyleContent, showStyleModal }
|
||||
}
|
||||
|
||||
function initStyle(data) {
|
||||
const { styleJsonData } = data
|
||||
const style = JSON.parse(styleJsonData || '{}')
|
||||
if (Object.keys(style).length > 0) {
|
||||
styleForm.value = style
|
||||
} else {
|
||||
styleForm.value = {
|
||||
fontFamily: '微软雅黑',
|
||||
fontSize: 14,
|
||||
textColor: 'rgba(255,255,0,1)',
|
||||
polygonColor: 'rgba(255,255,255,0.5)',
|
||||
lineColor: 'rgba(255,0,0,1)',
|
||||
lineWidth: 1,
|
||||
lineType: 'solid',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function renderStyleContent(data) {
|
||||
initStyle(data)
|
||||
return (
|
||||
<div class="flex flex-col gap-2 pt-4">
|
||||
<NForm
|
||||
@ -94,7 +107,7 @@ function renderStyleContent(data) {
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<div class="flex justify-end gap-2">
|
||||
<NButton type="primary" onClick={updateStyle}>
|
||||
<NButton type="primary" onClick={() => updateStyle(data)}>
|
||||
确定
|
||||
</NButton>
|
||||
<NButton onClick={updateStyle}>取消</NButton>
|
||||
@ -110,6 +123,22 @@ function showStyleModal(title, data) {
|
||||
})
|
||||
}
|
||||
|
||||
function updateStyle() {
|
||||
// TODO: 更新样式
|
||||
const { checkedKeys, searchHangjing } = useHangjing()
|
||||
|
||||
function updateStyle(data) {
|
||||
updateHjStyle({
|
||||
id: data.id,
|
||||
styleJsonData: JSON.stringify(styleForm.value),
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === '200') {
|
||||
window.$message.success('保存样式成功')
|
||||
const checkedBeforePut = JSON.parse(JSON.stringify(checkedKeys.value))
|
||||
checkedKeys.value = []
|
||||
searchHangjing(checkedBeforePut)
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
window.$message.error(`保存样式失败。${err}`)
|
||||
})
|
||||
}
|
||||
|
@ -12,10 +12,6 @@ import { useHangjingDetail } from './hooks/hangjingDetail'
|
||||
// import { useHangjingStyle } from './hooks/hangjingStyle'
|
||||
import Tree from '@/components/Tree/index.vue'
|
||||
|
||||
|
||||
|
||||
const timeRange = ref(null)
|
||||
|
||||
const rangeShortcuts = {
|
||||
近一天: () => {
|
||||
const cur = new Date().getTime()
|
||||
@ -35,9 +31,6 @@ const rangeShortcuts = {
|
||||
},
|
||||
}
|
||||
|
||||
const searchTitle = ref('')
|
||||
|
||||
const type = ref<string>('')
|
||||
const typeOptions = [
|
||||
{
|
||||
label: '全',
|
||||
@ -102,86 +95,69 @@ const drawArea = () => {
|
||||
}
|
||||
|
||||
const { showDetailsModal } = useHangjingDetail()
|
||||
// const { showStyleModal } = useHangjingStyle()
|
||||
|
||||
const data = ref([])
|
||||
|
||||
const renderSuffix = ({ option }: { option: TreeOption }) => {
|
||||
return option.data ? h('div', { class: 'flex items-center gap-2 pr-2' }, [
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
size: 'tiny',
|
||||
type: 'info',
|
||||
onClick: () => showDetailsModal(`${option.data.title}详情`, option.data),
|
||||
},
|
||||
{ default: () => '详情' }
|
||||
),
|
||||
// h(
|
||||
// NButton,
|
||||
// {
|
||||
// text: true,
|
||||
// size: 'tiny',
|
||||
// type: 'info',
|
||||
// onClick: () => showStyleModal(`${option.data.title}样式配置`, option.data),
|
||||
// },
|
||||
// { default: () => '样式配置' }
|
||||
// ),
|
||||
]) : null
|
||||
return option.data
|
||||
? h('div', { class: 'flex items-center gap-2 pr-2' }, [
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
size: 'tiny',
|
||||
type: 'info',
|
||||
onClick: () =>
|
||||
showDetailsModal(`${option.data.title}详情`, option.data),
|
||||
},
|
||||
{ default: () => '详情' }
|
||||
),
|
||||
// h(
|
||||
// NButton,
|
||||
// {
|
||||
// text: true,
|
||||
// size: 'tiny',
|
||||
// type: 'info',
|
||||
// onClick: () => showStyleModal(`${option.data.title}样式配置`, option.data),
|
||||
// },
|
||||
// { default: () => '样式配置' }
|
||||
// ),
|
||||
])
|
||||
: null
|
||||
}
|
||||
|
||||
const checkedKeys = ref<Array<string | number>>([])
|
||||
// const checkedKeys = ref<Array<string | number>>([])
|
||||
|
||||
const { addHangjing } = useHangjing()
|
||||
const {
|
||||
addHangjing,
|
||||
hjTreeData,
|
||||
isLoading,
|
||||
timeRange,
|
||||
searchTitle,
|
||||
type,
|
||||
searchHangjing,
|
||||
clearSelected,
|
||||
getHangjingData,
|
||||
checkedKeys,
|
||||
} = useHangjing()
|
||||
|
||||
watch(checkedKeys, val => {
|
||||
addHangjing(val, data)
|
||||
addHangjing(val)
|
||||
})
|
||||
|
||||
const handleCheck = (rowKeys: DataTableRowKey[]) => {
|
||||
const selectedList = data.value.filter(item => rowKeys.includes(item.id))
|
||||
addHangjing(selectedList)
|
||||
}
|
||||
|
||||
const isLoading = ref(false)
|
||||
const getHangjingData = async (params = {}) => {
|
||||
isLoading.value = true
|
||||
const { code, data: resData } = await getHangjing(params)
|
||||
|
||||
if (code === '200') {
|
||||
data.value = [resData]
|
||||
}
|
||||
isLoading.value = false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getHangjingData()
|
||||
})
|
||||
|
||||
const searchHangjing = () => {
|
||||
handleCheck([])
|
||||
getHangjingData({
|
||||
timeBegin: timeRange.value?.[0],
|
||||
timeEnd: timeRange.value?.[1],
|
||||
wkt: drawnArea.value,
|
||||
hjType: type.value === '' ? null : type.value,
|
||||
title: searchTitle.value,
|
||||
})
|
||||
}
|
||||
|
||||
const clearSelected = () => {
|
||||
timeRange.value = null
|
||||
type.value = ''
|
||||
searchTitle.value = ''
|
||||
searchHangjing()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-2 w-h-full" v-loading="isLoading">
|
||||
<n-date-picker v-model:formatted-value="timeRange" clearable type="datetimerange" :shortcuts="rangeShortcuts"
|
||||
:update-value-on-close="true" format="yyyy-MM-dd HH:mm:ss" />
|
||||
<n-date-picker
|
||||
v-model:formatted-value="timeRange"
|
||||
clearable
|
||||
type="datetimerange"
|
||||
:shortcuts="rangeShortcuts"
|
||||
:update-value-on-close="true"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
/>
|
||||
<div class="flex gap-2">
|
||||
<n-input class="w-auto" v-model:value="searchTitle" />
|
||||
<n-select class="w-40" v-model:value="type" :options="typeOptions" />
|
||||
@ -213,8 +189,14 @@ const clearSelected = () => {
|
||||
flex-height @update:checked-row-keys="handleCheck" /> -->
|
||||
<!-- :pagination="paginationReactive" -->
|
||||
|
||||
<tree :data="data" :key-field="'dataId'" :label-field="'nodeName'" v-model:checked="checkedKeys" showSearch
|
||||
:renderSuffix="renderSuffix" />
|
||||
<tree
|
||||
:data="hjTreeData"
|
||||
:key-field="'dataId'"
|
||||
:label-field="'nodeName'"
|
||||
v-model:checked="checkedKeys"
|
||||
showSearch
|
||||
:renderSuffix="renderSuffix"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1,86 +1,14 @@
|
||||
// import { h } from 'vue'
|
||||
import { NDataTable, NInputNumber, NSwitch } from 'naive-ui'
|
||||
import { useModal } from '@/views/Content/hooks/modal'
|
||||
import Detection from '@/views/Payload/Detection.jsx'
|
||||
import Communication from '@/views/Payload/Communication.jsx'
|
||||
|
||||
const { openDetailsModal } = useModal()
|
||||
export const useMubiaoDetail = () => {
|
||||
return { showDetailsMubiao }
|
||||
}
|
||||
|
||||
const detectingLoadColumns = [
|
||||
{
|
||||
title: '垂直起始角',
|
||||
key: 'minimumClock',
|
||||
width: 180,
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.minimumClock}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: '垂直终止角',
|
||||
// key: 'maximumClock',
|
||||
// width: 180,
|
||||
// render(row) {
|
||||
// return (
|
||||
// <NInputNumber
|
||||
// v-model:value={row.maximumClock}
|
||||
// // disabled={['光学', '雷达'].includes(row.type)}
|
||||
// ></NInputNumber>
|
||||
// )
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: '水平起始角',
|
||||
key: 'minimumCone',
|
||||
width: 180,
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.minimumCone}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '水平终止角',
|
||||
key: 'maximumCone',
|
||||
width: 180,
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.maximumCone}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '半径',
|
||||
key: 'radius',
|
||||
width: 180,
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.radius}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '是否开启',
|
||||
key: 'status',
|
||||
render(row) {
|
||||
return <NSwitch v-model:value={row.status}></NSwitch>
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const data = ref([
|
||||
{
|
||||
id: 3,
|
||||
@ -111,11 +39,7 @@ function renderMubiaoDetailsContent(mbData) {
|
||||
))}
|
||||
</div>
|
||||
<div class="detail-item-title">探测载荷</div>
|
||||
<NDataTable
|
||||
key={row => row.id}
|
||||
columns={detectingLoadColumns}
|
||||
data={data.value}
|
||||
/>
|
||||
<Detection type="radar" data={data.value} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import { useMuBiaoPositionWS } from './hooks/mubiaoPos'
|
||||
import { useMuBiaoDisappearWS } from './hooks/mubiaoDisappear'
|
||||
import { useMubiaoDetail } from './hooks/mubiaoDetail'
|
||||
import { useMBTrajectory } from './components/HisTrajectory/hooks/mbTraj'
|
||||
import { useDaodan } from '../Daodan/daodan'
|
||||
|
||||
const { addMubiao, data } = useMubiao()
|
||||
const useMbPosWS = useMuBiaoPositionWS()
|
||||
@ -37,30 +38,35 @@ watch(checkedKeys, val => {
|
||||
|
||||
const { showDetailsMubiao } = useMubiaoDetail()
|
||||
const { showOrHideHisTraj } = useMBTrajectory()
|
||||
const { showOrHideDdConfig } = useDaodan()
|
||||
const renderSuffix = ({ option }: { option: TreeOption }) => {
|
||||
// console.log(option.data)
|
||||
return option.data
|
||||
? h('div', { class: 'flex items-center gap-2 pr-2' }, [
|
||||
if (!option.data) {
|
||||
return undefined
|
||||
}
|
||||
return h('div', { class: 'flex items-center gap-2 pr-2' }, [
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
size: 'tiny',
|
||||
type: 'info',
|
||||
onClick: () => showDetailsMubiao(option.data),
|
||||
},
|
||||
{ default: () => '详情' }
|
||||
),
|
||||
option.data.targetType === '丙' &&
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
size: 'tiny',
|
||||
type: 'info',
|
||||
onClick: () => showDetailsMubiao(option.data),
|
||||
onClick: () => showOrHideDdConfig(option.data),
|
||||
},
|
||||
{ default: () => '详情' }
|
||||
{ default: () => '试验配置' }
|
||||
),
|
||||
// h(
|
||||
// NButton,
|
||||
// {
|
||||
// text: true,
|
||||
// size: 'tiny',
|
||||
// type: 'info',
|
||||
// onClick: () => showDetailsMubiao(option.data),
|
||||
// },
|
||||
// { default: () => '载荷' }
|
||||
// ),
|
||||
option.data.targetType !== '丙' &&
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
@ -71,8 +77,7 @@ const renderSuffix = ({ option }: { option: TreeOption }) => {
|
||||
},
|
||||
{ default: () => '轨迹回放' }
|
||||
),
|
||||
])
|
||||
: undefined
|
||||
])
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -99,8 +104,14 @@ const renderSuffix = ({ option }: { option: TreeOption }) => {
|
||||
@update:checked-row-keys="handleCheck"
|
||||
/> -->
|
||||
<div class="h-0 flex-1">
|
||||
<tree :data="data" :key-field="'dataId'" :label-field="'nodeName'" v-model:checked="checkedKeys" showSearch
|
||||
:renderSuffix="renderSuffix" />
|
||||
<tree
|
||||
:data="data"
|
||||
:key-field="'dataId'"
|
||||
:label-field="'nodeName'"
|
||||
v-model:checked="checkedKeys"
|
||||
showSearch
|
||||
:renderSuffix="renderSuffix"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- :nodeProps="nodeProps" -->
|
||||
|
44
src/views/Payload/Communication.jsx
Normal file
44
src/views/Payload/Communication.jsx
Normal file
@ -0,0 +1,44 @@
|
||||
import { NDataTable, NButton, NSelect, NInputNumber, NSwitch } from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DetectionPayload',
|
||||
props: {},
|
||||
setup(props) {
|
||||
const communicationPayloadColumns = [
|
||||
{
|
||||
title: '通信对象',
|
||||
key: 'target',
|
||||
render(row) {
|
||||
return (
|
||||
<NSelect
|
||||
v-model:value={row.target}
|
||||
options={[{ label: '3', value: '3' }]}
|
||||
></NSelect>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '是否开启',
|
||||
key: 'status',
|
||||
width: 120,
|
||||
render(row) {
|
||||
return <NSwitch v-model:value={row.status}></NSwitch>
|
||||
},
|
||||
},
|
||||
]
|
||||
const communicationPayload = ref([
|
||||
{
|
||||
id: 3,
|
||||
target: '3',
|
||||
status: true,
|
||||
},
|
||||
])
|
||||
return () => (
|
||||
<NDataTable
|
||||
key={row => row.id}
|
||||
columns={communicationPayloadColumns}
|
||||
data={communicationPayload.value}
|
||||
/>
|
||||
)
|
||||
},
|
||||
})
|
172
src/views/Payload/Detection.jsx
Normal file
172
src/views/Payload/Detection.jsx
Normal file
@ -0,0 +1,172 @@
|
||||
import { NDataTable, NButton, NSelect, NInputNumber, NSwitch } from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DetectionPayload',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'radar',
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const detectingPayloadColumns = {
|
||||
radar: [
|
||||
{
|
||||
title: '垂直起始角',
|
||||
key: 'minimumClock',
|
||||
width: 180,
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.minimumClock}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: '垂直终止角',
|
||||
// key: 'maximumClock',
|
||||
// width: 180,
|
||||
// render(row) {
|
||||
// return (
|
||||
// <NInputNumber
|
||||
// v-model:value={row.maximumClock}
|
||||
// // disabled={['光学', '雷达'].includes(row.type)}
|
||||
// ></NInputNumber>
|
||||
// )
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: '水平起始角',
|
||||
key: 'minimumCone',
|
||||
width: 180,
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.minimumCone}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '水平终止角',
|
||||
key: 'maximumCone',
|
||||
width: 180,
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.maximumCone}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '半径',
|
||||
key: 'radius',
|
||||
width: 180,
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.radius}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '是否开启',
|
||||
key: 'status',
|
||||
width: 120,
|
||||
render(row) {
|
||||
return <NSwitch v-model:value={row.status}></NSwitch>
|
||||
},
|
||||
},
|
||||
],
|
||||
corner: [
|
||||
// {
|
||||
// title: '载荷类型',
|
||||
// key: 'type',
|
||||
// render(row) {
|
||||
// return (
|
||||
// <NSelect
|
||||
// v-model:value={row.type}
|
||||
// options={[
|
||||
// { label: '电子', value: '电子' },
|
||||
// { label: '雷达', value: '雷达' },
|
||||
// { label: '光学', value: '光学' },
|
||||
// ]}
|
||||
// ></NSelect>
|
||||
// )
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: '开合角',
|
||||
key: 'angle',
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.angle}
|
||||
max={120}
|
||||
min={0}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: '水平半角',
|
||||
// key: 'xHalfAngle',
|
||||
// width: 120,
|
||||
// render(row) {
|
||||
// return (
|
||||
// <NInputNumber
|
||||
// v-model:value={row.angle}
|
||||
// max={120}
|
||||
// min={0}
|
||||
// disabled={['电子'].includes(row.type)}
|
||||
// ></NInputNumber>
|
||||
// )
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: '垂直半角',
|
||||
// key: 'yHalfAngle',
|
||||
// width: 120,
|
||||
// render(row) {
|
||||
// return (
|
||||
// <NInputNumber
|
||||
// v-model:value={row.angle}
|
||||
// max={120}
|
||||
// min={0}
|
||||
// disabled={['电子'].includes(row.type)}
|
||||
// ></NInputNumber>
|
||||
// )
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: '是否开启',
|
||||
key: 'status',
|
||||
width: 120,
|
||||
render(row) {
|
||||
return <NSwitch v-model:value={row.status}></NSwitch>
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return () => (
|
||||
<NDataTable
|
||||
key={row => row.id}
|
||||
columns={detectingPayloadColumns[props.type]}
|
||||
data={props.data}
|
||||
/>
|
||||
)
|
||||
},
|
||||
})
|
152
src/views/PlaceName/hooks.jsx
Normal file
152
src/views/PlaceName/hooks.jsx
Normal file
@ -0,0 +1,152 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
let viewer = null
|
||||
const model = ref({
|
||||
name: null,
|
||||
lon: null,
|
||||
lat: null,
|
||||
level: null,
|
||||
})
|
||||
export function usePlaceName() {
|
||||
const showPlace = ref(true)
|
||||
function addPlaceName() {
|
||||
showPlace.value = !showPlace.value
|
||||
}
|
||||
|
||||
return {
|
||||
model,
|
||||
showPlace,
|
||||
addPlaceName,
|
||||
initViewer,
|
||||
clickPoint,
|
||||
}
|
||||
}
|
||||
|
||||
async function initViewer() {
|
||||
viewer = new Cesium.Viewer('place-earth', {
|
||||
selectionIndicator: false,
|
||||
animation: false,
|
||||
baseLayerPicker: false,
|
||||
// geocoder: false,
|
||||
timeline: false,
|
||||
sceneModePicker: false,
|
||||
navigationHelpButton: false,
|
||||
infoBox: false,
|
||||
fullscreenButton: false,
|
||||
homeButton: false,
|
||||
|
||||
imageryProvider: false,
|
||||
geocoder: new OpenStreetMapNominatimGeocoder(),
|
||||
// geocoder: new Cesium.CartographicGeocoderService(),
|
||||
})
|
||||
|
||||
viewer.scene.debugShowFramesPerSecond = true
|
||||
viewer.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(117.48, 30.67, 18000000.0),
|
||||
})
|
||||
|
||||
viewer.clock.shouldAnimate = true
|
||||
viewer.shadows = false
|
||||
// viewer.scene.globe.enableLighting = true
|
||||
|
||||
if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
|
||||
viewer.resolutionScale = window.devicePixelRatio
|
||||
}
|
||||
|
||||
// 开启抗锯齿
|
||||
// viewer.scene.fxaa = true
|
||||
viewer.scene.postProcessStages.fxaa.enabled = true
|
||||
viewer.scene.skyBox = new Cesium.SkyBox({
|
||||
sources: {
|
||||
positiveX: 'GV/resources/theme/skyBox/PositiveX.jpg',
|
||||
negativeX: 'GV/resources/theme/skyBox/NegativeX.jpg',
|
||||
positiveY: 'GV/resources/theme/skyBox/PositiveY.jpg',
|
||||
negativeY: 'GV/resources/theme/skyBox/NegativeY.jpg',
|
||||
positiveZ: 'GV/resources/theme/skyBox/PositiveZ.jpg',
|
||||
negativeZ: 'GV/resources/theme/skyBox/NegativeZ.jpg',
|
||||
// positiveX: './images/skybox/skyCube2k_px.jpg',
|
||||
// negativeX: './images/skybox/skyCube2k_mx.jpg',
|
||||
// positiveY: './images/skybox/skyCube2k_py.jpg',
|
||||
// negativeY: './images/skybox/skyCube2k_my.jpg',
|
||||
// positiveZ: './images/skybox/skyCube2k_pz.jpg',
|
||||
// negativeZ: './images/skybox/skyCube2k_mz.jpg',
|
||||
},
|
||||
})
|
||||
|
||||
viewer.terrainProvider = await Cesium.CesiumTerrainProvider.fromUrl(
|
||||
'http://192.168.10.201:2022/api/maptilecache/service/terrain/taiwan-HeightMap-4326',
|
||||
{
|
||||
requestVertexNormals: true,
|
||||
requestWaterMask: true,
|
||||
}
|
||||
)
|
||||
|
||||
viewer.imageryLayers.addImageryProvider(
|
||||
new Cesium.UrlTemplateImageryProvider({
|
||||
url: window.settings.map[3].url,
|
||||
tilingScheme: new Cesium[window.settings.map[3].tilingScheme](),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
let getPointHandler = null
|
||||
function clickPoint() {
|
||||
if (getPointHandler) {
|
||||
return
|
||||
}
|
||||
getPointHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
|
||||
viewer._container.style.cursor = 'crosshair'
|
||||
getPointHandler.setInputAction(event => {
|
||||
const cartesian = viewer.scene.pickPosition(event.position)
|
||||
if (Cesium.defined(cartesian)) {
|
||||
const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
|
||||
const longitude = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
const latitude = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
|
||||
model.value.lon = longitude
|
||||
model.value.lat = latitude
|
||||
}
|
||||
|
||||
getPointHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
|
||||
getPointHandler = null
|
||||
viewer._container.style.cursor = ''
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
|
||||
}
|
||||
|
||||
function OpenStreetMapNominatimGeocoder() {}
|
||||
OpenStreetMapNominatimGeocoder.prototype.geocode = function (input) {
|
||||
const query = `format=jsonv2&accept-language=zh&polygon_geojson=1&countrycodes=cn&q=${input}`
|
||||
const requestString = 'https://nominatim.openstreetmap.org/search?' + query
|
||||
return Cesium.Resource.fetchJson(requestString) //请求url获取json数据
|
||||
.then(function (results) {
|
||||
let bboxDegrees
|
||||
return results.map(function (resultObject) {
|
||||
bboxDegrees = resultObject.boundingbox
|
||||
return {
|
||||
displayName: resultObject.display_name,
|
||||
destination: Cesium.Rectangle.fromDegrees(
|
||||
bboxDegrees[2],
|
||||
bboxDegrees[0],
|
||||
bboxDegrees[3],
|
||||
bboxDegrees[1]
|
||||
),
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function AMapNominatimGeocoder() {}
|
||||
AMapNominatimGeocoder.prototype.geocode = function (input) {
|
||||
const query = `key=****&keywords=${input}`
|
||||
const requestString = 'https://restapi.amap.com/v3/place/text?' + query
|
||||
return Cesium.Resource.fetchJson(requestString) //请求url获取json数据
|
||||
.then(function (results) {
|
||||
return results.pois.map(function (bboxDegrees) {
|
||||
let [lng, lat] = bboxDegrees['location'].split(',')
|
||||
return {
|
||||
displayName: bboxDegrees['name'],
|
||||
destination: Cesium.Rectangle.fromDegrees(lng, lat, lng, lat),
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
225
src/views/PlaceName/index.jsx
Normal file
225
src/views/PlaceName/index.jsx
Normal file
@ -0,0 +1,225 @@
|
||||
import {
|
||||
NButton,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NInputNumber,
|
||||
NSelect,
|
||||
} from 'naive-ui'
|
||||
import { usePlaceName } from './hooks'
|
||||
import maplibregl from 'maplibre-gl'
|
||||
import 'maplibre-gl/dist/maplibre-gl.css'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { model, showPlace, addPlaceName, initViewer, clickPoint } =
|
||||
usePlaceName()
|
||||
onMounted(async () => {
|
||||
const style = {
|
||||
version: 8,
|
||||
sources: {
|
||||
composite: {
|
||||
url: 'mapbox://mapbox.mapbox-streets-v8',
|
||||
type: 'vector',
|
||||
},
|
||||
os: {
|
||||
type: 'vector',
|
||||
scheme: 'tms',
|
||||
tiles: [
|
||||
'http://192.168.10.187:18080/geoserver/gwc/service/tms/1.0.0/osm%3Aosm_admin@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf',
|
||||
],
|
||||
},
|
||||
},
|
||||
sprite: 'mapbox://sprites/mapbox/streets-v8',
|
||||
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
|
||||
layers: [
|
||||
{
|
||||
id: 'background',
|
||||
type: 'background',
|
||||
paint: {
|
||||
'background-color': '#ffffff',
|
||||
},
|
||||
interactive: true,
|
||||
},
|
||||
{
|
||||
id: 'traffic',
|
||||
type: 'line',
|
||||
source: 'os',
|
||||
'source-layer': 'traffic3857',
|
||||
layout: {
|
||||
'line-join': 'round',
|
||||
'line-cap': 'round',
|
||||
},
|
||||
paint: {
|
||||
'line-color': '#C1FFC1',
|
||||
'line-width': 2,
|
||||
},
|
||||
interactive: true,
|
||||
},
|
||||
{
|
||||
id: 'hydro',
|
||||
type: 'line',
|
||||
source: 'os',
|
||||
'source-layer': 'hydro3857',
|
||||
layout: {
|
||||
'line-join': 'round',
|
||||
'line-cap': 'round',
|
||||
},
|
||||
paint: {
|
||||
'line-color': '#3031ff',
|
||||
'line-width': 1,
|
||||
'line-dasharray': [1.5, 3],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
const map = new maplibregl.Map({
|
||||
container: 'place-earth', // container id
|
||||
// style: 'https://demotiles.maplibre.org/style.json', // style URL
|
||||
style: '/style.json', // style URL
|
||||
center: [120.85, 23.86], // starting position [lng, lat]
|
||||
zoom: 7,
|
||||
})
|
||||
|
||||
map.on('click', e => {
|
||||
const features = map.queryRenderedFeatures(e.point)
|
||||
|
||||
// Limit the number of properties we're displaying for
|
||||
// legibility and performance
|
||||
const displayProperties = [
|
||||
'type',
|
||||
'properties',
|
||||
'id',
|
||||
'layer',
|
||||
'source',
|
||||
'sourceLayer',
|
||||
'state',
|
||||
]
|
||||
|
||||
const displayFeatures = features.map(feat => {
|
||||
console.log(feat)
|
||||
// const displayFeat = {}
|
||||
// displayProperties.forEach(prop => {
|
||||
// displayFeat[prop] = feat[prop]
|
||||
// })
|
||||
// return displayFeat
|
||||
})
|
||||
|
||||
// console.log(displayFeatures)
|
||||
// document.getElementById('features').innerHTML = JSON.stringify(
|
||||
// displayFeatures,
|
||||
// null,
|
||||
// 2
|
||||
// )
|
||||
})
|
||||
// initViewer()
|
||||
|
||||
// let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
|
||||
|
||||
// handler.setInputAction(async function (event) {
|
||||
// const pickRay = viewer.camera.getPickRay(event.position)
|
||||
|
||||
// const cartesian = viewer.scene.pickPosition(event.position)
|
||||
// if (Cesium.defined(cartesian)) {
|
||||
// const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
|
||||
// const longitude = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
// const latitude = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
|
||||
// const results = new Cesium.CartographicGeocoderService().geocode(
|
||||
// `${longitude} ${latitude}`
|
||||
// )
|
||||
// console.log(results)
|
||||
|
||||
// if (results && results.length > 0) {
|
||||
// console.log('Picked Name:', results[0].displayName)
|
||||
// }
|
||||
// }
|
||||
// }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
|
||||
})
|
||||
|
||||
return () => (
|
||||
<div class="h-full w-full">
|
||||
<div id="place-earth" class="h-full w-full"></div>
|
||||
<div class="absolute left-0 top-0 p-2">
|
||||
<NButton class="z-10" type="primary" onClick={() => addPlaceName()}>
|
||||
添加地名
|
||||
</NButton>
|
||||
</div>
|
||||
|
||||
{showPlace.value && (
|
||||
<div class="corner-border absolute left-2 top-14 z-30 flex w-[280px] flex-col gap-2 bg-[var(--color-bg)] p-2 p-2">
|
||||
<NForm
|
||||
class="p-2 pb-0"
|
||||
model={model.value}
|
||||
label-placement="left"
|
||||
label-width="auto"
|
||||
>
|
||||
<NFormItem label="名称" path="name">
|
||||
<NInput v-model:value={model.value.name} />
|
||||
</NFormItem>
|
||||
<NFormItem label="级别" path="level">
|
||||
<NSelect
|
||||
v-model:value={model.value.level}
|
||||
options={[
|
||||
{ label: '国', value: '2' },
|
||||
{ label: '省', value: '4' },
|
||||
{ label: '市', value: '5' },
|
||||
]}
|
||||
></NSelect>
|
||||
</NFormItem>
|
||||
<NFormItem label="经度" path="lon">
|
||||
<NInputNumber
|
||||
v-model:value={model.value.lon}
|
||||
min={-180}
|
||||
max={180}
|
||||
></NInputNumber>
|
||||
</NFormItem>
|
||||
<NFormItem label="纬度" path="lat">
|
||||
<NInputNumber
|
||||
v-model:value={model.value.lat}
|
||||
min={-90}
|
||||
max={90}
|
||||
></NInputNumber>
|
||||
</NFormItem>
|
||||
<NFormItem label=" " path="lat">
|
||||
<NButton onClick={clickPoint}>坐标拾取</NButton>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
|
||||
<div class="flex justify-end gap-2 p-2 pt-0">
|
||||
<NButton
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
showPlace.value = false
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</NButton>
|
||||
<NButton
|
||||
type="error"
|
||||
onClick={() => {
|
||||
showPlace.value = false
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</NButton>
|
||||
<NButton
|
||||
onClick={() => {
|
||||
showPlace.value = false
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</NButton>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
@ -1,91 +1,20 @@
|
||||
import { useModal } from '@/views/Content/hooks/modal'
|
||||
import { NDataTable, NSelect, NInputNumber, NSwitch } from 'naive-ui'
|
||||
|
||||
import { NDataTable, NButton, NSelect, NInputNumber, NSwitch } from 'naive-ui'
|
||||
import Detection from '@/views/Payload/Detection.jsx'
|
||||
import Communication from '@/views/Payload/Communication.jsx'
|
||||
const { openDetailsModal } = useModal()
|
||||
|
||||
const detectingLoadColumns = [
|
||||
// {
|
||||
// title: '载荷类型',
|
||||
// key: 'type',
|
||||
// render(row) {
|
||||
// return (
|
||||
// <NSelect
|
||||
// v-model:value={row.type}
|
||||
// options={[
|
||||
// { label: '电子', value: '电子' },
|
||||
// { label: '雷达', value: '雷达' },
|
||||
// { label: '光学', value: '光学' },
|
||||
// ]}
|
||||
// ></NSelect>
|
||||
// )
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: '开合角',
|
||||
key: 'angle',
|
||||
width: 120,
|
||||
render(row) {
|
||||
return (
|
||||
<NInputNumber
|
||||
v-model:value={row.angle}
|
||||
max={120}
|
||||
min={0}
|
||||
// disabled={['光学', '雷达'].includes(row.type)}
|
||||
></NInputNumber>
|
||||
)
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: '水平半角',
|
||||
// key: 'xHalfAngle',
|
||||
// width: 120,
|
||||
// render(row) {
|
||||
// return (
|
||||
// <NInputNumber
|
||||
// v-model:value={row.angle}
|
||||
// max={120}
|
||||
// min={0}
|
||||
// disabled={['电子'].includes(row.type)}
|
||||
// ></NInputNumber>
|
||||
// )
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: '垂直半角',
|
||||
// key: 'yHalfAngle',
|
||||
// width: 120,
|
||||
// render(row) {
|
||||
// return (
|
||||
// <NInputNumber
|
||||
// v-model:value={row.angle}
|
||||
// max={120}
|
||||
// min={0}
|
||||
// disabled={['电子'].includes(row.type)}
|
||||
// ></NInputNumber>
|
||||
// )
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: '是否开启',
|
||||
key: 'status',
|
||||
render(row) {
|
||||
return <NSwitch v-model:value={row.status}></NSwitch>
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const data = ref([
|
||||
{
|
||||
id: 3,
|
||||
angle: 30,
|
||||
// xHalfAngle: 20,
|
||||
// yHalfAngle: 25,
|
||||
// type: '电子',
|
||||
status: true,
|
||||
},
|
||||
])
|
||||
|
||||
export function showDetailsSatellite(option) {
|
||||
const detectingPayload = ref([
|
||||
{
|
||||
id: 3,
|
||||
angle: 30,
|
||||
// xHalfAngle: 20,
|
||||
// yHalfAngle: 25,
|
||||
// type: '电子',
|
||||
status: true,
|
||||
},
|
||||
])
|
||||
openDetailsModal({
|
||||
titleString: '' + option.name + ' 详情',
|
||||
contentSlot: () => (
|
||||
@ -103,17 +32,14 @@ export function showDetailsSatellite(option) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-item-title">探测载荷</div>
|
||||
<NDataTable
|
||||
key={row => row.id}
|
||||
columns={detectingLoadColumns}
|
||||
data={data.value}
|
||||
/>
|
||||
<div class="detail-item-title">通信载荷</div>
|
||||
{/* <NDataTable
|
||||
key={row => row.id}
|
||||
columns={detectingLoadColumns}
|
||||
data={data.value}
|
||||
/> */}
|
||||
<Detection type="corner" data={detectingPayload.value} />
|
||||
<div class="flex justify-between">
|
||||
<div class="detail-item-title">通信载荷</div>
|
||||
<NButton quaternary type="primary">
|
||||
添加
|
||||
</NButton>
|
||||
</div>
|
||||
<Communication />
|
||||
</div>
|
||||
),
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user