Browse Source

巡检相关

aliyun8775019416 1 month ago
parent
commit
da433e2707

+ 3 - 2
build/vite/index.ts

@@ -15,7 +15,7 @@ import topLevelAwait from 'vite-plugin-top-level-await'
 import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
 import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
 import UnoCSS from 'unocss/vite'
-
+import cesium from "vite-plugin-cesium";
 export function createVitePlugins() {
   const root = process.cwd()
 
@@ -95,6 +95,7 @@ export function createVitePlugins() {
       promiseExportName: '__tla',
       // The function to generate import names of top-level await promise in each chunk module
       promiseImportName: (i) => `__tla_${i}`
-    })
+    }),
+    cesium()
   ]
 }

+ 2 - 0
package.json

@@ -74,6 +74,7 @@
     "xml-js": "^1.6.11"
   },
   "devDependencies": {
+    "cesium": "~1.118.2",
     "@commitlint/cli": "^19.0.1",
     "@commitlint/config-conventional": "^19.0.0",
     "@iconify/json": "^2.2.187",
@@ -121,6 +122,7 @@
     "unplugin-element-plus": "^0.8.0",
     "unplugin-vue-components": "^0.25.2",
     "vite": "5.1.4",
+    "vite-plugin-cesium": "^1.2.23",
     "vite-plugin-compression": "^0.5.1",
     "vite-plugin-ejs": "^1.7.0",
     "vite-plugin-eslint": "^1.8.1",

+ 429 - 0
pnpm-lock.yaml

@@ -207,6 +207,9 @@ importers:
       bpmn-js-properties-panel:
         specifier: 0.46.0
         version: 0.46.0(bpmn-js@8.9.0)
+      cesium:
+        specifier: ~1.118.2
+        version: 1.118.2
       consola:
         specifier: ^3.2.3
         version: 3.2.3
@@ -288,6 +291,9 @@ importers:
       vite:
         specifier: 5.1.4
         version: 5.1.4(@types/node@20.12.7)(sass@1.75.0)(terser@5.30.4)
+      vite-plugin-cesium:
+        specifier: ^1.2.23
+        version: 1.2.23(cesium@1.118.2)(rollup@4.17.1)(vite@5.1.4(@types/node@20.12.7)(sass@1.75.0)(terser@5.30.4))
       vite-plugin-compression:
         specifier: ^0.5.1
         version: 0.5.1(vite@5.1.4(@types/node@20.12.7)(sass@1.75.0)(terser@5.30.4))
@@ -952,6 +958,14 @@ packages:
   '@camunda/element-templates-json-schema@0.4.0':
     resolution: {integrity: sha512-M5xW61ba7z2maBxfoT4c1bjuLD8OIL7863et/hULiNG6+R/B9CZ4Qze1juuIfXv4zpF2fYSuUsTPkTtiZrcspQ==}
 
+  '@cesium/engine@9.2.0':
+    resolution: {integrity: sha512-vFVITo7UwIY1H8zK53etljv1w0CVaFSzOcLyItrM88r47zyPL7/RgooVKqZXnM5V8prs33S5TO/JSqJmvpyMTQ==}
+    engines: {node: '>=14.0.0'}
+
+  '@cesium/widgets@6.1.2':
+    resolution: {integrity: sha512-RNgogbRqlzjZxxG7icAUIDFZ0rm4OpHJ9b9lS/TGVm44PVVNG0Umhp4Tlf9U6r4ggwayKUkGV5dDIDa+pJGcVQ==}
+    engines: {node: '>=14.0.0'}
+
   '@commitlint/cli@19.3.0':
     resolution: {integrity: sha512-LgYWOwuDR7BSTQ9OLZ12m7F/qhNY+NpAyPBgo4YNMkACE7lGuUnuQq1yi9hz1KA4+3VqpOYl8H1rY/LYK43v7g==}
     engines: {node: '>=v18'}
@@ -1408,6 +1422,36 @@ packages:
   '@polka/url@1.0.0-next.25':
     resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
 
+  '@protobufjs/aspromise@1.1.2':
+    resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
+
+  '@protobufjs/base64@1.1.2':
+    resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
+
+  '@protobufjs/codegen@2.0.4':
+    resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
+
+  '@protobufjs/eventemitter@1.1.0':
+    resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
+
+  '@protobufjs/fetch@1.1.0':
+    resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
+
+  '@protobufjs/float@1.0.2':
+    resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
+
+  '@protobufjs/inquire@1.1.0':
+    resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
+
+  '@protobufjs/path@1.1.2':
+    resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
+
+  '@protobufjs/pool@1.1.0':
+    resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
+
+  '@protobufjs/utf8@1.1.0':
+    resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
+
   '@purge-icons/core@0.10.0':
     resolution: {integrity: sha512-AtJbZv5Yy+vWX5v32DPTr+CW7AkSK8HJx52orDbrYt/9s4lGM2t4KKAmwaTQEH2HYr2HVh1mlqs54/S1s3WT1g==}
 
@@ -1620,6 +1664,9 @@ packages:
     resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
     engines: {node: '>=10.13.0'}
 
+  '@tweenjs/tween.js@23.1.3':
+    resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==}
+
   '@types/conventional-commits-parser@5.0.0':
     resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==}
 
@@ -2120,6 +2167,10 @@ packages:
     resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==}
     engines: {node: '>=10.0.0'}
 
+  '@zip.js/zip.js@2.7.57':
+    resolution: {integrity: sha512-BtonQ1/jDnGiMed6OkV6rZYW78gLmLswkHOzyMrMb+CAR7CZO8phOHO6c2qw6qb1g1betN7kwEHhhZk30dv+NA==}
+    engines: {bun: '>=0.7.0', deno: '>=1.0.0', node: '>=16.5.0'}
+
   '@zxcvbn-ts/core@3.0.4':
     resolution: {integrity: sha512-aQeiT0F09FuJaAqNrxynlAwZ2mW/1MdXakKWNmGM1Qp/VaY6CnB/GfnMS2T8gB2231Esp1/maCWd8vTG4OuShw==}
 
@@ -2240,11 +2291,18 @@ packages:
   asynckit@0.4.0:
     resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
 
+  at-least-node@1.0.0:
+    resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
+    engines: {node: '>= 4.0.0'}
+
   atob@2.1.2:
     resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==}
     engines: {node: '>= 4.5.0'}
     hasBin: true
 
+  autolinker@4.1.0:
+    resolution: {integrity: sha512-mYzdZMei1zIXcHVS/LjnuCJG+C/hNi8O+5m0R8YWtrIBWGrjL8CVzEZXxOfH0l1kioEXHNpUJRkgZdyL4GgIHQ==}
+
   autoprefixer@10.4.19:
     resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==}
     engines: {node: ^10 || ^12 || >=14}
@@ -2300,6 +2358,9 @@ packages:
     resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
     engines: {node: '>=8'}
 
+  bitmap-sdf@1.0.4:
+    resolution: {integrity: sha512-1G3U4n5JE6RAiALMxu0p1XmeZkTeCwGKykzsLTCqVzfSDaN6S7fKnkIkfejogz+iwqBWc0UYAIKnKHNN7pSfDg==}
+
   bluebird@3.7.2:
     resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
 
@@ -2379,6 +2440,10 @@ packages:
   caniuse-lite@1.0.30001614:
     resolution: {integrity: sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==}
 
+  cesium@1.118.2:
+    resolution: {integrity: sha512-b7nf9wWA49HLMDxZtF3wViqvNu2ha5MUsUOpf+9khsohjVSx/GSI6lg89wA0/QwzkCU0plYFY2qMWgM7n6kigQ==}
+    engines: {node: '>=18.18.0'}
+
   chalk@1.1.3:
     resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
     engines: {node: '>=0.10.0'}
@@ -2699,9 +2764,17 @@ packages:
     resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
     engines: {node: '>=0.4.0'}
 
+  depd@2.0.0:
+    resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+    engines: {node: '>= 0.8'}
+
   destr@2.0.3:
     resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==}
 
+  destroy@1.2.0:
+    resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
+    engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+
   diagram-js-direct-editing@1.8.0:
     resolution: {integrity: sha512-B4Xj+PJfgBjbPEzT3uZQEkZI5xHFB0Izc+7BhDFuHidzrEMzQKZrFGdA3PqfWhReHf3dp+iB6Tt11G9eGNjKMw==}
     peerDependencies:
@@ -2784,12 +2857,18 @@ packages:
     resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==}
     engines: {node: '>=8'}
 
+  draco3d@1.5.7:
+    resolution: {integrity: sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==}
+
   driver.js@1.3.1:
     resolution: {integrity: sha512-MvUdXbqSgEsgS/H9KyWb5Rxy0aE6BhOVT4cssi2x2XjmXea6qQfgdx32XKVLLSqTaIw7q/uxU5Xl3NV7+cN6FQ==}
 
   duplexer@0.1.2:
     resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
 
+  earcut@2.2.4:
+    resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==}
+
   eastasianwidth@0.2.0:
     resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
 
@@ -2801,6 +2880,9 @@ packages:
   echarts@5.5.0:
     resolution: {integrity: sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw==}
 
+  ee-first@1.1.1:
+    resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
   ejs@3.1.10:
     resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==}
     engines: {node: '>=0.10.0'}
@@ -2835,6 +2917,14 @@ packages:
   encode-utf8@1.0.3:
     resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==}
 
