فهرست منبع

ue功能接入;merge

gr 1 ماه پیش
والد
کامیت
14dd853d7e

+ 1 - 0
.husky/.gitignore

@@ -0,0 +1 @@
+_

+ 4 - 0
.husky/pre-commit

@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+npx lint-staged

+ 38 - 0
.prettierrc.yaml

@@ -0,0 +1,38 @@
+# 一行最多多少个字符
+printWidth: 120
+# 指定每个缩进级别的空格数
+tabWidth: 2
+# 使用制表符而不是空格缩进行
+useTabs: true
+# 在语句末尾打印分号
+semi: false
+# 使用单引号而不是双引号
+singleQuote: true
+# 控制对象属性名是否使用引号 可选值<as-needed|consistent|preserve>
+quoteProps: 'as-needed'
+# 在JSX中使用单引号而不是双引号
+jsxSingleQuote: false
+# 多行时是否在末行添加逗号 可选值<none|es5|all>,默认none
+trailingComma: 'es5'
+# 在对象文字中的括号之间打印空格
+bracketSpacing: true
+# jsx 标签的反尖括号需要换行
+jsxBracketSameLine: false
+# HTML 标签的闭合括号是否与标签名在同一行
+bracketSameLine: true
+# 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
+arrowParens: 'always'
+# 仅格式化需要 pragma 的文件 @prettier
+requirePragma: false
+# 在已格式化的文件开头插入 @prettier
+insertPragma: false
+# 使用默认的折行标准 always\never\preserve
+proseWrap: 'preserve'
+# 指定HTML文件的全局空格敏感度 css\strict\ignore
+htmlWhitespaceSensitivity: 'css'
+# Vue文件脚本和样式标签缩进
+vueIndentScriptAndStyle: false
+# 换行符使用 lf 结尾是 可选值<auto|lf|crlf|cr>
+endOfLine: 'lf'
+# 是否将每个属性放在单独一行
+singleAttributePerLine: false

+ 553 - 0
package-lock.json

@@ -20,8 +20,11 @@
       "devDependencies": {
         "@vitejs/plugin-vue": "^5.0.5",
         "autoprefixer": "^10.4.20",
+        "husky": "^9.1.7",
+        "lint-staged": "^15.5.0",
         "postcss": "^8.5.3",
         "postcss-px-to-viewport": "^1.1.1",
+        "prettier": "^3.5.3",
         "sass": "^1.79.3",
         "tailwindcss": "^3.4.17",
         "unplugin-auto-import": "^19.1.0",
@@ -1125,6 +1128,21 @@
         "node": ">=0.4.0"
       }
     },
+    "node_modules/ansi-escapes": {
+      "version": "7.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/ansi-escapes/-/ansi-escapes-7.0.0.tgz",
+      "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==",
+      "dev": true,
+      "dependencies": {
+        "environment": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/ansi-regex": {
       "version": "6.1.0",
       "resolved": "https://mirrors.tencent.com/npm/ansi-regex/-/ansi-regex-6.1.0.tgz",
@@ -1342,6 +1360,18 @@
         }
       ]
     },
