智慧园区前端大屏
21 files modified
16 files added
4540 ■■■■■ changed files
package.json 5 ●●●●● patch | view | raw | blame | history
pnpm-lock.yaml 859 ●●●●● patch | view | raw | blame | history
src/App.vue 5 ●●●● patch | view | raw | blame | history
src/main.js 4 ●●●● patch | view | raw | blame | history
src/pages/first/components/mainMenu.vue 22 ●●●●● patch | view | raw | blame | history
src/pages/first/index.vue 16 ●●●● patch | view | raw | blame | history
src/pages/layout/components/mainSearch.vue 14 ●●●● patch | view | raw | blame | history
src/pages/layout/components/scomponents/layersControl.vue 11 ●●●● patch | view | raw | blame | history
src/pages/layout/index.vue 260 ●●●●● patch | view | raw | blame | history
src/pages/map/components/mainMenu.vue 120 ●●●●● patch | view | raw | blame | history
src/pages/map/components/mainSearch.vue 208 ●●●●● patch | view | raw | blame | history
src/pages/map/components/mainTool.vue 115 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/baseMap.vue 359 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/cesium/AmapMercatorTilingScheme/CoordTransform.js 178 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/cesium/AmapMercatorTilingScheme/index.js 53 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/layersControl.vue 968 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/popup/panorama.vue 70 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/tool/curtain.vue 108 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/tool/exportScene.vue 10 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/tool/location.vue 89 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/tool/measure.vue 220 ●●●●● patch | view | raw | blame | history
src/pages/map/components/scomponents/toolList.vue 134 ●●●●● patch | view | raw | blame | history
src/pages/map/index.vue 260 ●●●●● patch | view | raw | blame | history
src/pages/single/components/mainMenu.vue 120 ●●●●● patch | view | raw | blame | history
src/pages/single/index.vue 223 ●●●●● patch | view | raw | blame | history
src/router/index.js 48 ●●●●● patch | view | raw | blame | history
src/views/companyInfo/components/box/dataContent.vue 3 ●●●●● patch | view | raw | blame | history
src/views/companyInfo/components/box/fireTrend.vue 10 ●●●● patch | view | raw | blame | history
src/views/companyInfo/components/box/unitContent.vue 8 ●●●● patch | view | raw | blame | history
src/views/companyInfo/index.vue 1 ●●●● patch | view | raw | blame | history
src/views/pac/components/box/dataContent.vue 4 ●●● patch | view | raw | blame | history
src/views/pd/components/dynamicPanel.vue 14 ●●●● patch | view | raw | blame | history
src/views/rs/components/box/dataContent.vue 3 ●●●●● patch | view | raw | blame | history
src/views/rt/index.vue 2 ●●● patch | view | raw | blame | history
src/views/space/components/box/dataContent.vue 5 ●●●● patch | view | raw | blame | history
src/views/supplies/index.vue 5 ●●●●● patch | view | raw | blame | history
vite.config.js 6 ●●●●● patch | view | raw | blame | history
package.json
@@ -21,7 +21,7 @@
    "cesium": "^1.123.1",
    "crypto-js": "^4.1.1",
    "echarts": "^5.5.1",
    "element-plus": "^2.8.6",
    "element-plus": "^2.9.0",
    "element-tree-line": "^0.2.1",
    "js-base64": "^3.7.4",
    "js-md5": "^0.7.3",
@@ -41,6 +41,7 @@
    "sass-loader": "^16.0.2",
    "terser": "^5.31.1",
    "unplugin-auto-import": "^0.18.3",
    "vite": "^5.4.9"
    "vite": "^5.4.9",
    "vite-plugin-vue-devtools": "^7.6.7"
  }
}
pnpm-lock.yaml
@@ -33,8 +33,8 @@
    specifier: ^5.5.1
    version: 5.5.1
  element-plus:
    specifier: ^2.8.6
    version: 2.8.6(vue@3.5.12)
    specifier: ^2.9.0
    version: 2.9.0(vue@3.5.12)
  element-tree-line:
    specifier: ^0.2.1
    version: 0.2.1(vue@3.5.12)
@@ -91,11 +91,176 @@
  vite:
    specifier: ^5.4.9
    version: 5.4.10(sass@1.80.4)(terser@5.31.1)
  vite-plugin-vue-devtools:
    specifier: ^7.6.7
    version: 7.6.7(vite@5.4.10)(vue@3.5.12)
packages:
  /@ampproject/remapping@2.3.0:
    resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
    engines: {node: '>=6.0.0'}
    dependencies:
      '@jridgewell/gen-mapping': 0.3.5
      '@jridgewell/trace-mapping': 0.3.25
    dev: true
  /@antfu/utils@0.7.10:
    resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==}
    dev: true
  /@babel/code-frame@7.26.2:
    resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/helper-validator-identifier': 7.25.9
      js-tokens: 4.0.0
      picocolors: 1.1.1
    dev: true
  /@babel/compat-data@7.26.2:
    resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==}
    engines: {node: '>=6.9.0'}
    dev: true
  /@babel/core@7.26.0:
    resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@ampproject/remapping': 2.3.0
      '@babel/code-frame': 7.26.2
      '@babel/generator': 7.26.2
      '@babel/helper-compilation-targets': 7.25.9
      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
      '@babel/helpers': 7.26.0
      '@babel/parser': 7.26.2
      '@babel/template': 7.25.9
      '@babel/traverse': 7.25.9
      '@babel/types': 7.26.0
      convert-source-map: 2.0.0
      debug: 4.3.7
      gensync: 1.0.0-beta.2
      json5: 2.2.3
      semver: 6.3.1
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/generator@7.26.2:
    resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/parser': 7.26.2
      '@babel/types': 7.26.0
      '@jridgewell/gen-mapping': 0.3.5
      '@jridgewell/trace-mapping': 0.3.25
      jsesc: 3.0.2
    dev: true
  /@babel/helper-annotate-as-pure@7.25.9:
    resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/types': 7.25.9
    dev: true
  /@babel/helper-compilation-targets@7.25.9:
    resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/compat-data': 7.26.2
      '@babel/helper-validator-option': 7.25.9
      browserslist: 4.24.2
      lru-cache: 5.1.1
      semver: 6.3.1
    dev: true
  /@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.0):
    resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-annotate-as-pure': 7.25.9
      '@babel/helper-member-expression-to-functions': 7.25.9
      '@babel/helper-optimise-call-expression': 7.25.9
      '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0)
      '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
      '@babel/traverse': 7.25.9
      semver: 6.3.1
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/helper-member-expression-to-functions@7.25.9:
    resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/traverse': 7.25.9
      '@babel/types': 7.25.9
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/helper-module-imports@7.25.9:
    resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/traverse': 7.25.9
      '@babel/types': 7.25.9
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0):
    resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-module-imports': 7.25.9
      '@babel/helper-validator-identifier': 7.25.9
      '@babel/traverse': 7.25.9
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/helper-optimise-call-expression@7.25.9:
    resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/types': 7.25.9
    dev: true
  /@babel/helper-plugin-utils@7.25.9:
    resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==}
    engines: {node: '>=6.9.0'}
    dev: true
  /@babel/helper-replace-supers@7.25.9(@babel/core@7.26.0):
    resolution: {integrity: sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-member-expression-to-functions': 7.25.9
      '@babel/helper-optimise-call-expression': 7.25.9
      '@babel/traverse': 7.25.9
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/helper-skip-transparent-expression-wrappers@7.25.9:
    resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/traverse': 7.25.9
      '@babel/types': 7.25.9
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/helper-string-parser@7.25.9:
@@ -106,6 +271,19 @@
    resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
    engines: {node: '>=6.9.0'}
  /@babel/helper-validator-option@7.25.9:
    resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==}
    engines: {node: '>=6.9.0'}
    dev: true
  /@babel/helpers@7.26.0:
    resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/template': 7.25.9
      '@babel/types': 7.26.0
    dev: true
  /@babel/parser@7.25.9:
    resolution: {integrity: sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==}
    engines: {node: '>=6.0.0'}
@@ -113,12 +291,131 @@
    dependencies:
      '@babel/types': 7.25.9
  /@babel/parser@7.26.2:
    resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==}
    engines: {node: '>=6.0.0'}
    hasBin: true
    dependencies:
      '@babel/types': 7.26.0
    dev: true
  /@babel/plugin-proposal-decorators@7.25.9(@babel/core@7.26.0):
    resolution: {integrity: sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
      '@babel/helper-plugin-utils': 7.25.9
      '@babel/plugin-syntax-decorators': 7.25.9(@babel/core@7.26.0)
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/plugin-syntax-decorators@7.25.9(@babel/core@7.26.0):
    resolution: {integrity: sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-plugin-utils': 7.25.9
    dev: true
  /@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0):
    resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-plugin-utils': 7.25.9
    dev: true
  /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0):
    resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-plugin-utils': 7.25.9
    dev: true
  /@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0):
    resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-plugin-utils': 7.25.9
    dev: true
  /@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.0):
    resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-plugin-utils': 7.25.9
    dev: true
  /@babel/plugin-transform-typescript@7.25.9(@babel/core@7.26.0):
    resolution: {integrity: sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-annotate-as-pure': 7.25.9
      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
      '@babel/helper-plugin-utils': 7.25.9
      '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
      '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0)
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/template@7.25.9:
    resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/code-frame': 7.26.2
      '@babel/parser': 7.26.2
      '@babel/types': 7.26.0
    dev: true
  /@babel/traverse@7.25.9:
    resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/code-frame': 7.26.2
      '@babel/generator': 7.26.2
      '@babel/parser': 7.26.2
      '@babel/template': 7.25.9
      '@babel/types': 7.26.0
      debug: 4.3.7
      globals: 11.12.0
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@babel/types@7.25.9:
    resolution: {integrity: sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/helper-string-parser': 7.25.9
      '@babel/helper-validator-identifier': 7.25.9
  /@babel/types@7.26.0:
    resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/helper-string-parser': 7.25.9
      '@babel/helper-validator-identifier': 7.25.9
    dev: true
  /@cesium/engine@12.0.1:
    resolution: {integrity: sha512-ou/Vu/tthTHDa2GbCrPiVWgue9AhPevWRk8hOQiEmwd1gy8aQCeMfCAfN3DXfBu7uj4wcw0+AeM7ObQgfVjjdg==}
@@ -382,8 +679,8 @@
      '@floating-ui/utils': 0.2.8
    dev: false
  /@floating-ui/dom@1.6.11:
    resolution: {integrity: sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==}
  /@floating-ui/dom@1.6.12:
    resolution: {integrity: sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==}
    dependencies:
      '@floating-ui/core': 1.6.8
      '@floating-ui/utils': 0.2.8
@@ -573,6 +870,10 @@
      '@parcel/watcher-win32-ia32': 2.4.1
      '@parcel/watcher-win32-x64': 2.4.1
  /@polka/url@1.0.0-next.28:
    resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==}
    dev: true
  /@protobufjs/aspromise@1.1.2:
    resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
    dev: false
@@ -750,6 +1051,15 @@
    os: [win32]
    requiresBuild: true
    optional: true
  /@sec-ant/readable-stream@0.4.1:
    resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
    dev: true
  /@sindresorhus/merge-streams@4.0.0:
    resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
    engines: {node: '>=18'}
    dev: true
  /@sxzz/popperjs-es@2.11.7:
    resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==}
@@ -2101,11 +2411,11 @@
  /@types/lodash-es@4.17.12:
    resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
    dependencies:
      '@types/lodash': 4.17.12
      '@types/lodash': 4.17.13
    dev: false
  /@types/lodash@4.17.12:
    resolution: {integrity: sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==}
  /@types/lodash@4.17.13:
    resolution: {integrity: sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==}
    dev: false
  /@types/node@22.9.0:
@@ -2136,6 +2446,48 @@
    dependencies:
      vite: 5.4.10(sass@1.80.4)(terser@5.31.1)
      vue: 3.5.12
    dev: true
  /@vue/babel-helper-vue-transform-on@1.2.5:
    resolution: {integrity: sha512-lOz4t39ZdmU4DJAa2hwPYmKc8EsuGa2U0L9KaZaOJUt0UwQNjNA3AZTq6uEivhOKhhG1Wvy96SvYBoFmCg3uuw==}
    dev: true
  /@vue/babel-plugin-jsx@1.2.5(@babel/core@7.26.0):
    resolution: {integrity: sha512-zTrNmOd4939H9KsRIGmmzn3q2zvv1mjxkYZHgqHZgDrXz5B1Q3WyGEjO2f+JrmKghvl1JIRcvo63LgM1kH5zFg==}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    peerDependenciesMeta:
      '@babel/core':
        optional: true
    dependencies:
      '@babel/core': 7.26.0
      '@babel/helper-module-imports': 7.25.9
      '@babel/helper-plugin-utils': 7.25.9
      '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0)
      '@babel/template': 7.25.9
      '@babel/traverse': 7.25.9
      '@babel/types': 7.25.9
      '@vue/babel-helper-vue-transform-on': 1.2.5
      '@vue/babel-plugin-resolve-type': 1.2.5(@babel/core@7.26.0)
      html-tags: 3.3.1
      svg-tags: 1.0.0
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@vue/babel-plugin-resolve-type@1.2.5(@babel/core@7.26.0):
    resolution: {integrity: sha512-U/ibkQrf5sx0XXRnUZD1mo5F7PkpKyTbfXM3a3rC4YnUz6crHEz9Jg09jzzL6QYlXNto/9CePdOg/c87O4Nlfg==}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/code-frame': 7.26.2
      '@babel/core': 7.26.0
      '@babel/helper-module-imports': 7.25.9
      '@babel/helper-plugin-utils': 7.25.9
      '@babel/parser': 7.25.9
      '@vue/compiler-sfc': 3.5.12
    transitivePeerDependencies:
      - supports-color
    dev: true
  /@vue/compiler-core@3.5.12:
@@ -2175,6 +2527,40 @@
  /@vue/devtools-api@6.6.4:
    resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==}
    dev: false
  /@vue/devtools-core@7.6.7(vite@5.4.10)(vue@3.5.12):
    resolution: {integrity: sha512-6fW8Q0H1NHDXdEcuV6dylT5U2Yxg3SdMnVCey99Y6S4R2PNgFL2vC+VU9U9rHIiaoEUkeza42S7FfHxV4VI3Jg==}
    peerDependencies:
      vue: ^3.0.0
    dependencies:
      '@vue/devtools-kit': 7.6.7
      '@vue/devtools-shared': 7.6.7
      mitt: 3.0.1
      nanoid: 5.0.9
      pathe: 1.1.2
      vite-hot-client: 0.2.4(vite@5.4.10)
      vue: 3.5.12
    transitivePeerDependencies:
      - vite
    dev: true
  /@vue/devtools-kit@7.6.7:
    resolution: {integrity: sha512-V8/jrXY/swHgnblABG9U4QCbE60c6RuPasmv2d9FvVqc5d94t1vDiESuvRmdNJBdWz4/D3q6ffgyAfRVjwHYEw==}
    dependencies:
      '@vue/devtools-shared': 7.6.7
      birpc: 0.2.19
      hookable: 5.5.3
      mitt: 3.0.1
      perfect-debounce: 1.0.0
      speakingurl: 14.0.1
      superjson: 2.2.1
    dev: true
  /@vue/devtools-shared@7.6.7:
    resolution: {integrity: sha512-QggO6SviAsolrePAXZ/sA1dSicSPt4TueZibCvydfhNDieL1lAuyMTgQDGst7TEvMGb4vgYv2I+1sDkO4jWNnw==}
    dependencies:
      rfdc: 1.4.1
    dev: true
  /@vue/reactivity@3.5.12:
    resolution: {integrity: sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==}
@@ -2282,6 +2668,10 @@
    resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
    dev: true
  /birpc@0.2.19:
    resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==}
    dev: true
  /bitmap-sdf@1.0.4:
    resolution: {integrity: sha512-1G3U4n5JE6RAiALMxu0p1XmeZkTeCwGKykzsLTCqVzfSDaN6S7fKnkIkfejogz+iwqBWc0UYAIKnKHNN7pSfDg==}
    dev: false
@@ -2298,8 +2688,30 @@
    dependencies:
      fill-range: 7.1.1
  /browserslist@4.24.2:
    resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==}
    engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
    hasBin: true
    dependencies:
      caniuse-lite: 1.0.30001684
      electron-to-chromium: 1.5.67
      node-releases: 2.0.18
      update-browserslist-db: 1.1.1(browserslist@4.24.2)
    dev: true
  /buffer-from@1.1.2:
    resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
  /bundle-name@4.1.0:
    resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
    engines: {node: '>=18'}
    dependencies:
      run-applescript: 7.0.0
    dev: true
  /caniuse-lite@1.0.30001684:
    resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==}
    dev: true
  /cesium@1.123.1:
    resolution: {integrity: sha512-3BMru4i1aNa98YhaA9pLbJkc1Ghpt6BZjJMsSLkD1UVUZzxu3xTYe/3/woKNRmMtBzvx13wyiS5QADyns2w5qA==}