+  encodeurl@1.0.2:
+    resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
+    engines: {node: '>= 0.8'}
+
+  encodeurl@2.0.0:
+    resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+    engines: {node: '>= 0.8'}
+
   entities@1.1.2:
     resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==}
 
@@ -3134,10 +3224,18 @@ packages:
     resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==}
     engines: {node: '>=0.10.0'}
 
+  fresh@0.5.2:
+    resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
+    engines: {node: '>= 0.6'}
+
   fs-extra@10.1.0:
     resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
     engines: {node: '>=12'}
 
+  fs-extra@9.1.0:
+    resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
+    engines: {node: '>=10'}
+
   fs.realpath@1.0.0:
     resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
 
@@ -3252,6 +3350,9 @@ packages:
   graceful-fs@4.2.11:
     resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
 
+  grapheme-splitter@1.0.4:
+    resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
+
   graphemer@1.4.0:
     resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
 
@@ -3341,6 +3442,10 @@ packages:
   htmlparser2@8.0.2:
     resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
 
+  http-errors@2.0.0:
+    resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
+    engines: {node: '>= 0.8'}
+
   human-signals@2.1.0:
     resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
     engines: {node: '>=10.17.0'}
@@ -3533,6 +3638,9 @@ packages:
     resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
     engines: {node: '>=0.10.0'}
 
+  is-reference@1.2.1:
+    resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
+
   is-regex@1.1.4:
     resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
     engines: {node: '>= 0.4'}
@@ -3621,6 +3729,10 @@ packages:
   jsencrypt@3.3.2:
     resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==}
 
+  jsep@1.4.0:
+    resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==}
+    engines: {node: '>= 10.16.0'}
+
   jsesc@0.5.0:
     resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==}
     hasBin: true
@@ -3668,6 +3780,9 @@ packages:
     resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
     engines: {'0': node >= 0.2.0}
 
+  kdbush@4.0.2:
+    resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==}
+
   keycode@2.2.1:
     resolution: {integrity: sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==}
 
@@ -3696,6 +3811,12 @@ packages:
   kolorist@1.8.0:
     resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
 
+  ktx-parse@0.7.1:
+    resolution: {integrity: sha512-FeA3g56ksdFNwjXJJsc1CCc7co+AJYDp6ipIp878zZ2bU8kWROatLYf39TQEd4/XRSUvBXovQ8gaVKWPXsCLEQ==}
+
+  lerc@2.0.0:
+    resolution: {integrity: sha512-7qo1Mq8ZNmaR4USHHm615nEW2lPeeWJ3bTyoqFbd35DLx0LUH7C6ptt5FDCTAlbIzs3+WKrk5SkJvw8AFDE2hg==}
+
   levn@0.4.1:
     resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
     engines: {node: '>= 0.8.0'}
@@ -3812,6 +3933,9 @@ packages:
     resolution: {integrity: sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==}
     engines: {node: '>= 0.6.0'}
 
+  long@5.3.1:
+    resolution: {integrity: sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==}
+
   lru-cache@10.2.2:
     resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==}
     engines: {node: 14 || >=16.14}
@@ -3826,6 +3950,9 @@ packages:
   m3u8-parser@4.8.0:
     resolution: {integrity: sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA==}
 
+  magic-string@0.25.9:
+    resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
+
   magic-string@0.30.10:
     resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==}
 
@@ -3876,6 +4003,12 @@ packages:
     resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
     engines: {node: '>= 8'}
 
+  mersenne-twister@1.1.0:
+    resolution: {integrity: sha512-mUYWsMKNrm4lfygPkL3OfGzOPTR2DBlTkBNHM//F6hGp8cLThY897crAlk3/Jo17LEOOjQUrNAx6DvgO77QJkA==}
+
+  meshoptimizer@0.20.0:
+    resolution: {integrity: sha512-olcJ1q+YVnjroRJpCL1Dj5aZxr2JMr2hRutMUwhuHZvpAL7SIZgOT6eMlFF4TbBGSR89tawE/gqB79J/LrW/Nw==}
+
   micromatch@3.1.0:
     resolution: {integrity: sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==}
     engines: {node: '>=0.10.0'}
@@ -3895,6 +4028,11 @@ packages:
     resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
     engines: {node: '>= 0.6'}
 
+  mime@1.6.0:
+    resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
+    engines: {node: '>=4'}
+    hasBin: true
+
   mimic-fn@2.1.0:
     resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
     engines: {node: '>=6'}
@@ -3976,6 +4114,9 @@ packages:
   ms@2.1.2:
     resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
 
+  ms@2.1.3:
+    resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
   muggle-string@0.3.1:
     resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==}
 
@@ -4028,6 +4169,9 @@ packages:
   normalize-wheel-es@1.2.0:
     resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
 
+  nosleep.js@0.12.0:
+    resolution: {integrity: sha512-9d1HbpKLh3sdWlhXMhU6MMH+wQzKkrgfRkYV0EBdvt99YJfj0ilCJrWRDYG2130Tm4GXbEoTCx5b34JSaP+HhA==}
+
   npm-run-path@4.0.1:
     resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
     engines: {node: '>=8'}
@@ -4075,6 +4219,10 @@ packages:
   ofetch@1.3.4:
     resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==}
 
+  on-finished@2.4.1:
+    resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+    engines: {node: '>= 0.8'}
+
   once@1.4.0:
     resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
 
@@ -4118,6 +4266,9 @@ packages:
     resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
     engines: {node: '>=6'}
 
+  pako@2.1.0:
+    resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
+
   parent-module@1.0.1:
     resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
     engines: {node: '>=6'}
@@ -4126,6 +4277,10 @@ packages:
     resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
     engines: {node: '>=8'}
 
+  parseurl@1.3.3:
+    resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+    engines: {node: '>= 0.8'}
+
   pascalcase@0.1.1:
     resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==}
     engines: {node: '>=0.10.0'}
@@ -4335,6 +4490,10 @@ packages:
     resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
     engines: {node: '>=0.4.0'}
 
+  protobufjs@7.4.0:
+    resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==}
+    engines: {node: '>=12.0.0'}
+
   proxy-from-env@1.1.0:
     resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
 
@@ -4361,6 +4520,16 @@ packages:
   queue-microtask@1.2.3:
     resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
 
+  quickselect@2.0.0:
+    resolution: {integrity: sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==}
+
+  range-parser@1.2.1:
+    resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
+    engines: {node: '>= 0.6'}
+
+  rbush@3.0.1:
+    resolution: {integrity: sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==}
+
   rd@2.0.1:
     resolution: {integrity: sha512-/XdKU4UazUZTXFmI0dpABt8jSXPWcEyaGdk340KdHnsEOdkTctlX23aAK7ChQDn39YGNlAJr1M5uvaKt4QnpNw==}
 
@@ -4466,6 +4635,11 @@ packages:
     engines: {node: '>=14'}
     hasBin: true
 
+  rollup-plugin-external-globals@0.6.1:
+    resolution: {integrity: sha512-mlp3KNa5sE4Sp9UUR2rjBrxjG79OyZAh/QC18RHIjM+iYkbBwNXSo8DHRMZWtzJTrH8GxQ+SJvCTN3i14uMXIA==}
+    peerDependencies:
+      rollup: ^2.25.0
+
   rollup-plugin-purge-icons@0.10.0:
     resolution: {integrity: sha512-GD2ftg4L9G/sagIhtCmBn5vdyzePOisniythubpbywP0Q3ix9rZuDeFvgXTPemOsc22pvH7t22ryYQIl0rwGog==}
     engines: {node: '>= 12'}
@@ -4535,6 +4709,14 @@ packages:
     engines: {node: '>=10'}
     hasBin: true
 
+  send@0.19.0:
+    resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==}
+    engines: {node: '>= 0.8.0'}
+
+  serve-static@1.16.2:
+    resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
+    engines: {node: '>= 0.8.0'}
+
   set-blocking@2.0.0:
     resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
 
@@ -4550,6 +4732,9 @@ packages:
     resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==}
     engines: {node: '>=0.10.0'}
 
+  setprototypeof@1.2.0:
+    resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
   shebang-command@2.0.0:
     resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
     engines: {node: '>=8'}
@@ -4639,6 +4824,10 @@ packages:
     resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
     engines: {node: '>=0.10.0'}
 
+  sourcemap-codec@1.4.8:
+    resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
+    deprecated: Please use @jridgewell/sourcemap-codec instead
+
   split-string@3.1.0:
     resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==}
     engines: {node: '>=0.10.0'}
@@ -4658,6 +4847,10 @@ packages:
     resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==}
     engines: {node: '>=0.10.0'}
 
+  statuses@2.0.1:
+    resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
+    engines: {node: '>= 0.8'}
+
   steady-xml@0.1.0:
     resolution: {integrity: sha512-5sk17qO2wWRtonTNoBhoKAB35OSsGJOa3+NEa6D+1GS+de+ujDWxnflMkXBrviOfkNrPTUqduAdXhrMJs89nAw==}
     engines: {node: '>=12.0.0'}
@@ -4848,6 +5041,14 @@ packages:
     resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==}
     engines: {node: '>=0.10.0'}
 
+  toidentifier@1.0.1:
+    resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+    engines: {node: '>=0.6'}
+
+  topojson-client@3.1.0:
+    resolution: {integrity: sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==}
+    hasBin: true
+
   totalist@3.0.1:
     resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
     engines: {node: '>=6'}
@@ -5011,6 +5212,9 @@ packages:
   uri-js@4.4.1:
     resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
 