+    "node_modules/chalk": {
+      "version": "5.4.1",
+      "resolved": "https://mirrors.tencent.com/npm/chalk/-/chalk-5.4.1.tgz",
+      "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
+      "dev": true,
+      "engines": {
+        "node": "^12.17.0 || ^14.13 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
     "node_modules/chokidar": {
       "version": "4.0.1",
       "resolved": "https://r.cnpmjs.org/chokidar/-/chokidar-4.0.1.tgz",
@@ -1358,6 +1388,60 @@
         "url": "https://paulmillr.com/funding/"
       }
     },
+    "node_modules/cli-cursor": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/cli-cursor/-/cli-cursor-5.0.0.tgz",
+      "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
+      "dev": true,
+      "dependencies": {
+        "restore-cursor": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cli-truncate": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/cli-truncate/-/cli-truncate-4.0.0.tgz",
+      "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==",
+      "dev": true,
+      "dependencies": {
+        "slice-ansi": "^5.0.0",
+        "string-width": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cli-truncate/node_modules/emoji-regex": {
+      "version": "10.4.0",
+      "resolved": "https://mirrors.tencent.com/npm/emoji-regex/-/emoji-regex-10.4.0.tgz",
+      "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+      "dev": true
+    },
+    "node_modules/cli-truncate/node_modules/string-width": {
+      "version": "7.2.0",
+      "resolved": "https://mirrors.tencent.com/npm/string-width/-/string-width-7.2.0.tgz",
+      "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^10.3.0",
+        "get-east-asian-width": "^1.0.0",
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/color-convert": {
       "version": "2.0.1",
       "resolved": "https://mirrors.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz",
@@ -1376,6 +1460,12 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
+    "node_modules/colorette": {
+      "version": "2.0.20",
+      "resolved": "https://mirrors.tencent.com/npm/colorette/-/colorette-2.0.20.tgz",
+      "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+      "dev": true
+    },
     "node_modules/combined-stream": {
       "version": "1.0.8",
       "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -1663,6 +1753,18 @@
         "url": "https://github.com/fb55/entities?sponsor=1"
       }
     },
+    "node_modules/environment": {
+      "version": "1.1.0",
+      "resolved": "https://mirrors.tencent.com/npm/environment/-/environment-1.1.0.tgz",
+      "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/esbuild": {
       "version": "0.21.5",
       "resolved": "https://r.cnpmjs.org/esbuild/-/esbuild-0.21.5.tgz",
@@ -1735,6 +1837,35 @@
       "resolved": "https://mirrors.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz",
       "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
     },
+    "node_modules/eventemitter3": {
+      "version": "5.0.1",
+      "resolved": "https://mirrors.tencent.com/npm/eventemitter3/-/eventemitter3-5.0.1.tgz",
+      "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+      "dev": true
+    },
+    "node_modules/execa": {
+      "version": "8.0.1",
+      "resolved": "https://mirrors.tencent.com/npm/execa/-/execa-8.0.1.tgz",
+      "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
+      "dev": true,
+      "dependencies": {
+        "cross-spawn": "^7.0.3",
+        "get-stream": "^8.0.1",
+        "human-signals": "^5.0.0",
+        "is-stream": "^3.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^5.1.0",
+        "onetime": "^6.0.0",
+        "signal-exit": "^4.1.0",
+        "strip-final-newline": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=16.17"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/execa?sponsor=1"
+      }
+    },
     "node_modules/fast-glob": {
       "version": "3.3.3",
       "resolved": "https://mirrors.tencent.com/npm/fast-glob/-/fast-glob-3.3.3.tgz",
@@ -1871,6 +2002,30 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/get-east-asian-width": {
+      "version": "1.3.0",
+      "resolved": "https://mirrors.tencent.com/npm/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz",
+      "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/get-stream": {
+      "version": "8.0.1",
+      "resolved": "https://mirrors.tencent.com/npm/get-stream/-/get-stream-8.0.1.tgz",
+      "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
+      "dev": true,
+      "engines": {
+        "node": ">=16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/glob": {
       "version": "10.4.5",
       "resolved": "https://mirrors.tencent.com/npm/glob/-/glob-10.4.5.tgz",
@@ -1920,6 +2075,30 @@
       "resolved": "https://mirrors.tencent.com/npm/hookable/-/hookable-5.5.3.tgz",
       "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
     },
+    "node_modules/human-signals": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/human-signals/-/human-signals-5.0.0.tgz",
+      "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=16.17.0"
+      }
+    },
+    "node_modules/husky": {
+      "version": "9.1.7",
+      "resolved": "https://mirrors.tencent.com/npm/husky/-/husky-9.1.7.tgz",
+      "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
+      "dev": true,
+      "bin": {
+        "husky": "bin.js"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/typicode"
+      }
+    },
     "node_modules/immutable": {
       "version": "4.3.7",
       "resolved": "https://r.cnpmjs.org/immutable/-/immutable-4.3.7.tgz",
@@ -1993,6 +2172,18 @@
         "node": ">=0.12.0"
       }
     },
+    "node_modules/is-stream": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/is-stream/-/is-stream-3.0.0.tgz",
+      "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+      "dev": true,
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/is-what": {
       "version": "4.1.16",
       "resolved": "https://mirrors.tencent.com/npm/is-what/-/is-what-4.1.16.tgz",
@@ -2059,6 +2250,99 @@
       "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
       "dev": true
     },
+    "node_modules/lint-staged": {
+      "version": "15.5.0",
+      "resolved": "https://mirrors.tencent.com/npm/lint-staged/-/lint-staged-15.5.0.tgz",
+      "integrity": "sha512-WyCzSbfYGhK7cU+UuDDkzUiytbfbi0ZdPy2orwtM75P3WTtQBzmG40cCxIa8Ii2+XjfxzLH6Be46tUfWS85Xfg==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^5.4.1",
+        "commander": "^13.1.0",
+        "debug": "^4.4.0",
+        "execa": "^8.0.1",
+        "lilconfig": "^3.1.3",
+        "listr2": "^8.2.5",
+        "micromatch": "^4.0.8",
+        "pidtree": "^0.6.0",
+        "string-argv": "^0.3.2",
+        "yaml": "^2.7.0"
+      },
+      "bin": {
+        "lint-staged": "bin/lint-staged.js"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/lint-staged"
+      }
+    },
+    "node_modules/lint-staged/node_modules/commander": {
+      "version": "13.1.0",
+      "resolved": "https://mirrors.tencent.com/npm/commander/-/commander-13.1.0.tgz",
+      "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/listr2": {
+      "version": "8.2.5",
+      "resolved": "https://mirrors.tencent.com/npm/listr2/-/listr2-8.2.5.tgz",
+      "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==",
+      "dev": true,
+      "dependencies": {
+        "cli-truncate": "^4.0.0",
+        "colorette": "^2.0.20",
+        "eventemitter3": "^5.0.1",
+        "log-update": "^6.1.0",
+        "rfdc": "^1.4.1",
+        "wrap-ansi": "^9.0.0"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/listr2/node_modules/emoji-regex": {
+      "version": "10.4.0",
+      "resolved": "https://mirrors.tencent.com/npm/emoji-regex/-/emoji-regex-10.4.0.tgz",
+      "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+      "dev": true
+    },
+    "node_modules/listr2/node_modules/string-width": {
+      "version": "7.2.0",
+      "resolved": "https://mirrors.tencent.com/npm/string-width/-/string-width-7.2.0.tgz",
+      "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^10.3.0",
+        "get-east-asian-width": "^1.0.0",
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/listr2/node_modules/wrap-ansi": {
+      "version": "9.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+      "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^6.2.1",
+        "string-width": "^7.0.0",
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
     "node_modules/local-pkg": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-1.0.0.tgz",
@@ -2099,6 +2383,96 @@
         "lodash-es": "*"
       }
     },
+    "node_modules/log-update": {
+      "version": "6.1.0",
+      "resolved": "https://mirrors.tencent.com/npm/log-update/-/log-update-6.1.0.tgz",
+      "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==",
+      "dev": true,
+      "dependencies": {
+        "ansi-escapes": "^7.0.0",
+        "cli-cursor": "^5.0.0",
+        "slice-ansi": "^7.1.0",
+        "strip-ansi": "^7.1.0",
+        "wrap-ansi": "^9.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/log-update/node_modules/emoji-regex": {
+      "version": "10.4.0",
+      "resolved": "https://mirrors.tencent.com/npm/emoji-regex/-/emoji-regex-10.4.0.tgz",
+      "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+      "dev": true
+    },
+    "node_modules/log-update/node_modules/is-fullwidth-code-point": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz",
+      "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==",
+      "dev": true,
+      "dependencies": {
+        "get-east-asian-width": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/log-update/node_modules/slice-ansi": {
+      "version": "7.1.0",
+      "resolved": "https://mirrors.tencent.com/npm/slice-ansi/-/slice-ansi-7.1.0.tgz",
+      "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^6.2.1",
+        "is-fullwidth-code-point": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+      }
+    },
+    "node_modules/log-update/node_modules/string-width": {
+      "version": "7.2.0",
+      "resolved": "https://mirrors.tencent.com/npm/string-width/-/string-width-7.2.0.tgz",
+      "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^10.3.0",
+        "get-east-asian-width": "^1.0.0",
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/log-update/node_modules/wrap-ansi": {
+      "version": "9.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+      "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^6.2.1",
+        "string-width": "^7.0.0",
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
     "node_modules/lru-cache": {
       "version": "10.4.3",
       "resolved": "https://mirrors.tencent.com/npm/lru-cache/-/lru-cache-10.4.3.tgz",
@@ -2119,6 +2493,12 @@
       "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
       "license": "MIT"
     },
+    "node_modules/merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "dev": true
+    },
     "node_modules/merge2": {
       "version": "1.4.1",
       "resolved": "https://mirrors.tencent.com/npm/merge2/-/merge2-1.4.1.tgz",
@@ -2162,6 +2542,30 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/mimic-fn": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/mimic-fn/-/mimic-fn-4.0.0.tgz",
+      "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/mimic-function": {
+      "version": "5.0.1",
+      "resolved": "https://mirrors.tencent.com/npm/mimic-function/-/mimic-function-5.0.1.tgz",
+      "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/minimatch": {
       "version": "9.0.5",
       "resolved": "https://mirrors.tencent.com/npm/minimatch/-/minimatch-9.0.5.tgz",
@@ -2270,6 +2674,33 @@
       "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
       "license": "BSD-3-Clause"
     },
+    "node_modules/npm-run-path": {
+      "version": "5.3.0",
+      "resolved": "https://mirrors.tencent.com/npm/npm-run-path/-/npm-run-path-5.3.0.tgz",
+      "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^4.0.0"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/npm-run-path/node_modules/path-key": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/path-key/-/path-key-4.0.0.tgz",
+      "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/object-assign": {
       "version": "4.1.1",
       "resolved": "https://r2.cnpmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -2289,6 +2720,21 @@
         "node": ">= 6"
       }
     },
+    "node_modules/onetime": {
+      "version": "6.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/onetime/-/onetime-6.0.0.tgz",
+      "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+      "dev": true,
+      "dependencies": {
+        "mimic-fn": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/package-json-from-dist": {
       "version": "1.0.1",
       "resolved": "https://mirrors.tencent.com/npm/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
@@ -2355,6 +2801,18 @@
         "url": "https://github.com/sponsors/jonschlinkert"
       }
     },
+    "node_modules/pidtree": {
+      "version": "0.6.0",
+      "resolved": "https://mirrors.tencent.com/npm/pidtree/-/pidtree-0.6.0.tgz",
+      "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+      "dev": true,
+      "bin": {
+        "pidtree": "bin/pidtree.js"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
     "node_modules/pify": {
       "version": "2.3.0",
       "resolved": "https://mirrors.tencent.com/npm/pify/-/pify-2.3.0.tgz",
@@ -2558,6 +3016,21 @@
       "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
       "dev": true
     },
+    "node_modules/prettier": {
+      "version": "3.5.3",
+      "resolved": "https://mirrors.tencent.com/npm/prettier/-/prettier-3.5.3.tgz",
+      "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
+      "dev": true,
+      "bin": {
+        "prettier": "bin/prettier.cjs"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/prettier/prettier?sponsor=1"
+      }
+    },
     "node_modules/proxy-from-env": {
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -2627,6 +3100,37 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/restore-cursor": {
+      "version": "5.1.0",
+      "resolved": "https://mirrors.tencent.com/npm/restore-cursor/-/restore-cursor-5.1.0.tgz",
+      "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
+      "dev": true,
+      "dependencies": {
+        "onetime": "^7.0.0",
+        "signal-exit": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/restore-cursor/node_modules/onetime": {
+      "version": "7.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/onetime/-/onetime-7.0.0.tgz",
+      "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
+      "dev": true,
+      "dependencies": {
+        "mimic-function": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/reusify": {
       "version": "1.0.4",
       "resolved": "https://mirrors.tencent.com/npm/reusify/-/reusify-1.0.4.tgz",
@@ -2759,6 +3263,34 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/slice-ansi": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/slice-ansi/-/slice-ansi-5.0.0.tgz",
+      "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^6.0.0",
+        "is-fullwidth-code-point": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+      }
+    },
+    "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
+      "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/source-map-js": {
       "version": "1.2.1",
       "resolved": "https://r.cnpmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -2776,6 +3308,15 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/string-argv": {
+      "version": "0.3.2",
+      "resolved": "https://mirrors.tencent.com/npm/string-argv/-/string-argv-0.3.2.tgz",
+      "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.6.19"
+      }
+    },
     "node_modules/string-width": {
       "version": "5.1.2",
       "resolved": "https://mirrors.tencent.com/npm/string-width/-/string-width-5.1.2.tgz",
@@ -2872,6 +3413,18 @@
         "node": ">=8"
       }
     },
+    "node_modules/strip-final-newline": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.tencent.com/npm/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+      "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/strip-literal": {
       "version": "3.0.0",
       "resolved": "https://registry.npmmirror.com/strip-literal/-/strip-literal-3.0.0.tgz",

+ 8 - 1
package.json

@@ -6,7 +6,8 @@
   "scripts": {
     "dev": "vite --host",
     "build": "vite build",
-    "preview": "vite preview"
+    "preview": "vite preview",
+    "prepare": "husky install"
   },
   "dependencies": {
     "@vueuse/core": "^11.1.0",
@@ -21,12 +22,18 @@
   "devDependencies": {
     "@vitejs/plugin-vue": "^5.0.5",
     "autoprefixer": "^10.4.20",
+    "husky": "^9.1.7",
+    "lint-staged": "^15.5.0",
     "postcss": "^8.5.3",
     "postcss-px-to-viewport": "^1.1.1",
+    "prettier": "^3.5.3",
     "sass": "^1.79.3",
     "tailwindcss": "^3.4.17",
     "unplugin-auto-import": "^19.1.0",
     "unplugin-vue-components": "^28.4.0",
     "vite": "^5.3.1"
+  },
+  "lint-staged": {
+    "*.{vue,js,css,md}": "prettier --write"
   }
 }

+ 16 - 13
src/components/NumberScroll.vue

@@ -1,26 +1,29 @@
 <template>
-  <CountTo v-bind="$attrs" :start-val="start" :end-val="end" />
+	<CountTo v-bind="$attrs" :start-val="start" :end-val="end" />
 </template>
 
 <script setup>
-import { CountTo } from 'vue3-count-to';
-import { ref, defineProps, watch } from 'vue';
+import { CountTo } from 'vue3-count-to'
+import { ref, watch } from 'vue'
 
 const props = defineProps({
-  value: {
-    type: Number,
-    required: true
-  },
+	value: {
+		type: Number,
+		required: true,
+	},
 })
 
 const start = ref(0)
 const end = ref(0)
 
-watch(() => props.value, (newVal, oldVal=0) => {
-  start.value = oldVal
-  end.value = newVal
-}, { immediate: true })
-
+watch(
+	() => props.value,
+	(newVal, oldVal = 0) => {
+		start.value = oldVal
+		end.value = newVal
+	},
+	{ immediate: true }
+)
 </script>
 
-<style lang="scss"></style>
+<style lang="scss"></style>

+ 126 - 164
src/components/UeVideo.vue

@@ -1,199 +1,161 @@
 <template>
-  <div class="ue-wrapper">
-    <div class="connect-status" v-show="connectStatus !== '连接成功'">连接状态:{{ connectStatus }}</div>
-    <div ref="videoContainerRef" class="video-container"></div>
-    <!-- <dialog id="login-dialog" data-bs-theme="dark">
-      <h2 class="mb-3 fs-6">登录以获取场景资源</h2>
-      <form :model="form" v-on:submit="handleLogin">
-        <div class="mb-3">
-          <label htmlFor="userName" class="form-label">用户名</label>
-          <input v-model="form.userName" id="userName" type="text" class="form-control" />
-        </div>
-        <div class="mb-3">
-          <label htmlFor="password" class="form-label">密码</label>
-          <input v-model="form.password" id="password" type="password" class="form-control" />
-        </div>
-        <div class="text-center">
-          <button type="submit" class="btn btn-primary">登录</button>
-        </div>
-      </form>
-      <div v-if="loginMsg" class="mt-3 text-danger">{{ loginMsg }}</div>
-    </dialog> -->
-  </div>
+	<div class="ue-wrapper">
+		<div class="connect-status" v-show="connectStatus !== '连接成功'">连接状态:{{ connectStatus }}</div>
+		<div ref="videoContainerRef" class="video-container"></div>
+	</div>
 </template>
 
 <script setup>
 import { onMounted, ref, getCurrentInstance, onBeforeUnmount } from 'vue'
-import axios from 'axios';
+import axios from 'axios'
 import baseUrl from '@/utils/peer-stream'
+import useLayoutStore from '@/store/layout'
+
+const layoutStore = useLayoutStore()
 
 const { proxy } = getCurrentInstance()
 
-const connectStatus = ref("未连接"); // State to store the input content
+const connectStatus = ref('未连接') // State to store the input content
 
 const peerStreamRef = ref(null)
 // 用来存储视频容器的引用
-const videoContainerRef = ref(null);
+const videoContainerRef = ref(null)
 
 // 关闭场景的函数
 const closeScene = () => {
-  if (videoContainerRef.value) {
-    videoContainerRef.value.removeChild(peerStreamRef.value);
-    console.log("Scene closed");
-  }
-};
+	if (videoContainerRef.value) {
+		videoContainerRef.value.removeChild(peerStreamRef.value)
+		console.log('Scene closed')
+	}
+}
 
 // 连接场景
 const wsConnect = (sceneId, view_mode, token) => {
-  // 确保 videoContainerRef 指向一个有效的容器
-  if (videoContainerRef.value) {
-    // 清空容器
-    videoContainerRef.value.innerHTML = '';
-    // 创建 PeerStream 元素
-    peerStreamRef.value = document.createElement('video', { is: 'peer-stream' });
-    peerStreamRef.value.dataset.sceneId = sceneId;
-    peerStreamRef.value.dataset.viewMode = view_mode;
-    peerStreamRef.value.dataset.token = token;
-    peerStreamRef.value.style.width = '100%';
-    videoContainerRef.value.appendChild(peerStreamRef.value);
-
-    //场景事件
-    peerStreamRef.value.addEventListener("playing", () => {
-      connectStatus.value = ("连接成功");
-      proxy.$bus.emit('ueConnected')
-    });
-    peerStreamRef.value.addEventListener("disConnected", () => connectStatus.value = ("连接断开"));
-    peerStreamRef.value.addEventListener("message", (e) => {
-      const message = JSON.parse(e.detail);
-      console.log("收到消息:", message)
-      proxy.$bus.emit('ueMsgReceived', message)
-      // connectStatus.value = ("收到消息:" + message);
-    });
-  }
+	// 确保 videoContainerRef 指向一个有效的容器
+	if (videoContainerRef.value) {
+		// 清空容器
+		videoContainerRef.value.innerHTML = ''
+		// 创建 PeerStream 元素
+		peerStreamRef.value = document.createElement('video', { is: 'peer-stream' })
+		peerStreamRef.value.dataset.sceneId = sceneId
+		peerStreamRef.value.dataset.viewMode = view_mode
+		peerStreamRef.value.dataset.token = token
+		peerStreamRef.value.style.width = '100%'
+		videoContainerRef.value.appendChild(peerStreamRef.value)
+		//场景事件
+		peerStreamRef.value.addEventListener('playing', () => {
+			layoutStore.toggleGlobalLoading(false)
+			connectStatus.value = '连接成功'
+			proxy.$bus.emit('ueConnected')
+		})
+		peerStreamRef.value.addEventListener('disConnected', () => (connectStatus.value = '连接断开'))
+		peerStreamRef.value.addEventListener('message', (e) => {
+			const message = JSON.parse(e.detail)
+			console.log('收到消息:', message)
+			proxy.$bus.emit('ueMsgReceived', message)
+			// connectStatus.value = ("收到消息:" + message);
+		})
+	}
 }
 
 const sendDataChannelCommand = (command) => {
-  if (peerStreamRef.value) {
-    // console.error((peerStreamRef.value), (peerStreamRef.value).dc);
-    // Call the send method on the custom peer-stream element
-    (peerStreamRef.value).emitMessage((JSON.parse(command)));
-    console.log('Sending command:', command);
-  } else {
-    console.warn('Send failed, stream is not connected:', command);
-  }
+	if (peerStreamRef.value) {
+		// console.error((peerStreamRef.value), (peerStreamRef.value).dc);
+		// Call the send method on the custom peer-stream element
+		peerStreamRef.value.emitMessage(command)
+		console.log('Sending command:', command)
+	} else {
+		console.warn('Send failed, stream is not connected:', command)
+	}
 }
 
-const form = ref({
-  userName: '',
-  password: ''
-})
-
-const loginMsg = ref('')
-
-function handleLogin(e) {
-  e.preventDefault();
-  console.log(form.value)
-  axios.post(`http://${baseUrl}/auth/login`, form.value)
-    .then(response => {
-      if (response.status === 201) {
-        localStorage.setItem('token', response.data.access_token);
-        // 获取场景列表
-        axios({
-          method: 'get',
-          url: `http://${baseUrl}/scenePermission`,
-          headers: {
-            'Authorization': `Bearer ${localStorage.getItem('token')}`
-          }
-        }).then(res => {
-          if (res.data) {
-            const targetScene = res.data.find(row => row.name === "低空经济")
-            if (!targetScene) {
-              loginMsg.value = '未发现场景资源'
-              return
-            }
-            wsConnect(targetScene.scene_id, targetScene.permission, localStorage.getItem('token'));
-            // 关闭弹窗和页面loading
-            const dialog = document.getElementById('login-dialog')
-            dialog.close()
-            proxy.$bus.emit('toggleLoading', false)
-          }
-        })
-      } else {
-        loginMsg.value = '登录失败'
-      }
-    })
-    .catch((e) => {
-      console.log(e)
-      loginMsg.value = '登录失败'
-    })
+function handleConnect() {
+	axios
+		.post(`http://${baseUrl}/auth/login`, {
+			userName: '',
+			password: '',
+		})
+		.then((response) => {
+			const token = response.data.access_token
+			if (response.status === 201) {
+				// 获取场景列表
+				axios({
+					method: 'get',
+					url: `http://${baseUrl}/scenePermission`,
+					headers: {
+						Authorization: `Bearer ${token}`,
+					},
+				}).then((res) => {
+					if (res.data) {
+						const targetScene = res.data.find((row) => row.name === '低空经济')
+						if (!targetScene) {
+							connectStatus.value = '未发现场景资源'
+							return
+						}
+						wsConnect(targetScene.scene_id, targetScene.permission, token)
+					}
+				})
+			} else {
+				connectStatus.value = '登录失败'
+			}
+		})
+		.catch((e) => {
+			console.log(e)
+			connectStatus.value = '登录失败'
+		})
 }
 
 onMounted(() => {
-  const script = document.createElement('script');
-  script.type = "module";
-  script.src = new URL(`/src/utils/peer-stream.js`, import.meta.url).href // 自定义元素文件的路径
-  script.async = true;
-  script.onload = () => {
-    console.log('PeerStream custom element script loaded');
-  };
-  document.body.appendChild(script);
-  const dialog = document.getElementById('login-dialog')
-  dialog?.showModal()
-
-  // setTimeout(() => {
-  //   proxy.$bus.emit('toggleLoading', false)
-  // }, 1000);
-
-  // 添加全局调用监听
-  proxy.$bus.on('callUE', (command) => {
-    sendDataChannelCommand(command)
-  })
+	// layoutStore.toggleGlobalLoading(true)
+	const script = document.createElement('script')
+	script.type = 'module'
+	script.src = new URL(`/src/utils/peer-stream.js`, import.meta.url).href // 自定义元素文件的路径
+	script.async = true
+	script.onload = () => {
+		console.log('PeerStream custom element script loaded')
+	}
+	document.body.appendChild(script)
+
+	handleConnect()
+
+	// 添加全局调用监听
+	proxy.$bus.on('callUE', (command) => {
+		sendDataChannelCommand(command)
+	})
 })
 
 onBeforeUnmount(() => {
-  proxy.$bus.off('callUE')
+	proxy.$bus.off('callUE')
 })
-
 </script>
 
 <style lang="scss" scoped>
 .ue-wrapper {
-  box-sizing: border-box;
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-
-  .connect-status {
-    position: absolute;
-    top: 50%;
-    width: 100%;
-    text-align: center;
-    z-index: 200
-  }
-
-  .video-container {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-  }
-
-  #login-dialog {
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    transform: translateX(-50%) translateY(-50%);
-    padding: 30px 40px;
-    border: 2px solid #003e58;
-    border-radius: 15px;
-    color: #888;
-  }
+	box-sizing: border-box;
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	overflow: hidden;
+
+	.connect-status {
+		position: absolute;
+		top: 50%;
+		width: 100%;
+		text-align: center;
+		z-index: 200;
+	}
+
+	.video-container {
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
 }
-</style>
+</style>

+ 4 - 4
src/main.js

@@ -1,16 +1,16 @@
 import { createApp } from 'vue'
 import App from './App.vue'
-import mitt from "mitt";
+import bus from './utils/bus'
 import './assets/styles/index.scss'
 import { createPinia } from 'pinia'
 
-const app = createApp(App);
+const app = createApp(App)
 
 const store = createPinia()
 
 app.use(store)
 
 // 全局方法挂载
-app.config.globalProperties.$bus = new mitt();
+app.config.globalProperties.$bus = bus
 
-app.mount('#app')
+app.mount('#app')

+ 0 - 963
src/utils/UIInteractions.js

@@ -1,963 +0,0 @@
-/**
- * 获取操作
- * @param {string} cName 操作对应的自定义名称
- * @param {object} Params 自定义参数,覆盖 Params 中对应的部分
- * @returns JSON String
- */
-function getFn(cName, cParams = {}) {
-  const target = fnList.find(i => i.cName === cName)
-  if (!target) return ''
-  const targetDup = JSON.parse(JSON.stringify(target))
-  const paramKeys = Object.keys(cParams)
-  if (paramKeys.length !== 0) {
-    paramKeys.forEach(key => {
-      targetDup.content.Params[key] = cParams[key]
-    })
-  }
-  return JSON.stringify(targetDup.content)
-}
-
-const fnList = [
-  {
-    cName: "toggleGrid",
-    remark: '网格显示/隐藏',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "AirGrid",
-        "ActionName": "ShowHidden",
-        "Id": "Green",  // 'Green' | 'Red'
-        "Visible": true
-      }
-    }
-
-  },
-  {
-    cName: 'toggleRoute',
-    remark: '航路显示/隐藏',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "AirRoute",
-        "ActionName": "ShowHidden",
-        "Id": "1",
-        "Visible": true
-      }
-    }
-
-  },
-  {
-    cName: 'toggleLine',
-    remark: '航线显示/隐藏(Block--碰撞,Normal--无碰撞,Back--返回)',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "AirLine",
-        "ActionName": "ShowHidden",
-        "Id": "Block",   // 'Normal' | 'Block' | 'Back'
-        "Visible": true
-      }
-    }
-  },
-  {
-    cName: 'initUavNormal',
-    remark: '初始化无人机飞行路线--无碰撞路线',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "InitUav",
-        "Id": "UavId",
-        "Speed": 2000.0,
-        "SplinePoints": [
-          {
-            "Location": "X=443230,Y=-736980,Z=5250",
-            "Rotation": "Pitch=89,Yaw=71,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=443240,Y=-736952,Z=6610",
-            "Rotation": "Pitch=26,Yaw=101,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=442020,Y=-730610,Z=9720",
-            "Rotation": "Pitch=-3,Yaw=68,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=449660,Y=-711980,Z=8820",
-            "Rotation": "Pitch=-1,Yaw=73,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=454810,Y=-695130,Z=8650",
-            "Rotation": "Pitch=0,Yaw=70,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=466190,Y=-664600,Z=8830",
-            "Rotation": "Pitch=-1,Yaw=49,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=471450,Y=-658450,Z=8710",
-            "Rotation": "Pitch=1,Yaw=33,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=474820,Y=-656240,Z=8780",
-            "Rotation": "Pitch=3,Yaw=-14,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=480660,Y=-657700,Z=9130",
-            "Rotation": "Pitch=0,Yaw=-21,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=489870,Y=-661280,Z=9200",
-            "Rotation": "Pitch=-2,Yaw=-22,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=502730,Y=-666350,Z=8830",
-            "Rotation": "Pitch=0,Yaw=-17,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=517900,Y=-671020,Z=8910",
-            "Rotation": "Pitch=0,Yaw=-34,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=520366,Y=-672669,Z=8910",
-            "Rotation": "Pitch=1,Yaw=-36,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=528910,Y=-678970,Z=9070",
-            "Rotation": "Pitch=1,Yaw=-37,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=536911,Y=-685079,Z=9162",
-            "Rotation": "Pitch=-1,Yaw=1,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=538750,Y=-685060,Z=9130",
-            "Rotation": "Pitch=-10,Yaw=56,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=544910,Y=-675790,Z=7150",
-            "Rotation": "Pitch=0,Yaw=52,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=547850,Y=-672060,Z=7150",
-            "Rotation": "Pitch=0,Yaw=65,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=550480,Y=-666430,Z=7150",
-            "Rotation": "Pitch=-34,Yaw=28,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=554110,Y=-664540,Z=4370",
-            "Rotation": "Pitch=-90,Yaw=0,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=554110,Y=-664540,Z=2040",
-            "Rotation": "Pitch=0,Yaw=0,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          }
-        ]
-      }
-    }
-  },
-  {
-    cName: 'initUavBlock',
-    remark: '初始化无人机飞行路线--有碰撞路线',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "InitUav",
-        "Id": "UavId",
-        "Speed": 2000.0,
-        "SplinePoints": [
-          {
-            "Location": "X=443230,Y=-736980,Z=5250",
-            "Rotation": "Pitch=89,Yaw=71,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=443240,Y=-736952,Z=6610",
-            "Rotation": "Pitch=26,Yaw=84,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=443890,Y=-730610,Z=9720",
-            "Rotation": "Pitch=-3,Yaw=68,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=451260,Y=-711980,Z=8820",
-            "Rotation": "Pitch=-1,Yaw=70,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=457420,Y=-695130,Z=8650",
-            "Rotation": "Pitch=0,Yaw=69,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=469110,Y=-664600,Z=8830",
-            "Rotation": "Pitch=-1,Yaw=69,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=471450,Y=-658450,Z=8710",
-            "Rotation": "Pitch=1,Yaw=33,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=474820,Y=-656240,Z=8780",
-            "Rotation": "Pitch=3,Yaw=-14,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=480660,Y=-657700,Z=9130",
-            "Rotation": "Pitch=0,Yaw=-21,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=489870,Y=-661280,Z=9200",
-            "Rotation": "Pitch=-2,Yaw=-22,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=502730,Y=-666350,Z=8830",
-            "Rotation": "Pitch=0,Yaw=-17,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=517900,Y=-671020,Z=8910",
-            "Rotation": "Pitch=0,Yaw=-34,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=520366,Y=-672669,Z=8910",
-            "Rotation": "Pitch=1,Yaw=-36,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=528910,Y=-678970,Z=9070",
-            "Rotation": "Pitch=1,Yaw=-37,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=536911,Y=-685079,Z=9162",
-            "Rotation": "Pitch=-1,Yaw=1,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=538750,Y=-685060,Z=9130",
-            "Rotation": "Pitch=-10,Yaw=56,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=544910,Y=-675790,Z=7150",
-            "Rotation": "Pitch=0,Yaw=52,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=547850,Y=-672060,Z=7150",
-            "Rotation": "Pitch=0,Yaw=65,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=550480,Y=-666430,Z=7150",
-            "Rotation": "Pitch=-34,Yaw=28,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=554110,Y=-664540,Z=4370",
-            "Rotation": "Pitch=-90,Yaw=0,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=554110,Y=-664540,Z=2040",
-            "Rotation": "Pitch=0,Yaw=0,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          }
-        ]
-      }
-    }
-  },
-  {
-    cName: 'initUavBack',
-    remark: '初始化无人机飞行路线--返航路线',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "InitUav",
-        "Id": "UavId",
-        "Speed": 2000.0,
-        "SplinePoints": [
-          {
-            "Location": "X=554110,Y=-664540,Z=2040",
-            "Rotation": "Pitch=0,Yaw=0,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=554110,Y=-664540,Z=4370",
-            "Rotation": "Pitch=-90,Yaw=0,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=550480,Y=-666430,Z=7150",
-            "Rotation": "Pitch=-34,Yaw=28,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=547850,Y=-672060,Z=9640",
-            "Rotation": "Pitch=-22,Yaw=65,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=544910,Y=-675790,Z=9890",
-            "Rotation": "Pitch=-3,Yaw=52,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=538750,Y=-685060,Z=10990",
-            "Rotation": "Pitch=-6,Yaw=56,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=536911,Y=-685079,Z=10982",
-            "Rotation": "Pitch=0,Yaw=1,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=528910,Y=-678970,Z=11490",
-            "Rotation": "Pitch=-3,Yaw=-37,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=520366,Y=-672669,Z=11310",
-            "Rotation": "Pitch=1,Yaw=-36,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=517900,Y=-671020,Z=11180",
-            "Rotation": "Pitch=3,Yaw=-34,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=502730,Y=-666350,Z=10840",
-            "Rotation": "Pitch=1,Yaw=-17,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=489870,Y=-661280,Z=10980",
-            "Rotation": "Pitch=-1,Yaw=-22,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=480660,Y=-657700,Z=11030",
-            "Rotation": "Pitch=0,Yaw=-21,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=474820,Y=-656240,Z=11090",
-            "Rotation": "Pitch=-1,Yaw=-14,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=471450,Y=-658450,Z=10900",
-            "Rotation": "Pitch=3,Yaw=33,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=467700,Y=-664600,Z=10880",
-            "Rotation": "Pitch=0,Yaw=59,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=456270,Y=-695130,Z=11360",
-            "Rotation": "Pitch=-1,Yaw=69,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=449660,Y=-711980,Z=11570",
-            "Rotation": "Pitch=-1,Yaw=69,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=442020,Y=-730610,Z=11930",
-            "Rotation": "Pitch=-1,Yaw=68,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=443240,Y=-736952,Z=6610",
-            "Rotation": "Pitch=39,Yaw=101,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=443230,Y=-736980,Z=5250",
-            "Rotation": "Pitch=89,Yaw=71,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          }
-        ]
-      }
-    }
-  },
-  {
-    cName: 'initUavFall',
-    remark: '初始化无人机飞行路线--坠落路线',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "InitUav",
-        "Id": "UavId",
-        "Speed": 2000.0,
-        "SplinePoints": [
-          {
-            "Location": "X=443230,Y=-736980,Z=5250",
-            "Rotation": "Pitch=89,Yaw=71,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=443240,Y=-736952,Z=6610",
-            "Rotation": "Pitch=39,Yaw=101,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=442020,Y=-730610,Z=11930",
-            "Rotation": "Pitch=-1,Yaw=68,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=449660,Y=-711980,Z=11570",
-            "Rotation": "Pitch=-1,Yaw=69,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=456270,Y=-695130,Z=11360",
-            "Rotation": "Pitch=-86,Yaw=90,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=456270,Y=-694860,Z=7390",
-            "Rotation": "Pitch=-83,Yaw=90,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          },
-          {
-            "Location": "X=456270,Y=-694270,Z=2290",
-            "Rotation": "Pitch=0,Yaw=0,Roll=0",
-            "Scale": "X=1,Y=1,Z=1"
-          }
-        ]
-      }
-    }
-  },
-  {
-    cName: 'startUav',
-    remark: '无人机开始飞行',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "StartUav",
-        "Id": "UavId"
-      }
-    }
-  },
-  {
-    cName: 'pauseUav',
-    remark: '无人机暂停飞行',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "PauseUav",
-        "Id": "UavId"
-      }
-    }
-  },
-  {
-    cName: 'stopUav',
-    remark: '无人机停止飞行',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "StopUav",
-        "Id": "UavId"
-      }
-    }
-  },
-  {
-    cName: 'startFollowUav',
-    remark: '无人机视角跟随-开始',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "StartPawnFollowUav",
-        "Id": "UavId"
-      }
-    }
-  },
-  {
-    cName: 'endFollowUav',
-    remark: '无人机视角跟随-结束',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "EndPawnFollowUav"
-      }
-    }
-  },
-  {
-    cName: 'setGoodsVisible',
-    remark: '无人机设置货物显隐',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "SetGoodsBox",
-        "Id": "UavId",
-        "Visible": false
-      }
-    }
-  },
-  {
-    cName: 'destroyUav',
-    remark: '无人机销毁',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "Uav",
-        "ActionName": "DestroyUav",
-        "Id": "UavId"
-      }
-    }
-  },
-  {
-    cName: 'toggleSignalTower',
-    remark: '信号塔显示/隐藏',
-    content: {
-      "ModuleName": "BluePrint",
-      "ActionName": "",
-      "Params": {
-        "ModuleName": "SignalTower",
-        "ActionName": "PoiShowHidden",
-        "Visible": true
-      }
-    }
-  },
-  {
-    cName: 'locateTakeoff',
-    remark: '起飞点定位',
-    content: {
-      "ModuleName": "Roam",
-      "ActionName": "Goto",
-      "Params": {
-        "X": 441357.803266,
-        "Y": -738441.043188,
-        "Z": 6880.074496,
-        "Pitch": -37.385139,
-        "Yaw": 36.402233,
-        "Roll": -0.000219,
-        "Duration": 0.1
-      }
-    }
-  },
-  {
-    cName: 'locateLandfall',
-    remark: '降落点定位',
-    content: {
-      "ModuleName": "Roam",
-      "ActionName": "Goto",
-      "Params": {
-        "X": 552993.01402,
-        "Y": -663972.824815,
-        "Z": 2846.776697,
-        "Pitch": -32.906322,
-        "Yaw": -30.157532,
-        "Roll": -1.833872,
-        "Duration": 0.1
-      }
-    }
-  },
-  {
-    cName: 'resetCamera',
-    remark: '回到初始视角',
-    content: {
-      "ModuleName": "Roam",
-      "ActionName": "Goto",
-      "Params": {
-        "X": 424678.164214,
-        "Y": -750393.023912,
-        "Z": 26005.213753,
-        "Pitch": -21.6,
-        "Yaw": 42.600002,
-        "Roll": 0.0,
-        "Duration": 0.1
-      }
-    }
-  },
-  {
-    cName: 'setRotateSpeed',
-    remark: '调整操控灵敏度',
-    content: {
-      "ModuleName": "Roam",
-      "ActionName": "Update",
-      "Params": {
-        "MovementSpeedMultiplier": 0.03,
-        "RotationSpeedMultiplier": 0.5,
-        "ScaleSpeedMultiplier": 0.1,
-        "MinMovementLimit": {
-          "X": 0,
-          "Y": 0,
-          "Z": 0
-        },
-        "MaxMovementLimit": {
-          "X": 0,
-          "Y": 0,
-          "Z": 0
-        }
-      }
-    }
-  },
-  {
-    cName: 'createLineGo',
-    remark: '创建飞行路线--去程',
-    content: {
-      "ModuleName": "Line",
-      "ActionName": "Create",
-      "Params": {
-        "pointArray": [
-          {
-            "x": 443230,
-            "y": -736980,
-            "z": 5250
-          },
-          {
-            "x": 443239.53170699999,
-            "y": -736951.55571900005,
-            "z": 6609.7363160000004
-          },
-          {
-            "x": 442020,
-            "y": -730610,
-            "z": 9720
-          },
-          {
-            "x": 449660,
-            "y": -711980,
-            "z": 8820
-          },
-          {
-            "x": 454810,
-            "y": -695130,
-            "z": 8650
-          },
-          {
-            "x": 466190,
-            "y": -664600,
-            "z": 8830
-          },
-          {
-            "x": 471450,
-            "y": -658450,
-            "z": 8710
-          },
-          {
-            "x": 474820,
-            "y": -656240,
-            "z": 8780
-          },
-          {
-            "x": 480660,
-            "y": -657700,
-            "z": 9130
-          },
-          {
-            "x": 489870,
-            "y": -661280,
-            "z": 9200
-          },
-          {
-            "x": 502730,
-            "y": -666350,
-            "z": 8830
-          },
-          {
-            "x": 517900,
-            "y": -671020,
-            "z": 8910
-          },
-          {
-            "x": 520366.22116099996,
-            "y": -672668.99856600002,
-            "z": 8910.4187010000005
-          },
-          {
-            "x": 528910,
-            "y": -678970,
-            "z": 9070
-          },
-          {
-            "x": 536911.35989199998,
-            "y": -685078.85117499996,
-            "z": 9161.9883630000004
-          },
-          {
-            "x": 538750,
-            "y": -685060,
-            "z": 9130
-          },
-          {
-            "x": 544910,
-            "y": -675790,
-            "z": 7150
-          },
-          {
-            "x": 547850,
-            "y": -672060,
-            "z": 7150
-          },
-          {
-            "x": 550480,
-            "y": -666430,
-            "z": 7150
-          },
-          {
-            "x": 554110,
-            "y": -664540,
-            "z": 4370
-          },
-          {
-            "x": 554110,
-            "y": -664540,
-            "z": 2040
-          }
-        ],
-        "lineStyle": "Style3",
-        "Tag": "GoPolyline",
-        "Color": { "R": 1, "G": 0, "B": 0, "A": 0.5 },
-        "Width": 20.0,
-        "Tilling": 5000.0,
-        "Speed": 1.0,
-        "SplinePointType": "Linear"
-      }
-    }
-  },
-  {
-    cName: 'createLineBack',
-    remark: '创建飞行路线--回程',
-    content: {
-      "ModuleName": "Line",
-      "ActionName": "Create",
-      "Params": {
-        "pointArray": [
-          {
-            "x": 554110,
-            "y": -664540,
-            "z": 2040
-          },
-          {
-            "x": 554110,
-            "y": -664540,
-            "z": 4370
-          },
-          {
-            "x": 550480,
-            "y": -666430,
-            "z": 7150
-          },
-          {
-            "x": 547850,
-            "y": -672060,
-            "z": 9640
-          },
-          {
-            "x": 544910,
-            "y": -675790,
-            "z": 9890
-          },
-          {
-            "x": 538750,
-            "y": -685060,
-            "z": 10990
-          },
-          {
-            "x": 536911.35989199998,
-            "y": -685078.85117499996,
-            "z": 10981.988363
-          },
-          {
-            "x": 528910,
-            "y": -678970,
-            "z": 11490
-          },
-          {
-            "x": 520366.22116099996,
-            "y": -672668.99856600002,
-            "z": 11310.418701000001
-          },
-          {
-            "x": 517900,
-            "y": -671020,
-            "z": 11180
-          },
-          {
-            "x": 502730,
-            "y": -666350,
-            "z": 10840
-          },
-          {
-            "x": 489870,
-            "y": -661280,
-            "z": 10980
-          },
-          {
-            "x": 480660,
-            "y": -657700,
-            "z": 11030
-          },
-          {
-            "x": 474820,
-            "y": -656240,
-            "z": 11090
-          },
-          {
-            "x": 471450,
-            "y": -658450,
-            "z": 10900
-          },
-          {
-            "x": 467700,
-            "y": -664600,
-            "z": 10880
-          },
-          {
-            "x": 456270,
-            "y": -695130,
-            "z": 11360
-          },
-          {
-            "x": 449660,
-            "y": -711980,
-            "z": 11570
-          },
-          {
-            "x": 442020,
-            "y": -730610,
-            "z": 11930
-          },
-          {
-            "x": 443239.53170699999,
-            "y": -736951.55571900005,
-            "z": 6609.7363160000004
-          },
-          {
-            "x": 443230,
-            "y": -736980,
-            "z": 5250
-          }
-        ],
-        "lineStyle": "Style3",
-        "Tag": "BackPolyline",
-        "Color": { "R": 0, "G": 0, "B": 1, "A": 0.5 },
-        "Width": 20.0,
-        "Tilling": 5000.0,
-        "Speed": 1.0,
-        "SplinePointType": "Linear"
-      }
-    },
-
-  },
-  {
-    cName: 'clearLineGo',
-    remark: '清除飞行路径--去程',
-    content: {
-      "ModuleName": "Line",
-      "ActionName": "DeleteById",
-      "Params": {
-        "Tag": "GoPolyline"
-      }
-    }
-  },
-  {
-    cName: 'clearLineBack',
-    remark: '清除飞行路径--回程',
-    content: {
-      "ModuleName": "Line",
-      "ActionName": "DeleteById",
-      "Params": {
-        "Tag": "BackPolyline"
-      }
-    }
-  },
-]
-
-// 旧版功能
-const nameFunctions = {
-  // '正常航线': "rodOkShow", ✅
-  // '异常航线': "rodNoShow", ✅
-  // '隐藏航线': "rodHidden", ✅
-  // '网格展示': "netShow", ✅
-  // '网格隐藏': "netHidden", ✅
-  // '适飞区': "netGreen", ✅
-  // '禁飞区': "netRed", ✅
-  // '跟随飞行(自动来回)': "flay", ✅ (暂无法实现自动来回)
-  // '清除跟随无人机': "clearFlowFlay", ✅
-  // '起飞点定位': "upLocation", ✅
-  // '降落点定位': "downLocation", ✅
-  // '航路显示': "rowShow", ✅
-  // '航路隐藏': "rowHidden", ✅
-  // '信号塔显示': "signShow", ✅
-  // '信号塔隐藏': "signHidden", ✅
-  // '坠落飞行': "downFly", ✅
-  // '风险区': "netYellow", ❌
-  // '空间网格整体查看': "netLookUp", ❌
-  // '查看航路视角移动': "lookFlyRow", ❌
-  // '飞行全景查看': "LookflayAll", ❌
-  // '场景概览': "lookAll", ❌
-  // '预警视角移动': "yujingFly" ❌
-
-
-  '区域展示': "areaInfoShow",
-  '区域隐藏': "areaInfoHidden",
-  '清除有问题航线并查看没问题航线': "autoRow",
-  '自动生成对面无人机': "autoMakeFlay",
-  '清除自动生成无人机': "closeAutoFlay",
-}
-
-export default getFn