@@ -2357,6 +2769,26 @@
    resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
    dev: true
  /convert-source-map@2.0.0:
    resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
    dev: true
  /copy-anything@3.0.5:
    resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
    engines: {node: '>=12.13'}
    dependencies:
      is-what: 4.1.16
    dev: true
  /cross-spawn@7.0.6:
    resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
    engines: {node: '>= 8'}
    dependencies:
      path-key: 3.1.1
      shebang-command: 2.0.0
      which: 2.0.2
    dev: true
  /crypto-js@4.1.1:
    resolution: {integrity: sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==}
    dev: false
@@ -2403,7 +2835,24 @@
        optional: true
    dependencies:
      ms: 2.1.3
    dev: false
  /default-browser-id@5.0.0:
    resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==}
    engines: {node: '>=18'}
    dev: true
  /default-browser@5.2.1:
    resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==}
    engines: {node: '>=18'}
    dependencies:
      bundle-name: 4.1.0
      default-browser-id: 5.0.0
    dev: true
  /define-lazy-prop@3.0.0:
    resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
    engines: {node: '>=12'}
    dev: true
  /delayed-stream@1.0.0:
    resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
@@ -2452,16 +2901,20 @@
    resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
    dev: false
  /element-plus@2.8.6(vue@3.5.12):
    resolution: {integrity: sha512-fk5jB8V3efM02/4roZ5SWOLArgaYXbxEydZLlXSr+KPAwjNyHBlk2+HO5em8YKo5+RLBoHnn6BaThj6IE4nXoQ==}
  /electron-to-chromium@1.5.67:
    resolution: {integrity: sha512-nz88NNBsD7kQSAGGJyp8hS6xSPtWwqNogA0mjtc2nUYeEf3nURK9qpV18TuBdDmEDgVWotS8Wkzf+V52dSQ/LQ==}
    dev: true
  /element-plus@2.9.0(vue@3.5.12):
    resolution: {integrity: sha512-ccOFXKsauo2dtokAr4OX7gZsb7TuAoVxA2zGRZo5o2yyDDBLBaZxOoFQPoxITSLcHbBfQuNDGK5Iag5hnyKkZA==}
    peerDependencies:
      vue: ^3.2.0
    dependencies:
      '@ctrl/tinycolor': 3.6.1
      '@element-plus/icons-vue': 2.3.1(vue@3.5.12)
      '@floating-ui/dom': 1.6.11
      '@floating-ui/dom': 1.6.12
      '@popperjs/core': /@sxzz/popperjs-es@2.11.7
      '@types/lodash': 4.17.12
      '@types/lodash': 4.17.13
      '@types/lodash-es': 4.17.12
      '@vueuse/core': 9.13.0(vue@3.5.12)
      async-validator: 4.2.5
@@ -2499,6 +2952,10 @@
    resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
    engines: {node: '>=0.12'}
  /error-stack-parser-es@0.1.5:
    resolution: {integrity: sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==}
    dev: true
  /esbuild@0.21.5:
    resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
    engines: {node: '>=12'}
@@ -2529,6 +2986,11 @@
      '@esbuild/win32-ia32': 0.21.5
      '@esbuild/win32-x64': 0.21.5
  /escalade@3.2.0:
    resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
    engines: {node: '>=6'}
    dev: true
  /escape-html@1.0.3:
    resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
    dev: false
@@ -2552,6 +3014,24 @@
    engines: {node: '>= 0.6'}
    dev: false
  /execa@9.5.1:
    resolution: {integrity: sha512-QY5PPtSonnGwhhHDNI7+3RvY285c7iuJFFB+lU+oEzMY/gEGJ808owqJsrr8Otd1E/x07po1LkUBmdAc5duPAg==}
    engines: {node: ^18.19.0 || >=20.5.0}
    dependencies:
      '@sindresorhus/merge-streams': 4.0.0
      cross-spawn: 7.0.6
      figures: 6.1.0
      get-stream: 9.0.1
      human-signals: 8.0.0
      is-plain-obj: 4.1.0
      is-stream: 4.0.1
      npm-run-path: 6.0.0
      pretty-ms: 9.2.0
      signal-exit: 4.1.0
      strip-final-newline: 4.0.0
      yoctocolors: 2.1.1
    dev: true
  /fast-deep-equal@3.1.3:
    resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
    dev: false
@@ -2571,6 +3051,13 @@
    resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
    dependencies:
      reusify: 1.0.4
    dev: true
  /figures@6.1.0:
    resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
    engines: {node: '>=18'}
    dependencies:
      is-unicode-supported: 2.1.0
    dev: true
  /fill-range@7.1.1:
@@ -2612,6 +3099,15 @@
      universalify: 2.0.1
    dev: false
  /fs-extra@11.2.0:
    resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
    engines: {node: '>=14.14'}
    dependencies:
      graceful-fs: 4.2.11
      jsonfile: 6.1.0
      universalify: 2.0.1
    dev: true
  /fs-extra@9.1.0:
    resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
    engines: {node: '>=10'}
@@ -2629,6 +3125,11 @@
    requiresBuild: true
    optional: true
  /gensync@1.0.0-beta.2:
    resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
    engines: {node: '>=6.9.0'}
    dev: true
  /geojson-equality-ts@1.0.2:
    resolution: {integrity: sha512-h3Ryq+0mCSN/7yLs0eDgrZhvc9af23o/QuC4aTiuuzP/MRCtd6mf5rLsLRY44jX0RPUfM8c4GqERQmlUxPGPoQ==}
    dependencies:
@@ -2641,6 +3142,14 @@
      rbush: 2.0.2
    dev: false
  /get-stream@9.0.1:
    resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
    engines: {node: '>=18'}
    dependencies:
      '@sec-ant/readable-stream': 0.4.1
      is-stream: 4.0.1
    dev: true
  /glob-parent@5.1.2:
    resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
    engines: {node: '>= 6'}
@@ -2648,9 +3157,13 @@
      is-glob: 4.0.3
    dev: true
  /globals@11.12.0:
    resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
    engines: {node: '>=4'}
    dev: true
  /graceful-fs@4.2.11:
    resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
    dev: false
  /grapheme-splitter@1.0.4:
    resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
@@ -2660,6 +3173,15 @@
    resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
    engines: {node: '>=8'}
    dev: false
  /hookable@5.5.3:
    resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
    dev: true
  /html-tags@3.3.1:
    resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==}
    engines: {node: '>=8'}
    dev: true
  /http-errors@2.0.0:
    resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
@@ -2672,12 +3194,23 @@
      toidentifier: 1.0.1
    dev: false
  /human-signals@8.0.0:
    resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==}
    engines: {node: '>=18.18.0'}
    dev: true
  /immutable@4.3.7:
    resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==}
  /inherits@2.0.4:
    resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
    dev: false
  /is-docker@3.0.0:
    resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
    hasBin: true
    dev: true
  /is-extglob@2.1.1:
    resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
@@ -2689,9 +3222,48 @@
    dependencies:
      is-extglob: 2.1.1
  /is-inside-container@1.0.0:
    resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
    engines: {node: '>=14.16'}
    hasBin: true
    dependencies:
      is-docker: 3.0.0
    dev: true
  /is-number@7.0.0:
    resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
    engines: {node: '>=0.12.0'}
  /is-plain-obj@4.1.0:
    resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
    engines: {node: '>=12'}
    dev: true
  /is-stream@4.0.1:
    resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
    engines: {node: '>=18'}
    dev: true
  /is-unicode-supported@2.1.0:
    resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
    engines: {node: '>=18'}
    dev: true
  /is-what@4.1.16:
    resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
    engines: {node: '>=12.13'}
    dev: true
  /is-wsl@3.1.0:
    resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
    engines: {node: '>=16'}
    dependencies:
      is-inside-container: 1.0.0
    dev: true
  /isexe@2.0.0:
    resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
    dev: true
  /js-base64@3.7.4:
    resolution: {integrity: sha512-wpM/wi20Tl+3ifTyi0RdDckS4YTD4Lf953mBRrpG8547T7hInHNPEj8+ck4gB8VDcGyeAWFK++Wb/fU1BeavKQ==}
@@ -2700,6 +3272,10 @@
  /js-md5@0.7.3:
    resolution: {integrity: sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ==}
    dev: false
  /js-tokens@4.0.0:
    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
    dev: true
  /js-tokens@9.0.0:
    resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==}
@@ -2710,13 +3286,24 @@
    engines: {node: '>= 10.16.0'}
    dev: false
  /jsesc@3.0.2:
    resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==}
    engines: {node: '>=6'}
    hasBin: true
    dev: true
  /json5@2.2.3:
    resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
    engines: {node: '>=6'}
    hasBin: true
    dev: true
  /jsonfile@6.1.0:
    resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
    dependencies:
      universalify: 2.0.1
    optionalDependencies:
      graceful-fs: 4.2.11
    dev: false
  /jsts@2.7.1:
    resolution: {integrity: sha512-x2wSZHEBK20CY+Wy+BPE7MrFQHW6sIsdaGUMEqmGAio+3gFzQaBYPwLRonUfQf9Ak8pBieqj9tUofX1+WtAEIg==}
@@ -2726,6 +3313,10 @@
  /kdbush@4.0.2:
    resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==}
    dev: false
  /kolorist@1.8.0:
    resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
    dev: true
  /ktx-parse@0.7.1:
    resolution: {integrity: sha512-FeA3g56ksdFNwjXJJsc1CCc7co+AJYDp6ipIp878zZ2bU8kWROatLYf39TQEd4/XRSUvBXovQ8gaVKWPXsCLEQ==}
@@ -2766,6 +3357,12 @@
  /long@5.2.3:
    resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==}
    dev: false
  /lru-cache@5.1.1:
    resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
    dependencies:
      yallist: 3.1.1
    dev: true
  /magic-string@0.30.12:
    resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==}
@@ -2827,7 +3424,6 @@
  /mitt@3.0.1:
    resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
    dev: false
  /mlly@1.7.2:
    resolution: {integrity: sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==}
@@ -2838,18 +3434,28 @@
      ufo: 1.5.4
    dev: true
  /mrmime@2.0.0:
    resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
    engines: {node: '>=10'}
    dev: true
  /ms@2.0.0:
    resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
    dev: false
  /ms@2.1.3:
    resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
    dev: false
  /nanoid@3.3.7:
    resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
    engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
    hasBin: true
  /nanoid@5.0.9:
    resolution: {integrity: sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==}
    engines: {node: ^18 || >=20}
    hasBin: true
    dev: true
  /neo-async@2.6.2:
    resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
@@ -2858,6 +3464,10 @@
  /node-addon-api@7.1.1:
    resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
  /node-releases@2.0.18:
    resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
    dev: true
  /normalize-wheel-es@1.2.0:
    resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
    dev: false
@@ -2865,6 +3475,14 @@
  /nosleep.js@0.12.0:
    resolution: {integrity: sha512-9d1HbpKLh3sdWlhXMhU6MMH+wQzKkrgfRkYV0EBdvt99YJfj0ilCJrWRDYG2130Tm4GXbEoTCx5b34JSaP+HhA==}
    dev: false
  /npm-run-path@6.0.0:
    resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
    engines: {node: '>=18'}
    dependencies:
      path-key: 4.0.0
      unicorn-magic: 0.3.0
    dev: true
  /nprogress@0.2.0:
    resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==}
@@ -2877,17 +3495,46 @@
      ee-first: 1.1.1
    dev: false
  /open@10.1.0:
    resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==}
    engines: {node: '>=18'}
    dependencies:
      default-browser: 5.2.1
      define-lazy-prop: 3.0.0
      is-inside-container: 1.0.0
      is-wsl: 3.1.0
    dev: true
  /pako@2.1.0:
    resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
    dev: false
  /parse-ms@4.0.0:
    resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
    engines: {node: '>=18'}
    dev: true
  /parseurl@1.3.3:
    resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
    engines: {node: '>= 0.8'}
    dev: false
  /path-key@3.1.1:
    resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
    engines: {node: '>=8'}
    dev: true
  /path-key@4.0.0:
    resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
    engines: {node: '>=12'}
    dev: true
  /pathe@1.1.2:
    resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
    dev: true
  /perfect-debounce@1.0.0:
    resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
    dev: true
  /picocolors@1.1.1:
@@ -2965,6 +3612,13 @@
      picocolors: 1.1.1
      source-map-js: 1.2.1
  /pretty-ms@9.2.0:
    resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==}
    engines: {node: '>=18'}
    dependencies:
      parse-ms: 4.0.0
    dev: true
  /protobufjs@7.4.0:
    resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==}
    engines: {node: '>=12.0.0'}
@@ -3026,6 +3680,10 @@
    engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
    dev: true
  /rfdc@1.4.1:
    resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
    dev: true
  /robust-predicates@2.0.4:
    resolution: {integrity: sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==}
    dev: false
@@ -3058,6 +3716,11 @@
      '@rollup/rollup-win32-ia32-msvc': 4.24.0
      '@rollup/rollup-win32-x64-msvc': 4.24.0
      fsevents: 2.3.3
  /run-applescript@7.0.0:
    resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==}
    engines: {node: '>=18'}
    dev: true
  /run-parallel@1.2.0:
    resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
@@ -3104,6 +3767,11 @@
    resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==}
    dev: true
  /semver@6.3.1:
    resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
    hasBin: true
    dev: true
  /send@0.19.0:
    resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==}
    engines: {node: '>= 0.8.0'}
@@ -3141,6 +3809,32 @@
    resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
    dev: false
  /shebang-command@2.0.0:
    resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
    engines: {node: '>=8'}
    dependencies:
      shebang-regex: 3.0.0
    dev: true
  /shebang-regex@3.0.0:
    resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
    engines: {node: '>=8'}
    dev: true
  /signal-exit@4.1.0:
    resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
    engines: {node: '>=14'}
    dev: true
  /sirv@3.0.0:
    resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==}
    engines: {node: '>=18'}
    dependencies:
      '@polka/url': 1.0.0-next.28
      mrmime: 2.0.0
      totalist: 3.0.1
    dev: true
  /skmeans@0.9.7:
    resolution: {integrity: sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==}
    dev: false
@@ -3159,6 +3853,11 @@
    resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
    engines: {node: '>=0.10.0'}
  /speakingurl@14.0.1:
    resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
    engines: {node: '>=0.10.0'}
    dev: true
  /splaytree@3.1.2:
    resolution: {integrity: sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A==}
    dev: false
@@ -3168,10 +3867,22 @@
    engines: {node: '>= 0.8'}
    dev: false
  /strip-final-newline@4.0.0:
    resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
    engines: {node: '>=18'}
    dev: true
  /strip-literal@2.1.0:
    resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==}
    dependencies:
      js-tokens: 9.0.0
    dev: true
  /superjson@2.2.1:
    resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==}
    engines: {node: '>=16'}
    dependencies:
      copy-anything: 3.0.5
    dev: true
  /supports-color@7.2.0:
@@ -3180,6 +3891,10 @@
    dependencies:
      has-flag: 4.0.0
    dev: false
  /svg-tags@1.0.0:
    resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==}
    dev: true
  /sweepline-intersections@1.5.0:
    resolution: {integrity: sha512-AoVmx72QHpKtItPu72TzFL+kcYjd67BPLDoR0LarIk+xyaRg+pDTMFXndIEvZf9xEKnJv6JdhgRMnocoG0D3AQ==}
@@ -3226,6 +3941,11 @@
      commander: 2.20.3
    dev: false
  /totalist@3.0.1:
    resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
    engines: {node: '>=6'}
    dev: true
  /tslib@2.3.0:
    resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
    dev: false
@@ -3241,6 +3961,11 @@
  /undici-types@6.19.8:
    resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
    dev: false
  /unicorn-magic@0.3.0:
    resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
    engines: {node: '>=18'}
    dev: true
  /unimport@3.13.1:
    resolution: {integrity: sha512-nNrVzcs93yrZQOW77qnyOVHtb68LegvhYFwxFMfuuWScmwQmyVCG/NBuN8tYsaGzgQUVYv34E/af+Cc9u4og4A==}
@@ -3266,7 +3991,6 @@
  /universalify@2.0.1:
    resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
    engines: {node: '>= 10.0.0'}
    dev: false
  /unplugin-auto-import@0.18.3:
    resolution: {integrity: sha512-q3FUtGQjYA2e+kb1WumyiQMjHM27MrTQ05QfVwtLRVhyYe+KF6TblBYaEX9L6Z0EibsqaXAiW+RFfkcQpfaXzg==}