+  urijs@1.19.11:
+    resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==}
+
   urix@0.1.0:
     resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==}
     deprecated: Please see https://github.com/lydell/urix#deprecated
@@ -5045,6 +5249,12 @@ packages:
   videojs-vtt.js@0.15.5:
     resolution: {integrity: sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==}
 
+  vite-plugin-cesium@1.2.23:
+    resolution: {integrity: sha512-x9A8ZCEoegceXg/E+LnxKr0XBsI9CR4cgYWQ2Dd3cUEYwKcTnHQ3kBfpol7BUcGtgQnQos/mtVrRmuVQBXFjHw==}
+    peerDependencies:
+      cesium: ^1.95.0
+      vite: '>=2.7.1'
+
   vite-plugin-compression@0.5.1:
     resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==}
     peerDependencies:
@@ -6084,6 +6294,33 @@ snapshots:
 
   '@camunda/element-templates-json-schema@0.4.0': {}
 
+  '@cesium/engine@9.2.0':
+    dependencies:
+      '@tweenjs/tween.js': 23.1.3
+      '@zip.js/zip.js': 2.7.57
+      autolinker: 4.1.0
+      bitmap-sdf: 1.0.4
+      dompurify: 3.1.1
+      draco3d: 1.5.7
+      earcut: 2.2.4
+      grapheme-splitter: 1.0.4
+      jsep: 1.4.0
+      kdbush: 4.0.2
+      ktx-parse: 0.7.1
+      lerc: 2.0.0
+      mersenne-twister: 1.1.0
+      meshoptimizer: 0.20.0
+      pako: 2.1.0
+      protobufjs: 7.4.0
+      rbush: 3.0.1
+      topojson-client: 3.1.0
+      urijs: 1.19.11
+
+  '@cesium/widgets@6.1.2':
+    dependencies:
+      '@cesium/engine': 9.2.0
+      nosleep.js: 0.12.0
+
   '@commitlint/cli@19.3.0(@types/node@20.12.7)(typescript@5.3.3)':
     dependencies:
       '@commitlint/format': 19.3.0
@@ -6552,6 +6789,29 @@ snapshots:
 
   '@polka/url@1.0.0-next.25': {}
 
+  '@protobufjs/aspromise@1.1.2': {}
+
+  '@protobufjs/base64@1.1.2': {}
+
+  '@protobufjs/codegen@2.0.4': {}
+
+  '@protobufjs/eventemitter@1.1.0': {}
+
+  '@protobufjs/fetch@1.1.0':
+    dependencies:
+      '@protobufjs/aspromise': 1.1.2
+      '@protobufjs/inquire': 1.1.0
+
+  '@protobufjs/float@1.0.2': {}
+
+  '@protobufjs/inquire@1.1.0': {}
+
+  '@protobufjs/path@1.1.2': {}
+
+  '@protobufjs/pool@1.1.0': {}
+
+  '@protobufjs/utf8@1.1.0': {}
+
   '@purge-icons/core@0.10.0':
     dependencies:
       '@iconify/iconify': 2.1.2
@@ -6696,6 +6956,8 @@ snapshots:
 
   '@trysound/sax@0.2.0': {}
 
+  '@tweenjs/tween.js@23.1.3': {}
+
   '@types/conventional-commits-parser@5.0.0':
     dependencies:
       '@types/node': 20.12.7
@@ -7446,6 +7708,8 @@ snapshots:
 
   '@xmldom/xmldom@0.8.10': {}
 
+  '@zip.js/zip.js@2.7.57': {}
+
   '@zxcvbn-ts/core@3.0.4':
     dependencies:
       fastest-levenshtein: 1.0.16
@@ -7551,8 +7815,14 @@ snapshots:
 
   asynckit@0.4.0: {}
 
+  at-least-node@1.0.0: {}
+
   atob@2.1.2: {}
 
+  autolinker@4.1.0:
+    dependencies:
+      tslib: 2.8.1
+
   autoprefixer@10.4.19(postcss@8.4.38):
     dependencies:
       browserslist: 4.23.0
@@ -7629,6 +7899,8 @@ snapshots:
 
   binary-extensions@2.3.0: {}
 
+  bitmap-sdf@1.0.4: {}
+
   bluebird@3.7.2: {}
 
   boolbase@1.0.0: {}
@@ -7745,6 +8017,11 @@ snapshots:
 
   caniuse-lite@1.0.30001614: {}
 
+  cesium@1.118.2:
+    dependencies:
+      '@cesium/engine': 9.2.0
+      '@cesium/widgets': 6.1.2
+
   chalk@1.1.3:
     dependencies:
       ansi-styles: 2.2.1
@@ -8058,8 +8335,12 @@ snapshots:
 
   delayed-stream@1.0.0: {}
 
+  depd@2.0.0: {}
+
   destr@2.0.3: {}
 
+  destroy@1.2.0: {}
+
   diagram-js-direct-editing@1.8.0(diagram-js@7.9.0):
     dependencies:
       diagram-js: 7.9.0
@@ -8171,10 +8452,14 @@ snapshots:
     dependencies:
       is-obj: 2.0.0
 
+  draco3d@1.5.7: {}
+
   driver.js@1.3.1: {}
 
   duplexer@0.1.2: {}
 
+  earcut@2.2.4: {}
+
   eastasianwidth@0.2.0: {}
 
   echarts-wordcloud@2.1.0(echarts@5.5.0):
@@ -8186,6 +8471,8 @@ snapshots:
       tslib: 2.3.0
       zrender: 5.5.0
 
+  ee-first@1.1.1: {}
+
   ejs@3.1.10:
     dependencies:
       jake: 10.8.7
@@ -8244,6 +8531,10 @@ snapshots:
 
   encode-utf8@1.0.3: {}
 
+  encodeurl@1.0.2: {}
+
+  encodeurl@2.0.0: {}
+
   entities@1.1.2: {}
 
   entities@2.2.0: {}
@@ -8680,12 +8971,21 @@ snapshots:
     dependencies:
       map-cache: 0.2.2
 
+  fresh@0.5.2: {}
+
   fs-extra@10.1.0:
     dependencies:
       graceful-fs: 4.2.11
       jsonfile: 6.1.0
       universalify: 2.0.1
 
+  fs-extra@9.1.0:
+    dependencies:
+      at-least-node: 1.0.0
+      graceful-fs: 4.2.11
+      jsonfile: 6.1.0
+      universalify: 2.0.1
+
   fs.realpath@1.0.0: {}
 
   fsevents@2.3.3:
@@ -8807,6 +9107,8 @@ snapshots:
 
   graceful-fs@4.2.11: {}
 
+  grapheme-splitter@1.0.4: {}
+
   graphemer@1.4.0: {}
 
   gzip-size@6.0.0:
@@ -8888,6 +9190,14 @@ snapshots:
       domutils: 3.1.0
       entities: 4.5.0
 
+  http-errors@2.0.0:
+    dependencies:
+      depd: 2.0.0
+      inherits: 2.0.4
+      setprototypeof: 1.2.0
+      statuses: 2.0.1
+      toidentifier: 1.0.1
+
   human-signals@2.1.0: {}
 
   human-signals@5.0.0: {}
@@ -9042,6 +9352,10 @@ snapshots:
 
   is-plain-object@5.0.0: {}
 
+  is-reference@1.2.1:
+    dependencies:
+      '@types/estree': 1.0.5
+
   is-regex@1.1.4:
     dependencies:
       call-bind: 1.0.7
@@ -9118,6 +9432,8 @@ snapshots:
 
   jsencrypt@3.3.2: {}
 
+  jsep@1.4.0: {}
+
   jsesc@0.5.0: {}
 
   jsesc@2.5.2: {}
@@ -9155,6 +9471,8 @@ snapshots:
 
   jsonparse@1.3.1: {}
 
+  kdbush@4.0.2: {}
+
   keycode@2.2.1: {}
 
   keyv@4.5.4:
@@ -9177,6 +9495,10 @@ snapshots:
 
   kolorist@1.8.0: {}
 
+  ktx-parse@0.7.1: {}
+
+  lerc@2.0.0: {}
+
   levn@0.4.1:
     dependencies:
       prelude-ls: 1.2.1
@@ -9292,6 +9614,8 @@ snapshots:
 
   loglevel@1.9.1: {}
 
+  long@5.3.1: {}
+
   lru-cache@10.2.2: {}
 
   lru-cache@5.1.1:
@@ -9308,6 +9632,10 @@ snapshots:
       '@videojs/vhs-utils': 3.0.5
       global: 4.4.0
 
+  magic-string@0.25.9:
+    dependencies:
+      sourcemap-codec: 1.4.8
+
   magic-string@0.30.10:
     dependencies:
       '@jridgewell/sourcemap-codec': 1.4.15
@@ -9342,6 +9670,10 @@ snapshots:
 
   merge2@1.4.1: {}
 
+  mersenne-twister@1.1.0: {}
+
+  meshoptimizer@0.20.0: {}
+
   micromatch@3.1.0:
     dependencies:
       arr-diff: 4.0.0
@@ -9375,6 +9707,8 @@ snapshots:
     dependencies:
       mime-db: 1.52.0
 
+  mime@1.6.0: {}
+
   mimic-fn@2.1.0: {}
 
   mimic-fn@4.0.0: {}
@@ -9470,6 +9804,8 @@ snapshots:
 
   ms@2.1.2: {}
 
+  ms@2.1.3: {}
+
   muggle-string@0.3.1: {}
 
   mux.js@6.0.1:
@@ -9515,6 +9851,8 @@ snapshots:
 
   normalize-wheel-es@1.2.0: {}
 
+  nosleep.js@0.12.0: {}
+
   npm-run-path@4.0.1:
     dependencies:
       path-key: 3.1.1
@@ -9564,6 +9902,10 @@ snapshots:
       node-fetch-native: 1.6.4
       ufo: 1.5.3
 
+  on-finished@2.4.1:
+    dependencies:
+      ee-first: 1.1.1
+
   once@1.4.0:
     dependencies:
       wrappy: 1.0.2
@@ -9611,6 +9953,8 @@ snapshots:
 
   p-try@2.2.0: {}
 
+  pako@2.1.0: {}
+
   parent-module@1.0.1:
     dependencies:
       callsites: 3.1.0
@@ -9622,6 +9966,8 @@ snapshots:
       json-parse-even-better-errors: 2.3.1
       lines-and-columns: 1.2.4
 
+  parseurl@1.3.3: {}
+
   pascalcase@0.1.1: {}
 
   path-browserify@1.0.1: {}
@@ -9798,6 +10144,21 @@ snapshots:
 
   progress@2.0.3: {}
 
+  protobufjs@7.4.0:
+    dependencies:
+      '@protobufjs/aspromise': 1.1.2
+      '@protobufjs/base64': 1.1.2
+      '@protobufjs/codegen': 2.0.4
+      '@protobufjs/eventemitter': 1.1.0
+      '@protobufjs/fetch': 1.1.0
+      '@protobufjs/float': 1.0.2
+      '@protobufjs/inquire': 1.1.0
+      '@protobufjs/path': 1.1.2
+      '@protobufjs/pool': 1.1.0
+      '@protobufjs/utf8': 1.1.0
+      '@types/node': 20.12.7
+      long: 5.3.1
+
   proxy-from-env@1.1.0: {}
 
   punycode@1.4.1: {}
@@ -9822,6 +10183,14 @@ snapshots:
 
   queue-microtask@1.2.3: {}
 
+  quickselect@2.0.0: {}
+
+  range-parser@1.2.1: {}
+
+  rbush@3.0.1:
+    dependencies:
+      quickselect: 2.0.0
+
   rd@2.0.1:
     dependencies:
       '@types/node': 10.17.60
@@ -9918,6 +10287,14 @@ snapshots:
     dependencies:
       glob: 10.3.12
 
+  rollup-plugin-external-globals@0.6.1(rollup@4.17.1):
+    dependencies:
+      '@rollup/pluginutils': 4.2.1
+      estree-walker: 2.0.2
+      is-reference: 1.2.1
+      magic-string: 0.25.9
+      rollup: 4.17.1
+
   rollup-plugin-purge-icons@0.10.0:
     dependencies:
       '@purge-icons/core': 0.10.0
@@ -10013,6 +10390,33 @@ snapshots:
     dependencies:
       lru-cache: 6.0.0
 
+  send@0.19.0:
+    dependencies:
+      debug: 2.6.9
+      depd: 2.0.0
+      destroy: 1.2.0
+      encodeurl: 1.0.2
+      escape-html: 1.0.3
+      etag: 1.8.1
+      fresh: 0.5.2
+      http-errors: 2.0.0
+      mime: 1.6.0
+      ms: 2.1.3
+      on-finished: 2.4.1
+      range-parser: 1.2.1
+      statuses: 2.0.1
+    transitivePeerDependencies:
+      - supports-color
+
+  serve-static@1.16.2:
+    dependencies:
+      encodeurl: 2.0.0
+      escape-html: 1.0.3
+      parseurl: 1.3.3
+      send: 0.19.0
+    transitivePeerDependencies:
+      - supports-color
+
   set-blocking@2.0.0: {}
 
   set-function-length@1.2.2:
@@ -10038,6 +10442,8 @@ snapshots:
       is-plain-object: 2.0.4
       split-string: 3.1.0
 
+  setprototypeof@1.2.0: {}
+
   shebang-command@2.0.0:
     dependencies:
       shebang-regex: 3.0.0
@@ -10138,6 +10544,8 @@ snapshots:
 
   source-map@0.6.1: {}
 
+  sourcemap-codec@1.4.8: {}
+
   split-string@3.1.0:
     dependencies:
       extend-shallow: 3.0.2
@@ -10153,6 +10561,8 @@ snapshots:
       define-property: 0.2.5
       object-copy: 0.1.0
 
+  statuses@2.0.1: {}
+
   steady-xml@0.1.0: {}
 
   strict-uri-encode@1.1.0: {}
@@ -10398,6 +10808,12 @@ snapshots:
       regex-not: 1.0.2
       safe-regex: 1.1.0
 
+  toidentifier@1.0.1: {}
+
+  topojson-client@3.1.0:
+    dependencies:
+      commander: 2.20.3
+
   totalist@3.0.1: {}
 
   tr46@0.0.3: {}
@@ -10620,6 +11036,8 @@ snapshots:
     dependencies:
       punycode: 2.3.1
 
+  urijs@1.19.11: {}
+
   urix@0.1.0: {}
 
   url-toolkit@2.2.5: {}
@@ -10659,6 +11077,17 @@ snapshots:
     dependencies:
       global: 4.4.0
 
+  vite-plugin-cesium@1.2.23(cesium@1.118.2)(rollup@4.17.1)(vite@5.1.4(@types/node@20.12.7)(sass@1.75.0)(terser@5.30.4)):
+    dependencies:
+      cesium: 1.118.2
+      fs-extra: 9.1.0
+      rollup-plugin-external-globals: 0.6.1(rollup@4.17.1)
+      serve-static: 1.16.2
+      vite: 5.1.4(@types/node@20.12.7)(sass@1.75.0)(terser@5.30.4)
+    transitivePeerDependencies:
+      - rollup
+      - supports-color
+
   vite-plugin-compression@0.5.1(vite@5.1.4(@types/node@20.12.7)(sass@1.75.0)(terser@5.30.4)):
     dependencies:
       chalk: 4.1.2

+ 47 - 0
src/api/inspection/inspectionpath/index.ts

@@ -0,0 +1,47 @@
+import request from '@/config/axios'
+
+// 巡检路径 VO
+export interface PathVO {
+  shpName: string // 关联图层名
+  id: number // 用户ID
+  status: number // 状态(0正常 1停用)
+  code: string // 编号
+  remarks: string // 备注
+  picture: string // 图片路径
+  name: string // 巡检路线名称
+  username: string // 巡检人
+  sequence: string // 巡检点数组、顺序
+}
+
+// 巡检路径 API
+export const PathApi = {
+  // 查询巡检路径分页
+  getPathPage: async (params: any) => {
+    return await request.get({ url: `/inspection/path/page`, params })
+  },
+
+  // 查询巡检路径详情
+  getPath: async (id: number) => {
+    return await request.get({ url: `/inspection/path/get?id=` + id })
+  },
+
+  // 新增巡检路径
+  createPath: async (data: PathVO) => {
+    return await request.post({ url: `/inspection/path/create`, data })
+  },
+
+  // 修改巡检路径
+  updatePath: async (data: PathVO) => {
+    return await request.put({ url: `/inspection/path/update`, data })
+  },
+
+  // 删除巡检路径
+  deletePath: async (id: number) => {
+    return await request.delete({ url: `/inspection/path/delete?id=` + id })
+  },
+
+  // 导出巡检路径 Excel
+  exportPath: async (params) => {
+    return await request.download({ url: `/inspection/path/export-excel`, params })
+  },
+}

+ 50 - 0
src/api/inspection/inspectionpoint/index.ts

@@ -0,0 +1,50 @@
+import request from '@/config/axios'
+
+// 巡检路径 VO
+export interface PointVO {
+  shpName: string // 关联图层名
+  id: number // 用户ID
+  username: string // 用户账号
+  nickname: string // 用户昵称
+  status: number // 状态(0正常 1停用)
+  cycle : string // 周期
+  code: string // 编号
+  remarks: string // 备注
+  picture: string // 图片路径
+  name: string // 巡检点名称
+  shpGid: number // 对应点id
+  type: string // 巡检点类型
+}
+
+// 巡检路径 API
+export const PointApi = {
+  // 查询巡检分页
+  getPointPage: async (params: any) => {
+    return await request.get({ url: `/inspection/point/page`, params })
+  },
+
+  // 查询巡检详情
+  getPoint: async (id: number) => {
+    return await request.get({ url: `/inspection/point/get?id=` + id })
+  },
+
+  // 新增巡检
+  createPoint: async (data: PointVO) => {
+    return await request.post({ url: `/inspection/point/create`, data })
+  },
+
+  // 修改巡检路径
+  updatePoint: async (data: PointVO) => {
+    return await request.put({ url: `/inspection/point/update`, data })
+  },
+
+  // 删除巡检路径
+  deletePoint: async (id: number) => {
+    return await request.delete({ url: `/inspection/point/delete?id=` + id })
+  },
+
+  // 导出巡检路径 Excel
+  exportPoint: async (params) => {
+    return await request.download({ url: `/inspection/point/export-excel`, params })
+  },
+}

+ 48 - 0
src/api/inspection/inspectionrecord/index.ts