+ 5 - 0
src/utils/bus.js

@@ -0,0 +1,5 @@
+import mitt from 'mitt'
+
+const bus = new mitt()
+
+export default bus

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 510 - 537
src/utils/map/addLayer.js


+ 183 - 0
src/utils/ueActions.js

@@ -0,0 +1,183 @@
+import bus from './bus'
+
+function sendMessage(msgObj) {
+	bus.emit('callUE', msgObj)
+}
+
+// 图形绘制(回显)
+export function renderShapes({ id, data }) {
+	if (data) {
+		sendMessage({
+			ModuleName: 'BluePrint',
+			ActionName: '',
+			Params: {
+				ModuleName: 'GeometryDraw',
+				ActionName: 'Create',
+				Data: {
+					id,
+					...data,
+				},
+			},
+		})
+	} else {
+		sendMessage({
+			ModuleName: 'BluePrint',
+			ActionName: '',
+			Params: {
+				ModuleName: 'GeometryDraw',
+				ActionName: 'ShowHidden',
+				Id: id,
+				Visible: false,
+			},
+		})
+	}
+}
+
+// 清除全部图形绘制
+export function clearAllShapes() {
+	sendMessage({
+		ModuleName: 'BluePrint',
+		ActionName: '',
+		Params: {
+			ModuleName: 'GeometryDraw',
+			ActionName: 'DeleteAll',
+		},
+	})
+}
+
+// 空域分层
+export function AirSpaceLayer({ Heights, Visible }) {
+	const heightArr = Heights.split(',').map((h) => Number(h))
+	sendMessage({
+		ModuleName: 'BluePrint',
+		ActionName: '',
+		Params: {
+			ModuleName: 'AirSpaceLayer',
+			ActionName: 'ShowHidden',
+			Id: `YP_${heightArr[0]}-${heightArr[1]}`,
+			Visible: Visible,
+		},
+	})
+}
+
+// 人口热力图
+export function toggleHeatMap(show = true) {
+	if (show) {
+		sendMessage({
+			ModuleName: 'HeatMap',
+			ActionName: 'Create',
+			Params: {
+				url: 'http://10.1.162.49:8080/output.png',
+				X: 514067.5127,
+				Y: -698484.8542,
+				Z: 0,
+				Pitch: 0,
+				Yaw: 0,
+				Roll: 0,
+				ScaleX: 72,
+				ScaleY: -76,
+				ScaleZ: 100,
+				Tag: 'HeatMapTag',
+				MaxHeight: 600,
+				NoiseStrength: 10,
+			},
+		})
+	} else {
+		sendMessage({
+			ModuleName: 'HeatMap',
+			ActionName: 'Delete',
+			Params: {},
+		})
+	}
+}
+
+// 态势监视
+export function showAlertDemo(type) {
+	sendMessage({
+		ModuleName: 'BluePrint',
+		ActionName: '',
+		Params: {
+			ModuleName: 'Uav',
+			ActionName: 'DemoScene',
+			Type: type, // Near 临近、Yaw偏航、Electricity 电量、BreakInto 空入闯入、Weather 天气
+		},
+	})
+}
+
+// 视角跟随无人机
+export function followUav(uavId) {
+	sendMessage({
+		ModuleName: 'BluePrint',
+		ActionName: '',
+		Params: {
+			ModuleName: 'Uav',
+			ActionName: uavId ? 'StartPawnFollowUav' : 'EndPawnFollowUav',
+			Id: uavId,
+		},
+	})
+}
+
+// 轨迹线显示隐藏
+export function toggleTrackLine(status) {
+	sendMessage({
+		ModuleName: 'BluePrint',
+		ActionName: '',
+		Params: {
+			ModuleName: 'Uav',
+			ActionName: 'ShowHiddenTrackLine',
+			Visible: status,
+		},
+	})
+}
+
+// 态势-无人机
+export function toggleUav(status) {
+	sendMessage({
+		ModuleName: 'BluePrint',
+		ActionName: '',
+		Params: {
+			ModuleName: 'Uav',
+			ActionName: status ? 'CreateWebSocket' : 'CloseWebSocket',
+		},
+	})
+}
+
+// 绘制网格
+export function renderGrid() {
+	sendMessage({
+		ModuleName: 'BluePrint',
+		ActionName: '',
+		Params: {
+			ModuleName: 'AirGrid',
+			ActionName: 'GetViewGrid',
+			Data: {
+				MaxZ: 100,
+				MinZ: 90,
+				Level: 23,
+				elementFields: [
+					'demographics',
+					'green',
+					'river',
+					'road',
+					'collision_buffer',
+					'no_fly_zone_buffer',
+					'clear_zone_buffer',
+					'collision',
+				],
+			},
+		},
+	})
+}
+
+// 天气切换
+export function setWeather({ RealTime = true, UpdateTime, WeatherType }) {
+	sendMessage({
+		ModuleName: 'Weather',
+		ActionName: 'Update',
+		Params: {
+			RealTime,
+			UpdateTime, // "2025-02-21 8:00:00"
+			WeatherType, // "Clear Skies" | "Light Rain"
+		},
+	})
+}