@@ -3306,9 +4030,28 @@
      webpack-virtual-modules: 0.6.2
    dev: true
  /update-browserslist-db@1.1.1(browserslist@4.24.2):
    resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==}
    hasBin: true
    peerDependencies:
      browserslist: '>= 4.21.0'
    dependencies:
      browserslist: 4.24.2
      escalade: 3.2.0
      picocolors: 1.1.1
    dev: true
  /urijs@1.19.11:
    resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==}
    dev: false
  /vite-hot-client@0.2.4(vite@5.4.10):
    resolution: {integrity: sha512-a1nzURqO7DDmnXqabFOliz908FRmIppkBKsJthS8rbe8hBEXwEwe4C3Pp33Z1JoFCYfVL4kTOMLKk0ZZxREIeA==}
    peerDependencies:
      vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0
    dependencies:
      vite: 5.4.10(sass@1.80.4)(terser@5.31.1)
    dev: true
  /vite-plugin-compression@0.5.1(vite@5.4.10):
    resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==}
@@ -3322,6 +4065,71 @@
    transitivePeerDependencies:
      - supports-color
    dev: false
  /vite-plugin-inspect@0.8.8(vite@5.4.10):
    resolution: {integrity: sha512-aZlBuXsWUPJFmMK92GIv6lH7LrwG2POu4KJ+aEdcqnu92OAf+rhBnfMDQvxIJPEB7hE2t5EyY/PMgf5aDLT8EA==}
    engines: {node: '>=14'}
    peerDependencies:
      '@nuxt/kit': '*'
      vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0
    peerDependenciesMeta:
      '@nuxt/kit':
        optional: true
    dependencies:
      '@antfu/utils': 0.7.10
      '@rollup/pluginutils': 5.1.3
      debug: 4.3.7
      error-stack-parser-es: 0.1.5
      fs-extra: 11.2.0
      open: 10.1.0
      perfect-debounce: 1.0.0
      picocolors: 1.1.1
      sirv: 3.0.0
      vite: 5.4.10(sass@1.80.4)(terser@5.31.1)
    transitivePeerDependencies:
      - rollup
      - supports-color
    dev: true
  /vite-plugin-vue-devtools@7.6.7(vite@5.4.10)(vue@3.5.12):
    resolution: {integrity: sha512-H1ZyjtpWjP5mHA5R15sQeYgAARuh2Myg3TDFXWZK6QOQRy8s3XjTIt319DogVjU/x3rC3L/jJQjIasRU04mWXA==}
    engines: {node: '>=v14.21.3'}
    peerDependencies:
      vite: ^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0
    dependencies:
      '@vue/devtools-core': 7.6.7(vite@5.4.10)(vue@3.5.12)
      '@vue/devtools-kit': 7.6.7
      '@vue/devtools-shared': 7.6.7
      execa: 9.5.1
      sirv: 3.0.0
      vite: 5.4.10(sass@1.80.4)(terser@5.31.1)
      vite-plugin-inspect: 0.8.8(vite@5.4.10)
      vite-plugin-vue-inspector: 5.3.1(vite@5.4.10)
    transitivePeerDependencies:
      - '@nuxt/kit'
      - rollup
      - supports-color
      - vue
    dev: true
  /vite-plugin-vue-inspector@5.3.1(vite@5.4.10):
    resolution: {integrity: sha512-cBk172kZKTdvGpJuzCCLg8lJ909wopwsu3Ve9FsL1XsnLBiRT9U3MePcqrgGHgCX2ZgkqZmAGR8taxw+TV6s7A==}
    peerDependencies:
      vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0
    dependencies:
      '@babel/core': 7.26.0
      '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.0)
      '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0)
      '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.0)
      '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0)
      '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.0)
      '@vue/compiler-dom': 3.5.12
      kolorist: 1.8.0
      magic-string: 0.30.12
      vite: 5.4.10(sass@1.80.4)(terser@5.31.1)
    transitivePeerDependencies:
      - supports-color
    dev: true
  /vite@5.4.10(sass@1.80.4)(terser@5.31.1):
    resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==}
@@ -3419,6 +4227,23 @@
    resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
    dev: true
  /which@2.0.2:
    resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
    engines: {node: '>= 8'}
    hasBin: true
    dependencies:
      isexe: 2.0.0
    dev: true
  /yallist@3.1.1:
    resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
    dev: true
  /yoctocolors@2.1.1:
    resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==}
    engines: {node: '>=18'}
    dev: true
  /zrender@5.6.0:
    resolution: {integrity: sha512-uzgraf4njmmHAbEUxMJ8Oxg+P3fT04O+9p7gY+wJRVxo8Ge+KmYv0WJev945EH4wFuc4OY2NLXz46FZrWS9xJg==}
    dependencies:
src/App.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-25 10:56:27
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-25 17:42:09
 * @LastEditTime: 2024-11-29 23:26:21
 * @FilePath: \bigScreen\src\App.vue
 * @Description: 
 * 
@@ -16,6 +16,9 @@
provide("echarts", echarts)
onUnmounted(() => {
  echarts.cleanup() // 清理服务
})
</script>
<template>
src/main.js
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-25 10:56:27
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-08 20:11:07
 * @LastEditTime: 2024-12-01 00:28:09
 * @FilePath: \bigScreen\src\main.js
 * @Description: 
 * 