@@ -0,0 +1,48 @@
+import request from '@/config/axios'
+
+// 巡检记录 VO
+export interface RecordVO {
+  shpName: string // 关联图层名
+  id: number // 用户ID
+  status: number // 状态(0正常 1停用)
+  code: string // 编号
+  remarks: string // 备注
+  picture: string // 图片路径
+  name: string // 巡检点名称
+  username: string // 巡检人
+  sequence: string // 巡检点数组、顺序
+  geom: object // 巡检记录
+}
+
+// 巡检记录 API
+export const RecordApi = {
+  // 查询巡检记录分页
+  getRecordPage: async (params: any) => {
+    return await request.get({ url: `/inspection/record/page`, params })
+  },
+
+  // 查询巡检记录详情
+  getRecord: async (id: number) => {
+    return await request.get({ url: `/inspection/record/get?id=` + id })
+  },
+
+  // 新增巡检记录
+  createRecord: async (data: RecordVO) => {
+    return await request.post({ url: `/inspection/record/create`, data })
+  },
+
+  // 修改巡检记录
+  updateRecord: async (data: RecordVO) => {
+    return await request.put({ url: `/inspection/record/update`, data })
+  },
+
+  // 删除巡检记录
+  deleteRecord: async (id: number) => {
+    return await request.delete({ url: `/inspection/record/delete?id=` + id })
+  },
+
+  // 导出巡检记录 Excel
+  exportRecord: async (params) => {
+    return await request.download({ url: `/inspection/record/export-excel`, params })
+  },
+}

+ 4 - 0
src/api/layer/gisname/index.ts

@@ -44,6 +44,10 @@ export const GisNameApi = {
     return await request.download({ url: `/layer/gis-name/export-excel`, params })
   },
 
+  // 查询shp名分页
+  getShpAllRow: async (shpName: any) => {
+    return await request.get({ url: `/layer/ltygis/getShpAllRow?shpName=` + shpName })
+  },
   // getSimpleGisNameList: async () => {
   //   return await request.get({ url: '/layer/gis-name/simple-list' })
   // }

+ 1 - 0
src/components/DiyEditor/util.ts