+ 373 - 308
src/views/home/cpns/FloatPanelFcky.vue

@@ -1,389 +1,454 @@
 <!-- 分层空域 -->
 <template>
-  <Transition name="fade">
-    <div class="f-panel-left panel-fcky"
-      :class="{ 'bg-shrink': form.layeringType === '广域分层', 'collapse': layoutStore.leftCollapse }">
-      <h2 class="u-title">
-        分层空域
-        <i title="清空" @click="clearAll(true)"></i>
-      </h2>
-
-      <el-form v-model="form" class="form-top mt-3" label-position="left">
-        <el-form-item label="分层范围" prop="rangeType">
-          <el-radio-group v-model="form.rangeType" @change="handleRangeChange">
-            <el-radio label="行政区划" value="行政区划" />
-            <el-radio label="自定义绘制" value="自定义绘制" />
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="绘制/选择" prop="range">
-          <el-button v-if="form.rangeType === '自定义绘制'" @click="handleDraw" class="btn-secondary small">绘制</el-button>
-          <el-cascader v-else v-model="form.range" @change="handleSelectDistrict" :options="districtList"
-            :props="cascaderProps" class="w-full" />
-        </el-form-item>
-        <el-form-item label="分层方式" prop="layeringType">
-          <el-radio-group v-model="form.layeringType">
-            <el-radio label="广域分层" value="广域分层" />
-            <el-radio label="细微分层" value="细微分层" />
-          </el-radio-group>
-        </el-form-item>
-      </el-form>
-
-      <el-form v-model="form" class="mt-3" label-position="top">
-        <el-form-item label="分层空域" prop="layersBig" class="mb-0">
-          <el-checkbox v-if="form.layeringType === '广域分层'" v-model="checkAll.big" class="mr-auto"
-            :indeterminate="indeterminate.big" @change="val => handleCheckAll('big', val)">全选</el-checkbox>
-          <el-checkbox-group v-if="form.layeringType === '广域分层'" v-model="form.layersBig"
-            @change="val => handleCheck('big', val, 3)">
-            <el-checkbox v-for="item in layersListBig" :label="item.label" :value="item.value" />
-          </el-checkbox-group>
-
-          <template v-else>
-            <div class="title-sub mb-2 w-full">
-              120以下
-              <el-checkbox v-model="checkAll.small_1" @change="val => handleCheckAll('small_1', val)"
-                class="ml-auto pr-1" :indeterminate="indeterminate.small_1">全选</el-checkbox>
-            </div>
-            <el-checkbox-group v-model="form.layersSmall" @change="val => handleCheck('small_1', val)">
-              <el-checkbox v-for="item in layersListSmall.slice(0, 6)" :label="item.label" :value="item.value"
-                class="w-1/3 mr-0 mb-1 pl-2" />
-            </el-checkbox-group>
-            <div class="title-sub my-2 w-full">
-              120-300
-              <el-checkbox v-model="checkAll.small_2" @change="val => handleCheckAll('small_2', val)"
-                class="ml-auto pr-1" :indeterminate="indeterminate.small_2">全选</el-checkbox>
-            </div>
-            <el-checkbox-group v-model="form.layersSmall" @change="val => handleCheck('small_2', val)">
-              <el-checkbox v-for="item in layersListSmall.slice(6, 15)" :label="item.label" :value="item.value"
-                class="w-1/3 mr-0 mb-1 pl-2" />
-            </el-checkbox-group>
-            <div class="title-sub my-2 w-full">
-              300-600
-              <el-checkbox v-model="checkAll.small_3" @change="val => handleCheckAll('small_3', val)"
-                class="ml-auto pr-1" :indeterminate="indeterminate.small_3">全选</el-checkbox>
-            </div>
-            <el-checkbox-group v-model="form.layersSmall" class="w-full" @change="val => handleCheck('small_3', val)">
-              <el-checkbox v-for="item in layersListSmall.slice(15)" :label="item.label" :value="item.value"
-                class="w-1/3 mr-0 pl-2" />
-            </el-checkbox-group>
-          </template>
-        </el-form-item>
-      </el-form>
-    </div>
-  </Transition>
+	<Transition name="fade">
+		<div
+			class="f-panel-left panel-fcky"
+			:class="{ 'bg-shrink': form.layeringType === '广域分层', collapse: layoutStore.leftCollapse }">
+			<h2 class="u-title">
+				分层空域
+				<i title="清空" @click="clearAll(true)"></i>
+			</h2>
+
+			<el-form v-model="form" class="form-top mt-3" label-position="left">
+				<el-form-item label="分层范围" prop="rangeType">
+					<el-radio-group v-model="form.rangeType" @change="handleRangeChange">
+						<el-radio label="行政区划" value="行政区划" />
+						<el-radio label="自定义绘制" value="自定义绘制" />
+					</el-radio-group>
+				</el-form-item>
+				<el-form-item label="绘制/选择" prop="range">
+					<el-button v-if="form.rangeType === '自定义绘制'" @click="handleDraw" class="btn-secondary small"
+						>绘制</el-button
+					>
+					<el-cascader
+						v-else
+						v-model="form.range"
+						@change="handleSelectDistrict"
+						:options="districtList"
+						:props="cascaderProps"
+						class="w-full" />
+				</el-form-item>
+				<el-form-item label="分层方式" prop="layeringType">
+					<el-radio-group v-model="form.layeringType">
+						<el-radio label="广域分层" value="广域分层" />
+						<el-radio label="细微分层" value="细微分层" />
+					</el-radio-group>
+				</el-form-item>
+			</el-form>
+
+			<el-form v-model="form" class="mt-3" label-position="top">
+				<el-form-item label="分层空域" prop="layersBig" class="mb-0">
+					<el-checkbox
+						v-if="form.layeringType === '广域分层'"
+						v-model="checkAll.big"
+						class="mr-auto"
+						:indeterminate="indeterminate.big"
+						@change="(val) => handleCheckAll('big', val)"
+						>全选</el-checkbox
+					>
+					<el-checkbox-group
+						v-if="form.layeringType === '广域分层'"
+						v-model="form.layersBig"
+						@change="(val) => handleCheck('big', val, 3)">
+						<el-checkbox v-for="item in layersListBig" :label="item.label" :value="item.value" />
+					</el-checkbox-group>
+
+					<template v-else>
+						<div class="title-sub mb-2 w-full">
+							120以下
+							<el-checkbox
+								v-model="checkAll.small_1"
+								@change="(val) => handleCheckAll('small_1', val)"
+								class="ml-auto pr-1"
+								:indeterminate="indeterminate.small_1"
+								>全选</el-checkbox
+							>
+						</div>
+						<el-checkbox-group v-model="form.layersSmall" @change="(val) => handleCheck('small_1', val)">
+							<el-checkbox
+								v-for="item in layersListSmall.slice(0, 6)"
+								:label="item.label"
+								:value="item.value"
+								class="w-1/3 mr-0 mb-1 pl-2" />
+						</el-checkbox-group>
+						<div class="title-sub my-2 w-full">
+							120-300
+							<el-checkbox
+								v-model="checkAll.small_2"
+								@change="(val) => handleCheckAll('small_2', val)"
+								class="ml-auto pr-1"
+								:indeterminate="indeterminate.small_2"
+								>全选</el-checkbox
+							>
+						</div>
+						<el-checkbox-group v-model="form.layersSmall" @change="(val) => handleCheck('small_2', val)">
+							<el-checkbox
+								v-for="item in layersListSmall.slice(6, 15)"
+								:label="item.label"
+								:value="item.value"
+								class="w-1/3 mr-0 mb-1 pl-2" />
+						</el-checkbox-group>
+						<div class="title-sub my-2 w-full">
+							300-600
+							<el-checkbox
+								v-model="checkAll.small_3"
+								@change="(val) => handleCheckAll('small_3', val)"
+								class="ml-auto pr-1"
+								:indeterminate="indeterminate.small_3"
+								>全选</el-checkbox
+							>
+						</div>
+						<el-checkbox-group v-model="form.layersSmall" class="w-full" @change="(val) => handleCheck('small_3', val)">
+							<el-checkbox
+								v-for="item in layersListSmall.slice(15)"
+								:label="item.label"
+								:value="item.value"
+								class="w-1/3 mr-0 pl-2" />
+						</el-checkbox-group>
+					</template>
+				</el-form-item>
+			</el-form>
+		</div>
+	</Transition>
 </template>
 
 <script setup>
-import { computed, onBeforeMount, onBeforeUnmount, reactive, ref, watch } from 'vue';
-import useLayoutStore from '@/store/layout';
+import { computed, onBeforeMount, onBeforeUnmount, reactive, ref, watch } from 'vue'
+import useLayoutStore from '@/store/layout'
 import { DrawPolygon, clearLayering, drawLayering, clearDraw, QueryDistrict } from '@/utils/map/addLayer'
-import { useMapStore } from '@/store/map';
-import { GetDistrictTree } from '@/service/http';
-import usePanelStore from '@/store/panel';
+import { useMapStore } from '@/store/map'
+import { GetDistrictTree } from '@/service/http'
+import usePanelStore from '@/store/panel'
+import { AirSpaceLayer } from '@/utils/ueActions'
 
 const layoutStore = useLayoutStore()
 const mapStore = useMapStore()
 const panelStore = usePanelStore()
 
 onBeforeMount(() => {
-  handleRestoreChecked()
+	handleRestoreChecked()
 })
 
 function handleRestoreChecked() {
-  const temp = panelStore.fcky
-  if (!Object.keys(temp).length) return
-  form.value = temp.form
-  lastBigLayers = temp.lastBigLayers
-  lastSmallLayers = temp.lastSmallLayers
-  Object.keys(checkAll).forEach(k => {
-    checkAll[k] = temp.checkAll[k]
-  })
-  drawResult = temp.drawResult
-  queryResult = temp.queryResult
+	const temp = panelStore.fcky
+	if (!Object.keys(temp).length) return
+	form.value = temp.form
+	lastBigLayers = temp.lastBigLayers
+	lastSmallLayers = temp.lastSmallLayers
+	Object.keys(checkAll).forEach((k) => {
+		checkAll[k] = temp.checkAll[k]
+	})
+	drawResult = temp.drawResult
+	queryResult = temp.queryResult
 }
 
 const form = ref({
-  rangeType: '自定义绘制',
-  layeringType: '广域分层',
-  layersBig: [],
-  layersSmall: [],
+	rangeType: '自定义绘制',
+	layeringType: '广域分层',
+	layersBig: [],
+	layersSmall: [],
 })
 
 const colorArr = [
-  [255, 0, 255, 0.2],
-  [255, 255, 0, 0.2],
-  [0, 255, 0, 0.2],
+	[255, 0, 255, 0.2],
+	[255, 255, 0, 0.2],
+	[0, 255, 0, 0.2],
 ]
 
 function handleDraw() {
-  clearAll()
-  DrawPolygon()
+	clearAll()
+	DrawPolygon()
 }
 
 function handleSelectDistrict(val) {
-  clearAll()
-  QueryDistrict(val)
+	clearAll()
+	QueryDistrict(val)
 }
 
 function handleRangeChange() {
-  clearAll()
+	clearAll()
 }
 
 const districtList = ref([])
 
 const cascaderProps = {
-  expandTrigger: 'hover',
-  checkStrictly: true
+	expandTrigger: 'hover',
+	checkStrictly: true,
 }
 
-watch(form, (val) => {
-  if (val.rangeType === '行政区划' && !districtList.value.length) {
-    GetDistrictTree().then(res => {
-      if (!Array.isArray(res.data)) {
-        ElMessage({ offset: 90, type: 'warning', message: '行政区划获取失败' })
-        return
-      }
-      districtList.value = res.data
-    }).catch(() => {
-      ElMessage({ offset: 90, type: 'warning', message: '行政区划获取失败' })
-    })
-  }
-  handleLayering()
-}, { deep: true })
+watch(
+	form,
+	(val) => {
+		if (val.rangeType === '行政区划' && !districtList.value.length) {
+			GetDistrictTree()
+				.then((res) => {
+					if (!Array.isArray(res.data)) {
+						ElMessage({ offset: 90, type: 'warning', message: '行政区划获取失败' })
+						return
+					}
+					districtList.value = res.data
+				})
+				.catch(() => {
+					ElMessage({ offset: 90, type: 'warning', message: '行政区划获取失败' })
+				})
+		}
+		handleLayering()
+	},
+	{ deep: true }
+)
 
 let drawResult
 let queryResult
 