@@ -52,4 +52,4 @@
app.use(router)
app.use(ElementPlus)
app.use(pinia)
router.isReady().then(() => app.mount('#app'))
app.mount('#app')
src/pages/first/components/mainMenu.vue
@@ -21,35 +21,35 @@
  [
    {
      menuName: '园区概况',
      path: '/layout/first/survey'
      path: '/layout/map/survey'
    },
    {
      menuName: '风险源',
      path: '/layout/first/rs'
      path: '/layout/map/rs'
    },
    {
      menuName: '应急空间',
      path: '/layout/first/space'
      path: '/layout/map/space'
    },
    {
      menuName: '应急物资',
      path: '/layout/first/supplies'
      path: '/layout/single/first/supplies'
    },
    {
      menuName: '三级防控',
      path: '/layout/first/pac'
      path: '/layout/map/first/pac'
    },
    {
      menuName: '救援队伍',
      path: '/layout/first/rt'
      path: '/layout/single/first/rt'
    },
    {
      menuName: '突发事件模拟',
      path: '/layout/first/pd'
      path: '/layout/map/first/pd'
    },
    {
      menuName: '作战图',
      path: '/layout/first/ochart'
      path: '/layout/single/first/ochart'
    },
  ]
)
@@ -59,12 +59,6 @@
  if (params.path) {
    if (router.currentRoute.value.path == params.path) return
    if (params.path == '/layout/first/supplies' || params.path == '/layout/first/rt' || params.path == '/layout/first/ochart') {
      store.setLoadSingle(true)
    } else {
      store.setLoadSingle(false)
    }
    router.push({
      path: params.path
    })
src/pages/first/index.vue
@@ -1,9 +1,19 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-11-27 18:00:02
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-29 21:28:06
 * @FilePath: \bigScreen\src\pages\first\index.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2022-08-18 16:18:24
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-10 20:03:06
 * @FilePath: \bigScreen\src\views\first\index.vue
 * @LastEditTime: 2024-11-27 20:21:08
 * @FilePath: \bigScreen\src\pages\first\index.vue
 * @Description: 
 * 
 * Copyright (c) 2022 by shuishen 1109946754@qq.com, All Rights Reserved. 
@@ -21,7 +31,7 @@
    <div class="main-container">
      <!-- 地图区域 -->
      <router-view key="2"></router-view>
      <router-view></router-view>
    </div>
    <main-menu></main-menu>
src/pages/layout/components/mainSearch.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-26 16:09:35
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-27 15:28:29
 * @LastEditTime: 2024-11-28 19:22:40
 * @FilePath: \bigScreen\src\pages\layout\components\mainSearch.vue
 * @Description: 
 * 
@@ -114,7 +114,8 @@
  } else {
    window.$viewer.removeLayer(addTileLayers[item.name])
    addTileLayers = {}
    addTileLayers[item.name] = null
    delete addTileLayers[item.name]
  }
}
@@ -122,15 +123,22 @@
function clearPoint () {
  let arr = Object.keys(addTileLayers)
  arr.forEach(i => {
    addTileLayers[i] && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
  addTileLayers = {}
}
onUnmounted(() => {
  let arr = Object.keys(addTileLayers)
  arr.forEach(i => {
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
  addTileLayers = null
})
</script>
src/pages/layout/components/scomponents/layersControl.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-31 10:47:29
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-28 15:23:01
 * @LastEditTime: 2024-11-28 19:23:46
 * @FilePath: \bigScreen\src\pages\layout\components\scomponents\layersControl.vue
 * @Description:
 *
@@ -843,7 +843,7 @@
        } else {
          addTileLayers[item.layerName].clear()
          window.$viewer && window.$viewer.removeLayer(addTileLayers[item.layerName])
          addTileLayers[item.layerName] = null
          delete addTileLayers[item.layerName]
        }
      }
@@ -928,8 +928,9 @@
  let arr = Object.keys(addPupoLayers)
  arr.filter(i => i != 'hgyq').forEach(i => {
    addPupoLayers[i] && window.$viewer && window.$viewer.removeLayer(addPupoLayers[i])
    addPupoLayers[i] = null
    delete addPupoLayers[i]
  })
  addPupoLayers = {}
}
onUnmounted(() => {
@@ -942,9 +943,13 @@
  let arr = Object.keys(addTileLayers)
  arr.filter(i => i != 'hgyq').forEach(i => {
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
  addTileLayers = null
  // 弹窗销毁
  destroy()
  addPupoLayers = null
  EventBus.off('restHandleCheckChange', restHandleCheckChange)
  EventBus.off('restHandleDelChange', restHandleDelChange)
src/pages/layout/index.vue
@@ -1,261 +1,17 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2022-08-18 16:18:24
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-21 12:29:12
 * @FilePath: \bigScreen\src\pages\layout\index.vue
 * @Description:
 *
 * Copyright (c) 2022 by shuishen 1109946754@qq.com, All Rights Reserved.
-->
<template>
  <div class="wrapper">
    <div v-if="showSinglePage" class="main-content single-page" id="MainContent">
      <router-view></router-view>
    </div>
    <map-container v-if="!showSinglePage" ref="MapContainer">
      <template #content>
        <div v-if="showContent" :class="[showSubLayout ? 'main-content-sub' : 'main-content']" id="MainContent">
          <main-search></main-search>
          <main-tool></main-tool>
          <router-view class="w100 h100" key="1"></router-view>
        </div>
      </template>
    </map-container>
  <div class="w100 h100">
    <router-view></router-view>
  </div>
</template>
<script setup>
import { useRouter, useRoute } from 'vue-router'
let router = useRouter()
import mainSearch from './components/mainSearch.vue'
import mainTool from './components/mainTool.vue'
<script>
export default {
  setup () {
import { useLogin } from 'store/login'
const loginStore = useLogin()
import { useMap } from 'store/map'
import { useRouterStore } from 'store/router'
const store = useMap()
const storeRouter = useRouterStore()
const showContent = ref(false)
const showSubLayout = ref(false)
const showSinglePage = ref(false)
// onMounted(() => {
//   store.setLoadSub(false)
// }),
// 监听createB的变化
watch(
  [
    () => store.loadMap,
    () => storeRouter.loadSub,
    () => storeRouter.loadSingle,
  ],
  ([newLoadMap, newLoadSub, newLoadSingle]) => {
    showContent.value = newLoadMap
    showSubLayout.value = newLoadSub
    showSinglePage.value = newLoadSingle
  },
  { immediate: true } // 设置immediate为true以便在组件挂载时立即检查createB的值
)
const signOut = () => {
  loginStore.LogOut().then(res => {
    router.push({
      path: '/login'
    })
  })
    return {}
  }
}
</script>
<style scoped lang="scss">
$bg-blue: rgba(24, 33, 92, 0.9);
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  #MainContent {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 99;
  }
  .main-content {
    height: 1080px;
    background: url(/images/header.png) no-repeat center / 100% 100%,
      url(/images/pro-bg.png) no-repeat center / 100% 100%;
    pointer-events: none;
    &.single-page {
      background: url(/images/header.png) no-repeat center / 100% 100%,
        url(/images/pro-bg.png) no-repeat center / 100% 100%,
        rgba(0, 0, 0, 1);
    }
    .main-header {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 40px;
      pointer-events: auto;
      .title {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: auto;
        width: 640px;
        height: 40px;
        font-size: 24px;
        font-family: YouSheBiaoTiHei;
        font-weight: 400;
        color: #eff8fc;
        line-height: 40px;
        text-align: center;
        letter-spacing: 8px;
        font-weight: bolder;
        background: linear-gradient(to bottom,
            #e2eaf0 0%,
            #aed1f1 100%);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        // opacity: 0.89;
        // text-shadow: 0px 4px 1px rgba(19, 80, 143, 0.66);
        // background: linear-gradient(0deg, rgba(119, 186, 255, 0.45) 0%, rgba(233, 248, 255, 0.45) 73.3154296875%, rgba(255, 255, 255, 0.45) 100%);
        // -webkit-background-clip: text;
        // -webkit-text-fill-color: transparent;
      }
      .login-out {
        position: absolute;
        top: 10px;
        right: 40px;
        height: 36px;
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 10px;
        cursor: pointer;
        .img {
          width: 16px;
          height: 16px;
          margin-right: 5px;
        }
        span {
          font-size: 13px;
        }
      }
      .login-out:hover {
        background-color: #3c5e8f;
        border-radius: 20px;
      }
    }
    .main-container {
      position: absolute;
      top: 40px;
      left: 40px;
      right: 40px;
      bottom: 40px;
    }
  }
  .main-content-sub {
    height: 1080px;
    background: url(/images/wrapper-box-bg.png) no-repeat center / 100% 100%,
      url(/images/pro-bg.png) no-repeat center / 100% 100%;
    pointer-events: none;
    .main-header {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 40px;
      pointer-events: auto;
      .title {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: auto;
        width: 640px;
        height: 40px;
        font-size: 24px;
        font-family: YouSheBiaoTiHei;
        font-weight: 400;
        color: #eff8fc;
        line-height: 40px;
        text-align: center;
        letter-spacing: 8px;
        font-weight: bolder;
        background: linear-gradient(to bottom,
            #e2eaf0 0%,
            #aed1f1 100%);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        // opacity: 0.89;
        // text-shadow: 0px 4px 1px rgba(19, 80, 143, 0.66);
        // background: linear-gradient(0deg, rgba(119, 186, 255, 0.45) 0%, rgba(233, 248, 255, 0.45) 73.3154296875%, rgba(255, 255, 255, 0.45) 100%);
        // -webkit-background-clip: text;
        // -webkit-text-fill-color: transparent;
      }
      .login-out {
        position: absolute;
        top: 10px;
        right: 40px;
        height: 36px;
        color: #fff;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: space-between;
        cursor: pointer;
        .img {
          width: 16px;
          height: 16px;
        }
        span {
          font-size: 13px;
        }
      }
    }
    .main-container {
      position: absolute;
      top: 40px;
      left: 40px;
      right: 40px;
      bottom: 40px;
    }
  }
}
</style>
<style lang="scss" scoped></style>
src/pages/map/components/mainMenu.vue
New file
@@ -0,0 +1,120 @@
<template>
  <div class="page-mode">
    <div @mouseenter="item.childrenFlag = true" :class="{ active: currentUrl.indexOf(item.path) != -1 }"
      @mouseleave="item.childrenFlag = false" @click="goToPath(item)" v-for="(item, index) in menuList" :key="index">
      {{ item.menuName }}
    </div>
  </div>
</template>
<script setup>
import { ref, reactive, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { Search } from '@element-plus/icons-vue'
import { getTime } from '@/utils/getTime.js'
import { useRouterStore } from 'store/router'
const store = useRouterStore()
let router = useRouter()
let currentUrl = ref('statistics')
const menuList = ref(
  [
    {
      menuName: '园区概况',
      path: '/layout/map/survey'
    },
    {
      menuName: '风险源',
      path: '/layout/map/rs'
    },
    {
      menuName: '应急空间',
      path: '/layout/map/space'
    },
    {
      menuName: '应急物资',
      path: '/layout/single/supplies'
    },
    {
      menuName: '三级防控',
      path: '/layout/map/pac'
    },
    {
      menuName: '救援队伍',
      path: '/layout/single/rt'
    },
    {
      menuName: '突发事件模拟',
      path: '/layout/map/pd'
    },
    {
      menuName: '作战图',
      path: '/layout/single/ochart'
    },
  ]
)
const goToPath = (params) => {
  if (params.children && params.children.length > 0) return
  if (params.path) {
    if (router.currentRoute.value.path == params.path) return
    router.push({
      path: params.path
    })
  } else {
    params.childrenFlag = !params.childrenFlag
  }
}
watch(
  () => router.currentRoute.value,
  (newValue, oldValue) => {
    currentUrl.value = newValue.path
  },
  { immediate: true }
)
const userName = ref('管理员')
</script>
<style lang="scss" scoped>
.page-mode {
  position: absolute;
  top: auto;
  bottom: 55px;
  left: 50%;
  z-index: 99;
  transform: translateX(-50%);
  display: flex;
  pointer-events: auto;
  &>div {
    background-image: url(/images/mode-tab.png);
    background-size: cover;
    width: 136px;
    height: 50px;
    font-size: 16px;
    text-align: center;
    font-weight: bold;
    color: #BFD3E5;
    line-height: 32px;
    padding-top: 12px;
    margin-right: -20px;
    font-style: italic;
    cursor: pointer;
    box-sizing: border-box;
    &:last-child {
      margin-right: 0px;
    }
    &.active {
      color: #F6FCFF;
      background-image: url(/images/mode-tab-ac.png);
    }
  }
}
</style>
src/pages/map/components/mainSearch.vue
New file
@@ -0,0 +1,208 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-26 16:09:35
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-28 19:25:51
 * @FilePath: \bigScreen\src\pages\map\components\mainSearch.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <div class="page-search">
    <el-input placeholder="请输入内容" :suffix-icon="Search" @input="onSearch()" v-model="searchVal"
      @focus="onFocus"></el-input>
    <div class="page-search-value-box" v-show="isShowSearchSKValBox">
      <ul>
        <li v-if="searchSKValList.length > 0" v-for="(item, index) in searchSKValList" :key="index"
          @click="sKValItemClick(item)">{{ item.name }}
        </li>
        <!-- <li v-else>暂无数据</li> -->
        <span v-else>{{ showText }}</span>
      </ul>
    </div>
  </div>
</template>
<script setup>
import { Search } from '@element-plus/icons-vue'
import { fuzzyQuery } from '../../../api/firmInfo/firmInfo'
// 搜索栏相关
let isShowSearchSKValBox = false
let searchVal = ref('')
let searchSKValList = ref([])
let showText = ref('暂无数据')
const onSearch = () => {
  if (searchVal.value == '') {
    isShowSearchSKValBox = false
    // 清空
    clearPoint()
  } else {
    showText.value = '搜索中...'
    searchSKValList.value = []
    isShowSearchSKValBox = true
    getFuzzyQuery()
  }
}
function getFuzzyQuery () {
  fuzzyQuery({
    name: searchVal.value
  }).then(res => {
    if (res.data.data.length > 0) {
      searchSKValList.value = res.data.data
    } else {
      showText.value = '暂无数据'
    }
  })
}
const onFocus = () => {
  onSearch()
}
const sKValItemClick = (item) => {
  isShowSearchSKValBox = false
  if (item.lat && item.lng) {
    handleCheckChange(item)
  } else {
    console.log('没有经纬度')
  }
}
let addTileLayers = {}
const handleCheckChange = (item) => {
  // 先清空,在添加
  clearPoint()
  if (!addTileLayers[item.name]) {
    addTileLayers[item.name] = new DC.HtmlLayer(item.name)
    window.$viewer.addLayer(addTileLayers[item.name])
    let iconEl = ''
    if ('showPanel' in item && item.showPanel == false) {
      if (item.backgroundIcon) {
        iconEl = `
                        <div class="map-name">${i[item.showParams] || item.name}</div>
                        <div class="map-icon">
                          <img src="${item.backgroundIcon}">
                        </div>
                        `
      }
    } else {
      iconEl = `<div class="marsBlueGradientPnl">
                               <div>${item.name}</div>  </div>`
    }
    let divIcon = new DC.DivIcon(
      new DC.Position(item.lng, item.lat, 0),
      `<div class="public-map-popup">
                  ${iconEl}
                </div>`
    )
    divIcon.attrParams = item
    let incident = () => { }
    if (item.incident) incident = item.incident
    divIcon.on(DC.MouseEventType.CLICK, incident)
    addTileLayers[item.name].addOverlay(divIcon)
    window.$viewer.flyToPosition(new DC.Position(item.lng, item.lat, 2000, 0, -90, 0))
  } else {
    window.$viewer.removeLayer(addTileLayers[item.name])
    addTileLayers[item.name] = null
    delete addTileLayers[item.name]
  }
}
function clearPoint () {
  let arr = Object.keys(addTileLayers)
  arr.forEach(i => {
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
}
onUnmounted(() => {
  let arr = Object.keys(addTileLayers)
  arr.forEach(i => {
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
  addTileLayers = null
})
</script>
<style lang="scss" scoped>
.page-search {
  position: absolute;
  left: 488px;
  z-index: 99;
  top: 110px;
  pointer-events: auto;
  ::v-deep(.el-input) {
    height: 38px;
    width: 280px;
    .el-input__wrapper {
      font-size: 16px;
      font-weight: 400;
      border: 1px solid #4081CB;
      border-radius: 4px;
      background: rgba(135, 158, 199, 0.3);
      box-shadow: inset 0px 3px 7px 0px rgba(42, 138, 236, 0.95);
      .el-input__inner {
        color: #BFD3E5;
      }
    }
  }
  .page-search-value-box {
    position: absolute;
    width: 100%;
    height: 200px;
    left: 0;
    top: 40px;
    background: rgba(135, 158, 199, 0.3);
    border-radius: 2px;
    overflow-y: scroll;
    ul>li {
      color: #ffffff;
      cursor: pointer;
      height: 20px;
      margin: 3px;
      line-height: 20px;
      padding-left: 10px;
      overflow: hidden;
    }
    ul>li:hover {
      background-color: #949597;
    }
  }
  .page-search-value-box>ul>span {
    color: #fff;
    display: flex;
    justify-content: center;
    margin-top: 20px;
  }
  .page-search-value-box::-webkit-scrollbar {
    display: none
  }
}
</style>
src/pages/map/components/mainTool.vue
New file
@@ -0,0 +1,115 @@
<template>
  <div class="toolBarRight animation-slide-top no-print-view">
    <el-button v-for="item, index in btnGroup" :key="index" @click="btnClick(item)"
      class="btn btn-link toolBarRight-btn">
      <i :class="item.icon"></i>{{ item.name }}
    </el-button>
  </div>
  <base-map v-show="currentComponent == 'map'" @close="closeBox"></base-map>
  <layers-control :show="currentComponent == 'layers'" @close="closeBox"></layers-control>
  <tool-list :moreToolShow="moreToolShow" @close="closeBox"></tool-list>
</template>
<script setup>
import baseMap from './scomponents/baseMap.vue'
import layersControl from './scomponents/layersControl.vue'
import toolList from './scomponents/toolList.vue'
const currentComponent = ref('')
let moreToolShow = ref(false)
const btnGroup = [
  {
    name: '底图',
    icon: 'fa fa-map',
    key: 'map',
  },
  {
    name: '图层',
    icon: 'fa fa-tasks',
    key: 'layers',
  },
  {
    name: '工具',
    icon: 'fa fa-cubes',
    key: 'tool',
  },
]
const btnClick = (item) => {
  if (item.key == 'tool') {
    moreToolShow.value = !moreToolShow.value
    return
  }
  if (currentComponent.value == item.key) {
    closeBox(item.key)
    return
  }
  currentComponent.value = item.key
}
const closeBox = (type) => {
  if (type == 'tool') {
    moreToolShow.value = false
  } else {
    currentComponent.value = ''
  }
}
</script>
<style lang="scss" scoped>
.toolBarRight {
  display: flex;
  flex-wrap: nowrap;
  position: absolute;
  right: 540px;
  z-index: 99;
  top: 110px;
  border: 1px solid #4081CB;
  border-radius: 4px;
  background: rgba(135, 158, 199, 0.3);
  box-shadow: inset 0px 3px 7px 0px rgba(42, 138, 236, 0.95);
  pointer-events: auto;
  ::v-deep(.el-button) {
    margin-left: 0;
    border: none;
    border-radius: 0;
    background: transparent;
    &.btn {
      padding: 4px 12px;
      font-size: 14px;
      line-height: 1.6;
      -webkit-transition: border .2s linear, color .2s linear, width .2s linear, background-color .2s linear;
      -o-transition: border .2s linear, color .2s linear, width .2s linear, background-color .2s linear;
      transition: border .2s linear, color .2s linear, width .2s linear, background-color .2s linear;
    }
    &.btn-link {
      font-weight: 400;
      color: #007bff;
      text-decoration: none;
    }
    &.toolBarRight-btn {
      list-style-type: none;
      cursor: pointer;
      border-right: solid 1px #2b2c2f;
      color: #edffff;
    }
    &.toolBarRight-btn:last-child {
      border-right: none;
    }
    i {
      margin-right: 4px;
    }
  }
}
</style>
src/pages/map/components/scomponents/baseMap.vue
New file
@@ -0,0 +1,359 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-28 11:44:45
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-25 19:39:24
 * @FilePath: \bigScreen\src\pages\layout\components\scomponents\baseMap.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <public-box>
    <template #name>
      <div class="name"><i class="fa fa-map"></i>&nbsp;底图</div>
    </template>
    <template #close>
      <div class="close cursor-p" @click="$emit('close', 'map')"><i class="fa fa-close"></i></div>
    </template>
    <template #content>
      <div class="layers-box-content">
        <ul class="layers-box">
          <li :class="{ on: item.mode == curMode }" v-for="item, index in baseMaps" :key="index"
            @click="loadLAYER(item.mode, index)">
            <div><img :src="item.src"></div>
            <div>{{ item.name }}</div>
          </li>
        </ul>
      </div>
      <div class="show-terrain" style="margin-left:10px;color:#fff">
        <el-checkbox @change="terrainChange" v-model="showTerrainFlag" label="显示地形" size="large" />
      </div>
    </template>
  </public-box>
</template>
<script setup>
import { getAssetsFile } from 'utils/utils'
import AmapMercatorTilingScheme from './cesium/AmapMercatorTilingScheme/index'
const { appContext } = getCurrentInstance()
const global = appContext.config.globalProperties
const cesiumToken =
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTZlNGNlYS01NTU1LTQ1MGEtYmNlZS0yNTE2NDk5YWM2MjEiLCJpZCI6MTc5Njk2LCJpYXQiOjE3MDA1NDcwMjV9.qcl4AH2731cfFd0-I1ZLUINPXqvglLkDFD-UGR2zU5M'
window.$Cesium.Ion.defaultAccessToken = cesiumToken
const TDT_Token = 'c6eea7dad4fa1e2d1e32ec0e7c9735db'
// 天地图Key
// 天地图地图
const TDT_IMG_C = 'https://{s}.tianditu.gov.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0' +
  '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
  '&style=default&format=tiles&tk=' + TDT_Token
// 天地图注记
const TDT_ZJ = 'https://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0' +
  '&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
  '&style=default&format=tiles&tk=' + TDT_Token
// 标准地图注记
const TID_STAND = 'https://{s}.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0' +
  '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
  '&style=default&format=tiles&tk=' + TDT_Token
const imageryProvider_standZh = new window.$Cesium.UrlTemplateImageryProvider({
  url: 'https://t{s}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
  subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
  maximumLevel: 18,
  credit: 'stand_zj',
})
const imageryProvider_stand = new window.$Cesium.UrlTemplateImageryProvider({
  url: 'https://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
  subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
  // format: 'image/jpeg',
  // show: true,
  maximumLevel: 18,
  credit: 'stand_tc',
})
const annotation = new window.$Cesium.WebMapTileServiceImageryProvider({
  url: TDT_ZJ,
  layer: 'tdtZwImg_c',
  style: 'default',
  format: 'tiles',
  tileMatrixSetID: 'c',
  subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
  tilingScheme: new window.$Cesium.GeographicTilingScheme(),
  tileMatrixLabels: [
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    '10',
    '11',
    '12',
    '13',
    '14',
    '15',
    '16',
    '17',
    '18',
    '19',
  ],
  maximumLevel: 50,
})
const imageryProvider_tdt = new window.$Cesium.WebMapTileServiceImageryProvider({
  url: TDT_IMG_C,
  layer: 'tdtImg_c',
  style: 'default',
  format: 'tiles',
  tileMatrixSetID: 'c',
  subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
  tilingScheme: new window.$Cesium.GeographicTilingScheme(),
  tileMatrixLabels: [
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    '10',
    '11',
    '12',
    '13',
    '14',
    '15',
    '16',
    '17',
    '18',
    '19',
  ],
  maximumLevel: 17,
})
const imageryProvider_ammapSL = new window.$Cesium.UrlTemplateImageryProvider({
  url: 'https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
  layer: 'tdtVecBasicLayer',
  style: 'default',
  format: 'image/png',
  tileMatrixSetID: 'GoogleMapsCompatible',
  subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
  maximumLevel: 18,
  tilingScheme: new AmapMercatorTilingScheme(),
  credit: 'amap_SL',
})
const imageryProvider_ammap = new window.$Cesium.UrlTemplateImageryProvider({
  url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
  layer: 'tdtVecBasicLayer',
  style: 'default',
  format: 'image/png',
  tileMatrixSetID: 'GoogleMapsCompatible',
  subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
  maximumLevel: 18,
  tilingScheme: new AmapMercatorTilingScheme(),
  credit: 'amap_stand',
})
const imageryProvider_ammapBz = new window.$Cesium.UrlTemplateImageryProvider({
  url: 'https://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8',
  tilingScheme: new AmapMercatorTilingScheme(),
  minimumLevel: 3,
})
let mapLayers = [
  {
    src: getAssetsFile('stand.png'),
    mode: '0',
    name: '天地图矢量',
    layers: [
      { key: 'imageryProvider_standZh', layer: imageryProvider_standZh },
      { key: 'imageryProvider_stand', layer: imageryProvider_stand },
    ]
  },
  {
    src: getAssetsFile('satellite.png'),
    mode: '1',
    name: '天地图影像',
    layers: [
      { key: 'annotation', layer: annotation },
      {
        key: 'imageryProvider_tdt',
        layer: imageryProvider_tdt,
      }
    ]
  },
  {
    src: getAssetsFile('stand.png'),
    mode: '2',
    name: '高德矢量',
    layers: [
      {
        key: 'imageryProvider_ammapSL',
        layer: imageryProvider_ammapSL,
      }
    ]
  },
  {
    src: getAssetsFile('satellite.png'),
    mode: '3',
    name: '高德影像',
    layers: [
      { key: 'imageryProvider_ammapBz', layer: imageryProvider_ammapBz },
      { key: 'imageryProvider_ammap', layer: imageryProvider_ammap },
    ]
  }
]
let curMode = ref(null)
let baseMaps = reactive([])
baseMaps = mapLayers.map(item => {
  return {
    src: item.src,
    mode: item.mode,
    name: item.name,
  }
})
let globalBaseMapLayers = []
const loadLAYER = (mode, ind, cb = () => { }) => {
  if (mode == curMode.value) return
  let curmapLayers = []
  globalBaseMapLayers.length &&
    globalBaseMapLayers.forEach((item) => {
      item.mapLayer.show = false
    })
  curmapLayers.push(
    ...mapLayers[ind].layers,
  )
  // 创建一个Set来快速查找array2中的id
  let keyBaseMap = new Set(globalBaseMapLayers.map((item) => item.key))
  let keyMapLayers = new Set(curmapLayers.map((item) => item.key))
  let keyExistBaseMap = curmapLayers.filter((item) => !keyBaseMap.has(item.key))
  let keyNoExistBaseMap = globalBaseMapLayers.filter((item) =>
    keyMapLayers.has(item.key),
  )
  keyExistBaseMap.length &&
    keyExistBaseMap.forEach((item) => {
      let curLayer = {
        key: item.key,
        mapLayer: window.$viewer?.imageryLayers.addImageryProvider(item.layer),
      }
      curLayer.mapLayer.show = true
      window.$viewer?.imageryLayers.lowerToBottom(curLayer.mapLayer)
      globalBaseMapLayers.push(curLayer)
    })
  keyNoExistBaseMap.length &&
    keyNoExistBaseMap.forEach((item) => {
      item.mapLayer.show = true
      window.$viewer?.imageryLayers.lowerToBottom(item.mapLayer)
    })
  curMode.value = mode
}
setTimeout(() => {
  loadLAYER(1, 1)
}, 0)
const showTerrainFlag = ref(true)
const terrainChange = (e) => {
  if (e) {
    let terrain = DC.TerrainFactory.createTerrain(DC.TerrainType.XYZ, {
      url: 'https://data.mars3d.cn/terrain'
    })
    window.$viewer.setTerrain(terrain)
  } else {
    window.$viewer.setTerrain()
  }
}
terrainChange(true)
</script>
<style lang="scss" scoped>
.close {
  cursor: pointer;
}
.layers-box-content {
  .layers-box {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    width: 354px;
    padding: 0 10px;
    box-sizing: border-box;
    li {
      margin-top: 10px;
      cursor: pointer;
      &.on,
      &:hover {
        div:first-child {
          border: solid 2px #337fe5;
        }
        div:last-child {
          color: #337fe5;
        }
      }
      div:first-child {
        width: 76px;
        height: 76px;
        background: red;
        border: 2px solid white;
        box-sizing: border-box;
        img {
          width: 100%;
          height: 100%;
        }
      }
      div:last-child {
        width: 76px;
        height: 20px;
        line-height: 20px;
        color: #fff;
        font-size: 12px;
        text-align: center;
      }
    }
  }
}
.show-terrain {
  ::v-deep(.el-checkbox) {
    .el-checkbox__label {
      color: #fff;
    }
  }
}
</style>
src/pages/map/components/scomponents/cesium/AmapMercatorTilingScheme/CoordTransform.js
New file
@@ -0,0 +1,178 @@
// 定义一些常量
const BD_FACTOR = (3.14159265358979324 * 3000.0) / 180.0;
const PI = 3.1415926535897932384626;
const RADIUS = 6378245.0;
const EE = 0.00669342162296594323;
class CoordTransform {
    /**
     * BD-09(百度坐标系) To GCJ-02(火星坐标系)
     * @param lng
     * @param lat
     * @returns {number[]}
     */
    static BD09ToGCJ02(lng, lat) {
        let x = +lng - 0.0065;
        let y = +lat - 0.006;
        let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * BD_FACTOR);
        let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * BD_FACTOR);
        let gg_lng = z * Math.cos(theta);
        let gg_lat = z * Math.sin(theta);
        return [gg_lng, gg_lat];
    }
    /**
     * GCJ-02(火星坐标系) To BD-09(百度坐标系)
     * @param lng
     * @param lat
     * @returns {number[]}
     * @constructor
     */
    static GCJ02ToBD09(lng, lat) {
        lat = +lat;
        lng = +lng;
        let z =
            Math.sqrt(lng * lng + lat * lat) +
            0.00002 * Math.sin(lat * BD_FACTOR);
        let theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * BD_FACTOR);
        let bd_lng = z * Math.cos(theta) + 0.0065;
        let bd_lat = z * Math.sin(theta) + 0.006;
        return [bd_lng, bd_lat];
    }
    /**
     * WGS-84(世界大地坐标系) To GCJ-02(火星坐标系)
     * @param lng
     * @param lat
     * @returns {number[]}
     */
    static WGS84ToGCJ02(lng, lat) {
        lat = +lat;
        lng = +lng;
        if (this.out_of_china(lng, lat)) {
            return [lng, lat];
        } else {
            let d = this.delta(lng, lat);
            return [lng + d[0], lat + d[1]];
        }
    }
    /**
     * GCJ-02(火星坐标系) To WGS-84(世界大地坐标系)
     * @param lng
     * @param lat
     * @returns {number[]}
     * @constructor
     */
    static GCJ02ToWGS84(lng, lat) {
        lat = +lat;
        lng = +lng;
        if (this.out_of_china(lng, lat)) {
            return [lng, lat];
        } else {
            let d = this.delta(lng, lat);
            let mgLng = lng + d[0];
            let mgLat = lat + d[1];
            return [lng * 2 - mgLng, lat * 2 - mgLat];
        }
    }
    /**
     *
     * @param lng
     * @param lat
     * @returns {number[]}
     */
    static delta(lng, lat) {
        let dLng = this.transformLng(lng - 105, lat - 35);
        let dLat = this.transformLat(lng - 105, lat - 35);
        const radLat = (lat / 180) * PI;
        let magic = Math.sin(radLat);
        magic = 1 - EE * magic * magic;
        const sqrtMagic = Math.sqrt(magic);
        dLng = (dLng * 180) / ((RADIUS / sqrtMagic) * Math.cos(radLat) * PI);
        dLat =
            (dLat * 180) / (((RADIUS * (1 - EE)) / (magic * sqrtMagic)) * PI);
        return [dLng, dLat];
    }
    /**
     *
     * @param lng
     * @param lat
     * @returns {number}
     */
    static transformLng(lng, lat) {
        lat = +lat;
        lng = +lng;
        let ret =
            300.0 +
            lng +
            2.0 * lat +
            0.1 * lng * lng +
            0.1 * lng * lat +
            0.1 * Math.sqrt(Math.abs(lng));
        ret +=
            ((20.0 * Math.sin(6.0 * lng * PI) +
                20.0 * Math.sin(2.0 * lng * PI)) *
                2.0) /
            3.0;
        ret +=
            ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) *
                2.0) /
            3.0;
        ret +=
            ((150.0 * Math.sin((lng / 12.0) * PI) +
                300.0 * Math.sin((lng / 30.0) * PI)) *
                2.0) /
            3.0;
        return ret;
    }
    /**
     *
     * @param lng
     * @param lat
     * @returns {number}
     */
    static transformLat(lng, lat) {
        lat = +lat;
        lng = +lng;
        let ret =
            -100.0 +
            2.0 * lng +
            3.0 * lat +
            0.2 * lat * lat +
            0.1 * lng * lat +
            0.2 * Math.sqrt(Math.abs(lng));
        ret +=
            ((20.0 * Math.sin(6.0 * lng * PI) +
                20.0 * Math.sin(2.0 * lng * PI)) *
                2.0) /
            3.0;
        ret +=
            ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) *
                2.0) /
            3.0;
        ret +=
            ((160.0 * Math.sin((lat / 12.0) * PI) +
                320 * Math.sin((lat * PI) / 30.0)) *
                2.0) /
            3.0;
        return ret;
    }
    /**
     * 判断是否在国内。不在国内不做偏移
     * @param lng
     * @param lat
     * @returns {boolean}
     */
    static out_of_china(lng, lat) {
        lat = +lat;
        lng = +lng;
        return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
    }
}
export default CoordTransform;
src/pages/map/components/scomponents/cesium/AmapMercatorTilingScheme/index.js
New file
@@ -0,0 +1,53 @@
/*
 * @Author: GuLiMmo 2820890765@qq.com
 * @Date: 2024-05-11 09:18:29
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-27 11:19:55
 * @FilePath: \bigScreen\src\pages\layout\components\scomponents\cesium\AmapMercatorTilingScheme\index.js
 * @Description: 高德地图纠偏
 * Copyright (c) 2024 by GuLiMmo, All Rights Reserved.
 */
const {
  WebMercatorProjection,
  WebMercatorTilingScheme,
  Math,
  Cartographic,
  Cartesian2,
} = DC.__namespace.Cesium
// window.DC.getLib('Cesium')
import CoordTransform from './CoordTransform'
class AmapMercatorTilingScheme extends WebMercatorTilingScheme {
  constructor() {
    super()
    let projection = new WebMercatorProjection()
    this._projection.project = function (cartographic, result) {
      result = CoordTransform.WGS84ToGCJ02(
        Math.toDegrees(cartographic.longitude),
        Math.toDegrees(cartographic.latitude),
      )
      result = projection.project(
        new Cartographic(
          Math.toRadians(result[0]),
          Math.toRadians(result[1]),
        ),
      )
      return new Cartesian2(result.x, result.y)
    }
    this._projection.unproject = function (cartesian, result) {
      let cartographic = projection.unproject(cartesian)
      result = CoordTransform.GCJ02ToWGS84(
        Math.toDegrees(cartographic.longitude),
        Math.toDegrees(cartographic.latitude),
      )
      return new Cartographic(
        Math.toRadians(result[0]),
        Math.toRadians(result[1]),
      )
    }
  }
}
export default AmapMercatorTilingScheme
src/pages/map/components/scomponents/layersControl.vue
New file
@@ -0,0 +1,968 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-31 10:47:29
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-12-01 21:45:13
 * @FilePath: \bigScreen\src\pages\map\components\scomponents\layersControl.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <public-box v-show="showLayerControl">
    <template #name>
      <div class="name"><i class="fa fa-tasks"></i>&nbsp;图层</div>
    </template>
    <template #close>
      <div class="close cursor-p" @click="emit('close', 'layers')"><i class="fa fa-close"></i></div>
    </template>
    <template #content>
      <div class="tree-content">
        <el-tree ref="treeRef" :data="data" draggable="" show-checkbox node-key="id" default-expand-all
          :default-checked-keys="indexPoint" :props="defaultProps" :indent="treeProps['indent']"
          @check="handleCheckChange">
          <template v-slot:default="{ node }">
            <element-tree-line :node="node" :showLabelLine="treeProps['showLabelLine']" :indent="treeProps['indent']">
              <!-- 自定义label的slot -->
              <template v-slot:node-label>
                <span style="font-size: 12px">
                  {{ node.label }}
                  <i class="el-icon-eleme"></i></span>
              </template>
              <!-- 在右边追加内容的slot -->
              <!-- <template v-slot:after-node-label>
                <span style="padding-right: 10px">
                  <el-button type="primary" size="mini" @click.stop="openDrawer(node)">新增子节点</el-button>
                  <el-button type="primary" size="mini" @click.stop="openDrawer(node)">修改</el-button>
                  <el-button type="danger" size="mini" @click.stop="openDialog">删除</el-button></span>
              </template> -->
            </element-tree-line>
          </template>
        </el-tree>
      </div>
    </template>
  </public-box>
  <panorama v-show="panoramaShow" :title="panoramaTitle" :url="panoramaUrl" @closePanoramaPopup="closePanoramaPopup">
  </panorama>
</template>
<script setup>
let addPupoLayers = {}
let addTileLayers = {}
let tileLayers = new DC.TilesetLayer('tileLayers')
window.$viewer.addLayer(tileLayers)
const {
  show: showLayerControl
} = defineProps({
  show: {
    default: false
  }
})
const emit = defineEmits(['close'])
import panorama from './popup/panorama.vue'
import { getPage } from '@/api/indParkInfo'
import { getPage as getfirmPage } from '@/api/firmInfo/firmInfo'
import { getList, getGouQu } from "@/api/space/space"
import { getList as getRiskList } from "@/api/riskSource/riskSource"
import { getPanoramaList } from "@/api/panorama/"
import yqfw from "@/assets/json/yqfw"
import gsgw from "@/assets/json/gsgw"
import rqgw from "@/assets/json/rqgw"
import wsgw from "@/assets/json/wsgw"
import ysgw from "@/assets/json/ysgw"
import { onUnmounted } from 'vue'
import EventBus from 'utils/bus'
import { usePointStore } from 'store/usepoint'
const pointStore = usePointStore()
const { VITE_APP_BASE } = import.meta.env
// , '7',
let indexPoint = ref(['1', '5'])
const treeRef = ref(null)
const treeProps = {
  indent: 16,
  showLabelLine: true,
}
// 全景相关
const panoramaShow = ref(false)
const panoramaTitle = ref('')
const panoramaUrl = ref('')
const closePanoramaPopup = () => {
  panoramaShow.value = false
}
const data = [
  {
    id: '1',
    label: '园区倾斜摄影',
    type: 'layer',
    subType: '3Dtile',
    urlData: [
    ],
    layerName: 'hgyq'
  },
  {
    id: '2',
    label: '企业分布',
    type: 'layer',
    subType: 'labelPoint',
    method: getPage,
    params: {
      size: 1000
    },
    backgroundIcon: VITE_APP_BASE + 'img/mapicon/qy.png',
    className: 'qyfb-box',
    showPanel: false,
    layerName: 'qyfb'
  },
  {
    id: '3',
    label: '应急空间',
    children: [
      {
        id: '3-1',
        label: '应急池',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 1,
          size: 1000
        },
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/yjc.png',
        className: 'yjc-box',
        showPanel: false,
        layerName: 'yjc',
        incident: (e) => {
          const { attrParams } = e.overlay
          // 删除
          destroy()
          if (!attrParams.imageUrl) {
            return
          }
          addPupoLayers[attrParams.name] = new DC.HtmlLayer(attrParams.name)
          window.$viewer.addLayer(addPupoLayers[attrParams.name])
          let iconEl = `<div class="marsBlueGradientPnl">
            <div>${attrParams.fullName}</div>
            <img src="${attrParams.imageUrl}" />
                </div>`
          let divIcon = new DC.DivIcon(
            new DC.Position(attrParams.lng, attrParams.lat, 64),
            `<div class="public-map-popup-two">
                    ${iconEl}
                  </div>`
          )
          let incident = () => {
            destroy()
          }
          divIcon.on(DC.MouseEventType.CLICK, incident)
          addPupoLayers[attrParams.name].addOverlay(divIcon)
        }
      },
      {
        id: '3-2',
        label: '阀门',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 2,
          size: 1000
        },
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/ysf.png',
        className: 'ysf-box',
        showPanel: false,
        layerName: 'fm',
        incident: (e) => {
          const { attrParams } = e.overlay
          // 删除
          destroy()
          if (!attrParams.imageUrl) {
            return
          }
          addPupoLayers[attrParams.name] = new DC.HtmlLayer(attrParams.name)
          window.$viewer.addLayer(addPupoLayers[attrParams.name])
          let iconEl = `<div class="marsBlueGradientPnl">
                  <div>${attrParams.fullName}</div>
                  <img src="${attrParams.imageUrl}" width="160" height="160" />
                </div>`
          let divIcon = new DC.DivIcon(
            new DC.Position(attrParams.lng, attrParams.lat, 64),
            `<div class="public-map-popup-two">
                    ${iconEl}
                  </div>`
          )
          let incident = () => {
            destroy()
          }
          divIcon.on(DC.MouseEventType.CLICK, incident)
          addPupoLayers[attrParams.name].addOverlay(divIcon)
        }
      },
      {
        id: '3-3',
        label: '公共管网',
        children: [
          // 给水管网、污水管网、燃气管网、雨水管网
          {
            id: '3-3-1',
            label: '给水管网',
            type: 'layer',
            subType: 'geojsonPipe',
            layerName: 'gsgw',
            source: gsgw,
            color: DC.Color.BLUE.withAlpha(0.9),
            height: 65,
          },
          {
            id: '3-3-2',
            label: '污水管网',
            type: 'layer',
            subType: 'geojsonPipe',
            layerName: 'wsgw',
            source: wsgw,
            color: DC.Color.DARKBLUE.withAlpha(0.9),
            height: 68,
          },
          {
            id: '3-3-3',
            label: '燃气管网',
            type: 'layer',
            subType: 'geojsonPipe',
            layerName: 'rqgw',
            source: rqgw,
            color: DC.Color.RED.withAlpha(0.9),
            height: 71,
          },
          {
            id: '3-3-4',
            label: '雨水管网',
            type: 'layer',
            subType: 'geojsonPipe',
            layerName: 'ysgw',
            source: ysgw,
            color: DC.Color.CYAN.withAlpha(0.9),
            height: 75,
          },
        ]
      },
      {
        id: '3-4',
        label: '污水提升泵站',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 4,
          size: 1000
        },
        layerName: 'wstsbz',
        incident: (e) => {
          const { attrParams } = e.overlay
          // 删除
          destroy()
          if (!attrParams.imageUrl) {
            return
          }
          addPupoLayers[attrParams.name] = new DC.HtmlLayer(attrParams.name)
          window.$viewer.addLayer(addPupoLayers[attrParams.name])
          let iconEl = `<div class="marsBlueGradientPnl">
                  <div>${attrParams.fullName}</div>
                  <img src="${attrParams.imageUrl}" width="160" height="160" />
                </div>`
          let divIcon = new DC.DivIcon(
            new DC.Position(attrParams.lng, attrParams.lat, 64),
            `<div class="public-map-popup-two">
                    ${iconEl}
                  </div>`
          )
          let incident = () => {
            destroy()
          }
          divIcon.on(DC.MouseEventType.CLICK, incident)
          addPupoLayers[attrParams.name].addOverlay(divIcon)
        }
      },
      {
        id: '3-5',
        label: '水库',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 5,
          size: 1000
        },
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/sk.png',
        className: 'sk-box',
        showPanel: false,
        layerName: 'sk',
        incident: (e) => {
          const { attrParams } = e.overlay
          // 删除
          destroy()
          if (!attrParams.imageUrl) {
            return
          }
          addPupoLayers[attrParams.name] = new DC.HtmlLayer(attrParams.name)
          window.$viewer.addLayer(addPupoLayers[attrParams.name])
          let iconEl = `<div class="marsBlueGradientPnl">
                   <div>${attrParams.fullName}</div>
                  <img src="${attrParams.imageUrl}" width="160" height="160" />
                </div>`
          let divIcon = new DC.DivIcon(
            new DC.Position(attrParams.lng, attrParams.lat, 64),
            `<div class="public-map-popup-two">
                    ${iconEl}
                  </div>`
          )
          let incident = () => {
            destroy()
          }
          divIcon.on(DC.MouseEventType.CLICK, incident)
          addPupoLayers[attrParams.name].addOverlay(divIcon)
        }
      },
      {
        id: '3-6',
        label: '应急泵',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 6,
          size: 1000
        },
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/yjb.png',
        className: 'yjb-box',
        showPanel: false,
        layerName: 'yjb',
        incident: (e) => {
          const { attrParams } = e.overlay
          // 删除
          destroy()
          if (!attrParams.imageUrl) {
            return
          }
          addPupoLayers[attrParams.name] = new DC.HtmlLayer(attrParams.name)
          window.$viewer.addLayer(addPupoLayers[attrParams.name])
          let iconEl = `<div class="marsBlueGradientPnl">
                  <div>${attrParams.fullName}</div>
                  <img src="${attrParams.imageUrl}" width="160" height="160" />
                </div>`
          let divIcon = new DC.DivIcon(
            new DC.Position(attrParams.lng, attrParams.lat, 64),
            `<div class="public-map-popup-two">
                    ${iconEl}
                  </div>`
          )
          let incident = () => {
            destroy()
          }
          divIcon.on(DC.MouseEventType.CLICK, incident)
          addPupoLayers[attrParams.name].addOverlay(divIcon)
        }
      },
      {
        id: '3-8',
        label: '沟渠',
        type: 'layer',
        subType: 'geojsonPolygon',
        method: getGouQu,
        params: {
          type: 8,
          size: 1000
        },
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/gouqu.png',
        className: 'xfs-box',
        showPanel: false,
        layerName: 'gouqu'
      },
      {
        id: '3-9',
        label: '废水处理站',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 9,
          size: 1000
          // name: '吉水县绿源污水处理厂',
        },
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/wsclc.png',
        className: 'xfs-box',
        showPanel: false,
        layerName: 'fsclz'
      },
      {
        id: '3-10',
        label: '排水口',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 10,
          size: 1000
        },
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/psk.png',
        className: 'xfs-box',
        showPanel: false,
        layerName: 'psk'
      },
      {
        id: '3-11',
        label: '污水池',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 11,
          size: 1000
        },
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/wsc.png',
        className: 'xfs-box',
        showPanel: false,
        layerName: 'wsc'
      }
    ]
  },
  {
    id: '4',
    label: '风险源',
    children: [
      {
        id: '4-1',
        label: '一般',
        type: 'layer',
        subType: 'labelPoint',
        method: getRiskList,
        params: {
          riskLevel: 1,
          size: 1000
        },
        showParams: 'category',
        className: 'fxy-ordinary',
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/fxy.png',
        showPanel: false,
        layerName: 'fxyOrdinary',
        incident: (e) => {
          const { attrParams } = e.overlay
          // 删除
          destroy()
          addPupoLayers[attrParams.name] = new DC.HtmlLayer(attrParams.name)
          window.$viewer.addLayer(addPupoLayers[attrParams.name])
          let iconEl = `<div class="marsBlueGradientPnl">
            <li>${attrParams.firmName || ''}</li>
            <li>${attrParams.riskLevelName || ''}</li>
            </div>`
          let divIcon = new DC.DivIcon(
            new DC.Position(attrParams.lng, attrParams.lat, 64),
            `<div class="public-map-popup-three">
                    ${iconEl}
                  </div>`
          )
          let incident = () => {
            destroy()
          }
          divIcon.on(DC.MouseEventType.CLICK, incident)
          addPupoLayers[attrParams.name].addOverlay(divIcon)
        }
      },
      {
        id: '4-2',
        label: '较大',
        type: 'layer',
        subType: 'labelPoint',
        method: getRiskList,
        params: {
          riskLevel: 2,
          size: 1000
        },
        showParams: 'category',
        className: 'fxy-larger',
        backgroundIcon: VITE_APP_BASE + 'img/mapicon/fxy.png',
        showPanel: false,
        layerName: 'fxyLarger',
        incident: (e) => {
          const { attrParams } = e.overlay
          // 删除
          destroy()
          addPupoLayers[attrParams.name] = new DC.HtmlLayer(attrParams.name)
          window.$viewer.addLayer(addPupoLayers[attrParams.name])
          let iconEl = `<div class="marsBlueGradientPnl">
            <li>${attrParams.firmName || ''}</li>
            <li>${attrParams.riskLevelName || ''}</li>
            </div>`
          let divIcon = new DC.DivIcon(
            new DC.Position(attrParams.lng, attrParams.lat, 64),
            `<div class="public-map-popup-three">
                    ${iconEl}
                  </div>`
          )
          let incident = () => {
            destroy()
          }
          divIcon.on(DC.MouseEventType.CLICK, incident)
          addPupoLayers[attrParams.name].addOverlay(divIcon)
        }
      }
    ]
  },
  {
    id: '5',
    label: '园区范围',
    type: 'layer',
    subType: 'geojsonWall',
    layerName: 'yqfw',
    source: yqfw
  },
  {
    id: '7',
    label: '空中全景分布',
    type: 'layer',
    subType: 'labelPoint',
    method: getPanoramaList,
    params: {
      size: 1000,
      remark: '1'
    },
    backgroundIcon: VITE_APP_BASE + 'img/mapicon/qj.png',
    showPanel: false,
    layerName: 'kzqjdwfb',
    incident: (e) => {
      const { attrParams } = e.overlay
      panoramaTitle.value = attrParams.name
      if (
        attrParams.url.indexOf("http://vr.jxpskj.com:180") != -1
      ) {
        attrParams.url = attrParams.url.replace(
          "http://vr.jxpskj.com:180",
          "/panorama"
        )
      }
      panoramaUrl.value = attrParams.url
      panoramaShow.value = true
    }
  },
  {
    id: '8',
    label: '地面全景分布',
    type: 'layer',
    subType: 'labelPoint',
    method: getPanoramaList,
    params: {
      size: 1000,
      remark: '2'
    },
    backgroundIcon: VITE_APP_BASE + 'img/mapicon/qj.png',
    showPanel: false,
    layerName: 'dtqjdwfb',
    incident: (e) => {
      const { attrParams } = e.overlay
      panoramaTitle.value = attrParams.name
      if (
        attrParams.url.indexOf("http://vr.jxpskj.com:180") != -1
      ) {
        attrParams.url = attrParams.url.replace(
          "http://vr.jxpskj.com:180",
          "/panorama"
        )
      }
      panoramaUrl.value = attrParams.url
      panoramaShow.value = true
    }
  },
]
// let modellayer = new DC.VectorLayer("modellayer").addTo(window.$viewer)
// let model = new DC.Model("121.46748793889597,31.22345700031846,200", VITE_APP_BASE + 'gltf/dajiang.gltf')
// model.setStyle({
//   scale: 10000
// })
// modellayer.addOverlay(model)
// window.$viewer.flyToPosition("121.46748793889597,31.22345700031846,300,0,-90")
const defaultProps = {
  children: 'children',
  label: 'label',
}
const checkType = (value) => {
  if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
    return 'obj'
  } else if (Array.isArray(value)) {
    return 'arr'
  }
}
// 用于存储收集到的节点的数组
const collectedNodes = reactive([])
// 递归函数,收集所有 flag 为 true 的子节点
const collectNodesWithFlag = (nodes) => {
  if (checkType(nodes) == 'obj') {
    if (nodes.type == 'layer') {
      collectedNodes.value.push(nodes)
    }
    if (nodes.children && nodes.children.length > 0) {
      collectNodesWithFlag(nodes.children)
      return
    }
  }
  if (checkType(nodes) == 'arr') {
    nodes.forEach(item => {
      if (item) {
        if (item.type == 'layer') {
          collectedNodes.value.push(item)
        }
        if (item.children && item.children.length > 0) {
          collectNodesWithFlag(item.children)
        }
      }
    })
  }
}
const handleCheckChange = (data) => {
  let options = treeRef.value?.getCheckedNodes()
  collectedNodes.value = []
  collectNodesWithFlag(data)
  collectedNodes.value.forEach(item => {
    if (options?.some(i => i.id == item.id)) {
      //  const window.$Cesium  = DC
      if (item.subType == '3Dtile') {
        if (!addTileLayers[item.layerName]) {
          // addTileLayers[item.layerName] = []
          // let tile = window.$viewer.delegate.scene.primitives.add(new window.$Cesium.Cesium3DTileset({
          //   url: '/zhyq/mx/tile_01/tileset.json',
          // }))
          //   url: '/zhyq/mx/tile_01/tileset.json',
          // }), 121323)
          // item.urlData.forEach(i => {
          // })
          addTileLayers[item.layerName] = []
          item.urlData.forEach((m, ind) => {
            let tile = new DC.Tileset(m.url, {
              maximumMemoryUsage: 1024,
              maximumScreenSpaceError: 8,
              skipLevels: 5,
              skipLevelOfDetail: true,
              skipScreenSpaceErrorFactor: 128,
              progressiveResolutionHeightFraction: 0.5,
              baseScreenSpaceError: 1024
            })
            tile.setSplitDirection(1)
            // tile.setHeight(-420)
            // tile.setSplitDirection(-1)
            window.$viewer.sceneSplit.addTileset(tile)
            tileLayers.addOverlay(tile)
            window.$viewer.sceneSplit.enable = false
            addTileLayers[item.layerName][ind] = tile
          })
        } else {
          addTileLayers[item.layerName].forEach(m => m.show = true)
        }
      } else if (item.subType == 'labelPoint') {
        if (!addTileLayers[item.layerName]) {
          addTileLayers[item.layerName] = new DC.HtmlLayer(item.layerName)
          window.$viewer.addLayer(addTileLayers[item.layerName])
          item.method(item.params).then(res => {
            let data = res.data.data.records
            data.filter(i => i.lng && i.lng != '' && i.lat && i.lat != '').forEach(i => {
              let iconEl = ''
              if ('showPanel' in item && item.showPanel == false) {
                if (item.backgroundIcon) {
                  iconEl = `
                  <div class="map-name">${i[item.showParams] || i.name}</div>
                  <div class="map-icon">
                    <img src="${item.backgroundIcon}">
                  </div>
                  `
                }
              } else {
                iconEl = `<div class="marsBlueGradientPnl">
                  <div>${i[item.showParams] || i.name}</div>
                </div>`
              }
              let divIcon = new DC.DivIcon(
                new DC.Position(i.lng, i.lat, 64),
                `<div class="public-map-popup ${item.className || ''}">
                    ${iconEl}
                  </div>`
              )
              divIcon.attrParams = i
              let incident = () => {
              }
              if (item.incident) incident = item.incident
              divIcon.on(DC.MouseEventType.CLICK, incident)
              addTileLayers[item.layerName].addOverlay(divIcon)
            })
          })
        } else {
          addTileLayers[item.layerName].show = true
        }
      } else if (item.subType == 'geojsonWall') {
        if (!addTileLayers[item.layerName]) {
          addTileLayers[item.layerName] = new DC.VectorLayer(item.layerName)
          window.$viewer.addLayer(addTileLayers[item.layerName])
          item.source.features.forEach(i => {
            let wall = new DC.Wall(
              i.geometry.coordinates[0].map(d => [...d, 125].join(',')).join(';')
            )
            wall.setStyle({
              material: new DC.WallTrailMaterialProperty({
                color: window.$Cesium.Color.fromBytes(0, 123, 255, 180),
                speed: 8
              })
            })
            addTileLayers[item.layerName].addOverlay(wall)
          })
        } else {
          addTileLayers[item.layerName].show = true
        }
      } else if (item.subType == 'geojsonPipe') {
        if (!addTileLayers[item.layerName]) {
          addTileLayers[item.layerName] = new DC.VectorLayer(item.layerName)
          window.$viewer.addLayer(addTileLayers[item.layerName])
          function computeCircle (radius) {
            var positions = []
            for (var i = 0; i < 360; i++) {
              var radians = DC.Math.toRadians(i)
              positions.push({
                x: radius * Math.cos(radians),
                y: radius * Math.sin(radians),
              })
            }
            return positions
          }
          item.source.features.forEach(i => {
            let polylineVolume = new DC.PolylineVolume(
              i.geometry.coordinates.map(d => [d[0], d[1], item.height].join(',')).join(';'),
              computeCircle(2)
            )
            polylineVolume.setStyle({
              material: item.color
            })
            addTileLayers[item.layerName].addOverlay(polylineVolume)
          })
        } else {
          addTileLayers[item.layerName].show = true
        }
      } else if (item.subType == 'geojsonPolygon') {
        if (!addTileLayers[item.layerName]) {
          addTileLayers[item.layerName] = new DC.VectorLayer(item.layerName)
          window.$viewer.addLayer(addTileLayers[item.layerName])
          item.method(item.params).then(res => {
            let data = res.data.data.records
            data.forEach(i => {
              let stl = ''
              try {
                let geom = JSON.parse(i.geom)
                if (geom && geom.coordinates && geom.coordinates[0]) {
                  stl = geom.coordinates[0][0].map(d => d[0] + ',' + d[1]).join(';')
                } else {
                  console.error('Invalid geom structure')
                }
              } catch (error) {
                console.error('Failed to parse geom:', error)
              }
              let polygon = new DC.Polygon(stl)
              polygon.setStyle({
                width: 2,
                material: DC.Color.BLUE,
                clampToGround: true
              })
              addTileLayers[item.layerName].addOverlay(polygon)
            })
          })
        } else {
          addTileLayers[item.layerName].show = true
        }
      }
    } else {
      if (addTileLayers[item.layerName]) {
        if (item.subType == '3Dtile') {
          addTileLayers[item.layerName].forEach(m => m.show = false)
        } else {
          addTileLayers[item.layerName].clear()
          window.$viewer && window.$viewer.removeLayer(addTileLayers[item.layerName])
          addTileLayers[item.layerName] = null
          delete addTileLayers[item.layerName]
        }
      }
    }
  })
}
function findObjectById (data, id) {
  // 遍历数据数组
  for (let i = 0; i < data.length; i++) {
    const item = data[i]
    // 检查当前项的 id 是否匹配
    if (item.id === id) {
      return item // 找到匹配项,返回它
    }
    // 如果当前项有 children 数组,则递归查找
    if (item.children && item.children.length > 0) {
      const found = findObjectById(item.children, id)
      if (found) {
        return found // 在 children 中找到匹配项,返回它
      }
    }
  }
  // 如果没有找到匹配项,返回 null
  return null
}
const restHandleCheckChange = (key) => {
  let checkIds = treeRef.value?.getCheckedKeys()
  if (checkIds && checkIds.some(i => i == key)) {
    return
  }
  treeRef.value?.setCheckedKeys([...checkIds, key])
  handleCheckChange([findObjectById(data, key)])
}
const restHandleDelChange = (key) => {
  let checkIds = treeRef.value?.getCheckedKeys()
  if (checkIds && !checkIds.some(i => i == key)) {
    return
  }
  treeRef.value?.setCheckedKeys(checkIds.filter(i => i.indexOf(key)))
  handleCheckChange([findObjectById(data, key)])
}
// 飞到园区范围
const flyToyqfw = () => {
  window.$viewer.zoomToPosition(new DC.Position(
    115.1021,
    27.2360,
    5000,
    0,
    -45,
    0
  ), () => {
  })
}
EventBus.on('restHandleCheckChange', restHandleCheckChange)
EventBus.on('restHandleDelChange', restHandleDelChange)
EventBus.on('flyToyqfw', flyToyqfw)
onMounted(() => {
  setTimeout(() => {
    handleCheckChange(data.filter(i => indexPoint.value.includes(i.id)))
  }, 3000)
})
// const sharedData = computed(() => pointStore.sharedData);
// watch(sharedData, (newValue) => {
// });
// 销毁
function destroy () {
  let arr = Object.keys(addPupoLayers)
  arr.filter(i => i != 'hgyq').forEach(i => {
    addPupoLayers[i] && window.$viewer && window.$viewer.removeLayer(addPupoLayers[i])
    addPupoLayers[i] = null
    delete addPupoLayers[i]
  })
  addPupoLayers = {}
}
onUnmounted(() => {
  if (tileLayers) {
    tileLayers.clear()
    window.$viewer && window.$viewer.removeLayer(tileLayers)
    tileLayers = null
  }
  let arr = Object.keys(addTileLayers)
  arr.filter(i => i != 'hgyq').forEach(i => {
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
  addTileLayers = null
  // 弹窗销毁
  destroy()
  addPupoLayers = null
  EventBus.off('restHandleCheckChange', restHandleCheckChange)
  EventBus.off('restHandleDelChange', restHandleDelChange)
  EventBus.off('flyToyqfw', flyToyqfw)
})
</script>
<style lang="scss" scoped>
.tree-content {
  min-width: 200px;
  padding: 10px;
  ::v-deep(.el-tree) {
    color: #fff;
    background: transparent;
    /* 鼠标浮动过的背景颜色 */
    .el-tree-node__content:hover {
      background: #0074b7;
    }
    /* 鼠标点击时节点的背景颜色 */
    .el-tree-node:focus>.el-tree-node__content {
      background-color: #0074b7 !important;
      color: rgb(255, 255, 255);
    }
    /* 鼠标失去焦点时节点背景的颜色 */
    .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
      background: rgb(0, 129, 204);
    }
  }
}
</style>
src/pages/map/components/scomponents/popup/panorama.vue
New file
@@ -0,0 +1,70 @@
<template>
  <div class="panorama-container">
    <div class="title">
      <div>{{ title }}</div>
      <div class="close cursor-p" @click="$emit('closePanoramaPopup')">
        <i class="fa fa-close"></i>
      </div>
    </div>
    <div class="content">
      <iframe class="w100 h100" :src="url" frameborder="0"></iframe>
    </div>
  </div>
</template>
<script setup>
const {
  title,
  url
} = defineProps({
  title: {
    default: ''
  },
  url: {
    default: ''
  }
})
</script>
<style lang="scss" scoped>
.panorama-container {
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  z-index: 999;
  background: transparent;
  /* fallback for old browsers */
  // background: -webkit-linear-gradient(to right, #3a7bd5, #00d2ff);
  /* Chrome 10-25, Safari 5.1-6 */
  // background: linear-gradient(to right, #3a7bd5, #00d2ff);
  background-color: rgba($color: #000000, $alpha: 1.0);
  /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
  pointer-events: auto;
  box-shadow: inset 0 0 200px #0377eb;
  .title {
    padding: 0 10px;
    display: flex;
    justify-content: space-between;
    height: 44px;
    line-height: 44px;
    color: #fff;
    .close {
      cursor: pointer;
    }
  }
  .content {
    padding: 0 10px 10px;
    width: 100%;
    height: 0;
    flex: 1;
  }
}
</style>
src/pages/map/components/scomponents/tool/curtain.vue
New file
@@ -0,0 +1,108 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-29 15:48:36
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-27 19:17:04
 * @FilePath: \bigScreen\src\pages\layout\components\scomponents\tool\curtain.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <public-box style="z-index: 100;">
    <template #name>
      <div class="name"><i class="fa fa-map-pin"></i>&nbsp;卷帘对比 &nbsp;</div>
    </template>
    <template #close>
      <div class="close cursor-p" @click="$emit('closeChild')"><i class="fa fa-close"></i></div>
    </template>
    <template #content>
      <div class="cur-btn">
        <!-- <div class="m-4">
                    <p>左侧图层</p>
                    <el-select class="transparent-bg" v-model="value1" placeholder="天地图">
                        <el-option v-for="item in components" :key="item.value" :label="item.label" :value="item.value" />
                    </el-select>
                </div>
                <div class="m-4">
                    <p>右侧图层</p>
                    <el-select popper-class="transparent-bg" v-model="value2" collapse-tags placeholder="天地图">
                        <el-option v-for="item in components" :key="item.value" :label="item.label" :value="item.value" />
                    </el-select>
                </div> -->
      </div>
    </template>
  </public-box>
</template>
<script setup>
const value1 = ref([])
const value2 = ref([])
onMounted(() => {
  window.$viewer.sceneSplit.enable = true
})
// 关闭
const close = () => {
  window.$viewer.sceneSplit.enable = false
}
const flyTo = () => {
  // window.$viewer.flyToPosition(new DC.Position(longitude.value, latitude.value, height.value, 0, -90, 0), () => { }, 3)
}
onUnmounted(() => {
  window.$viewer && (window.$viewer.sceneSplit.enable = false)
})
const components = [
  { label: '天地图', value: '1' },
  { label: '谷歌影像', value: '2' },
  { label: '谷歌矢量', value: '3' },
  { label: '高德影像', value: '4' },
]
</script>
<style lang="scss" scoped>
.cur-btn {
  margin: 10px 0;
  display: flex;
  // justify-content: center;
  // align-items: center;
  // &.el-select {
  //     width: 50px;
  // }
}
.m-4 {
  text-align: center;
  width: 200px;
}
.transparent-bg {
  background: transparent;
}
// 重新el——select样式
::v-deep .el-select__wrapper {
  background: transparent;
}
::v-deep .el-select-dropdown {
  // background: transparent;
  background-color: aqua;
}
::v-deep .el-select .el-select__placeholder {
  color: #fff;
}
</style>
src/pages/map/components/scomponents/tool/exportScene.vue
New file
@@ -0,0 +1,10 @@
<template>
</template>
<script setup>
window.$viewer.exportScene()
const emit = defineEmits(['closeChild'])
emit('closeChild')
</script>
<style lang="scss" scoped></style>
src/pages/map/components/scomponents/tool/location.vue
New file
@@ -0,0 +1,89 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-29 15:48:36
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-29 19:53:49
 * @FilePath: \bigScreen\src\views\layout\components\scomponents\tool\location.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <public-box style="z-index: 100;">
    <template #name>
      <div class="name"><i class="fa fa-map-pin"></i>&nbsp;底图</div>
    </template>
    <template #close>
      <div class="close cursor-p" @click="$emit('closeChild')"><i class="fa fa-close"></i></div>
    </template>
    <template #content>
      <div class="cur-content">
        <div>
          <span>经度:</span>
          <el-input v-model="longitude" size="small" placeholder="请输入经度" />
        </div>
        <div>
          <span>纬度:</span>
          <el-input v-model="latitude" size="small" placeholder="请输入纬度" />
        </div>
        <div>
          <span>高度:</span>
          <el-input v-model="height" size="small" placeholder="请输入高度" />
        </div>
      </div>
      <div class="cur-btn">
        <el-button color="rgba(13,100,167,.8)" @click="flyTo" type="primary" size="small">坐标定位</el-button>
      </div>
    </template>
  </public-box>
</template>
<script setup>
const longitude = ref(0)
const latitude = ref(0)
const height = ref(0)
const flyTo = () => {
  window.$viewer.flyToPosition(new DC.Position(longitude.value, latitude.value, height.value, 0, -90, 0), () => { }, 3)
}
</script>
<style lang="scss" scoped>
.cur-content {
  &>div {
    margin-top: 10px;
    padding: 0 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    span {
      width: 54px;
    }
    ::v-deep(.el-input) {
      border: none !important;
      .el-input__wrapper {
        background: rgba(63, 72, 84, .7) !important;
        border: none !important;
        box-shadow: none;
        input {
          color: #fff;
        }
      }
    }
  }
}
.cur-btn {
  margin: 10px 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
src/pages/map/components/scomponents/tool/measure.vue
New file
@@ -0,0 +1,220 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-29 15:48:36
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-29 19:53:49
 * @FilePath: \bigScreen\src\views\layout\components\scomponents\tool\location.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
    <public-box style="z-index: 100;">
        <template #name>
            <div class="name"><i class="fa fa-map-pin"></i>&nbsp;测量工具</div>
        </template>
        <template #close>
            <div class="close cursor-p" @click="$emit('closeChild')"><i class="fa fa-close"></i></div>
        </template>
        <template #content>
            <div>
                <div class="container-box">
                    <div v-for="(item, index) in buttonList" :key="index" class="item" @click="item.click">
                        <img class="icon_img" src="../../../../../assets/images/add.png" alt="" srcset="">
                        <div class="text">{{ item.label }}</div>
                    </div>
                </div>
                <div class="button-clear">
                    <button @click="deactivate">清空测量数据</button>
                </div>
            </div>
        </template>
    </public-box>
</template>
<script setup>
const longitude = ref(0)
const latitude = ref(0)
const height = ref(0)
let measure = reactive({})
onMounted(() => {
    measure = new DC.Measure(window.$viewer)
})
onUnmounted(() => {
    deactivate()
})
// 空间距离
function calcDistance() {
    measure.distance()
}
// 贴地距离
function distanceSurface() {
    measure.distanceSurface()
}
// 水平面积
function calcArea(item) {
    measure.area()
}
// 贴地面积
function areaSurface() {
    measure.areaSurface()
}
// 角度
function calcAngle() {
    measure.angle()
}
// 模型角度
function calcModelAngle() {
    measure.angle({
        clampToModel: true
    })
}
//   高度
function calcHeight() {
    measure.height()
}
//   贴物高度
function calcModelHeight() {
    measure.height({
        clampToModel: true
    })
}
// 航向
function calcHeading() {
    measure.heading()
}
// 模型航向
function areaHeight() {
    measure.areaHeight()
}
// 三角测量
function calcTriangleHeight() {
    measure.triangleHeight()
}
// 模型三角测量
function calcModelTriangleHeight() {
    measure.triangleHeight({
        clampToModel: true
    })
}
// 清空
function deactivate() {
    measure.deactivate()
}
const buttonList = [
    {
        label: '空间距离',
        value: 'space',
        imges: '../../../../../assets/images/add.png',
        click: calcDistance
    },
    {
        label: '贴地距离',
        value: 'area',
        imges: '../../../../../assets/images/add.png',
        click: distanceSurface
    },
    // {
    //     label: '剖面',
    //     value: 'volume',
    //     imges: '../../../../../assets/images/add.png'
    // },
    {
        label: '水平面积',
        value: 'volume',
        imges: '../../../../../assets/images/add.png',
        click: calcArea
    },
    {
        label: '贴地面积', value: 'volume',
        imges: '../../../../../assets/images/add.png',
        click: areaSurface
    },
    {
        label: '角度',
        value: 'volume',
        imges: '../../../../../assets/images/add.png',
        click: calcAngle
    },
    {
        label: '高度差',
        value: 'volume',
        imges: '../../../../../assets/images/add.png',
        click: calcAngle
    },
    {
        label: '三角测量',
        value: 'volume',
        imges: '../../../../../assets/images/add.png',
        click: calcModelTriangleHeight
    },
    {
        label: '贴物高度',
        value: 'volume',
        imges: '../../../../../assets/images/add.png',
        click: calcModelHeight
    },
]
const flyTo = () => {
    // window.$viewer.flyToPosition(new DC.Position(longitude.value, latitude.value, height.value, 0, -90, 0), () => { }, 3)
}
</script>
<style lang="scss" >
.container-box {
    width: 230px;
    display: flex;
    flex-wrap: wrap;
    font-size: 12px;
}
.icon_img {
    width: 40px;
    height: 40px;
}
.item {
    width: 60px;
    margin: 8px;
    text-align: center;
    padding: 3px;
}
.button-clear {
    display: flex;
    justify-content: center;
    margin: 10px 0;
}
.button-clear button {
    padding: 6px;
    border: none;
}
.button-clear button:hover {
    background-color: blue;
    color: #fff;
}
.container-box .item:hover {
    box-shadow: inset 0px 0px 30px 20px rgba(31, 139, 247, 0.949);
    border-radius: 20%;
}
.text {
    // color: pink;
}
</style>
src/pages/map/components/scomponents/toolList.vue
New file
@@ -0,0 +1,134 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-29 14:20:49
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-27 15:34:16
 * @FilePath: \bigScreen\src\pages\layout\components\scomponents\toolList.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <ul v-show="moreToolShow" class="tool-list-box">
    <li @click="showComponent(item.component)" v-for="(item, index) in components" :key="index">
      <i :class="item.icon"></i> {{ item.title }}
    </li>
  </ul>
  <component :is="currentComponent" v-if="currentComponent" @closeChild="closeComponent" />
</template>
<script setup>
const { moreToolShow } = defineProps({
  moreToolShow: {
    type: Boolean, //参数类型
    default: false, //默认值
    required: true, //是否必须传递
  }
})
import location from './tool/location.vue'
import curtain from './tool/curtain.vue'
import measure from './tool/measure.vue'
import exportScene from './tool/exportScene.vue'
import component from 'element-plus/es/components/tree-select/src/tree-select-option.mjs'
const emit = defineEmits(['close'])
let currentComponent = shallowRef(null)
const components = [
  {
    icon: 'fa fa-calculator',
    title: '图上量算',
    component: measure,
  },
  // {
  //   icon: 'fa fa-bar-chart',
  //   title: '空间分析',
  // },
  {
    name: 'location',
    icon: 'fa fa-map-pin',
    title: '坐标定位',
    component: location
  },
  // {
  //   icon: 'fa fa-paper-plane',
  //   title: '地区导航',
  // },
  // {
  //   icon: 'fa fa-edit',
  //   title: '我的标记',
  // },
  // {
  //   icon: 'fa fa-tags',
  //   title: '视角书签',
  // },
  {
    name: 'exportScene',
    icon: 'fa fa-download',
    title: '场景导出',
    component: exportScene
  },
  // {
  //   icon: 'fa fa-object-group',
  //   title: '图上标绘',
  // },
  // {
  //   icon: 'fa fa-helicopter',
  //   title: '飞行漫游',
  // },
  // {
  //   icon: 'fa fa-level-up',
  //   title: '路线导航',
  // },
  // {
  //   icon: 'fa fa-columns',
  //   title: '卷帘对比',
  //   component: curtain
  // },
  // {
  //   icon: 'fa fa-window-restore',
  //   title: '分屏对比',
  // },
]
const showComponent = (component) => {
  currentComponent.value = component
  emit('close', 'tool')
}
const closeComponent = () => {
  currentComponent.value = null
}
</script>
<style lang="scss" scoped>
.tool-list-box {
  position: absolute;
  right: 540px;
  z-index: 101;
  top: 152px;
  background: rgba(63, 72, 84, .7);
  pointer-events: auto;
  li {
    padding: 6px 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #fff;
    cursor: pointer;
    i {
      margin-right: 5px;
    }
  }
  li:hover {
    background: #4db3ff;
  }
  li:first-child {
    margin-top: 0;
  }
}
</style>
src/pages/map/index.vue
New file
@@ -0,0 +1,260 @@
<template>
  <div class="wrapper">
    <map-container ref="MapContainer">
      <template #content>
        <div v-if="showContent" class="main-content" id="MainContent">
          <main-search></main-search>
          <main-tool></main-tool>
          <div class="w100 h100 relative">
            <div class="main-header">
              <div class="title">吉水化工园区“一园一策一图”VR平台</div>
              <div class="login-out" @click="signOut">
                <img :src="loginOutBg" class="img" />
                <span>退出</span>
              </div>
            </div>
            <div class="main-container">
              <!-- 地图区域 -->
              <router-view></router-view>
            </div>
            <main-menu></main-menu>
          </div>
        </div>
      </template>
    </map-container>
  </div>
</template>
<script setup>
import { getAssetsFile } from 'utils/utils'
const loginOutBg = getAssetsFile('login.png', '/images')
import mainMenu from './components/mainMenu.vue'
import { useRouter, useRoute } from 'vue-router'
let router = useRouter()
import mainSearch from './components/mainSearch.vue'
import mainTool from './components/mainTool.vue'
import { useLogin } from 'store/login'
const loginStore = useLogin()
import { useMap } from 'store/map'
import { useRouterStore } from 'store/router'
const store = useMap()
const showContent = ref(false)
const signOut = () => {
  loginStore.LogOut().then(res => {
    router.push({
      path: '/login'
    })
  })
}
// onMounted(() => {
//   store.setLoadSub(false)
// }),
// 监听createB的变化
watch(
  [
    () => store.loadMap,
  ],
  ([newLoadMap]) => {
    showContent.value = newLoadMap
  },
  { immediate: true } // 设置immediate为true以便在组件挂载时立即检查createB的值
)
</script>
<style lang="scss" scoped>
$bg-blue: rgba(24, 33, 92, 0.9);
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  #MainContent,
  #SingleMainContent {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 99;
  }
  .main-content {
    height: 1080px;
    background: url(/images/header.png) no-repeat center / 100% 100%,
      url(/images/pro-bg.png) no-repeat center / 100% 100%;
    pointer-events: none;
    &.single-page {
      background: url(/images/header.png) no-repeat center / 100% 100%,
        url(/images/pro-bg.png) no-repeat center / 100% 100%,
        rgba(0, 0, 0, 1);
    }
    .main-header {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 40px;
      pointer-events: auto;
      .title {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: auto;
        width: 640px;
        height: 40px;
        font-size: 24px;
        font-family: YouSheBiaoTiHei;
        font-weight: 400;
        color: #eff8fc;
        line-height: 40px;
        text-align: center;
        letter-spacing: 8px;
        font-weight: bolder;
        background: linear-gradient(to bottom,
            #e2eaf0 0%,
            #aed1f1 100%);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        // opacity: 0.89;
        // text-shadow: 0px 4px 1px rgba(19, 80, 143, 0.66);
        // background: linear-gradient(0deg, rgba(119, 186, 255, 0.45) 0%, rgba(233, 248, 255, 0.45) 73.3154296875%, rgba(255, 255, 255, 0.45) 100%);
        // -webkit-background-clip: text;
        // -webkit-text-fill-color: transparent;
      }
      .login-out {
        position: absolute;
        top: 10px;
        right: 40px;
        height: 36px;
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 10px;
        cursor: pointer;
        .img {
          width: 16px;
          height: 16px;
          margin-right: 5px;
        }
        span {
          font-size: 13px;
        }
      }
      .login-out:hover {
        background-color: #3c5e8f;
        border-radius: 20px;
      }
    }
    .main-container {
      position: absolute;
      top: 40px;
      left: 40px;
      right: 40px;
      bottom: 40px;
    }
  }
}
.main-header {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 40px;
  pointer-events: auto;
  .title {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    width: 640px;
    height: 40px;
    font-size: 24px;
    font-family: YouSheBiaoTiHei;
    font-weight: 400;
    color: #eff8fc;
    line-height: 40px;
    text-align: center;
    letter-spacing: 8px;
    font-weight: bolder;
    background: linear-gradient(to bottom,
        #e2eaf0 0%,
        #aed1f1 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    // opacity: 0.89;
    // text-shadow: 0px 4px 1px rgba(19, 80, 143, 0.66);
    // background: linear-gradient(0deg, rgba(119, 186, 255, 0.45) 0%, rgba(233, 248, 255, 0.45) 73.3154296875%, rgba(255, 255, 255, 0.45) 100%);
    // -webkit-background-clip: text;
    // -webkit-text-fill-color: transparent;
  }
  .login-out {
    position: absolute;
    top: 10px;
    right: 40px;
    height: 36px;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 10px;
    cursor: pointer;
    .img {
      width: 16px;
      height: 16px;
      margin-right: 5px;
    }
    span {
      font-size: 13px;
    }
  }
  .login-out:hover {
    background-color: #3c5e8f;
    border-radius: 20px;
  }
}
.main-container {
  position: absolute;
  top: 40px;
  left: 40px;
  right: 40px;
  bottom: 40px;
}
</style>
src/pages/single/components/mainMenu.vue
New file
@@ -0,0 +1,120 @@
<template>
  <div class="page-mode">
    <div @mouseenter="item.childrenFlag = true" :class="{ active: currentUrl.indexOf(item.path) != -1 }"
      @mouseleave="item.childrenFlag = false" @click="goToPath(item)" v-for="(item, index) in menuList" :key="index">
      {{ item.menuName }}
    </div>
  </div>
</template>
<script setup>
import { ref, reactive, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { Search } from '@element-plus/icons-vue'
import { getTime } from '@/utils/getTime.js'
import { useRouterStore } from 'store/router'
const store = useRouterStore()
let router = useRouter()
let currentUrl = ref('statistics')
const menuList = ref(
  [
    {
      menuName: '园区概况',
      path: '/layout/map/survey'
    },
    {
      menuName: '风险源',
      path: '/layout/map/rs'
    },
    {
      menuName: '应急空间',
      path: '/layout/map/space'
    },
    {
      menuName: '应急物资',
      path: '/layout/single/supplies'
    },
    {
      menuName: '三级防控',
      path: '/layout/map/pac'
    },
    {
      menuName: '救援队伍',
      path: '/layout/single/rt'
    },
    {
      menuName: '突发事件模拟',
      path: '/layout/map/pd'
    },
    {
      menuName: '作战图',
      path: '/layout/single/ochart'
    },
  ]
)
const goToPath = (params) => {
  if (params.children && params.children.length > 0) return
  if (params.path) {
    if (router.currentRoute.value.path == params.path) return
    router.push({
      path: params.path
    })
  } else {
    params.childrenFlag = !params.childrenFlag
  }
}
watch(
  () => router.currentRoute.value,
  (newValue, oldValue) => {
    currentUrl.value = newValue.path
  },
  { immediate: true }
)
const userName = ref('管理员')
</script>
<style lang="scss" scoped>
.page-mode {
  position: absolute;
  top: auto;
  bottom: 55px;
  left: 50%;
  z-index: 99;
  transform: translateX(-50%);
  display: flex;
  pointer-events: auto;
  &>div {
    background-image: url(/images/mode-tab.png);
    background-size: cover;
    width: 136px;
    height: 50px;
    font-size: 16px;
    text-align: center;
    font-weight: bold;
    color: #BFD3E5;
    line-height: 32px;
    padding-top: 12px;
    margin-right: -20px;
    font-style: italic;
    cursor: pointer;
    box-sizing: border-box;
    &:last-child {
      margin-right: 0px;
    }
    &.active {
      color: #F6FCFF;
      background-image: url(/images/mode-tab-ac.png);
    }
  }
}
</style>
src/pages/single/index.vue
New file
@@ -0,0 +1,223 @@
<template>
  <div class="wrapper">
    <div class="w100 h100 relative main-content single-page" id="MainContent">
      <div class="main-header">
        <div class="title">吉水化工园区“一园一策一图”VR平台</div>
        <div class="login-out" @click="signOut">
          <img :src="loginOutBg" class="img" />
          <span>退出</span>
        </div>
      </div>
      <div class="main-container">
        <!-- 地图区域 -->
        <router-view></router-view>
      </div>
      <main-menu></main-menu>
    </div>
  </div>
</template>
<script setup>
import { getAssetsFile } from 'utils/utils'
const loginOutBg = getAssetsFile('login.png', '/images')
import mainMenu from './components/mainMenu.vue'
const signOut = () => {
  loginStore.LogOut().then(res => {
    router.push({
      path: '/login'
    })
  })
}
</script>
<style lang="scss" scoped>
$bg-blue: rgba(24, 33, 92, 0.9);
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  #MainContent,
  #SingleMainContent {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 99;
  }
  .main-content {
    height: 1080px;
    background: url(/images/header.png) no-repeat center / 100% 100%,
      url(/images/pro-bg.png) no-repeat center / 100% 100%;
    pointer-events: none;
    &.single-page {
      background: url(/images/header.png) no-repeat center / 100% 100%,
        url(/images/pro-bg.png) no-repeat center / 100% 100%,
        rgba(0, 0, 0, 1);
    }
    .main-header {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 40px;
      pointer-events: auto;
      .title {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: auto;
        width: 640px;
        height: 40px;
        font-size: 24px;
        font-family: YouSheBiaoTiHei;
        font-weight: 400;
        color: #eff8fc;
        line-height: 40px;
        text-align: center;
        letter-spacing: 8px;
        font-weight: bolder;
        background: linear-gradient(to bottom,
            #e2eaf0 0%,
            #aed1f1 100%);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        // opacity: 0.89;
        // text-shadow: 0px 4px 1px rgba(19, 80, 143, 0.66);
        // background: linear-gradient(0deg, rgba(119, 186, 255, 0.45) 0%, rgba(233, 248, 255, 0.45) 73.3154296875%, rgba(255, 255, 255, 0.45) 100%);
        // -webkit-background-clip: text;
        // -webkit-text-fill-color: transparent;
      }
      .login-out {
        position: absolute;
        top: 10px;
        right: 40px;
        height: 36px;
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 10px;
        cursor: pointer;
        .img {
          width: 16px;
          height: 16px;
          margin-right: 5px;
        }
        span {
          font-size: 13px;
        }
      }
      .login-out:hover {
        background-color: #3c5e8f;
        border-radius: 20px;
      }
    }
    .main-container {
      position: absolute;
      top: 40px;
      left: 40px;
      right: 40px;
      bottom: 40px;
    }
  }
}
.main-header {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 40px;
  pointer-events: auto;
  .title {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    width: 640px;
    height: 40px;
    font-size: 24px;
    font-family: YouSheBiaoTiHei;
    font-weight: 400;
    color: #eff8fc;
    line-height: 40px;
    text-align: center;
    letter-spacing: 8px;
    font-weight: bolder;
    background: linear-gradient(to bottom,
        #e2eaf0 0%,
        #aed1f1 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    // opacity: 0.89;
    // text-shadow: 0px 4px 1px rgba(19, 80, 143, 0.66);
    // background: linear-gradient(0deg, rgba(119, 186, 255, 0.45) 0%, rgba(233, 248, 255, 0.45) 73.3154296875%, rgba(255, 255, 255, 0.45) 100%);
    // -webkit-background-clip: text;
    // -webkit-text-fill-color: transparent;
  }
  .login-out {
    position: absolute;
    top: 10px;
    right: 40px;
    height: 36px;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 10px;
    cursor: pointer;
    .img {
      width: 16px;
      height: 16px;
      margin-right: 5px;
    }
    span {
      font-size: 13px;
    }
  }
  .login-out:hover {
    background-color: #3c5e8f;
    border-radius: 20px;
  }
}
.main-container {
  position: absolute;
  top: 40px;
  left: 40px;
  right: 40px;
  bottom: 40px;
}
</style>
src/router/index.js
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-25 16:35:31
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-26 20:14:39
 * @LastEditTime: 2024-11-27 20:30:40
 * @FilePath: \bigScreen\src\router\index.js
 * @Description: 
 * 
@@ -12,6 +12,8 @@
const layout = () => import("@/pages/layout/index.vue")
const firstLayout = () => import('@/pages/first/index.vue')
const subLayout = () => import('@/pages/sub/index.vue')
const mapLayout = () => import('@/pages/map/index.vue')
const singleLayout = () => import('@/pages/single/index.vue')
const companyInfo = () => import('@/views/companyInfo/index.vue')
const routes = [
  // {
@@ -36,14 +38,13 @@
  {
    path: '/layout',
    name: 'layout',
    redirect: '/layout/first/survey',
    redirect: '/layout/map/survey',
    component: layout,
    children: [
      {
        path: 'first',
        name: 'first',
        component: firstLayout,
        redirect: '/layout/first/survey',
        path: 'map',
        name: 'map',
        component: mapLayout,
        children: [
          {
            path: 'survey',
@@ -67,13 +68,6 @@
            component: () => import('@/views/space/index.vue')
          },
          {
            path: 'supplies',
            meta: {
              title: '应急物资'
            },
            component: () => import('@/views/supplies/index.vue')
          },
          {
            path: 'pac',
            meta: {
              title: '三级防控'
@@ -81,19 +75,33 @@
            component: () => import('@/views/pac/index.vue')
          },
          {
            path: 'rt',
            meta: {
              title: '救援队伍'
            },
            component: () => import('@/views/rt/index.vue')
          },
          {
            path: 'pd',
            meta: {
              title: '突发事件模拟'
            },
            component: () => import('@/views/pd/index.vue')
          },
        ]
      },
      {
        path: 'single',
        name: 'single',
        component: singleLayout,
        children: [
          {
            path: 'supplies',
            meta: {
              title: '应急物资'
            },
            component: () => import('@/views/supplies/index.vue')
          },
          {
            path: 'rt',
            meta: {
              title: '救援队伍'
            },
            component: () => import('@/views/rt/index.vue')
          },
          {
            path: 'ochart',
            meta: {
src/views/companyInfo/components/box/dataContent.vue
@@ -114,7 +114,10 @@
  let arr = Object.keys(addTileLayers)
  arr.forEach(i => {
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
  addTileLayers = null
})
</script>
src/views/companyInfo/components/box/fireTrend.vue
@@ -2,8 +2,8 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-13 14:54:26
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-03-13 15:00:55
 * @FilePath: \forest-fire\src\views\statistics\components\box\dataContent.vue
 * @LastEditTime: 2024-11-28 19:28:35
 * @FilePath: \bigScreen\src\views\companyInfo\components\box\fireTrend.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
@@ -167,6 +167,8 @@
  let arr = Object.keys(addTileLayers)
  arr.forEach(i => {
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
  addTileLayers = {}
}
@@ -175,12 +177,16 @@
  let arr = Object.keys(addPupoLayers)
  arr.filter(i => i != 'hgyq').forEach(i => {
    addPupoLayers[i] && window.$viewer && window.$viewer.removeLayer(addPupoLayers[i])
    addPupoLayers[i] = null
    delete addPupoLayers[i]
  })
  addPupoLayers = {}
}
onUnmounted(() => {
  destroy()
  destroyPupoLayers()
  addTileLayers = null
  addPupoLayers = null
})
import { Search, Refresh } from '@element-plus/icons-vue'
</script>
src/views/companyInfo/components/box/unitContent.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-10 15:27:59
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-27 19:15:59
 * @LastEditTime: 2024-11-28 19:29:15
 * @FilePath: \bigScreen\src\views\companyInfo\components\box\unitContent.vue
 * @Description:
 *
@@ -103,6 +103,8 @@
  let arr = Object.keys(addPupoLayers)
  arr.filter(i => i != 'hgyq').forEach(i => {
    addPupoLayers[i] && window.$viewer && window.$viewer.removeLayer(addPupoLayers[i])
    addPupoLayers[i] = null
    delete addPupoLayers[i]
  })
  addPupoLayers = {}
}
@@ -114,8 +116,12 @@
  let arr = Object.keys(addTileLayers)
  arr.forEach(i => {
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
  destroy()
  addTileLayers = null
  addPupoLayers = null
  EventBus.emit('restHandleDelChange', `3-3-2`)
  EventBus.emit('restHandleDelChange', `3-3-4`)
})
src/views/companyInfo/index.vue
@@ -46,6 +46,7 @@
onUnmounted(() => {
  window.$viewer && window.$viewer.removeLayer(curCompanyWall)
  curCompanyWall = null
})
const handleChildEvent = (data) => {
src/views/pac/components/box/dataContent.vue
@@ -194,8 +194,10 @@
  let arr = Object.keys(addTileLayers)
  arr.forEach(i => {
    addTileLayers[i] && window.$viewer && window.$viewer.removeLayer(addTileLayers[i])
    addTileLayers[i] = null
    delete addTileLayers[i]
  })
  addTileLayers = null
  EventBus.emit('restHandleDelChange', `3-3-2`)
  EventBus.emit('restHandleDelChange', `3-3-4`)
})
src/views/pd/components/dynamicPanel.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-11-09 15:41:35
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-28 11:37:12
 * @LastEditTime: 2024-11-28 19:36:24
 * @FilePath: \bigScreen\src\views\pd\components\dynamicPanel.vue
 * @Description: 
 * 
@@ -156,9 +156,9 @@
  ]
})
const dynamicVectorLayer = new DC.VectorLayer('dynamicVectorLayer').addTo(window.$viewer)
const dynamicHtmlLayer = new DC.HtmlLayer('dynamicHtmlLayer').addTo(window.$viewer)
const dynamicLineVectorLayer = new DC.VectorLayer('dynamicLineVectorLayer').addTo(window.$viewer)
let dynamicVectorLayer = new DC.VectorLayer('dynamicVectorLayer').addTo(window.$viewer)
let dynamicHtmlLayer = new DC.HtmlLayer('dynamicHtmlLayer').addTo(window.$viewer)
let dynamicLineVectorLayer = new DC.VectorLayer('dynamicLineVectorLayer').addTo(window.$viewer)
let modelPosition = [
  {
@@ -433,6 +433,12 @@
  dynamicVectorLayer && window.$viewer && window.$viewer.removeLayer(dynamicVectorLayer)
  dynamicHtmlLayer && window.$viewer && window.$viewer.removeLayer(dynamicHtmlLayer)
  dynamicLineVectorLayer && window.$viewer && window.$viewer.removeLayer(dynamicLineVectorLayer)
  tc = null
  track = null
  dynamicVectorLayer = null
  dynamicHtmlLayer = null
  dynamicLineVectorLayer = null
})
</script>
src/views/rs/components/box/dataContent.vue
@@ -210,6 +210,7 @@
  EventBus.off('rsTabChange', spaceTabChange)
  if (curSelect.value) EventBus.emit('restHandleDelChange', `4`)
  destroyPupoLayers()
  addPupoLayers = null
})
// 销毁
@@ -217,6 +218,8 @@
  let arr = Object.keys(addPupoLayers)
  arr.forEach(i => {
    addPupoLayers[i] && window.$viewer && window.$viewer.removeLayer(addPupoLayers[i])
    addPupoLayers[i] = null
    delete addPupoLayers[i]
  })
  addPupoLayers = {}
}
src/views/rt/index.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-10 15:27:59
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-27 19:28:17
 * @LastEditTime: 2024-12-01 21:43:40
 * @FilePath: \bigScreen\src\views\rt\index.vue
 * @Description: 综合设计
 * 
src/views/space/components/box/dataContent.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-13 14:54:26
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-27 14:27:09
 * @LastEditTime: 2024-11-28 19:30:58
 * @FilePath: \bigScreen\src\views\space\components\box\dataContent.vue
 * @Description:
 *
@@ -179,6 +179,7 @@
onUnmounted(() => {
  EventBus.off('spaceTabChange', spaceTabChange)
  destroyPupoLayers()
  addPupoLayers = null
})
// 销毁
@@ -186,6 +187,8 @@
  let arr = Object.keys(addPupoLayers)
  arr.forEach(i => {
    addPupoLayers[i] && window.$viewer && window.$viewer.removeLayer(addPupoLayers[i])
    addPupoLayers[i] = null
    delete addPupoLayers[i]
  })
  addPupoLayers = {}
}
src/views/supplies/index.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-10 15:27:59
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-27 19:26:43
 * @LastEditTime: 2024-12-01 00:24:40
 * @FilePath: \bigScreen\src\views\supplies\index.vue
 * @Description: 综合设计
 * 
@@ -15,8 +15,7 @@
<template>
  <div class="container page-container">
    <div class="data box w100 h100">
      <data-content>
      </data-content>
      <data-content></data-content>
    </div>
  </div>
</template>
vite.config.js
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-25 10:56:27
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-27 14:15:57
 * @LastEditTime: 2024-12-01 21:17:55
 * @FilePath: \bigScreen\vite.config.js
 * @Description: 
 * 
@@ -17,6 +17,7 @@
import basicSsl from '@vitejs/plugin-basic-ssl'
import { fa } from 'element-plus/es/locales.mjs'
import viteCompression from 'vite-plugin-compression'
// import vueDevTools from 'vite-plugin-vue-devtools'
export default ({ mode, command }) => {
  const env = loadEnv(mode, process.cwd())
@@ -61,7 +62,8 @@
        algorithm: 'gzip', // 压缩方式
        ext: 'gz', // 后缀名
        deleteOriginFile: false, // 压缩后是否删除压缩源文件
      })
      }),
      // vueDevTools()
    ],
    css: {