@@ -85,6 +85,7 @@ export function usePropertyForm<T>(modelValue: T, emit: Function): { formData: R
   watch(
     () => modelValue,
     () => {
+      console.log(modelValue)
       formData.value = modelValue
     },
     {

+ 4 - 2
src/components/Draggable/index.vue

@@ -31,7 +31,7 @@
       </div>
     </template>
   </VueDraggable>
-  <el-tooltip :disabled="limit < 1" :content="`最多添加${limit}个`">
+  <el-tooltip v-if="isAdd" :disabled="limit < 1" :content="`最多添加${limit}个`">
     <el-button
       type="primary"
       plain
@@ -62,7 +62,9 @@ const props = defineProps({
   // 空的元素:点击添加按钮时,创建元素并添加到列表;默认为空对象
   emptyItem: any<unknown>().def({}),
   // 数量限制:默认为0,表示不限制
-  limit: propTypes.number.def(0)
+  limit: propTypes.number.def(0),
+
+  isAdd: propTypes.bool.def(true)
 })
 // 定义事件
 const emit = defineEmits(['update:modelValue'])

+ 1 - 1
src/config/axios/config.ts

@@ -16,7 +16,7 @@ const config: {
   /**
    * 接口请求超时时间
    */
-  request_timeout: 30000,
+  request_timeout: 300000,
 
   /**
    * 默认接口请求类型

+ 212 - 0
src/views/inspection/Inspectionpath/GisNameForm.vue

@@ -0,0 +1,212 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="100px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="图层名" prop="shpName">
+        <el-input v-model="formData.shpName" placeholder="请输入图层名" />
+      </el-form-item>
+
+      <el-form-item label="显示配置" prop="showitem"  v-if="formType == 'update'">
+            <el-select
+              v-model="formData.showitem"
+              multiple
+              filterable
+              allow-create
+              default-first-option
+              placeholder="请选择项目相关图层">
+              <el-option
+                v-for="dict in datagisname"
+                :key="dict"
+                :label="dict"
+                :value="dict"
+              />
+            </el-select>
+      </el-form-item>
+
+      <el-form-item label="Label配置" prop="labelItem"  v-if="formType == 'update'">
+            <el-select
+              v-model="formData.labelItem"
+              multiple
+              filterable
+              default-first-option
+              placeholder="请选择项目相关图层">
+              <el-option
+                v-for="dict in datagisname"
+                :key="dict"
+                :label="dict"
+                :value="dict"
+              />
+            </el-select>
+      </el-form-item>
+
+      <el-form-item label="符号化模型" prop="symbolizeModel">
+        <el-input v-model="formData.symbolizeModel" placeholder="请输入符号化模型Url地址" />
+      </el-form-item>
+      <el-form-item label="文本显示" prop="textDisplay">
+        <el-select v-model="formData.textDisplay" placeholder="请选择文本显示">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="描述" prop="description">
+        <el-input v-model="formData.description" placeholder="请输入描述" />
+      </el-form-item>
+      <el-form-item label="文件地址" prop="fileAddress" v-if="formType != 'update'">
+        <!-- <UploadFile 
+          v-model="fakefileref" 
+          :limit = "10"
+          :fileType = "['cpg', 'dbf', 'prj', 'sbn', 'sbx','shp','shx']"
+          /> -->
+        <el-upload
+          ref="upload"
+          v-model:file-list="fakefileref"
+          :on-change="changeFile"
+          :drag = "true"
+          :accept = "'.shp'"
+          :limit="1"
+          :on-exceed="handleExceed"
+          :http-request = "()=>{}"
+        >
+          <el-button type="primary">Click to upload</el-button>
+          <template #tip>
+            <div class="el-upload__tip">
+              请选择'shp'格式文件上传,并在同目录存放'cpg', 'dbf', 'prj', 'sbn', 'sbx', 'shx'文件
+            </div>
+          </template>
+        </el-upload>
+      </el-form-item>
+      <!-- <el-form-item label="数据标识" prop="shpType">
+        <el-select v-model="formData.shpType" placeholder="请选择数据标识">
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.LAYER_NAME_SHPTYPE)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item> -->
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
+import { GisNameApi, GisNameVO } from '@/api/layer/gisname'
+import {genFileId} from 'element-plus'
+import {getgisAttr} from "@/api/layer/gisname";
+/** shp名 表单 */
+defineOptions({ name: 'GisNameForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  shpName: undefined,
+  description: undefined,
+  id: undefined,
+  shpType: 0,
+  symbolizeModel: undefined,
+  textDisplay: undefined,
+})
+const fakefileref = ref();
+const datagisname = ref([]);
+
+
+const upload = ref<UploadInstance>()
+
+const formRules = reactive({
+})
+const formRef = ref() // 表单 Ref
+const handleExceed: UploadProps['onExceed'] = (files) => {
+  upload.value!.clearFiles()
+  const file = files[0] as UploadRawFile
+  file.uid = genFileId()
+  upload.value!.handleStart(file)
+}
+const changeFile = (file: any) => {
+  console.log(file);
+  // fakefileref.value = file.raw;
+  formData.value.fileAddress = file.raw.name;
+}
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await GisNameApi.getGisName(id)
+      formData.value.showitem = formData.value.showitem=="[]"?null:formData.value.showitem;
+      formData.value.labelItem = formData.value.labelItem=="[]"?null:formData.value.labelItem;
+      console.log(formData.value.labelItem);
+      datagisname.value = await getgisAttr(formData.value.shpName);
+      console.log(datagisname.value);
+      formData.value.shpType = 0;
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  await formRef.value.validate()
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as unknown as GisNameVO
+    data.shpType = 0;
+    if (formType.value === 'create') {
+      await GisNameApi.createGisName(data)
+      // await GisNameApi.LtyReadSHP({
+      //   shpPath: `E:\\gis_data\\ys\\Kunming\\${formData.value.fileAddress}`,
+      //   shpName: data.shpName
+      // });
+      message.success(t('common.createSuccess'))
+    } else {
+      //NOTE - data格式修改为json
+      await GisNameApi.updateGisName(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    shpName: undefined,
+    description: undefined,
+    id: undefined,
+    shpType: 0,
+    shpitem: undefined,
+    symbolizeModel: undefined,
+    textDisplay: undefined,
+
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 265 - 0
src/views/inspection/Inspectionpath/PathForm.vue

@@ -0,0 +1,265 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="100px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="路线名称" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入巡检路线名称" />
+      </el-form-item>
+      <el-form-item label="巡检人员" prop="userId">
+        <el-select
+            v-model="formData.userId"
+            filterable
+            placeholder="请选择巡检人员"
+            style="width: 100%"
+        >
+          <el-option
+              v-for="user in userList"
+              :key="user.id"
+              :label="user.nickname"
+              :value="user.id"
+          />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="巡检点位" prop="pathPoints">
+
+        <div class="selected-points">
+          <draggable
+              class="component-container"
+              ghost-class="draggable-ghost"
+              item-key="sort"
+              :list="formData.pathPoints"
+              :animation="200"
+              :force-fallback="true"
+              @end="updateSortNumbers"
+          >
+            <template #item="{ element }">
+            <div
+                class="mb-4px flex flex-col gap-4px border border-gray-2 border-rounded rounded border-solid p-8px"
+            >
+              <!-- 操作按钮区 -->
+              <div class="m--8px m-b-4px flex flex-row items-center justify-between bg-gray-1 p-8px">
+                <el-tooltip content="拖动排序">
+                  <Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
+                </el-tooltip>
+                <span class="point-info">
+                  {{ element.name }}
+                  <el-tag size="small">ID: {{ element.pointId }}</el-tag>
+                </span>
+              </div>
+
+            </div>
+          </template>
+
+          </draggable>
+          <el-button
+              type="primary"
+              plain
+              @click="openPointSelector"
+          >
+            添加巡检点
+          </el-button>
+        </div>
+      </el-form-item>
+      <el-form-item label="备注" prop="remarks">
+        <el-input v-model="formData.remarks" placeholder="请输入备注" />
+      </el-form-item>
+
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+    <PointSelectorDialog
+        ref="pointSelectorRef"
+        :selected="formData.points"
+        @confirm="handleSelectPoints"
+    />
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { PathApi, PathVO } from '@/api/inspection/inspectionpath'
+import PointSelectorDialog from './PointSelectorDialog.vue'
+import * as UserApi from "@/api/system/user";
+import draggable from 'vuedraggable'
+
+/** 巡检路径 表单 */
+defineOptions({ name: 'PathForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  status: undefined,
+  remarks: undefined,
+  name: undefined,
+  username: undefined,
+  userId: undefined,
+  pathPoints: [],
+})
+
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await PathApi.getPath(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+
+const showPointSelector = ref(false)
+const userList = ref<any[]>([])
+
+// 表单验证规则
+const formRules = reactive({
+  name: [{ required: true, message: '请输入路线名称', trigger: 'blur' }],
+  userIds: [{ required: true, message: '请选择巡检人员', trigger: 'change' }],
+  points: [
+    {
+      validator: (_, v, cb) => v?.length > 0 ? cb() : cb(new Error('请至少选择一个巡检点')),
+      trigger: 'change'
+    }
+  ]
+})
+const pointSelectorRef = ref()
+// 打开点位选择器
+const openPointSelector = () => {
+  pointSelectorRef.value.open()
+}
+
+// 删除点位
+const removePoint = (index) => {
+  formData.value.pathPoints.splice(index, 1);
+};
+
+// 处理点位选择
+const handleSelectPoints = (points) => {
+  if (!points) {
+    ElMessage.error('请选择至少一个点位');
+    return;
+  }
+
+  formData.value.pathPoints = points.map(point => ({
+    pointId: point.id,
+    name: point.name,
+    cycle: point.cycle,
+    type: point.type,
+    remarks: point.remarks,
+    // 初始的 sort 值根据现有 length 决定,或者设置默认值
+  }));
+  updateSortNumbers() // 添加新点位后更新排序
+};
+
+// 更新排序序号
+const updateSortNumbers = () => {
+  formData.value.pathPoints.forEach((point, index) => {
+    point.sort = index + 1; // 从 1 开始排序
+  });
+};
+// 加载用户列表
+const loadUsers = async () => {
+  try {
+    const res = await UserApi.getSimpleUserList()
+    userList.value = res
+  } catch (e) {
+    ElMessage.error('加载用户列表失败')
+  }
+}
+
+// 提交表单时处理数据
+const submitForm = async () => {
+  // 转换数据格式
+  const submitData = {
+    ...formData.value,
+  }
+  try {
+    if (formType.value === 'create') {
+      await PathApi.createPath(submitData)
+    } else {
+      await PathApi.updatePath(submitData)
+    }
+    message.success('操作成功')
+    emit('success')
+    dialogVisible.value = false
+  } catch (e) {
+    message.error('操作失败')
+  }
+}
+
+onMounted(() => {
+  loadUsers()
+})
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    status: undefined,
+    code: undefined,
+    remarks: undefined,
+    picture: undefined,
+    name: undefined,
+    username: undefined,
+    sequence: undefined,
+    points: undefined,
+  }
+}
+</script>
+
+
+<style scoped>
+.point-list .selected-points {
+  border: 1px solid #ebeef5;
+  border-radius: 4px;
+  padding: 10px;
+}
+
+.point-item {
+  display: flex;
+  align-items: center;
+  padding: 8px;
+  margin: 4px 0;
+  background: #f5f7fa;
+  border-radius: 4px;
+  transition: all 0.3s;
+}
+
+.point-item:hover {
+  background: #ebedf0;
+}
+
+.drag-handle {
+  margin-right: 8px;
+  cursor: move;
+  color: #909399;
+}
+
+.point-info {
+  flex: 1;
+  margin-right: 12px;
+}
+</style>

+ 180 - 0
src/views/inspection/Inspectionpath/PointSelectorDialog.vue

@@ -0,0 +1,180 @@
+<!-- components/PointSelectorDialog.vue -->
+<template>
+  <el-dialog
+      title="选择巡检点"
+      v-model="dialogVisible"
+      width="60%"
+      append-to-body
+      footer-class="footer-class"
+  >
+      <ContentWrap>
+        <!-- 搜索工作栏 -->
+        <el-form
+            class="-mb-15px"
+            :model="queryParams"
+            ref="queryFormRef"
+            :inline="true"
+            label-width="68px"
+        >
+          <el-form-item label="编号" prop="id">
+            <el-input
+                v-model="queryParams.id"
+                placeholder="请输入编号"
+                clearable
+                @keyup.enter="handleQuery"
+                class="!w-240px"
+            />
+          </el-form-item>
+          <el-form-item label="名称" prop="name">
+            <el-input
+                v-model="queryParams.name"
+                placeholder="请输入巡检点名称"
+                clearable
+                @keyup.enter="handleQuery"
+                class="!w-240px"
+            />
+          </el-form-item>
+
+          <el-form-item label="类型" prop="type">
+            <el-select
+                v-model="queryParams.type"
+                placeholder="请选择巡检点类型"
+                clearable
+                class="!w-240px"
+            >
+              <el-option label="请选择字典生成" value="" />
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+            <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+          </el-form-item>
+        </el-form>
+      </ContentWrap>
+      <!-- 点位列表 -->
+      <el-table
+          :data="list"
+          height="400px"
+          @selection-change="handleSelectionChange"
+          row-key="id"
+          v-loading="loading"
+      >
+        <el-table-column type="selection" width="55" reserve-selection />
+        <el-table-column label="编号" align="center" prop="id" />
+        <el-table-column label="周期" align="center" prop="cycle" />
+        <el-table-column label="巡检点名称" align="center" prop="name" />
+        <el-table-column label="经度" align="center" prop="longitude" />
+        <el-table-column label="纬度" align="center" prop="latitude" />
+        <el-table-column label="巡检点类型" align="center" prop="type" />
+        <el-table-column label="备注" align="center" prop="remarks" />
+        <el-table-column label="图片" align="center" prop="picture" />
+        <el-table-column
+            label="创建时间"
+            align="center"
+            prop="createTime"
+            :formatter="dateFormatter"
+            width="180px"
+        />
+      </el-table>
+      <Pagination
+          :total="total"
+          :small="true"
+          v-model:page="queryParams.pageNo"
+          v-model:limit="queryParams.pageSize"
+          @pagination="getList"
+      />
+
+    <template #footer >
+      <el-button type="primary" @click="confirmSelect">确认选择</el-button>
+      <el-button @click="cancelSelection" >取消</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import {PointApi, PointVO} from '@/api/inspection/inspectionpoint'
+import {dateFormatter} from "@/utils/formatTime";
+
+const props = defineProps({
+  selected: Array
+})
+
+const emit = defineEmits([ 'confirm'])
+
+const searchKey = ref('')
+const currentPage = ref(1)
+const pageSize = 10
+const loading = ref(true) // 列表的加载中
+const list = ref<PointVO[]>([]) // 列表的数据const pointList = ref<any[]>([])
+const selectedPoints = ref<any[]>([])
+const dialogVisible = ref(false)
+const total = ref(0) // 列表的总页数
+
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  createTime: [],
+  shpName: undefined,
+  id: undefined,
+  remarks: undefined,
+  picture: undefined,
+  name: undefined,
+  shpGid: undefined,
+  type: undefined,
+})
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryParams.pageNo = 1
+  queryParams.id = undefined
+  queryParams.remarks = undefined
+  queryParams.remarks = undefined
+  queryParams.name = undefined
+  queryParams.type = undefined
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await PointApi.getPointPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+// 确认选择
+const confirmSelect = () => {
+  emit('confirm', selectedPoints.value)
+  dialogVisible.value = false
+}
+const cancelSelection = ()=>{
+  dialogVisible.value = false
+}
+const handleSelectionChange = (val: any[]) => {
+  selectedPoints.value = val;
+};
+/** 打开弹窗 */
+const open = async () => {
+  dialogVisible.value = true
+  // 初始化加载
+  getList()
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+</script>
+<!--<style scoped>-->
+<!--  .footer-class{-->
+<!--    margin-right:  50px;-->
+<!--  }-->
+<!--</style>-->

+ 246 - 0
src/views/inspection/Inspectionpath/index.vue

@@ -0,0 +1,246 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="路线名称" prop="name">
+        <el-input
+            v-model="queryParams.name"
+            placeholder="请输入巡检路线名称"
+            clearable
+            @keyup.enter="handleQuery"
+            class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="巡检人" prop="username">
+        <el-input
+            v-model="queryParams.username"
+            placeholder="请输入巡检人"
+            clearable
+            @keyup.enter="handleQuery"
+            class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="编号" prop="code">
+        <el-input
+          v-model="queryParams.code"
+          placeholder="请输入编号"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="巡检点" prop="sequence">
+        <el-input
+          v-model="queryParams.sequence"
+          placeholder="请输入巡检点数组、顺序"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="备注" prop="remarks">
+        <el-input
+            v-model="queryParams.remarks"
+            placeholder="请输入备注"
+            clearable
+            @keyup.enter="handleQuery"
+            class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+            v-model="queryParams.createTime"
+            value-format="YYYY-MM-DD HH:mm:ss"
+            type="daterange"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+            class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          type="primary"
+          plain
+          @click="openForm('create')"
+          v-hasPermi="['inspection:path:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['inspection:path:export']"
+        >
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <el-table-column label="编号" align="center" prop="id" />
+      <el-table-column label="巡检路线名称" align="center" prop="name" />
+      <el-table-column label="巡检人" align="center" prop="username" />
+      <el-table-column label="巡检点" align="center" prop="sequence" />
+      <el-table-column label="关联图层名" align="center" prop="shpName" />
+      <el-table-column label="用户ID" align="center" prop="id" />
+      <el-table-column label="状态" align="center" prop="status" />
+      <el-table-column label="备注" align="center" prop="remarks" />
+      <el-table-column
+          label="创建时间"
+          align="center"
+          prop="createTime"
+          :formatter="dateFormatter"
+          width="180px"
+      />
+      <el-table-column label="操作" align="center">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['inspection:path:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['inspection:path:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <PathForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { PathApi, PathVO } from '@/api/inspection/inspectionpath'
+import PathForm from './PathForm.vue'
+
+/** 巡检路径 列表 */
+defineOptions({ name: 'Path' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<PathVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  createTime: [],
+  shpName: undefined,
+  status: undefined,
+  code: undefined,
+  remarks: undefined,
+  picture: undefined,
+  name: undefined,
+  username: undefined,
+  sequence: undefined,
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await PathApi.getPathPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await PathApi.deletePath(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await PathApi.exportPath(queryParams)
+    download.excel(data, '巡检路径.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 190 - 0
src/views/inspection/Inspectionpoint/PointForm.vue

@@ -0,0 +1,190 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="100px"
+      v-loading="formLoading"
+    >
+
+      <el-form-item label="巡检点名称" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入巡检点名称" />
+      </el-form-item>
+<!--      <el-form-item label="对应点id" prop="shpGid">-->
+<!--        <el-input v-model="formData.shpGid" placeholder="请输入对应点id" />-->
+<!--      </el-form-item>-->
+      <el-form-item label="巡检点类型" prop="type">
+        <el-select
+            v-model="formData.type"
+            filterable
+            allow-create
+            default-first-option
+            placeholder="请选择巡检点类型"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+<!--      <el-form-item label="数据绑定" prop="itemShp">-->
+<!--        &lt;!&ndash; <el-input v-model="formData.itemShp" placeholder="请输入项目相关shp上传(保存url,可null)" />-->
+<!--          &ndash;&gt;-->
+<!--        <el-select-->
+<!--            v-model="formData.shpName"-->
+<!--            filterable-->
+<!--            allow-create-->
+<!--            default-first-option-->
+<!--            placeholder="请选择项目相关图层">-->
+<!--          <el-option-->
+<!--              v-for="dict in datagisname"-->
+<!--              :key="dict.id"-->
+<!--              :label="dict.shpName"-->
+<!--              :value="dict.shpName"-->
+<!--          />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
+
+      <el-form-item label="周期" prop="cycle ">
+        <el-input v-model="formData.cycle " placeholder="请输入周期" />
+      </el-form-item>
+      <el-form-item label="经度" prop="longitude">
+        <el-input v-model="formData.longitude" placeholder="请输入经度" />
+      </el-form-item>
+
+      <el-form-item label="纬度" prop="latitude">
+        <el-input v-model="formData.latitude" placeholder="请输入纬度" />
+      </el-form-item>
+      <el-form-item label="选择点位" prop="location">
+        <el-button type="primary" @click="openMapDialog">地图选点</el-button>
+      </el-form-item>
+
+      <el-form-item label="备注" prop="remarks">
+        <el-input v-model="formData.remarks" placeholder="请输入备注" />
+      </el-form-item>
+      <el-form-item label="图片" prop="picture">
+        <UploadImg v-model="formData.picture" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+
+    <orientation ref="orientationRef"  @selected="handleMapSelection" />
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { PointApi, PointVO } from '@/api/inspection/inspectionpoint'
+import {getSimpleGisNameList} from "@/api/layer/gisname";
+
+import orientation from './orientation.vue'
+/** 巡检路径 表单 */
+defineOptions({ name: 'PointForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  shpName: undefined,
+  id: undefined,
+  username: undefined,
+  nickname: undefined,
+  status: undefined,
+  cycle : undefined,
+  code: undefined,
+  remarks: undefined,
+  picture: undefined,
+  name: undefined,
+  shpGid: undefined,
+  type: undefined,
+  longitude: '',
+  latitude: '',
+})
+const formRules = reactive({
+  name: [{ required: true, message: '巡检点名称不能为空', trigger: 'blur' }],
+  name: [{ required: true, message: '对应点不能为空', trigger: 'blur' }],
+  name: [{ required: true, message: '绑定图层不能为空', trigger: 'blur' }],
+  nickname: [{ required: true, message: '不能为空', trigger: 'blur' }],
+  status: [{ required: true, message: '状态(0正常 1停用)不能为空', trigger: 'blur' }],
+})
+const formRef = ref() // 表单 Ref
+const datagisname = ref([]);
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  gisnamedatalist()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await PointApi.getPoint(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  await formRef.value.validate()
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as unknown as PointVO
+    if (formType.value === 'create') {
+      await PointApi.createPoint(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await PointApi.updatePoint(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+const gisnamedatalist = async () => {
+  datagisname.value = await getSimpleGisNameList();
+  console.log(datagisname.value);
+}
+/** 处理地图选点 */
+const handleMapSelection = (point) => {
+  formData.value.longitude = point.longitude;
+  formData.value.latitude = point.latitude;
+};
+const orientationRef = ref();
+const openMapDialog = () => {
+  orientationRef.value.openDialog()
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    shpName: undefined,
+    id: undefined,
+    username: undefined,
+    nickname: undefined,
+    status: undefined,
+    cycle : undefined,
+    code: undefined,
+    remarks: undefined,
+    picture: undefined,
+    name: undefined,
+    shpGid: undefined,
+    type: undefined,
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 252 - 0
src/views/inspection/Inspectionpoint/index.vue

@@ -0,0 +1,252 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="queryParams.createTime"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="daterange"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="关联图层名" prop="shpName">
+        <el-input
+          v-model="queryParams.shpName"
+          placeholder="请输入关联图层名"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="用户账号" prop="username">
+        <el-input
+          v-model="queryParams.username"
+          placeholder="请输入用户账号"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="编号" prop="code">
+        <el-input
+          v-model="queryParams.code"
+          placeholder="请输入编号"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="备注" prop="remarks">
+        <el-input
+          v-model="queryParams.remarks"
+          placeholder="请输入备注"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+
+      <el-form-item label="巡检点名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入巡检点名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+
+      <el-form-item label="巡检点类型" prop="type">
+        <el-select
+          v-model="queryParams.type"
+          placeholder="请选择巡检点类型"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          type="primary"
+          plain
+          @click="openForm('create')"
+          v-hasPermi="['inspection:point:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['inspection:point:export']"
+        >
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <el-table-column label="编号" align="center" prop="id" />
+      <el-table-column label="周期" align="center" prop="cycle" />
+
+      <el-table-column label="巡检点名称" align="center" prop="name" />
+      <el-table-column label="经度" align="center" prop="longitude" />
+      <el-table-column label="纬度" align="center" prop="latitude" />
+      <el-table-column label="巡检点类型" align="center" prop="type" />
+      <el-table-column label="备注" align="center" prop="remarks" />
+      <el-table-column label="图片" align="center" prop="picture" />
+      <el-table-column
+          label="创建时间"
+          align="center"
+          prop="createTime"
+          :formatter="dateFormatter"
+          width="180px"
+      />
+      <el-table-column label="操作" align="center">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['inspection:point:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['inspection:point:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <PointForm ref="formRef" @success="getList" />
+
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { PointApi, PointVO } from '@/api/inspection/inspectionpoint'
+import PointForm from './PointForm.vue'
+/** 巡检路径 列表 */
+defineOptions({ name: 'Point' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<PointVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  createTime: [],
+  shpName: undefined,
+  username: undefined,
+  nickname: undefined,
+  status: undefined,
+  cycle : undefined,
+  code: undefined,
+  remarks: undefined,
+  picture: undefined,
+  name: undefined,
+  shpGid: undefined,
+  type: undefined,
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await PointApi.getPointPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await PointApi.deletePoint(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await PointApi.exportPoint(queryParams)
+    download.excel(data, '巡检路径.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 197 - 0
src/views/inspection/Inspectionpoint/orientation.vue

@@ -0,0 +1,197 @@
+<template>
+  <Dialog title="地图选点" v-model="dialogVisible">
+    <div class="container">
+      <div id="cesiumContainer"></div>
+    </div>
+    <template #footer>
+      <el-button @click="cancelSelection">取消</el-button>
+      <el-button type="primary" @click="confirmSelection">确认选点</el-button>
+    </template>
+  </Dialog>
+</template>
+
+<script setup>
+import { ref, onMounted, nextTick } from 'vue';
+import * as Cesium from 'cesium';
+import {ElMessage} from "element-plus";
+
+// 设置 Cesium 的访问令牌
+Cesium.Ion.defaultAccessToken =
+    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxYWE5M2QzNy1hNGFjLTQ3YzItYmU0ZS05MDkyODc1MzVhNzAiLCJpZCI6MTE1MDQwLCJpYXQiOjE2Njg1OTA2NDh9.oW-_utGumUSPqYzlWGjhG8hbda-b4UxZdL0_2t4ASig";
+
+const dialogVisible = ref(false);
+const userLocation = ref(null); // 存储用户的位置
+const selectedPosition = ref(null); // 选中的点的坐标
+// 获取用户当前位置
+// 修改1: 增强定位错误处理
+const getUserPosition = () => {
+  return new Promise((resolve, reject) => {
+    if (!navigator.geolocation) {
+      ElMessage.error('浏览器不支持地理定位');
+      reject(new Error('Geolocation not supported'));
+      return;
+    }
+
+    navigator.geolocation.getCurrentPosition(
+        position => {
+          resolve({
+            longitude: position.coords.longitude,
+            latitude: position.coords.latitude,
+            height: position.coords.altitude || 1000 // 处理altitude为null的情况
+          });
+        },
+        error => {
+          const errorMessage = {
+            1: '权限被拒绝',
+            2: '位置不可用',
+            3: '请求超时'
+          }[error.code] || '无法获取位置';
+          ElMessage.warning(`定位失败: ${errorMessage}`);
+          reject(error);
+        },
+        { timeout: 5000 } // 添加超时设置
+    );
+  });
+};
+
+// 确认选点
+const confirmSelection = () => {
+  if (!selectedPosition.value) {
+    console.error('没有选中任何点');
+    return;
+  }
+  // 将坐标传递给父组件
+  emit('selected', selectedPosition.value);
+  dialogVisible.value = false;
+};
+const emit = defineEmits(['selected']);
+
+const viewer = ref(null);
+// 初始化 Cesium 地图
+const initializeMap = async () => {
+  try {
+    // 获取用户当前位置
+    userLocation.value = await getUserPosition();
+  } catch (error) {
+    console.error('Failed to get user position:', error);
+    userLocation.value = null;
+  }
+
+  nextTick(() => {
+    const container = document.getElementById('cesiumContainer');
+    if (!container) {
+      console.error('Cesium container not found!');
+      return;
+    }
+    const initialPosition = userLocation.value
+        ? Cesium.Cartesian3.fromDegrees(
+            userLocation.value.longitude,
+            userLocation.value.latitude,
+            userLocation.value.height
+        )
+        : Cesium.Cartesian3.fromDegrees(108.914547, 34.378463, 20384);
+
+    viewer.value = new Cesium.Viewer(container, {
+      infoBox: false,
+      selectedImageryProviderViewModel: undefined,
+      selectedTerrainProviderViewModel: undefined,
+      animation: false, //是否显示动画控件
+      baseLayerPicker: false, //是否显示图层选择控件
+      geocoder: false, //是否显示地名查找控件
+      timeline: false, //是否显示时间线控件
+      sceneModePicker: false, //是否显示投影方式控件
+      navigationHelpButton: false, //是否显示帮助信息控件
+      fullscreenButton: false, //是否显示全屏按钮
+    });
+
+    console.log(initialPosition, 'initialPosition')
+    // 设置初始视角
+    viewer.value.camera.flyTo({
+      destination: initialPosition,
+      duration: 2,
+    });
+
+    viewer.value.screenSpaceEventHandler.setInputAction((evt) => {
+      let ray=viewer.value.camera.getPickRay(evt.position);
+      let cartesian=viewer.value.scene.globe.pick(ray,viewer.value.scene);
+      let cartographic=Cesium.Cartographic.fromCartesian(cartesian);
+      let lng=Cesium.Math.toDegrees(cartographic.longitude);//经度
+      let lat=Cesium.Math.toDegrees(cartographic.latitude);//纬度
+      let mapPosition={longitude:lng,latitude:lat,height:cartographic.height};
+      selectedPosition.value = mapPosition;
+      console.log(mapPosition)
+      addMarker(mapPosition)
+    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+  });
+};
+
+const pointEntity = ref(null);
+
+// 实体添加(使用 fromDegrees 转换)
+const addMarker = (coord) => {
+  // 移除旧标记
+  if (pointEntity.value) {
+    viewer.value.entities.remove(pointEntity.value);
+  }
+
+  pointEntity.value = viewer.value.entities.add({
+    position: Cesium.Cartesian3.fromDegrees(
+        coord.longitude,
+        coord.latitude,
+        coord.height
+    ),
+    point: {
+      pixelSize: 12,
+      color: Cesium.Color.RED,
+      outlineColor: Cesium.Color.WHITE,
+      outlineWidth: 2
+    },
+    label: {
+      text: `经度: ${coord.longitude.toFixed(6)}\n纬度: ${coord.latitude.toFixed(6)}`,
+      font: '14px monospace',
+      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+      outlineWidth: 2,
+      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+      pixelOffset: new Cesium.Cartesian2(0, -20)
+    }
+  });
+};
+// 打开弹窗
+const openDialog = async () => {
+  dialogVisible.value = true;
+  nextTick(() => {
+    initializeMap();
+  });
+};
+
+defineExpose({ openDialog });
+const destroyViewer = () => {
+  if (viewer.value && !viewer.value.isDestroyed) {
+    viewer.value.destroy();
+    viewer.value = null;
+  }
+  pointEntity.value = null; // 清除标记引用
+};
+const cancelSelection = () => {
+  dialogVisible.value = false;
+  destroyViewer();
+};
+
+</script>
+
+<style scoped>
+.container {
+  width: 100%;
+  height: 60vh; /* 响应式高度 */
+}
+
+#cesiumContainer {
+  width: 100%;
+  height: 100%;
+}
+::v-deep .cesium-widget-credits{
+  display:none !important;
+  visibility:hide !important;
+}
+
+</style>

+ 112 - 0
src/views/inspection/inspectionrecord/RecordForm.vue

@@ -0,0 +1,112 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="100px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="巡检点名称" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入巡检点名称" />
+      </el-form-item>
+      <el-form-item label="路线id" prop="pathId">
+        <el-input v-model="formData.pathId" placeholder="pathId" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { RecordApi, RecordVO } from '@/api/inspection/inspectionrecord'
+
+/** 巡检记录 表单 */
+defineOptions({ name: 'RecordForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  shpName: undefined,
+  id: undefined,
+  status: undefined,
+  code: undefined,
+  remarks: undefined,
+  picture: undefined,
+  name: undefined,
+  username: undefined,
+  sequence: undefined,
+  geom: undefined,
+  pathId:undefined
+})
+const formRules = reactive({
+  status: [{ required: true, message: '状态(0正常 1停用)不能为空', trigger: 'blur' }],
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await RecordApi.getRecord(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  await formRef.value.validate()
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as unknown as RecordVO
+    if (formType.value === 'create') {
+      await RecordApi.createRecord(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await RecordApi.updateRecord(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    shpName: undefined,
+    id: undefined,
+    status: undefined,
+    code: undefined,
+    remarks: undefined,
+    picture: undefined,
+    name: undefined,
+    username: undefined,
+    sequence: undefined,
+    geom: undefined,
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 238 - 0
src/views/inspection/inspectionrecord/index.vue

@@ -0,0 +1,238 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="queryParams.createTime"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="daterange"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="编号" prop="code">
+        <el-input
+          v-model="queryParams.code"
+          placeholder="请输入编号"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+
+      <el-form-item label="路线名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入巡检路线名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="巡检人" prop="username">
+        <el-input
+          v-model="queryParams.username"
+          placeholder="请输入巡检人"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="备注" prop="remarks">
+        <el-input
+            v-model="queryParams.remarks"
+            placeholder="请输入备注"
+            clearable
+            @keyup.enter="handleQuery"
+            class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          type="primary"
+          plain
+          @click="openForm('create')"
+          v-hasPermi="['inspection:record:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['inspection:record:export']"
+        >
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <el-table-column label="关联图层名" align="center" prop="shpName" />
+      <el-table-column label="用户ID" align="center" prop="id" />
+      <el-table-column label="巡检人" align="center" prop="username" />
+      <el-table-column label="状态" align="center" prop="status" />
+      <el-table-column label="路线记录" align="center" prop="geom" />
+      <el-table-column label="备注" align="center" prop="remarks" />
+      <el-table-column label="图片路径" align="center" prop="picture" />
+      <el-table-column label="操作" align="center">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['inspection:record:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['inspection:record:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <RecordForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { RecordApi, RecordVO } from '@/api/inspection/inspectionrecord'
+import RecordForm from './RecordForm.vue'
+
+/** 巡检记录 列表 */
+defineOptions({ name: 'Record' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<RecordVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  createTime: [],
+  shpName: undefined,
+  status: undefined,
+  code: undefined,
+  remarks: undefined,
+  picture: undefined,
+  name: undefined,
+  username: undefined,
+  sequence: undefined,
+  geom: undefined,
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await RecordApi.getRecordPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await RecordApi.deleteRecord(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await RecordApi.exportRecord(queryParams)
+    download.excel(data, '巡检记录.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 1 - 1
src/views/layer/gisname/index.vue

@@ -204,7 +204,7 @@ const exportLoading = ref(false) // 导出的加载中
 const getList = async () => {
   loading.value = true
   try {
-    const data = await GisNameApi.getGisNamePage(queryParams)
+    const data = await GisNameApi.getShpAllRow(queryParams)
     list.value = data.list
     total.value = data.total
   } finally {