-watch(() => mapStore.draw_geometry, (val) => {
-  drawResult = val.rings
-  console.log('drawResult', val)
-  handleLayering()
-}, { deep: true })
-
-watch(() => mapStore.queryResult, (val) => {
-  queryResult = val[0].geometry.rings
-  console.log('queryResult', val)
-  handleLayering()
-}, { deep: true })
+watch(
+	() => mapStore.draw_geometry,
+	(val) => {
+		drawResult = val.rings
+		console.log('drawResult', val)
+		handleLayering()
+	},
+	{ deep: true }
+)
+
+watch(
+	() => mapStore.queryResult,
+	(val) => {
+		queryResult = val[0].geometry.rings
+		console.log('queryResult', val)
+		handleLayering()
+	},
+	{ deep: true }
+)
+
+function toggleSingleLayer(data, show = true) {
+	if (layoutStore.sceneType === 'gis') {
+		if (show) {
+			drawLayering({
+				id: data.id,
+				height: data.value,
+				rings: data.rings,
+				color: data.color,
+			})
+		} else {
+			clearLayering(data.id)
+		}
+	} else {
+		AirSpaceLayer({
+			Visible: show,
+			Heights: data.value,
+		})
+	}
+}
 
 let timer_handleLayering
 let lastBigLayers = []
 let lastSmallLayers = []
 function handleLayering() {
-  if (timer_handleLayering) {
-    clearTimeout(timer_handleLayering)
-  }
-  timer_handleLayering = setTimeout(() => {
-    const { layeringType, layersBig, layersSmall, rangeType, range } = form.value
-    const rings = rangeType === '自定义绘制' ? drawResult : queryResult
-    if (!rings) return
-    console.log('start draw')
-    console.log('range', range)
-
-    if (layeringType === '广域分层') {
-      layersListSmall.value.forEach(i => {
-        if (lastSmallLayers.includes(i.value)) {
-          clearLayering(i.id)
-        }
-      })
-      lastSmallLayers = []
-      layersListBig.forEach(i => {
-        if (layersBig.includes(i.value) && !lastBigLayers.includes(i.value)) {
-          drawLayering({
-            id: i.id,
-            height: i.value,
-            rings,
-            color: i.color
-          })
-        } else if (!layersBig.includes(i.value) && lastBigLayers.includes(i.value)) {
-          clearLayering(i.id)
-        }
-      })
-      lastBigLayers = JSON.parse(JSON.stringify(layersBig))
-    } else {
-      // 细微分层
-      layersListBig.forEach(i => {
-        if (lastBigLayers.includes(i.value)) {
-          clearLayering(i.id)
-        }
-      })
-      lastBigLayers = []
-      layersListSmall.value.forEach(i => {
-        if (layersSmall.includes(i.value) && !lastSmallLayers.includes(i.value)) {
-          drawLayering({
-            id: i.id,
-            height: i.value,
-            rings,
-            color: i.color
-          })
-        } else if (!layersSmall.includes(i.value) && lastSmallLayers.includes(i.value)) {
-          clearLayering(i.id)
-        }
-      })
-      lastSmallLayers = JSON.parse(JSON.stringify(layersSmall))
-    }
-
-  }, 1000);
+	if (timer_handleLayering) {
+		clearTimeout(timer_handleLayering)
+	}
+	timer_handleLayering = setTimeout(() => {
+		const { layeringType, layersBig, layersSmall, rangeType, range } = form.value
+		const rings = rangeType === '自定义绘制' ? drawResult : queryResult
+		if (!rings) return
+		console.log('start draw')
+		console.log('range', range)
+
+		if (layeringType === '广域分层') {
+			layersListSmall.value.forEach((i) => {
+				if (lastSmallLayers.includes(i.value)) {
+					toggleSingleLayer({ id: i.id, value: i.value }, false)
+				}
+			})
+			lastSmallLayers = []
+			layersListBig.forEach((i) => {
+				if (layersBig.includes(i.value) && !lastBigLayers.includes(i.value)) {
+					toggleSingleLayer({ ...i, rings }, true)
+				} else if (!layersBig.includes(i.value) && lastBigLayers.includes(i.value)) {
+					toggleSingleLayer({ ...i }, false)
+				}
+			})
+			lastBigLayers = JSON.parse(JSON.stringify(layersBig))
+		} else {
+			// 细微分层
+			layersListBig.forEach((i) => {
+				if (lastBigLayers.includes(i.value)) {
+					toggleSingleLayer({ id: i.id, value: i.value }, false)
+				}
+			})
+			lastBigLayers = []
+			layersListSmall.value.forEach((i) => {
+				if (layersSmall.includes(i.value) && !lastSmallLayers.includes(i.value)) {
+					toggleSingleLayer({ ...i, rings }, true)
+				} else if (!layersSmall.includes(i.value) && lastSmallLayers.includes(i.value)) {
+					toggleSingleLayer({ ...i }, false)
+				}
+			})
+			lastSmallLayers = JSON.parse(JSON.stringify(layersSmall))
+		}
+	}, 1000)
 }
 
 const layersListBig = [
-  { label: '120以下', id: 'big_1', value: '0,120', color: colorArr[0] },
-  { label: '120-300', id: 'big_2', value: '120,300', color: colorArr[1] },
-  { label: '300-600', id: 'big_3', value: '300,600', color: colorArr[2] },
+	{ label: '120以下', id: 'big_1', value: '0,120', color: colorArr[0] },
+	{ label: '120-300', id: 'big_2', value: '120,300', color: colorArr[1] },
+	{ label: '300-600', id: 'big_3', value: '300,600', color: colorArr[2] },
 ]
 
 const layersListSmall = computed(() => {
-  let res = []
-  let last = 0
-  for (let i = 0; i < 18; i++) {
-    const step = i < 15 ? 20 : 100
-    const end = last + step
-    res.push({
-      label: `${last}-${end}`,
-      value: `${last},${end}`,
-      id: `small_${i + 1}`,
-      color: i < 6 ? colorArr[0] : i > 14 ? colorArr[2] : colorArr[1]
-    })
-    last = end
-  }
-  return res
+	let res = []
+	let last = 0
+	for (let i = 0; i < 18; i++) {
+		const step = i < 15 ? 20 : 100
+		const end = last + step
+		res.push({
+			label: `${last}-${end}`,
+			value: `${last},${end}`,
+			id: `small_${i + 1}`,
+			color: i < 6 ? colorArr[0] : i > 14 ? colorArr[2] : colorArr[1],
+		})
+		last = end
+	}
+	return res
 })
 
 const checkAll = reactive({
-  big: false,
-  small_1: false,
-  small_2: false,
-  small_3: false,
+	big: false,
+	small_1: false,
+	small_2: false,
+	small_3: false,
 })
 
 const indeterminate = reactive({
-  big: false,
-  small_1: false,
-  small_2: false,
-  small_3: false,
+	big: false,
+	small_1: false,
+	small_2: false,
+	small_3: false,
 })
 
 function handleCheck(type, checkVal) {
-  let checkedLen
-  let typeAll
-  if(type==='big') {
-    checkedLen = checkVal.length
-    typeAll = layersListBig
-  } else {
-    typeAll = layersListSmall.value.slice(typeMap[type][0], typeMap[type][1])
-    checkedLen = typeAll.filter(a => checkVal.indexOf(a) > -1).length
-  }
-  indeterminate[type] = checkedLen < typeAll.length && checkedLen > 0
-  checkAll[type] = checkedLen === typeAll.length
+	let checkedLen
+	let typeAll
+	if (type === 'big') {
+		checkedLen = checkVal.length
+		typeAll = layersListBig
+	} else {
+		typeAll = layersListSmall.value.slice(typeMap[type][0], typeMap[type][1])
+		checkedLen = typeAll.filter((a) => checkVal.indexOf(a) > -1).length
+	}
+	indeterminate[type] = checkedLen < typeAll.length && checkedLen > 0
+	checkAll[type] = checkedLen === typeAll.length
 }
 
 const typeMap = {
-  'small_1': [0, 5],
-  'small_2': [6, 14],
-  'small_3': [15, 17],
+	small_1: [0, 5],
+	small_2: [6, 14],
+	small_3: [15, 17],
 }
 
 function handleCheckAll(type, checkVal) {
-  indeterminate[type] = false
-  
-  if (type === 'big') {
-    form.value.layersBig = checkVal ? layersListBig.map(i => i.value) : []
-  } else {
-    const iMin = typeMap[type][0]
-    const iMax = typeMap[type][1]
-    let layersSmallTemp = JSON.parse(JSON.stringify(form.value.layersSmall))
-    layersListSmall.value.forEach((row, index) => {
-      const isInclude = layersSmallTemp.includes(row.value)
-      if (index >= iMin && index <= iMax) {
-        if (checkVal && !isInclude) {
-          layersSmallTemp.push(row.value)
-        } else if (!checkVal && isInclude) {
-          const targetIndex = layersSmallTemp.findIndex(i => i === row.value)
-          layersSmallTemp.splice(targetIndex, 1)
-        }
-      }
-    })
-    form.value.layersSmall = layersSmallTemp
-  }
+	indeterminate[type] = false
+
+	if (type === 'big') {
+		form.value.layersBig = checkVal ? layersListBig.map((i) => i.value) : []
+	} else {
+		const iMin = typeMap[type][0]
+		const iMax = typeMap[type][1]
+		let layersSmallTemp = JSON.parse(JSON.stringify(form.value.layersSmall))
+		layersListSmall.value.forEach((row, index) => {
+			const isInclude = layersSmallTemp.includes(row.value)
+			if (index >= iMin && index <= iMax) {
+				if (checkVal && !isInclude) {
+					layersSmallTemp.push(row.value)
+				} else if (!checkVal && isInclude) {
+					const targetIndex = layersSmallTemp.findIndex((i) => i === row.value)
+					layersSmallTemp.splice(targetIndex, 1)
+				}
+			}
+		})
+		form.value.layersSmall = layersSmallTemp
+	}
 }
 
-function clearAll(all=false) {
-  const currentList = form.value.layeringType === '广域分层' ? layersListBig : layersListSmall.value
-  currentList.forEach(i => {
-    if ([...lastBigLayers, ...lastSmallLayers].includes(i.value)) {
-      clearLayering(i.id)
-    }
-  })
-  lastBigLayers = []
-  lastSmallLayers = []
-  clearDraw()
-  if(all) {
-    Object.keys(checkAll).forEach(k => checkAll[k] = false)
-    Object.keys(indeterminate).forEach(k => indeterminate[k] = false)
-    form.value.layersBig = []
-    form.value.layersSmall = []
-    drawResult = null
-    queryResult = null
-  }
+function clearAll(all = false) {
+	const currentList = form.value.layeringType === '广域分层' ? layersListBig : layersListSmall.value
+	currentList.forEach((i) => {
+		if ([...lastBigLayers, ...lastSmallLayers].includes(i.value)) {
+			toggleSingleLayer({ id: i.id, value: i.value })
+		}
+	})
+	lastBigLayers = []
+	lastSmallLayers = []
+	clearDraw()
+	if (all) {
+		Object.keys(checkAll).forEach((k) => (checkAll[k] = false))
+		Object.keys(indeterminate).forEach((k) => (indeterminate[k] = false))
+		form.value.layersBig = []
+		form.value.layersSmall = []
+		drawResult = null
+		queryResult = null
+	}
 }
 
 function handleStoreChecked() {
-  panelStore.setFcky({
-    form: form.value,
-    checkAll,
-    lastBigLayers,
-    lastSmallLayers,
-    drawResult,
-    queryResult
-  })
+	panelStore.setFcky({
+		form: form.value,
+		checkAll,
+		lastBigLayers,
+		lastSmallLayers,
+		drawResult,
+		queryResult,
+	})
 }
 
 onBeforeUnmount(() => {
-  // clearAll()
-  handleStoreChecked()
+	// clearAll()
+	handleStoreChecked()
 })
-
 </script>
 
 <style lang="scss" scoped>
 .panel-fcky {
-  display: flex;
-  flex-direction: column;
-  width: 399px;
-  padding: 20px 25px 25px;
-  background: url('../../../assets/images/page/bg-dialog.png');
-  background-size: 100% 100% !important;
-
-  &.bg-shrink {
-    background: url('../../../assets/images/page/bg-dialog-s.png');
-    padding-bottom: 35px;
-  }
-
-  .u-title {
-    display: flex;
-    justify-content: space-between;
-    font-size: 26px;
-    background: linear-gradient(186deg, rgba(128, 155, 237, 1) 0%, rgba(255, 255, 255, 1) 100%);
-    -webkit-background-clip: text;
-    -webkit-text-fill-color: transparent;
-    i {
-      display: block;
-      width: 34px;
-      height: 34px;
-      margin-left: 5px;
-      background: url('../../../assets/images/buttons/btn-delete.png');
-      background-size: 40px 40px;
-      background-position: center;
-      cursor: pointer;
-      &:hover {
-        transform: scale(1.1);
-      }
-    }
-  }
-
-  :deep(.form-top) {
-    .el-form-item__label {
-      width: 105px;
-    }
-  }
+	display: flex;
+	flex-direction: column;
+	width: 399px;
+	padding: 20px 25px 25px;
+	background: url('../../../assets/images/page/bg-dialog.png');
+	background-size: 100% 100% !important;
+
+	&.bg-shrink {
+		background: url('../../../assets/images/page/bg-dialog-s.png');
+		padding-bottom: 35px;
+	}
+
+	.u-title {
+		display: flex;
+		justify-content: space-between;
+		font-size: 26px;
+		background: linear-gradient(186deg, rgba(128, 155, 237, 1) 0%, rgba(255, 255, 255, 1) 100%);
+		-webkit-background-clip: text;
+		-webkit-text-fill-color: transparent;
+
+		i {
+			display: block;
+			width: 34px;
+			height: 34px;
+			margin-left: 5px;
+			background: url('../../../assets/images/buttons/btn-delete.png');
+			background-size: 40px 40px;
+			background-position: center;
+			cursor: pointer;
+
+			&:hover {
+				transform: scale(1.1);
+			}
+		}
+	}
+
+	:deep(.form-top) {
+		.el-form-item__label {
+			width: 105px;
+		}
+	}
 }
-</style>
+</style>

+ 0 - 474
src/views/home/cpns/FloatPanelKysg_old.vue

@@ -1,474 +0,0 @@
-<template>
-  <div class="slider-container" v-if="!layoutStore.footerCollapse">
-
-    <el-form v-model="form" inline class="top-form">
-      <el-form-item label="类型" prop="meshType">
-        <el-radio-group v-model="form.meshType">
-          <el-radio label="二维" value="二维" />
-          <el-radio label="三维" value="三维" />
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item>
-        <el-checkbox v-model="form.grade">三维评分</el-checkbox>
-      </el-form-item>
-      <el-form-item>
-        <el-checkbox v-model="form.deepShow">深度显示</el-checkbox>
-      </el-form-item>
-      <el-form-item label="范围" prop="meshRange">
-        <el-radio-group v-model="form.meshRange">
-          <el-radio label="自适应" value="自适应" />
-          <el-radio label="自定义" value="自定义" />
-          <el-radio label="行政区划" value="行政区划" />
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item v-if="form.meshRange === '自定义'">
-        <el-button class="btn-secondary" @click="handleDraw">绘制</el-button>
-      </el-form-item>
-      <el-form-item v-if="form.meshRange === '行政区划'">
-        <el-cascader v-model="form.district" @change="handleSelectDistrict" :options="districtList"
-          :props="cascaderProps" placeholder="请选择行政区划" />
-      </el-form-item>
-    </el-form>
-
-    <!-- 单点选择滑动条 -->
-    <div class="slider-bg single-slider">
-      <div class="slider">
-        <div v-for="(point, index) in DenseData" :key="index" class="marker"
-          :class="{ 'key-point': selectedPoint === index }"
-          :style="{ left: index * (100 / (DenseData.length - 1)) + '%' }" @click="selectPoint(index)">
-          <span class="label">{{ point.label }}</span>
-          <span class="des">{{ point.des }}</span>
-        </div>
-      </div>
-    </div>
-
-    <!-- 范围选择滑动条 -->
-    <div class="slider-bg range-slider">
-      <div class="slider">
-        <!-- 高亮背景 -->
-        <div class="range-highlight" v-if="rangeStart !== null && rangeEnd !== null" :style="{
-          left: rangeStart * (100 / (heightData.length - 1)) + 1.5 + '%',
-          width: (rangeEnd - rangeStart) * (100 / (heightData.length - 1)) + '%',
-        }"></div>
-        <!-- 数据点 -->
-        <div v-for="(point, index) in heightData" :key="index" class="marker" :class="{
-          'active': (rangeStart !== null && rangeEnd === null && index === rangeStart) || (rangeStart !== null && rangeEnd !== null && index >= rangeStart && index <= rangeEnd),
-          'hover': shouldHighlightOnHover(index),
-          'key-point': index === rangeStart || index === rangeEnd
-        }" :style="{ left: index * (100 / (heightData.length - 1)) + '%' }" @click="selectRange(index)"
-          @mouseover="handleMouseOver(index)" @mouseleave="handleMouseLeave">
-          <span class="label">{{ point.label }}</span>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { ref, reactive, onMounted, onBeforeUnmount, watch } from 'vue';
-import { addKysgScale, DrawPolygon, QueryDistrict, QueryCube, clearDraw } from "@/utils/map/addLayer.js";
-import useLayoutStore from '@/store/layout';
-import { useMapStore } from '@/store/map';
-import { GetDistrictTree } from '@/service/http';
-import {geometryMeshEffect} from "@/utils/map/addTool.js";
-
-export default {
-  setup(props, { emit }) {
-    const mapStore = useMapStore()
-    const layoutStore = useLayoutStore()
-    const form = ref({
-      meshType: '二维',
-      grade: true,
-      deepShow:false,
-      meshRange: '自适应'
-    })
-
-    let lastEvaluation
-    let rings
-
-    const selectedPoint = ref(null); // 单点选择的索引
-    const rangeStart = ref(null); // 范围选择起点
-    const rangeEnd = ref(null); // 范围选择终点
-    const hoverIndex = ref(null); // 鼠标悬浮的索引
-
-    const districtList = ref([])
-
-    function handleSelectDistrict(val) {
-      QueryDistrict(val)
-    }
-
-    const cascaderProps = {
-      expandTrigger: 'hover',
-      checkStrictly: true
-    }
-
-    watch(() => form.value.meshRange, (val) => {
-      console.log(val)
-      clearDraw()
-      clearQueryCube()
-      rings = null
-      if (val === '自适应') {
-        layoutStore.toggleGlobalLoading(true)
-        setTimeout(() => {
-          layoutStore.toggleGlobalLoading(false)
-        }, 3000);
-        addKysgScale(true)
-        clearPoints()
-      } else {
-        addKysgScale(false)
-        if (val === '行政区划' && !districtList.value.length) {
-          GetDistrictTree().then(res => {
-            if (!Array.isArray(res.data)) {
-              ElMessage({ offset: 90, type: 'warning', message: '行政区划获取失败' })
-              return
-            }
-            districtList.value = res.data
-          }).catch(() => {
-            ElMessage({ offset: 90, type: 'warning', message: '行政区划获取失败' })
-          })
-        }
-      }
-    }, { immediate: true })
-
-    watch(form, (val) => {
-      showGrid()
-    }, { deep: true })
-
-    function handleDraw() {
-      clearQueryCube();
-      getMesh("hide");
-      DrawPolygon({ hasZ: true })
-    }
-
-    watch(() => mapStore.draw_geometry, (val) => {
-      rings = val?.rings
-      clearDraw();
-      getMesh("show");
-      showGrid()
-    }, { deep: true })
-
-    watch(() => mapStore.queryResult, (val) => {
-      rings = val[0].geometry.rings
-      showGrid()
-    }, { deep: true })
-
-    const DenseData = reactive([
-      // { label: '1/8″网格', level: 24, size: { x: 3.3055614085396883, y: 3.8513467134689563, z: 3.3678982462941303 }, des: '(3.9m)'},
-      { label: '1/4″网格', level: 23, size: { x: 6.7358, y: 7.7024, z: 6.6111 }, des: '(7m)' },
-      { label: '1/2″网格', level: 22, size: { x: 13.222978864358083, y: 15.406742669116284, z: 13.471596544164798 }, des: '(15m)' },
-      { label: '1′网格', level: 21, size: { x: 26.44107169853396, y: 30.815525255577086, z: 26.943221541824816 }, des: '(30.9m)' },
-      { label: '2′网格', level: 20, size: { x: 52.887881893650956, y: 61.627412608112536, z: 53.887012166300096 }, des: '(61m)' },
-      { label: '4′网格', level: 19, size: { x: 105.79869494173579, y: 123.43930203184209, z: 107.77356906534683 }, des: '(123.7m)' },
-      { label: '8′网格', level: 18, size: { x: 211.66439868324142, y: 246.49964316944533, z: 215.5489592181181 }, des: '(247.4m)' },
-      { label: '16′网格', level: 17, size: { x: 424.0518521273334, y: 492.09123171765896, z: 431.1052029077298 }, des: '(376.7m)' },
-      { label: '32′网格', level: 16, size: { x: 844.8477050379952, y: 990.1345935064928, z: 862.239544684298 }, des: '(746.4m)' },
-      { label: '1′网格', level: 15, size: { x: 1582.2726823222256, y: 1856.6079667204758, z: 1724.5956527210265 }, des: '(1850m)' },
-      // { label: '2′网格', level: 14, size: { x: 2984.4, y: 2984.4, z: 2984.4 }, des: '(2984.4m)'},
-    ]);
-
-    const heightData = reactive([
-      { label: "0m", value: 0 },
-      { label: "20m", value: 20 },
-      { label: "40m", value: 40 },
-      { label: "60m", value: 60 },
-      { label: "80m", value: 80 },
-      { label: "100m", value: 100 },
-      { label: "120m", value: 120 },
-      { label: "200m", value: 200 },
-      { label: "300m", value: 300 },
-      { label: "600m", value: 600 },
-      { label: "1000m", value: 1000 },
-    ]);
-
-    function clearPoints() {
-      selectedPoint.value = null
-      rangeStart.value = null
-      rangeEnd.value = null
-    }
-
-    // 单点选择逻辑
-    const selectPoint = (index) => {
-      selectedPoint.value = index;
-      showGrid()
-    };
-
-    // 范围选择逻辑
-    const selectRange = (index) => {
-      if (rangeStart.value === null || rangeEnd.value !== null) {
-        // 如果未选择起点或范围已完成,重新设置起点
-        rangeStart.value = index;
-        rangeEnd.value = null;
-      } else {
-        // 如果已经选择起点,设置终点
-        rangeEnd.value = index;
-        if (rangeEnd.value < rangeStart.value) {
-          // 保证起点小于终点
-          [rangeStart.value, rangeEnd.value] = [rangeEnd.value, rangeStart.value];
-        }
-      }
-      showGrid()
-    };
-
-    const handleMouseOver = (index) => {
-      hoverIndex.value = index;
-    };
-
-    const handleMouseLeave = () => {
-      hoverIndex.value = null;
-    };
-
-    const shouldHighlightOnHover = (index) => {
-      if ((hoverIndex.value !== null && rangeStart.value === null) || (rangeStart.value !== null && rangeEnd.value !== null)) {
-        // 如果未选择起点,只高亮当前悬浮的点
-        return index === hoverIndex.value;
-      } else if (hoverIndex.value !== null && rangeStart.value !== null && rangeEnd.value === null) {
-        // 如果已选择起点,且未选择终点,高亮起点到悬浮点之间的范围
-        return (
-          (index >= rangeStart.value && index <= hoverIndex.value) ||
-          (index <= rangeStart.value && index >= hoverIndex.value)
-        );
-      }
-      return false; // 不满足条件时,不高亮
-    };
-
-    let timer_showGrid
-
-    // 显示网格
-    const showGrid = () => {
-      if (timer_showGrid) {
-        clearTimeout(timer_showGrid)
-      }
-      timer_showGrid = setTimeout(() => {
-        console.log('showGrid')
-        console.log('rings:',rings)
-        console.log('points',selectedPoint.value, rangeStart.value, rangeEnd.value)
-        if (!rings) return
-        if (selectedPoint.value===null || rangeStart.value===null || rangeEnd.value===null) return
-        clearQueryCube()
-        setTimeout(() => {
-          QueryCube({
-            id: 'query_cube_kysg',
-            evaluation: form.value.grade,
-            deepShow: form.value.deepShow,
-            show: true,
-            level: DenseData[selectedPoint.value].level,
-            minZ: heightData[rangeStart.value].value,
-            maxZ: heightData[rangeEnd.value].value,
-            rings: rings
-          })
-        }, 300);
-        lastEvaluation = form.value.grade
-      }, 1000)
-    };
-
-    function clearQueryCube() {
-      QueryCube({
-        id: 'query_cube_kysg',
-        evaluation: lastEvaluation,
-        show: false,
-      })
-    }
-
-
-    //获取带高度三维体
-    function getMesh(status){
-      if(status == "hide"){
-        geometryMeshEffect({
-          id: 'sgzy_mesh',
-          status: "hide"
-        })
-        return
-      }
-      let height = heightData[rangeEnd.value].value - heightData[rangeStart.value].value;
-      let tempRings = [];
-      for(let i = 0; i < rings[0].length; i++){
-        tempRings.push([rings[0][i][0],rings[0][i][1],heightData[rangeStart.value].value - 0.01])
-      }
-      debugger
-      geometryMeshEffect({
-        id: 'sgzy_mesh',
-        status:"show",
-        data: [{
-          type: 'polygon',
-          shape: {
-            height: height,
-            rings: [tempRings],
-            color: [0,255,0,0.2]
-          }
-        }]
-      })
-
-    }
-
-    onBeforeUnmount(() => {
-      addKysgScale(false);
-      getMesh("hide")
-      clearDraw()
-      clearQueryCube()
-    })
-
-    return {
-      layoutStore,
-      form,
-      DenseData,
-      heightData,
-      selectedPoint,
-      rangeStart,
-      rangeEnd,
-      selectPoint,
-      selectRange,
-      handleMouseOver,
-      handleMouseLeave,
-      shouldHighlightOnHover,
-      handleDraw,
-      handleSelectDistrict,
-      cascaderProps,
-      districtList
-    };
-  },
-};
-</script>
-
-<style lang="scss" scoped>
-.slider-container {
-  position: absolute;
-  top: calc(var(--aside-height) - 246px - var(--footer-height));
-  left: calc(50% - 448px);
-  width: 896px;
-  height: 260px;
-  background: rgba(0, 10, 30, 0.6);
-  box-shadow: 0px 1px 6px 0px rgba(37, 37, 37, 0.6);
-  border: 1px solid #98baffb6;
-  visibility: visible;
-}
-
-.top-form {
-  display: flex;
-  flex-wrap: nowrap;
-  align-items: center;
-  margin: 15px 12px 0;
-
-  .el-form-item {
-    margin-right: 10px;
-  }
-}
-
-.type-list {
-  width: 100%;
-  height: 60px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.slider-bg {
-  width: calc(100% - 10px);
-  height: 25px;
-  background: url('../../../assets/images/page/slider-bg.png') no-repeat;
-  background-size: 100% 100%;
-  padding: 0 70px 0 60px;
-  margin-right: 10px;
-}
-
-.slider {
-  position: relative;
-  height: 100%;
-  /* background-color: #2a2f3a; */
-}
-
-.marker {
-  position: absolute;
-  width: 25px;
-  height: 25px;
-  cursor: pointer;
-  transition: background-color 0.3s;
-
-  &::before {
-    content: '';
-    position: absolute;
-    display: block;
-    top: 9px;
-    left: 8px;
-    width: 8px;
-    height: 8px;
-    transform: rotateZ(45deg);
-    border: 2px solid #6495ed;
-  }
-
-  &.active::before {
-    border-color: #ffd700;
-  }
-
-  &.hover::before {
-    background-color: #ffd700;
-  }
-
-  &.key-point {
-    span {
-      font-weight: bold;
-      font-size: 18px;
-      color: #FFFFFF;
-    }
-
-    &::before {
-      border-color: #FFFCF5;
-      box-shadow: 0 0 4px 5px #ffd90062;
-      background-color: #ffd700;
-    }
-  }
-
-}
-
-.label {
-  position: absolute;
-  top: -45px;
-  left: 50%;
-  transform: translateX(-50%);
-  white-space: nowrap;
-  font-size: 16px;
-  color: #9DAAC7;
-}
-
-.des {
-  position: absolute;
-  top: -25px;
-  left: 50%;
-  transform: translateX(-50%);
-  white-space: nowrap;
-  font-size: 14px;
-  color: #9DAAC7;
-}
-
-.range-highlight {
-  position: absolute;
-  top: 3px;
-  height: 80%;
-  background-color: rgba(255, 212, 0, 0.2);
-  z-index: 1;
-}
-
-.single-slider {
-  margin-top: 50px;
-
-  .label {
-    font-size: 14px;
-  }
-
-  .key-point span {
-    font-size: 16px;
-  }
-}
-
-.range-slider {
-  margin-top: 53px;
-
-  .slider .marker {
-    z-index: 2;
-  }
-
-  .label {
-    top: -25px;
-  }
-}
-</style>

+ 118 - 115
src/views/home/cpns/FloatPanelTsjs.vue

@@ -1,145 +1,148 @@
 <template>
-  <div class="panel-tsjs">
-    <ul class="type-list">
-      <li v-for="item in listData">
-        <img :src="getAssetsFile(`page/alert-bg-${item.id}.png`)" alt="">
-        <div>
-          {{ item.count }}
-          <span>个</span>
-        </div>
-        <span>{{ item.label }}</span>
-      </li>
-    </ul>
-
-    <div class="options">
-      <div class="switch" @click="toggleOption('airLine')">
-        <span>航线</span>
-        <i :class="{ 'on': options.airLine }"></i>
-      </div>
-      <div class="switch" @click="toggleOption('track')">
-        <span>轨迹</span>
-        <i :class="{ 'on': options.track }"></i>
-      </div>
-    </div>
-  </div>
+	<div class="panel-tsjs">
+		<ul class="type-list">
+			<li v-for="item in listData" @click="handleDemo(item)">
+				<img :src="getAssetsFile(`page/alert-bg-${item.pic}.png`)" alt="" />
+				<div>
+					{{ item.count }}
+					<span>个</span>
+				</div>
+				<span>{{ item.label }}</span>
+			</li>
+		</ul>
+
+		<div class="options">
+			<div class="switch" @click="toggleOption('airLine')">
+				<span>航线</span>
+				<i :class="{ on: options.airLine }"></i>
+			</div>
+			<div class="switch" @click="toggleOption('track')">
+				<span>轨迹</span>
+				<i :class="{ on: options.track }"></i>
+			</div>
+		</div>
+	</div>
 </template>
 
 <script setup>
-import { getAssetsFile } from '@/utils/require';
-import { reactive, ref, onBeforeMount } from 'vue';
+import { getAssetsFile } from '@/utils/require'
+import { showAlertDemo } from '@/utils/ueActions'
+import { reactive, ref, onBeforeMount } from 'vue'
 
 const listData = ref([
-  { label: '偏航预警', id: 'ph', count: 0 },
-  { label: '空域闯入', id: 'ky', count: 0 },
-  { label: '天气预警', id: 'tq', count: 0 },
-  { label: '碰撞预警', id: 'pz', count: 0 },
-  { label: '电量预警', id: 'dl', count: 0 },
+	{ label: '偏航预警', value: 'Yaw', pic: 'ph', count: 0 },
+	{ label: '空域闯入', value: 'BreakInto', pic: 'ky', count: 0 },
+	{ label: '天气预警', value: 'Weather', pic: 'tq', count: 0 },
+	{ label: '碰撞预警', value: 'Near', pic: 'pz', count: 0 },
+	{ label: '电量预警', value: 'Electricity', pic: 'dl', count: 0 },
 ])
 
+function handleDemo(item) {
+	showAlertDemo(item.value)
+}
+
 const options = reactive({
-  airLine: true,
-  track: true,
+	airLine: true,
+	track: true,
 })
 
 function toggleOption(target) {
-  options[target] = !options[target]
+	options[target] = !options[target]
 }
 
 function getData() {
-  listData.value.forEach(row => row.count = 5)
+	listData.value.forEach((row) => (row.count = 5))
 }
 
 onBeforeMount(() => {
-  getData()
+	getData()
 })
-
 </script>
 
 <style lang="scss" scoped>
 .panel-tsjs {
-  position: absolute;
-  left: var(--panel-gap);
-  height: var(--aside-height);
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
+	position: absolute;
+	left: var(--panel-gap);
+	height: var(--aside-height);
+	display: flex;
+	flex-direction: column;
+	justify-content: center;
 }
 
 .type-list {
-  li {
-    position: relative;
-    display: flex;
-    flex-direction: column;
-    justify-content: end;
-    align-items: start;
-    width: 188px;
-    height: 108px;
-    margin-bottom: 28px;
-    padding: 10px;
-    cursor: pointer;
-    transition: transform 0.3s ease;
-
-    &:hover {
-      transform: scale(1.05) translateX(10px);
-    }
-
-    img {
-      position: absolute;
-      top: 0;
-      left: 0;
-      object-fit: cover;
-      z-index: -1;
-    }
-    
-    &>div {
-      display: flex;
-      align-items: end;
-      margin-bottom: 10px;
-      font-family: BarlowMedium;
-      font-size: 34px;
-      line-height: 30px;
-      span {
-        margin-left: 5px;
-        font-size: 22px;
-        line-height: 22px;
-        font-family: ShuHei;
-      }
-    }
-
-    &>span {
-      font-size: 22px;
-      line-height: 22px;
-    }
-  }
+	li {
+		position: relative;
+		display: flex;
+		flex-direction: column;
+		justify-content: end;
+		align-items: start;
+		width: 188px;
+		height: 108px;
+		margin-bottom: 28px;
+		padding: 10px;
+		cursor: pointer;
+		transition: transform 0.3s ease;
+
+		&:hover {
+			transform: scale(1.05) translateX(10px);
+		}
+
+		img {
+			position: absolute;
+			top: 0;
+			left: 0;
+			object-fit: cover;
+			z-index: -1;
+		}
+
+		& > div {
+			display: flex;
+			align-items: end;
+			margin-bottom: 10px;
+			font-family: BarlowMedium;
+			font-size: 34px;
+			line-height: 30px;
+			span {
+				margin-left: 5px;
+				font-size: 22px;
+				line-height: 22px;
+				font-family: ShuHei;
+			}
+		}
+
+		& > span {
+			font-size: 22px;
+			line-height: 22px;
+		}
+	}
 }
 
 .options {
-  margin-top: 15px;
-  .switch {
-    display: flex;
-    align-items: center;
-    width: fit-content;
-    margin-bottom: 15px;
-    cursor: pointer;
-    span {
-      margin-right: 15px;
-      font-size: 18px;
-    }
-    i {
-      display: block;
-      width: 76px;
-      height: 35px;
-      background: url('@/assets/images/buttons/switch-off.png');
-      background-repeat: no-repeat !important;
-      background-size: cover !important;
-      transition: all 0.1s ease;
-    
-      &.on {
-        background: url('@/assets/images/buttons/switch-on.png');
-        background-position: -8px center;
-      }
-    }
-  }
-}
+	margin-top: 15px;
+	.switch {
+		display: flex;
+		align-items: center;
+		width: fit-content;
+		margin-bottom: 15px;
+		cursor: pointer;
+		span {
+			margin-right: 15px;
+			font-size: 18px;
+		}
+		i {
+			display: block;
+			width: 76px;
+			height: 35px;
+			background: url('@/assets/images/buttons/switch-off.png');
+			background-repeat: no-repeat !important;
+			background-size: cover !important;
+			transition: all 0.1s ease;
 
-</style>
+			&.on {
+				background: url('@/assets/images/buttons/switch-on.png');
+				background-position: -8px center;
+			}
+		}
+	}
+}
+</style>

+ 462 - 442
src/views/home/cpns/PanelSjwg.vue

@@ -1,274 +1,295 @@
 <template>
-  <div class="panel-sjwg flex flex-col aside-left-inner">
-    <div class="title-main shrink-0">数据网格可视化</div>
-
-    <div class="title-sub my-4 shrink-0">
-      底板数据
-      <i @click="toggleContentShow('b1')" class="drop-down" :class="{ 'reverse': contentShow.b1 }"></i>
-    </div>
-
-    <Transition>
-      <ul class="list-base flex flex-wrap shrink-0" v-if="contentShow.b1" v-collapse>
-        <li v-for="item in basicList" class="text-center w-1/4 mb-4 cursor-pointer" @click="handleBaseClick(item)">
-          <img :src="getAssetsFile(`page/${item.active ? item.icon + '-h' : item.icon}.png`)" alt="" class="ml-2 mb-1">
-          <span class="block text-base ml-2">{{ item.label }}</span>
-        </li>
-      </ul>
-    </Transition>
-
-    <div class="title-sub mb-4 shrink-0">
-      低空要素数据
-      <i @click="toggleContentShow('b2')" class="drop-down" :class="{ 'reverse': contentShow.b2 }"></i>
-    </div>
-
-    <Transition>
-      <div v-if="contentShow.b2" v-collapse="'scroll'" class="flex-1 pr-1">
-        <div class="title-shade">
-          <span @click="handleCheckShiFei">空域</span>
-          <i class="btn-selectall" :class="{ 'active': checkAll.area }" @click="handleCheckAll('area')"></i>
-          <i class="drop-down" @click="toggleContentShow('b2r1')" :class="{ 'reverse': contentShow.b2r1 }"></i>
-        </div>
-        <Transition>
-          <ul v-if="contentShow.b2r1" v-collapse>
-            <li v-for="item in areaList" class="list-item">
-              <img src="../../../assets/images/page/icon-location.png" alt="">
-              <span>{{ item.name }}</span>
-              <i title="查看" @click="handleCheck(item, 'area')" :class="{ 'active': item.check }"></i>
-              <i title="网格" @click="handleMesh(item, 'area')" :class="{ 'active': item.mesh }"></i>
-              <i title="删除" @click="handleDelete(item, 'area')"></i>
-            </li>
-          </ul>
-        </Transition>
-
-        <div class="title-shade">
-          <span>航线</span>
-          <i class="btn-selectall" :class="{ 'active': checkAll.route }" @click="handleCheckAll('route')"></i>
-          <i class="drop-down" @click="toggleContentShow('b2r2')" :class="{ 'reverse': contentShow.b2r2 }"></i>
-        </div>
-        <Transition>
-          <ul v-if="contentShow.b2r2" v-collapse>
-            <li v-for="item in routeList" class="list-item">
-              <img src="../../../assets/images/page/icon-route.png" alt="">
-              <span>{{ item.name }}</span>
-              <i title="查看" @click="handleCheck(item, 'route')" :class="{ 'active': item.check }"></i>
-              <i title="网格" @click="handleMesh(item, 'route')" :class="{ 'active': item.mesh }"></i>
-              <i title="删除" @click="handleDelete(item, 'route')"></i>
-            </li>
-          </ul>
-        </Transition>
-
-        <div class="title-shade">
-          <span>起降场</span>
-          <i class="btn-selectall" :class="{ 'active': checkAll.plot }" @click="handleCheckAll('plot')"></i>
-          <i class="drop-down" @click="toggleContentShow('b2r3')" :class="{ 'reverse': contentShow.b2r3 }"></i>
-        </div>
-        <Transition>
-          <ul v-if="contentShow.b2r3" v-collapse>
-            <li v-for="item in plotList" class="list-item">
-              <img src="../../../assets/images/page/icon-plot.png" alt="">
-              <span>{{ item.name }}</span>
-              <i title="查看" @click="handleCheck(item, 'plot')" :class="{ 'active': item.check }"></i>
-              <i title="网格" @click="handleMesh(item, 'plot')" :class="{ 'active': item.mesh }"></i>
-              <i title="删除" @click="handleDelete(item, 'plot')"></i>
-            </li>
-          </ul>
-        </Transition>
-      </div>
-    </Transition>
-  </div>
+	<div class="panel-sjwg flex flex-col aside-left-inner">
+		<div class="title-main shrink-0">数据网格可视化</div>
+
+		<div class="title-sub my-4 shrink-0">
+			底板数据
+			<i @click="toggleContentShow('b1')" class="drop-down" :class="{ reverse: contentShow.b1 }"></i>
+		</div>
+
+		<Transition>
+			<ul class="list-base flex flex-wrap shrink-0" v-if="contentShow.b1" v-collapse>
+				<li v-for="item in basicList" class="text-center w-1/4 mb-4 cursor-pointer" @click="handleBaseClick(item)">
+					<img
+						:src="getAssetsFile(`page/${item.active ? item.icon + '-h' : item.icon}.png`)"
+						alt=""
+						class="ml-2 mb-1" />
+					<span class="block text-base ml-2">{{ item.label }}</span>
+				</li>
+			</ul>
+		</Transition>
+
+		<div class="title-sub mb-4 shrink-0">
+			低空要素数据<i @click="toggleContentShow('b2')" class="drop-down" :class="{ reverse: contentShow.b2 }"></i>
+		</div>
+
+		<Transition>
+			<div v-if="contentShow.b2" v-collapse="'scroll'" class="flex-1 pr-1">
+				<div class="title-shade">
+					<span @click="handleCheckShiFei">空域</span>
+					<i class="btn-selectall" :class="{ active: checkAll.area }" @click="handleCheckAll('area')"></i>
+					<i class="drop-down" @click="toggleContentShow('b2r1')" :class="{ reverse: contentShow.b2r1 }"></i>
+				</div>
+				<Transition>
+					<ul v-if="contentShow.b2r1" v-collapse>
+						<li v-for="item in areaList" class="list-item">
+							<img src="../../../assets/images/page/icon-location.png" alt="" />
+							<span>{{ item.name }}</span>
+							<i title="查看" @click="handleCheck(item, 'area')" :class="{ active: item.check }"></i>
+							<i title="网格" @click="handleMesh(item, 'area')" :class="{ active: item.mesh }"></i>
+							<i title="删除" @click="handleDelete(item, 'area')"></i>
+						</li>
+					</ul>
+				</Transition>
+
+				<div class="title-shade">
+					<span>航线</span>
+					<i class="btn-selectall" :class="{ active: checkAll.route }" @click="handleCheckAll('route')"></i>
+					<i class="drop-down" @click="toggleContentShow('b2r2')" :class="{ reverse: contentShow.b2r2 }"></i>
+				</div>
+				<Transition>
+					<ul v-if="contentShow.b2r2" v-collapse>
+						<li v-for="item in routeList" class="list-item">
+							<img src="../../../assets/images/page/icon-route.png" alt="" />
+							<span>{{ item.name }}</span>
+							<i title="查看" @click="handleCheck(item, 'route')" :class="{ active: item.check }"></i>
+							<i title="网格" @click="handleMesh(item, 'route')" :class="{ active: item.mesh }"></i>
+							<i title="删除" @click="handleDelete(item, 'route')"></i>
+						</li>
+					</ul>
+				</Transition>
+
+				<div class="title-shade">
+					<span>起降场</span>
+					<i class="btn-selectall" :class="{ active: checkAll.plot }" @click="handleCheckAll('plot')"></i>
+					<i class="drop-down" @click="toggleContentShow('b2r3')" :class="{ reverse: contentShow.b2r3 }"></i>
+				</div>
+				<Transition>
+					<ul v-if="contentShow.b2r3" v-collapse>
+						<li v-for="item in plotList" class="list-item">
+							<img src="../../../assets/images/page/icon-plot.png" alt="" />
+							<span>{{ item.name }}</span>
+							<i title="查看" @click="handleCheck(item, 'plot')" :class="{ active: item.check }"></i>
+							<i title="网格" @click="handleMesh(item, 'plot')" :class="{ active: item.mesh }"></i>
+							<i title="删除" @click="handleDelete(item, 'plot')"></i>
+						</li>
+					</ul>
+				</Transition>
+			</div>
+		</Transition>
+	</div>
 </template>
 
 <script setup>
-import { getAssetsFile, getData } from '@/utils/require';
-import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue';
-import { showShapes, heatMap, AddSingleLayer, InspectCube } from '@/utils/map/addLayer'
-import { DeleteArea, DeletePlot, DeleteRoute, GetAreaList, GetPlotList, GetRouteList } from '@/service/http'
-import { airSpaceTypes } from '@/utils/options';
-import { hexToRgb } from '@/utils/tools';
-import usePanelStore from '@/store/panel';
 import shifei from '@/data/shifei.json'
+import { DeleteArea, DeletePlot, DeleteRoute, GetAreaList, GetPlotList, GetRouteList } from '@/service/http'
+import useLayoutStore from '@/store/layout'
+import usePanelStore from '@/store/panel'
+import { AddSingleLayer, heatMap, InspectCube, showShapes } from '@/utils/map/addLayer'
+import { airSpaceTypes } from '@/utils/options'
+import { getAssetsFile, getData } from '@/utils/require'
+import { hexToRgb } from '@/utils/tools'
+import { renderShapes } from '@/utils/ueActions'
+import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue'
+
 const panelStore = usePanelStore()
-let shifeiStatus = false;
+const layoutStore = useLayoutStore()
+
+let shifeiStatus = false
+
 onBeforeMount(() => {
-  getLists()
+	getLists()
 })
 
 function showWarning(message) {
-  ElMessage({ offset: 90, type: 'warning', message })
+	ElMessage({ offset: 90, type: 'warning', message })
 }
 
 function getLists() {
-  Promise.all([
-    GetAreaList().then(res => {
-      if (!Array.isArray(res.data.data)) {
-        showWarning('空域列表查询失败')
-        return
-      }
-      areaList.value = res.data.data.map(row => ({
-        ...row,
-        check: false,
-        mesh: false
-      }))
-      contentShow.b2r1 = true
-    }).catch(() => {
-      showWarning('空域列表查询失败')
-    }),
-    GetPlotList().then(res => {
-      if (!Array.isArray(res.data.data)) {
-        showWarning('起降场列表查询失败')
-        return
-      }
-      plotList.value = res.data.data.map(row => ({
-        ...row,
-        check: false,
-        mesh: false
-      }))
-    }).catch(() => {
-      showWarning('起降场列表查询失败')
-    }),
-    GetRouteList().then(res => {
-      if (!Array.isArray(res.data.data)) {
-        showWarning('航线列表查询失败')
-        return
-      }
-      routeList.value = res.data.data.map(row => ({
-        ...row,
-        check: false,
-        mesh: false
-      }))
-    }).catch(() => {
-      showWarning('航线列表查询失败')
-    })
-  ]).finally(() => {
-    // 恢复选中状态
-    handleRestoreChecked()
-  })
+	Promise.all([
+		GetAreaList()
+			.then((res) => {
+				if (!Array.isArray(res.data.data)) {
+					showWarning('空域列表查询失败')
+					return
+				}
+				areaList.value = res.data.data.map((row) => ({
+					...row,
+					check: false,
+					mesh: false,
+				}))
+				contentShow.b2r1 = true
+			})
+			.catch(() => {
+				showWarning('空域列表查询失败')
+			}),
+		GetPlotList()
+			.then((res) => {
+				if (!Array.isArray(res.data.data)) {
+					showWarning('起降场列表查询失败')
+					return
+				}
+				plotList.value = res.data.data.map((row) => ({
+					...row,
+					check: false,
+					mesh: false,
+				}))
+			})
+			.catch(() => {
+				showWarning('起降场列表查询失败')
+			}),
+		GetRouteList()
+			.then((res) => {
+				if (!Array.isArray(res.data.data)) {
+					showWarning('航线列表查询失败')
+					return
+				}
+				routeList.value = res.data.data.map((row) => ({
+					...row,
+					check: false,
+					mesh: false,
+				}))
+			})
+			.catch(() => {
+				showWarning('航线列表查询失败')
+			}),
+	]).finally(() => {
+		// 恢复选中状态
+		handleRestoreChecked()
+	})
 }
 
 const basicList = ref([
-  { label: '白模', alias: '全市白模', icon: 'icon-layer-bm', active: false },
-  { label: '精模', alias: '五角场精模', icon: 'icon-layer-jm', active: false },
-  { label: '道路', alias: ['快速路', '高速公路', '地面道路'], icon: 'icon-layer-dl', active: false },
-  { label: '河流', alias: '全市河流', icon: 'icon-layer-hl', active: false },
-  { label: '人口', alias: '人口', icon: 'icon-layer-rk', active: false },
+	{ label: '白模', alias: '全市白模', icon: 'icon-layer-bm', active: false },
+	{ label: '精模', alias: '五角场精模', icon: 'icon-layer-jm', active: false },
+	{ label: '道路', alias: ['快速路', '高速公路', '地面道路'], icon: 'icon-layer-dl', active: false },
+	{ label: '河流', alias: '全市河流', icon: 'icon-layer-hl', active: false },
+	{ label: '人口', alias: '人口', icon: 'icon-layer-rk', active: false },
 ])
 
 async function handleBaseClick(layer) {
-  layer.active = !layer.active
-  const aliasArr = Array.isArray(layer.alias) ? layer.alias : [layer.alias]
-  const resources = await getData('resources.json')
-  const targetServices = resources.filter(r => aliasArr.some(i => i === r.title))
-  if (targetServices.length === 0) return
-  targetServices.forEach(service => {
-    if (service.type == "feature") {
-      heatMap({
-        ...service,
-        visible: layer.active,
-      })
-    } else {
-      AddSingleLayer({
-        ...service,
-        visible: layer.active,
-        opacity: 1
-      })
-    }
-  })
+	layer.active = !layer.active
+	const aliasArr = Array.isArray(layer.alias) ? layer.alias : [layer.alias]
+	const resources = await getData('resources.json')
+	const targetServices = resources.filter((r) => aliasArr.some((i) => i === r.title))
+	if (targetServices.length === 0) return
+	targetServices.forEach((service) => {
+		if (service.type == 'feature') {
+			heatMap({
+				...service,
+				visible: layer.active,
+			})
+		} else {
+			AddSingleLayer({
+				...service,
+				visible: layer.active,
+				opacity: 1,
+			})
+		}
+	})
 }
 
 const areaList = ref([])
 
 function handleCheck(item, type) {
-  // console.log(item)
-  item.check = !item.check
-  let color
-  switch (type) {
-    case 'area':
-      color = hexToRgb(airSpaceTypes.find(i => i.value === item.spaceType).color, 0.5)
-      break;
-    case 'plot':
-      color = [0, 0, 255, 0.5]
-      break;
-    case 'route':
-      color = [255, 255, 0, 0.5]
-  }
-  const data = [{
-    type: type === 'route' ? item.type : item.geoType,
-    shape: {
-      ...JSON.parse(item.shape),
-      color
-    }
-  }]
-  showShapes({
-    id: item.id,
-    data: item.check ? data : null
-  })
+	// console.log(item)
+	item.check = !item.check
+	let color
+	switch (type) {
+		case 'area':
+			color = hexToRgb(airSpaceTypes.find((i) => i.value === item.spaceType).color, 0.5)
+			break
+		case 'plot':
+			color = [0, 0, 255, 0.5]
+			break
+		case 'route':
+			color = [255, 255, 0, 0.5]
+	}
+	const data = [
+		{
+			type: type === 'route' ? item.type : item.geoType,
+			shape: {
+				...JSON.parse(item.shape),
+				color,
+			},
+		},
+	]
+	if (layoutStore.sceneType === 'gis') {
+		showShapes({
+			id: item.id,
+			data: item.check ? data : null,
+		})
+	} else {
+		renderShapes({
+			id: item.id,
+			data: item.check ? data : null,
+		})
+	}
 }
 
-function handleCheckShiFei(){
-  shifeiStatus = !shifeiStatus;
-  if(shifeiStatus){
-    shifei.forEach((item) =>{
-      showShapes({
-        id:item.attributes.FID,
-        data:[
-          {
-            type: 'polygon',
-            shape:{
-              color:[0,255,0,0.5],
-              height:120,
-              rings:item.geometry.rings
-            }
-          }
-        ]
-      })
-    })
-  }else{
-    shifei.forEach((item) =>{
-      showShapes({
-        id:item.attributes.FID
-      })
-    })
-  }
+function handleCheckShiFei() {
+	shifeiStatus = !shifeiStatus
+	if (shifeiStatus) {
+		shifei.forEach((item) => {
+			showShapes({
+				id: item.attributes.FID,
+				data: [
+					{
+						type: 'polygon',
+						shape: {
+							color: [0, 255, 0, 0.5],
+							height: 120,
+							rings: item.geometry.rings,
+						},
+					},
+				],
+			})
+		})
+	} else {
+		shifei.forEach((item) => {
+			showShapes({
+				id: item.attributes.FID,
+			})
+		})
+	}
 }
 
-
-
 function handleDelete(item, type) {
-  switch (type) {
-    case 'area':
-      DeleteArea(item.id).then(res => {
-        if (res.data.code === 200) {
-          ElMessage.success('删除成功')
-          getLists()
-        }
-      })
-      break;
-    case 'plot':
-      DeletePlot(item.id).then(res => {
-        if (res.data.code === 200) {
-          ElMessage.success('删除成功')
-          getLists()
-        }
-      })
-      break;
-    case 'route':
-      DeleteRoute(item.id).then(res => {
-        if (res.data.code === 200) {
-          ElMessage.success('删除成功')
-          getLists()
-        }
-      })
-  }
+	switch (type) {
+		case 'area':
+			DeleteArea(item.id).then((res) => {
+				if (res.data.code === 200) {
+					ElMessage.success('删除成功')
+					getLists()
+				}
+			})
+			break
+		case 'plot':
+			DeletePlot(item.id).then((res) => {
+				if (res.data.code === 200) {
+					ElMessage.success('删除成功')
+					getLists()
+				}
+			})
+			break
+		case 'route':
+			DeleteRoute(item.id).then((res) => {
+				if (res.data.code === 200) {
+					ElMessage.success('删除成功')
+					getLists()
+				}
+			})
+	}
 }
 
 function handleMesh(item) {
-  item.mesh = !item.mesh
-  InspectCube({
-    id: item.id,
-    show: item.mesh,
-    type: item.geoType || item.type,
-    shape: JSON.parse(item.shape)
-  })
+	item.mesh = !item.mesh
+	InspectCube({
+		id: item.id,
+		show: item.mesh,
+		type: item.geoType || item.type,
+		shape: JSON.parse(item.shape),
+	})
 }
 
 const routeList = ref([])
@@ -276,24 +297,24 @@ const routeList = ref([])
 const plotList = ref([])
 
 const contentShow = reactive({
-  b1: true,
-  b2: true,
-  b2r1: false,
-  b2r2: false,
-  b2r3: false,
+	b1: true,
+	b2: true,
+	b2r1: false,
+	b2r2: false,
+	b2r3: false,
 })
 
 function toggleContentShow(id) {
-  contentShow[id] = !contentShow[id]
-  const subs = ['b2r1', 'b2r2', 'b2r3']
-  subs.forEach(i => {
-    if (contentShow[id] && subs.includes(id) && id !== i) {
-      contentShow[i] = false
-    }
-  })
+	contentShow[id] = !contentShow[id]
+	const subs = ['b2r1', 'b2r2', 'b2r3']
+	subs.forEach((i) => {
+		if (contentShow[id] && subs.includes(id) && id !== i) {
+			contentShow[i] = false
+		}
+	})
 }
 
-function clearAllFeatures() {
+/* function clearAllFeatures() {
   [...areaList.value, ...plotList.value, ...routeList.value].forEach(row => {
     if (row.check) {
       showShapes({
@@ -309,225 +330,224 @@ function clearAllFeatures() {
       })
     }
   })
-}
+} */
 
 const checkAll = reactive({
-  area: false,
-  route: false,
-  plot: false
+	area: false,
+	route: false,
+	plot: false,
 })
 
 function handleCheckAll(type) {
-  checkAll[type] = !checkAll[type]
-  const targetList = type === 'area' ? areaList.value : type === 'route' ? routeList.value : plotList.value
-  targetList.forEach(row => {
-    if (checkAll[type] && !row.check) {
-      handleCheck(row, type)
-    } else if (!checkAll[type] && row.check) {
-      handleCheck(row, type)
-    }
-  })
+	checkAll[type] = !checkAll[type]
+	const targetList = type === 'area' ? areaList.value : type === 'route' ? routeList.value : plotList.value
+	targetList.forEach((row) => {
+		if (checkAll[type] && !row.check) {
+			handleCheck(row, type)
+		} else if (!checkAll[type] && row.check) {
+			handleCheck(row, type)
+		}
+	})
 }
 
 function handleStoreChecked() {
-  panelStore.setSjwg({
-    basicList: basicList.value.map(({ label, active }) => ({ label, active })),
-    checkAll,
-    areaList: areaList.value.map(({ id, check, mesh }) => ({ id, check, mesh })),
-    routeList: routeList.value.map(({ id, check, mesh }) => ({ id, check, mesh })),
-    plotList: plotList.value.map(({ id, check, mesh }) => ({ id, check, mesh })),
-  })
+	panelStore.setSjwg({
+		basicList: basicList.value.map(({ label, active }) => ({ label, active })),
+		checkAll,
+		areaList: areaList.value.map(({ id, check, mesh }) => ({ id, check, mesh })),
+		routeList: routeList.value.map(({ id, check, mesh }) => ({ id, check, mesh })),
+		plotList: plotList.value.map(({ id, check, mesh }) => ({ id, check, mesh })),
+	})
 }
 
 function handleRestoreChecked() {
-  if (!Object.keys(panelStore.sjwg).length) return
-  const temp = panelStore.sjwg
-  basicList.value.forEach(i => {
-    i.active = temp.basicList.find(t => t.label === i.label).active
-  })
-  Object.keys(checkAll).forEach(k => {
-    checkAll[k] = temp.checkAll[k]
-  })
-  areaList.value.forEach(i => {
-    const target = temp.areaList.find(t => t.id === i.id)
-    if (target) {
-      i.check = target.check
-      i.mesh = target.mesh
-    }
-  })
-  routeList.value.forEach(i => {
-    const target = temp.routeList.find(t => t.id === i.id)
-    if (target) {
-      i.check = target.check
-      i.mesh = target.mesh
-    }
-  })
-  plotList.value.forEach(i => {
-    const target = temp.plotList.find(t => t.id === i.id)
-    if (target) {
-      i.check = target.check
-      i.mesh = target.mesh
-    }
-  })
+	if (!Object.keys(panelStore.sjwg).length) return
+	const temp = panelStore.sjwg
+	basicList.value.forEach((i) => {
+		i.active = temp.basicList.find((t) => t.label === i.label).active
+	})
+	Object.keys(checkAll).forEach((k) => {
+		checkAll[k] = temp.checkAll[k]
+	})
+	areaList.value.forEach((i) => {
+		const target = temp.areaList.find((t) => t.id === i.id)
+		if (target) {
+			i.check = target.check
+			i.mesh = target.mesh
+		}
+	})
+	routeList.value.forEach((i) => {
+		const target = temp.routeList.find((t) => t.id === i.id)
+		if (target) {
+			i.check = target.check
+			i.mesh = target.mesh
+		}
+	})
+	plotList.value.forEach((i) => {
+		const target = temp.plotList.find((t) => t.id === i.id)
+		if (target) {
+			i.check = target.check
+			i.mesh = target.mesh
+		}
+	})
 }
 
 onBeforeUnmount(() => {
-  // clearAllFeatures()
-  handleStoreChecked()
+	// clearAllFeatures()
+	handleStoreChecked()
 })
 
 const vCollapse = {
-  beforeMount(el, binding) {
-    el.style.height = '0';
-    el.style.overflow = binding.value === 'scroll' ? 'auto' : 'hidden';
-    el.style.transition = 'height 0.5s ease';
-  },
-  mounted(el) {
-    const naturalHeight = el.scrollHeight;
-    el.style.height = `${naturalHeight}px`;
-  },
-  beforeUnmount(el) {
-    el.style.height = '0';
-  }
+	beforeMount(el, binding) {
+		el.style.height = '0'
+		el.style.overflow = binding.value === 'scroll' ? 'auto' : 'hidden'
+		el.style.transition = 'height 0.5s ease'
+	},
+	mounted(el) {
+		const naturalHeight = el.scrollHeight
+		el.style.height = `${naturalHeight}px`
+	},
+	beforeUnmount(el) {
+		el.style.height = '0'
+	},
 }
 </script>
 
 <style lang="scss" scoped>
 .list-base {
-  li {
-    span {
-      width: 75px;
-    }
-
-    img {
-      width: 75px;
-      height: 77px;
-    }
-  }
+	li {
+		span {
+			width: 75px;
+		}
+
+		img {
+			width: 75px;
+			height: 77px;
+		}
+	}
 }
 
 .drop-down {
-  display: block;
-  width: 20px;
-  height: 20px;
-  margin-left: 10px;
-  background: url('../../../assets/images/buttons/btn-dropdown.png') no-repeat;
-  background-size: 10px 7px;
-  background-position: center;
-  transition: transform 0.3s ease;
-  cursor: pointer;
-
-  &.reverse {
-    transform: rotateZ(180deg);
-  }
+	display: block;
+	width: 20px;
+	height: 20px;
+	margin-left: 10px;
+	background: url('../../../assets/images/buttons/btn-dropdown.png') no-repeat;
+	background-size: 10px 7px;
+	background-position: center;
+	transition: transform 0.3s ease;
+	cursor: pointer;
+
+	&.reverse {
+		transform: rotateZ(180deg);
+	}
 }
 
 .title-shade {
-  position: relative;
-  height: 32px;
-  background: linear-gradient(to right, rgba(101, 131, 190, 1) 0%, rgba(101, 131, 190, 0) 100%);
-  display: flex;
-  align-items: center;
-  padding: 0 16px;
-  margin-bottom: 10px;
-
-  &::before {
-    content: '';
-    position: absolute;
-    left: 0;
-    top: 0;
-    width: 4px;
-    height: 32px;
-    background: #C0D5FF;
-  }
-
-  span {
-    text-shadow: 0px 4px 4px rgba(21, 41, 91, 0.45);
-    margin-right: 10px;
-  }
-
-  .btn-selectall {
-    display: block;
-    width: 26px;
-    height: 26px;
-    background: url('../../../assets/images/buttons/btn-selectall.png');
-    background-size: 100%;
-    background-position: center 1px;
-    cursor: pointer;
-    filter: opacity(0.6);
-
-    &.active {
-      filter: opacity(1) drop-shadow(0 0 5px #379bff);
-      transform: scale(1.1);
-    }
-  }
-
-  .drop-down {
-    margin-left: auto;
-  }
-
+	position: relative;
+	height: 32px;
+	background: linear-gradient(to right, rgba(101, 131, 190, 1) 0%, rgba(101, 131, 190, 0) 100%);
+	display: flex;
+	align-items: center;
+	padding: 0 16px;
+	margin-bottom: 10px;
+
+	&::before {
+		content: '';
+		position: absolute;
+		left: 0;
+		top: 0;
+		width: 4px;
+		height: 32px;
+		background: #c0d5ff;
+	}
+
+	span {
+		text-shadow: 0px 4px 4px rgba(21, 41, 91, 0.45);
+		margin-right: 10px;
+	}
+
+	.btn-selectall {
+		display: block;
+		width: 26px;
+		height: 26px;
+		background: url('../../../assets/images/buttons/btn-selectall.png');
+		background-size: 100%;
+		background-position: center 1px;
+		cursor: pointer;
+		filter: opacity(0.6);
+
+		&.active {
+			filter: opacity(1) drop-shadow(0 0 5px #379bff);
+			transform: scale(1.1);
+		}
+	}
+
+	.drop-down {
+		margin-left: auto;
+	}
 }
 
 .list-item {
-  position: relative;
-  height: 40px;
-  padding: 0 15px;
-  margin: 9px 0;
-  display: flex;
-  align-items: center;
-  background: #4352704d;
-
-  &::before {
-    content: '';
-    position: absolute;
-    left: 0;
-    top: 0;
-    width: 1px;
-    height: 40px;
-    background: #808DC9;
-  }
-
-  &:last-child {
-    margin-bottom: 15px;
-  }
-
-  img {
-    width: 24px;
-    height: 24px;
-    margin-right: 10px;
-  }
-
-  span {
-    flex: 1;
-  }
-
-  i {
-    display: block;
-    width: 34px;
-    height: 34px;
-    margin-left: 5px;
-    cursor: pointer;
-    filter: grayscale(1);
-
-    &.active {
-      filter: grayscale(0);
-    }
-  }
-
-  i:nth-child(3) {
-    background: url('../../../assets/images/buttons/btn-check.png');
-    background-size: cover;
-  }
-
-  i:nth-child(4) {
-    background: url('../../../assets/images/buttons/btn-mesh.png');
-    background-size: cover;
-  }
-
-  i:nth-child(5) {
-    background: url('../../../assets/images/buttons/btn-delete.png');
-    background-size: 40px 40px;
-    background-position: center;
-  }
+	position: relative;
+	height: 40px;
+	padding: 0 15px;
+	margin: 9px 0;
+	display: flex;
+	align-items: center;
+	background: #4352704d;
+
+	&::before {
+		content: '';
+		position: absolute;
+		left: 0;
+		top: 0;
+		width: 1px;
+		height: 40px;
+		background: #808dc9;
+	}
+
+	&:last-child {
+		margin-bottom: 15px;
+	}
+
+	img {
+		width: 24px;
+		height: 24px;
+		margin-right: 10px;
+	}
+
+	span {
+		flex: 1;
+	}
+
+	i {
+		display: block;
+		width: 34px;
+		height: 34px;
+		margin-left: 5px;
+		cursor: pointer;
+		filter: grayscale(1);
+
+		&.active {
+			filter: grayscale(0);
+		}
+	}
+
+	i:nth-child(3) {
+		background: url('../../../assets/images/buttons/btn-check.png');
+		background-size: cover;
+	}
+
+	i:nth-child(4) {
+		background: url('../../../assets/images/buttons/btn-mesh.png');
+		background-size: cover;
+	}
+
+	i:nth-child(5) {
+		background: url('../../../assets/images/buttons/btn-delete.png');
+		background-size: 40px 40px;
+		background-position: center;
+	}
 }
-</style>
+</style>