Commit f80a2a45f25f09cf88f2400a9ebfef25ac04ed3d

Authored by 杨鸣坤
0 parents

chore: 初始化项目

Too many changes to show.

To preserve performance only 20 of 33 files are displayed.

  1 +# Logs
  2 +logs
  3 +*.log
  4 +npm-debug.log*
  5 +yarn-debug.log*
  6 +yarn-error.log*
  7 +pnpm-debug.log*
  8 +lerna-debug.log*
  9 +
  10 +node_modules
  11 +.DS_Store
  12 +dist
  13 +dist-ssr
  14 +coverage
  15 +*.local
  16 +
  17 +# Editor directories and files
  18 +.vscode/*
  19 +!.vscode/extensions.json
  20 +.idea
  21 +*.suo
  22 +*.ntvs*
  23 +*.njsproj
  24 +*.sln
  25 +*.sw?
  26 +
  27 +*.tsbuildinfo
  28 +
  29 +.eslintcache
  30 +
  31 +# Cypress
  32 +/cypress/videos/
  33 +/cypress/screenshots/
  34 +
  35 +# Vitest
  36 +__screenshots__/
  37 +
  38 +# Vite
  39 +*.timestamp-*-*.mjs
  1 +{
  2 + "recommendations": ["Vue.volar"]
  3 +}
  1 +# iot-bridge-ui
  2 +
  3 +This template should help get you started developing with Vue 3 in Vite.
  4 +
  5 +## Recommended IDE Setup
  6 +
  7 +[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
  8 +
  9 +## Recommended Browser Setup
  10 +
  11 +- Chromium-based browsers (Chrome, Edge, Brave, etc.):
  12 + - [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
  13 + - [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters)
  14 +- Firefox:
  15 + - [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
  16 + - [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/)
  17 +
  18 +## Customize configuration
  19 +
  20 +See [Vite Configuration Reference](https://vite.dev/config/).
  21 +
  22 +## Project Setup
  23 +
  24 +```sh
  25 +npm install
  26 +```
  27 +
  28 +### Compile and Hot-Reload for Development
  29 +
  30 +```sh
  31 +npm run dev
  32 +```
  33 +
  34 +### Compile and Minify for Production
  35 +
  36 +```sh
  37 +npm run build
  38 +```
  1 +<!DOCTYPE html>
  2 +<html lang="">
  3 + <head>
  4 + <meta charset="UTF-8">
  5 + <link rel="icon" href="/favicon.ico">
  6 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7 + <title>Vite App</title>
  8 + </head>
  9 + <body>
  10 + <div id="app"></div>
  11 + <script type="module" src="/src/main.js"></script>
  12 + </body>
  13 +</html>
  1 +{
  2 + "compilerOptions": {
  3 + "paths": {
  4 + "@/*": ["./src/*"]
  5 + }
  6 + },
  7 + "exclude": ["node_modules", "dist"]
  8 +}
  1 +{
  2 + "name": "iot-bridge-ui",
  3 + "version": "0.0.0",
  4 + "lockfileVersion": 3,
  5 + "requires": true,
  6 + "packages": {
  7 + "": {
  8 + "name": "iot-bridge-ui",
  9 + "version": "0.0.0",
  10 + "dependencies": {
  11 + "@element-plus/icons-vue": "^2.3.2",
  12 + "element-plus": "^2.13.7",
  13 + "vue": "^3.5.32",
  14 + "vue-router": "^4.6.4"
  15 + },
  16 + "devDependencies": {
  17 + "@vitejs/plugin-vue": "^6.0.6",
  18 + "vite": "^8.0.8",
  19 + "vite-plugin-vue-devtools": "^8.1.1"
  20 + },
  21 + "engines": {
  22 + "node": "^20.19.0 || >=22.12.0"
  23 + }
  24 + },
  25 + "node_modules/@babel/code-frame": {
  26 + "version": "7.29.0",
  27 + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.0.tgz",
  28 + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
  29 + "dev": true,
  30 + "license": "MIT",
  31 + "dependencies": {
  32 + "@babel/helper-validator-identifier": "^7.28.5",
  33 + "js-tokens": "^4.0.0",
  34 + "picocolors": "^1.1.1"
  35 + },
  36 + "engines": {
  37 + "node": ">=6.9.0"
  38 + }
  39 + },
  40 + "node_modules/@babel/compat-data": {
  41 + "version": "7.29.0",
  42 + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.0.tgz",
  43 + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
  44 + "dev": true,
  45 + "license": "MIT",
  46 + "engines": {
  47 + "node": ">=6.9.0"
  48 + }
  49 + },
  50 + "node_modules/@babel/core": {
  51 + "version": "7.29.0",
  52 + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.29.0.tgz",
  53 + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
  54 + "dev": true,
  55 + "license": "MIT",
  56 + "dependencies": {
  57 + "@babel/code-frame": "^7.29.0",
  58 + "@babel/generator": "^7.29.0",
  59 + "@babel/helper-compilation-targets": "^7.28.6",
  60 + "@babel/helper-module-transforms": "^7.28.6",
  61 + "@babel/helpers": "^7.28.6",
  62 + "@babel/parser": "^7.29.0",
  63 + "@babel/template": "^7.28.6",
  64 + "@babel/traverse": "^7.29.0",
  65 + "@babel/types": "^7.29.0",
  66 + "@jridgewell/remapping": "^2.3.5",
  67 + "convert-source-map": "^2.0.0",
  68 + "debug": "^4.1.0",
  69 + "gensync": "^1.0.0-beta.2",
  70 + "json5": "^2.2.3",
  71 + "semver": "^6.3.1"
  72 + },
  73 + "engines": {
  74 + "node": ">=6.9.0"
  75 + },
  76 + "funding": {
  77 + "type": "opencollective",
  78 + "url": "https://opencollective.com/babel"
  79 + }
  80 + },
  81 + "node_modules/@babel/generator": {
  82 + "version": "7.29.1",
  83 + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.1.tgz",
  84 + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
  85 + "dev": true,
  86 + "license": "MIT",
  87 + "dependencies": {
  88 + "@babel/parser": "^7.29.0",
  89 + "@babel/types": "^7.29.0",
  90 + "@jridgewell/gen-mapping": "^0.3.12",
  91 + "@jridgewell/trace-mapping": "^0.3.28",
  92 + "jsesc": "^3.0.2"
  93 + },
  94 + "engines": {
  95 + "node": ">=6.9.0"
  96 + }
  97 + },
  98 + "node_modules/@babel/helper-annotate-as-pure": {
  99 + "version": "7.27.3",
  100 + "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
  101 + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
  102 + "dev": true,
  103 + "license": "MIT",
  104 + "dependencies": {
  105 + "@babel/types": "^7.27.3"
  106 + },
  107 + "engines": {
  108 + "node": ">=6.9.0"
  109 + }
  110 + },
  111 + "node_modules/@babel/helper-compilation-targets": {
  112 + "version": "7.28.6",
  113 + "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
  114 + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
  115 + "dev": true,
  116 + "license": "MIT",
  117 + "dependencies": {
  118 + "@babel/compat-data": "^7.28.6",
  119 + "@babel/helper-validator-option": "^7.27.1",
  120 + "browserslist": "^4.24.0",
  121 + "lru-cache": "^5.1.1",
  122 + "semver": "^6.3.1"
  123 + },
  124 + "engines": {
  125 + "node": ">=6.9.0"
  126 + }
  127 + },
  128 + "node_modules/@babel/helper-create-class-features-plugin": {
  129 + "version": "7.28.6",
  130 + "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz",
  131 + "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==",
  132 + "dev": true,
  133 + "license": "MIT",
  134 + "dependencies": {
  135 + "@babel/helper-annotate-as-pure": "^7.27.3",
  136 + "@babel/helper-member-expression-to-functions": "^7.28.5",
  137 + "@babel/helper-optimise-call-expression": "^7.27.1",
  138 + "@babel/helper-replace-supers": "^7.28.6",
  139 + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
  140 + "@babel/traverse": "^7.28.6",
  141 + "semver": "^6.3.1"
  142 + },
  143 + "engines": {
  144 + "node": ">=6.9.0"
  145 + },
  146 + "peerDependencies": {
  147 + "@babel/core": "^7.0.0"
  148 + }
  149 + },
  150 + "node_modules/@babel/helper-globals": {
  151 + "version": "7.28.0",
  152 + "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
  153 + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
  154 + "dev": true,
  155 + "license": "MIT",
  156 + "engines": {
  157 + "node": ">=6.9.0"
  158 + }
  159 + },
  160 + "node_modules/@babel/helper-member-expression-to-functions": {
  161 + "version": "7.28.5",
  162 + "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz",
  163 + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==",
  164 + "dev": true,
  165 + "license": "MIT",
  166 + "dependencies": {
  167 + "@babel/traverse": "^7.28.5",
  168 + "@babel/types": "^7.28.5"
  169 + },
  170 + "engines": {
  171 + "node": ">=6.9.0"
  172 + }
  173 + },
  174 + "node_modules/@babel/helper-module-imports": {
  175 + "version": "7.28.6",
  176 + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
  177 + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
  178 + "dev": true,
  179 + "license": "MIT",
  180 + "dependencies": {
  181 + "@babel/traverse": "^7.28.6",
  182 + "@babel/types": "^7.28.6"
  183 + },
  184 + "engines": {
  185 + "node": ">=6.9.0"
  186 + }
  187 + },
  188 + "node_modules/@babel/helper-module-transforms": {
  189 + "version": "7.28.6",
  190 + "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
  191 + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
  192 + "dev": true,
  193 + "license": "MIT",
  194 + "dependencies": {
  195 + "@babel/helper-module-imports": "^7.28.6",
  196 + "@babel/helper-validator-identifier": "^7.28.5",
  197 + "@babel/traverse": "^7.28.6"
  198 + },
  199 + "engines": {
  200 + "node": ">=6.9.0"
  201 + },
  202 + "peerDependencies": {
  203 + "@babel/core": "^7.0.0"
  204 + }
  205 + },
  206 + "node_modules/@babel/helper-optimise-call-expression": {
  207 + "version": "7.27.1",
  208 + "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz",
  209 + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==",
  210 + "dev": true,
  211 + "license": "MIT",
  212 + "dependencies": {
  213 + "@babel/types": "^7.27.1"
  214 + },
  215 + "engines": {
  216 + "node": ">=6.9.0"
  217 + }
  218 + },
  219 + "node_modules/@babel/helper-plugin-utils": {
  220 + "version": "7.28.6",
  221 + "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
  222 + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
  223 + "dev": true,
  224 + "license": "MIT",
  225 + "engines": {
  226 + "node": ">=6.9.0"
  227 + }
  228 + },
  229 + "node_modules/@babel/helper-replace-supers": {
  230 + "version": "7.28.6",
  231 + "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz",
  232 + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==",
  233 + "dev": true,
  234 + "license": "MIT",
  235 + "dependencies": {
  236 + "@babel/helper-member-expression-to-functions": "^7.28.5",
  237 + "@babel/helper-optimise-call-expression": "^7.27.1",
  238 + "@babel/traverse": "^7.28.6"
  239 + },
  240 + "engines": {
  241 + "node": ">=6.9.0"
  242 + },
  243 + "peerDependencies": {
  244 + "@babel/core": "^7.0.0"
  245 + }
  246 + },
  247 + "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
  248 + "version": "7.27.1",
  249 + "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz",
  250 + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==",
  251 + "dev": true,
  252 + "license": "MIT",
  253 + "dependencies": {
  254 + "@babel/traverse": "^7.27.1",
  255 + "@babel/types": "^7.27.1"
  256 + },
  257 + "engines": {
  258 + "node": ">=6.9.0"
  259 + }
  260 + },
  261 + "node_modules/@babel/helper-string-parser": {
  262 + "version": "7.27.1",
  263 + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
  264 + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
  265 + "license": "MIT",
  266 + "engines": {
  267 + "node": ">=6.9.0"
  268 + }
  269 + },
  270 + "node_modules/@babel/helper-validator-identifier": {
  271 + "version": "7.28.5",
  272 + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
  273 + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
  274 + "license": "MIT",
  275 + "engines": {
  276 + "node": ">=6.9.0"
  277 + }
  278 + },
  279 + "node_modules/@babel/helper-validator-option": {
  280 + "version": "7.27.1",
  281 + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
  282 + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
  283 + "dev": true,
  284 + "license": "MIT",
  285 + "engines": {
  286 + "node": ">=6.9.0"
  287 + }
  288 + },
  289 + "node_modules/@babel/helpers": {
  290 + "version": "7.29.2",
  291 + "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.29.2.tgz",
  292 + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
  293 + "dev": true,
  294 + "license": "MIT",
  295 + "dependencies": {
  296 + "@babel/template": "^7.28.6",
  297 + "@babel/types": "^7.29.0"
  298 + },
  299 + "engines": {
  300 + "node": ">=6.9.0"
  301 + }
  302 + },
  303 + "node_modules/@babel/parser": {
  304 + "version": "7.29.2",
  305 + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.2.tgz",
  306 + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
  307 + "license": "MIT",
  308 + "dependencies": {
  309 + "@babel/types": "^7.29.0"
  310 + },
  311 + "bin": {
  312 + "parser": "bin/babel-parser.js"
  313 + },
  314 + "engines": {
  315 + "node": ">=6.0.0"
  316 + }
  317 + },
  318 + "node_modules/@babel/plugin-proposal-decorators": {
  319 + "version": "7.29.0",
  320 + "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.0.tgz",
  321 + "integrity": "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==",
  322 + "dev": true,
  323 + "license": "MIT",
  324 + "dependencies": {
  325 + "@babel/helper-create-class-features-plugin": "^7.28.6",
  326 + "@babel/helper-plugin-utils": "^7.28.6",
  327 + "@babel/plugin-syntax-decorators": "^7.28.6"
  328 + },
  329 + "engines": {
  330 + "node": ">=6.9.0"
  331 + },
  332 + "peerDependencies": {
  333 + "@babel/core": "^7.0.0-0"
  334 + }
  335 + },
  336 + "node_modules/@babel/plugin-syntax-decorators": {
  337 + "version": "7.28.6",
  338 + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.28.6.tgz",
  339 + "integrity": "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==",
  340 + "dev": true,
  341 + "license": "MIT",
  342 + "dependencies": {
  343 + "@babel/helper-plugin-utils": "^7.28.6"
  344 + },
  345 + "engines": {
  346 + "node": ">=6.9.0"
  347 + },
  348 + "peerDependencies": {
  349 + "@babel/core": "^7.0.0-0"
  350 + }
  351 + },
  352 + "node_modules/@babel/plugin-syntax-import-attributes": {
  353 + "version": "7.28.6",
  354 + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz",
  355 + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==",
  356 + "dev": true,
  357 + "license": "MIT",
  358 + "dependencies": {
  359 + "@babel/helper-plugin-utils": "^7.28.6"
  360 + },
  361 + "engines": {
  362 + "node": ">=6.9.0"
  363 + },
  364 + "peerDependencies": {
  365 + "@babel/core": "^7.0.0-0"
  366 + }
  367 + },
  368 + "node_modules/@babel/plugin-syntax-import-meta": {
  369 + "version": "7.10.4",
  370 + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
  371 + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
  372 + "dev": true,
  373 + "license": "MIT",
  374 + "dependencies": {
  375 + "@babel/helper-plugin-utils": "^7.10.4"
  376 + },
  377 + "peerDependencies": {
  378 + "@babel/core": "^7.0.0-0"
  379 + }
  380 + },
  381 + "node_modules/@babel/plugin-syntax-jsx": {
  382 + "version": "7.28.6",
  383 + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
  384 + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
  385 + "dev": true,
  386 + "license": "MIT",
  387 + "dependencies": {
  388 + "@babel/helper-plugin-utils": "^7.28.6"
  389 + },
  390 + "engines": {
  391 + "node": ">=6.9.0"
  392 + },
  393 + "peerDependencies": {
  394 + "@babel/core": "^7.0.0-0"
  395 + }
  396 + },
  397 + "node_modules/@babel/plugin-syntax-typescript": {
  398 + "version": "7.28.6",
  399 + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
  400 + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==",
  401 + "dev": true,
  402 + "license": "MIT",
  403 + "dependencies": {
  404 + "@babel/helper-plugin-utils": "^7.28.6"
  405 + },
  406 + "engines": {
  407 + "node": ">=6.9.0"
  408 + },
  409 + "peerDependencies": {
  410 + "@babel/core": "^7.0.0-0"
  411 + }
  412 + },
  413 + "node_modules/@babel/plugin-transform-typescript": {
  414 + "version": "7.28.6",
  415 + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz",
  416 + "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==",
  417 + "dev": true,
  418 + "license": "MIT",
  419 + "dependencies": {
  420 + "@babel/helper-annotate-as-pure": "^7.27.3",
  421 + "@babel/helper-create-class-features-plugin": "^7.28.6",
  422 + "@babel/helper-plugin-utils": "^7.28.6",
  423 + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
  424 + "@babel/plugin-syntax-typescript": "^7.28.6"
  425 + },
  426 + "engines": {
  427 + "node": ">=6.9.0"
  428 + },
  429 + "peerDependencies": {
  430 + "@babel/core": "^7.0.0-0"
  431 + }
  432 + },
  433 + "node_modules/@babel/template": {
  434 + "version": "7.28.6",
  435 + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.28.6.tgz",
  436 + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
  437 + "dev": true,
  438 + "license": "MIT",
  439 + "dependencies": {
  440 + "@babel/code-frame": "^7.28.6",
  441 + "@babel/parser": "^7.28.6",
  442 + "@babel/types": "^7.28.6"
  443 + },
  444 + "engines": {
  445 + "node": ">=6.9.0"
  446 + }
  447 + },
  448 + "node_modules/@babel/traverse": {
  449 + "version": "7.29.0",
  450 + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.0.tgz",
  451 + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
  452 + "dev": true,
  453 + "license": "MIT",
  454 + "dependencies": {
  455 + "@babel/code-frame": "^7.29.0",
  456 + "@babel/generator": "^7.29.0",
  457 + "@babel/helper-globals": "^7.28.0",
  458 + "@babel/parser": "^7.29.0",
  459 + "@babel/template": "^7.28.6",
  460 + "@babel/types": "^7.29.0",
  461 + "debug": "^4.3.1"
  462 + },
  463 + "engines": {
  464 + "node": ">=6.9.0"
  465 + }
  466 + },
  467 + "node_modules/@babel/types": {
  468 + "version": "7.29.0",
  469 + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz",
  470 + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
  471 + "license": "MIT",
  472 + "dependencies": {
  473 + "@babel/helper-string-parser": "^7.27.1",
  474 + "@babel/helper-validator-identifier": "^7.28.5"
  475 + },
  476 + "engines": {
  477 + "node": ">=6.9.0"
  478 + }
  479 + },
  480 + "node_modules/@ctrl/tinycolor": {
  481 + "version": "4.2.0",
  482 + "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz",
  483 + "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==",
  484 + "license": "MIT",
  485 + "engines": {
  486 + "node": ">=14"
  487 + }
  488 + },
  489 + "node_modules/@element-plus/icons-vue": {
  490 + "version": "2.3.2",
  491 + "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
  492 + "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
  493 + "license": "MIT",
  494 + "peerDependencies": {
  495 + "vue": "^3.2.0"
  496 + }
  497 + },
  498 + "node_modules/@emnapi/core": {
  499 + "version": "1.10.0",
  500 + "resolved": "https://registry.npmmirror.com/@emnapi/core/-/core-1.10.0.tgz",
  501 + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
  502 + "dev": true,
  503 + "license": "MIT",
  504 + "optional": true,
  505 + "dependencies": {
  506 + "@emnapi/wasi-threads": "1.2.1",
  507 + "tslib": "^2.4.0"
  508 + }
  509 + },
  510 + "node_modules/@emnapi/runtime": {
  511 + "version": "1.10.0",
  512 + "resolved": "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.10.0.tgz",
  513 + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
  514 + "dev": true,
  515 + "license": "MIT",
  516 + "optional": true,
  517 + "dependencies": {
  518 + "tslib": "^2.4.0"
  519 + }
  520 + },
  521 + "node_modules/@emnapi/wasi-threads": {
  522 + "version": "1.2.1",
  523 + "resolved": "https://registry.npmmirror.com/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
  524 + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
  525 + "dev": true,
  526 + "license": "MIT",
  527 + "optional": true,
  528 + "dependencies": {
  529 + "tslib": "^2.4.0"
  530 + }
  531 + },
  532 + "node_modules/@floating-ui/core": {
  533 + "version": "1.7.5",
  534 + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.5.tgz",
  535 + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
  536 + "license": "MIT",
  537 + "dependencies": {
  538 + "@floating-ui/utils": "^0.2.11"
  539 + }
  540 + },
  541 + "node_modules/@floating-ui/dom": {
  542 + "version": "1.7.6",
  543 + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.6.tgz",
  544 + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
  545 + "license": "MIT",
  546 + "dependencies": {
  547 + "@floating-ui/core": "^1.7.5",
  548 + "@floating-ui/utils": "^0.2.11"
  549 + }
  550 + },
  551 + "node_modules/@floating-ui/utils": {
  552 + "version": "0.2.11",
  553 + "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.11.tgz",
  554 + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
  555 + "license": "MIT"
  556 + },
  557 + "node_modules/@jridgewell/gen-mapping": {
  558 + "version": "0.3.13",
  559 + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
  560 + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
  561 + "dev": true,
  562 + "license": "MIT",
  563 + "dependencies": {
  564 + "@jridgewell/sourcemap-codec": "^1.5.0",
  565 + "@jridgewell/trace-mapping": "^0.3.24"
  566 + }
  567 + },
  568 + "node_modules/@jridgewell/remapping": {
  569 + "version": "2.3.5",
  570 + "resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz",
  571 + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
  572 + "dev": true,
  573 + "license": "MIT",
  574 + "dependencies": {
  575 + "@jridgewell/gen-mapping": "^0.3.5",
  576 + "@jridgewell/trace-mapping": "^0.3.24"
  577 + }
  578 + },
  579 + "node_modules/@jridgewell/resolve-uri": {
  580 + "version": "3.1.2",
  581 + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
  582 + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
  583 + "dev": true,
  584 + "license": "MIT",
  585 + "engines": {
  586 + "node": ">=6.0.0"
  587 + }
  588 + },
  589 + "node_modules/@jridgewell/sourcemap-codec": {
  590 + "version": "1.5.5",
  591 + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
  592 + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
  593 + "license": "MIT"
  594 + },
  595 + "node_modules/@jridgewell/trace-mapping": {
  596 + "version": "0.3.31",
  597 + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
  598 + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
  599 + "dev": true,
  600 + "license": "MIT",
  601 + "dependencies": {
  602 + "@jridgewell/resolve-uri": "^3.1.0",
  603 + "@jridgewell/sourcemap-codec": "^1.4.14"
  604 + }
  605 + },
  606 + "node_modules/@napi-rs/wasm-runtime": {
  607 + "version": "1.1.4",
  608 + "resolved": "https://registry.npmmirror.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
  609 + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
  610 + "dev": true,
  611 + "license": "MIT",
  612 + "optional": true,
  613 + "dependencies": {
  614 + "@tybys/wasm-util": "^0.10.1"
  615 + },
  616 + "funding": {
  617 + "type": "github",
  618 + "url": "https://github.com/sponsors/Brooooooklyn"
  619 + },
  620 + "peerDependencies": {
  621 + "@emnapi/core": "^1.7.1",
  622 + "@emnapi/runtime": "^1.7.1"
  623 + }
  624 + },
  625 + "node_modules/@oxc-project/types": {
  626 + "version": "0.127.0",
  627 + "resolved": "https://registry.npmmirror.com/@oxc-project/types/-/types-0.127.0.tgz",
  628 + "integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==",
  629 + "dev": true,
  630 + "license": "MIT",
  631 + "funding": {
  632 + "url": "https://github.com/sponsors/Boshen"
  633 + }
  634 + },
  635 + "node_modules/@polka/url": {
  636 + "version": "1.0.0-next.29",
  637 + "resolved": "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.29.tgz",
  638 + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
  639 + "dev": true,
  640 + "license": "MIT"
  641 + },
  642 + "node_modules/@popperjs/core": {
  643 + "name": "@sxzz/popperjs-es",
  644 + "version": "2.11.8",
  645 + "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz",
  646 + "integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==",
  647 + "license": "MIT",
  648 + "funding": {
  649 + "type": "opencollective",
  650 + "url": "https://opencollective.com/popperjs"
  651 + }
  652 + },
  653 + "node_modules/@rolldown/binding-android-arm64": {
  654 + "version": "1.0.0-rc.17",
  655 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.17.tgz",
  656 + "integrity": "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==",
  657 + "cpu": [
  658 + "arm64"
  659 + ],
  660 + "dev": true,
  661 + "license": "MIT",
  662 + "optional": true,
  663 + "os": [
  664 + "android"
  665 + ],
  666 + "engines": {
  667 + "node": "^20.19.0 || >=22.12.0"
  668 + }
  669 + },
  670 + "node_modules/@rolldown/binding-darwin-arm64": {
  671 + "version": "1.0.0-rc.17",
  672 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.17.tgz",
  673 + "integrity": "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==",
  674 + "cpu": [
  675 + "arm64"
  676 + ],
  677 + "dev": true,
  678 + "license": "MIT",
  679 + "optional": true,
  680 + "os": [
  681 + "darwin"
  682 + ],
  683 + "engines": {
  684 + "node": "^20.19.0 || >=22.12.0"
  685 + }
  686 + },
  687 + "node_modules/@rolldown/binding-darwin-x64": {
  688 + "version": "1.0.0-rc.17",
  689 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.17.tgz",
  690 + "integrity": "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==",
  691 + "cpu": [
  692 + "x64"
  693 + ],
  694 + "dev": true,
  695 + "license": "MIT",
  696 + "optional": true,
  697 + "os": [
  698 + "darwin"
  699 + ],
  700 + "engines": {
  701 + "node": "^20.19.0 || >=22.12.0"
  702 + }
  703 + },
  704 + "node_modules/@rolldown/binding-freebsd-x64": {
  705 + "version": "1.0.0-rc.17",
  706 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.17.tgz",
  707 + "integrity": "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==",
  708 + "cpu": [
  709 + "x64"
  710 + ],
  711 + "dev": true,
  712 + "license": "MIT",
  713 + "optional": true,
  714 + "os": [
  715 + "freebsd"
  716 + ],
  717 + "engines": {
  718 + "node": "^20.19.0 || >=22.12.0"
  719 + }
  720 + },
  721 + "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
  722 + "version": "1.0.0-rc.17",
  723 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.17.tgz",
  724 + "integrity": "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==",
  725 + "cpu": [
  726 + "arm"
  727 + ],
  728 + "dev": true,
  729 + "license": "MIT",
  730 + "optional": true,
  731 + "os": [
  732 + "linux"
  733 + ],
  734 + "engines": {
  735 + "node": "^20.19.0 || >=22.12.0"
  736 + }
  737 + },
  738 + "node_modules/@rolldown/binding-linux-arm64-gnu": {
  739 + "version": "1.0.0-rc.17",
  740 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.17.tgz",
  741 + "integrity": "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==",
  742 + "cpu": [
  743 + "arm64"
  744 + ],
  745 + "dev": true,
  746 + "license": "MIT",
  747 + "optional": true,
  748 + "os": [
  749 + "linux"
  750 + ],
  751 + "engines": {
  752 + "node": "^20.19.0 || >=22.12.0"
  753 + }
  754 + },
  755 + "node_modules/@rolldown/binding-linux-arm64-musl": {
  756 + "version": "1.0.0-rc.17",
  757 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.17.tgz",
  758 + "integrity": "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==",
  759 + "cpu": [
  760 + "arm64"
  761 + ],
  762 + "dev": true,
  763 + "license": "MIT",
  764 + "optional": true,
  765 + "os": [
  766 + "linux"
  767 + ],
  768 + "engines": {
  769 + "node": "^20.19.0 || >=22.12.0"
  770 + }
  771 + },
  772 + "node_modules/@rolldown/binding-linux-ppc64-gnu": {
  773 + "version": "1.0.0-rc.17",
  774 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.17.tgz",
  775 + "integrity": "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==",
  776 + "cpu": [
  777 + "ppc64"
  778 + ],
  779 + "dev": true,
  780 + "license": "MIT",
  781 + "optional": true,
  782 + "os": [
  783 + "linux"
  784 + ],
  785 + "engines": {
  786 + "node": "^20.19.0 || >=22.12.0"
  787 + }
  788 + },
  789 + "node_modules/@rolldown/binding-linux-s390x-gnu": {
  790 + "version": "1.0.0-rc.17",
  791 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.17.tgz",
  792 + "integrity": "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==",
  793 + "cpu": [
  794 + "s390x"
  795 + ],
  796 + "dev": true,
  797 + "license": "MIT",
  798 + "optional": true,
  799 + "os": [
  800 + "linux"
  801 + ],
  802 + "engines": {
  803 + "node": "^20.19.0 || >=22.12.0"
  804 + }
  805 + },
  806 + "node_modules/@rolldown/binding-linux-x64-gnu": {
  807 + "version": "1.0.0-rc.17",
  808 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.17.tgz",
  809 + "integrity": "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==",
  810 + "cpu": [
  811 + "x64"
  812 + ],
  813 + "dev": true,
  814 + "license": "MIT",
  815 + "optional": true,
  816 + "os": [
  817 + "linux"
  818 + ],
  819 + "engines": {
  820 + "node": "^20.19.0 || >=22.12.0"
  821 + }
  822 + },
  823 + "node_modules/@rolldown/binding-linux-x64-musl": {
  824 + "version": "1.0.0-rc.17",
  825 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.17.tgz",
  826 + "integrity": "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==",
  827 + "cpu": [
  828 + "x64"
  829 + ],
  830 + "dev": true,
  831 + "license": "MIT",
  832 + "optional": true,
  833 + "os": [
  834 + "linux"
  835 + ],
  836 + "engines": {
  837 + "node": "^20.19.0 || >=22.12.0"
  838 + }
  839 + },
  840 + "node_modules/@rolldown/binding-openharmony-arm64": {
  841 + "version": "1.0.0-rc.17",
  842 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.17.tgz",
  843 + "integrity": "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==",
  844 + "cpu": [
  845 + "arm64"
  846 + ],
  847 + "dev": true,
  848 + "license": "MIT",
  849 + "optional": true,
  850 + "os": [
  851 + "openharmony"
  852 + ],
  853 + "engines": {
  854 + "node": "^20.19.0 || >=22.12.0"
  855 + }
  856 + },
  857 + "node_modules/@rolldown/binding-wasm32-wasi": {
  858 + "version": "1.0.0-rc.17",
  859 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.17.tgz",
  860 + "integrity": "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==",
  861 + "cpu": [
  862 + "wasm32"
  863 + ],
  864 + "dev": true,
  865 + "license": "MIT",
  866 + "optional": true,
  867 + "dependencies": {
  868 + "@emnapi/core": "1.10.0",
  869 + "@emnapi/runtime": "1.10.0",
  870 + "@napi-rs/wasm-runtime": "^1.1.4"
  871 + },
  872 + "engines": {
  873 + "node": "^20.19.0 || >=22.12.0"
  874 + }
  875 + },
  876 + "node_modules/@rolldown/binding-win32-arm64-msvc": {
  877 + "version": "1.0.0-rc.17",
  878 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.17.tgz",
  879 + "integrity": "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==",
  880 + "cpu": [
  881 + "arm64"
  882 + ],
  883 + "dev": true,
  884 + "license": "MIT",
  885 + "optional": true,
  886 + "os": [
  887 + "win32"
  888 + ],
  889 + "engines": {
  890 + "node": "^20.19.0 || >=22.12.0"
  891 + }
  892 + },
  893 + "node_modules/@rolldown/binding-win32-x64-msvc": {
  894 + "version": "1.0.0-rc.17",
  895 + "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.17.tgz",
  896 + "integrity": "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==",
  897 + "cpu": [
  898 + "x64"
  899 + ],
  900 + "dev": true,
  901 + "license": "MIT",
  902 + "optional": true,
  903 + "os": [
  904 + "win32"
  905 + ],
  906 + "engines": {
  907 + "node": "^20.19.0 || >=22.12.0"
  908 + }
  909 + },
  910 + "node_modules/@rolldown/pluginutils": {
  911 + "version": "1.0.0-rc.13",
  912 + "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.13.tgz",
  913 + "integrity": "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==",
  914 + "dev": true,
  915 + "license": "MIT"
  916 + },
  917 + "node_modules/@tybys/wasm-util": {
  918 + "version": "0.10.1",
  919 + "resolved": "https://registry.npmmirror.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
  920 + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
  921 + "dev": true,
  922 + "license": "MIT",
  923 + "optional": true,
  924 + "dependencies": {
  925 + "tslib": "^2.4.0"
  926 + }
  927 + },
  928 + "node_modules/@types/lodash": {
  929 + "version": "4.17.24",
  930 + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz",
  931 + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
  932 + "license": "MIT"
  933 + },
  934 + "node_modules/@types/lodash-es": {
  935 + "version": "4.17.12",
  936 + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
  937 + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
  938 + "license": "MIT",
  939 + "dependencies": {
  940 + "@types/lodash": "*"
  941 + }
  942 + },
  943 + "node_modules/@types/web-bluetooth": {
  944 + "version": "0.0.20",
  945 + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
  946 + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
  947 + "license": "MIT"
  948 + },
  949 + "node_modules/@vitejs/plugin-vue": {
  950 + "version": "6.0.6",
  951 + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-6.0.6.tgz",
  952 + "integrity": "sha512-u9HHgfrq3AjXlysn0eINFnWQOJQLO9WN6VprZ8FXl7A2bYisv3Hui9Ij+7QZ41F/WYWarHjwBbXtD7dKg3uxbg==",
  953 + "dev": true,
  954 + "license": "MIT",
  955 + "dependencies": {
  956 + "@rolldown/pluginutils": "1.0.0-rc.13"
  957 + },
  958 + "engines": {
  959 + "node": "^20.19.0 || >=22.12.0"
  960 + },
  961 + "peerDependencies": {
  962 + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
  963 + "vue": "^3.2.25"
  964 + }
  965 + },
  966 + "node_modules/@vue/babel-helper-vue-transform-on": {
  967 + "version": "1.5.0",
  968 + "resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz",
  969 + "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==",
  970 + "dev": true,
  971 + "license": "MIT"
  972 + },
  973 + "node_modules/@vue/babel-plugin-jsx": {
  974 + "version": "1.5.0",
  975 + "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz",
  976 + "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==",
  977 + "dev": true,
  978 + "license": "MIT",
  979 + "dependencies": {
  980 + "@babel/helper-module-imports": "^7.27.1",
  981 + "@babel/helper-plugin-utils": "^7.27.1",
  982 + "@babel/plugin-syntax-jsx": "^7.27.1",
  983 + "@babel/template": "^7.27.2",
  984 + "@babel/traverse": "^7.28.0",
  985 + "@babel/types": "^7.28.2",
  986 + "@vue/babel-helper-vue-transform-on": "1.5.0",
  987 + "@vue/babel-plugin-resolve-type": "1.5.0",
  988 + "@vue/shared": "^3.5.18"
  989 + },
  990 + "peerDependencies": {
  991 + "@babel/core": "^7.0.0-0"
  992 + },
  993 + "peerDependenciesMeta": {
  994 + "@babel/core": {
  995 + "optional": true
  996 + }
  997 + }
  998 + },
  999 + "node_modules/@vue/babel-plugin-resolve-type": {
  1000 + "version": "1.5.0",
  1001 + "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz",
  1002 + "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==",
  1003 + "dev": true,
  1004 + "license": "MIT",
  1005 + "dependencies": {
  1006 + "@babel/code-frame": "^7.27.1",
  1007 + "@babel/helper-module-imports": "^7.27.1",
  1008 + "@babel/helper-plugin-utils": "^7.27.1",
  1009 + "@babel/parser": "^7.28.0",
  1010 + "@vue/compiler-sfc": "^3.5.18"
  1011 + },
  1012 + "funding": {
  1013 + "url": "https://github.com/sponsors/sxzz"
  1014 + },
  1015 + "peerDependencies": {
  1016 + "@babel/core": "^7.0.0-0"
  1017 + }
  1018 + },
  1019 + "node_modules/@vue/compiler-core": {
  1020 + "version": "3.5.33",
  1021 + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.33.tgz",
  1022 + "integrity": "sha512-3PZLQwFw4Za3TC8t0FvTy3wI16Kt+pmwcgNZca4Pj9iWL2E72a/gZlpBtAJvEdDMdCxdG/qq0C7PN0bsJuv0Rw==",
  1023 + "license": "MIT",
  1024 + "dependencies": {
  1025 + "@babel/parser": "^7.29.2",
  1026 + "@vue/shared": "3.5.33",
  1027 + "entities": "^7.0.1",
  1028 + "estree-walker": "^2.0.2",
  1029 + "source-map-js": "^1.2.1"
  1030 + }
  1031 + },
  1032 + "node_modules/@vue/compiler-dom": {
  1033 + "version": "3.5.33",
  1034 + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.33.tgz",
  1035 + "integrity": "sha512-PXq0yrfCLzzL07rbXO4awtXY1Z06LG2eu6Adg3RJFa/j3Cii217XxxLXG22N330gw7GmALCY0Z8RgXEviwgpjA==",
  1036 + "license": "MIT",
  1037 + "dependencies": {
  1038 + "@vue/compiler-core": "3.5.33",
  1039 + "@vue/shared": "3.5.33"
  1040 + }
  1041 + },
  1042 + "node_modules/@vue/compiler-sfc": {
  1043 + "version": "3.5.33",
  1044 + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.33.tgz",
  1045 + "integrity": "sha512-UTUvRO9cY+rROrx/pvN9P5Z7FgA6QGfokUCfhQE4EnmUj3rVnK+CHI0LsEO1pg+I7//iRYMUfcNcCPe7tg0CoA==",
  1046 + "license": "MIT",
  1047 + "dependencies": {
  1048 + "@babel/parser": "^7.29.2",
  1049 + "@vue/compiler-core": "3.5.33",
  1050 + "@vue/compiler-dom": "3.5.33",
  1051 + "@vue/compiler-ssr": "3.5.33",
  1052 + "@vue/shared": "3.5.33",
  1053 + "estree-walker": "^2.0.2",
  1054 + "magic-string": "^0.30.21",
  1055 + "postcss": "^8.5.10",
  1056 + "source-map-js": "^1.2.1"
  1057 + }
  1058 + },
  1059 + "node_modules/@vue/compiler-ssr": {
  1060 + "version": "3.5.33",
  1061 + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.33.tgz",
  1062 + "integrity": "sha512-IErjYdnj1qIupG5xxiVIYiiRvDhGWV4zuh/RCrwfYpuL+HWQzeU6lCk/nF9r7olWMnjKxCAkOctT2qFWFkzb1A==",
  1063 + "license": "MIT",
  1064 + "dependencies": {
  1065 + "@vue/compiler-dom": "3.5.33",
  1066 + "@vue/shared": "3.5.33"
  1067 + }
  1068 + },
  1069 + "node_modules/@vue/devtools-api": {
  1070 + "version": "6.6.4",
  1071 + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
  1072 + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
  1073 + "license": "MIT"
  1074 + },
  1075 + "node_modules/@vue/devtools-core": {
  1076 + "version": "8.1.1",
  1077 + "resolved": "https://registry.npmmirror.com/@vue/devtools-core/-/devtools-core-8.1.1.tgz",
  1078 + "integrity": "sha512-bCCsSABp1/ot4j8xJEycM6Mtt2wbuucfByr6hMgjbYhrtlscOJypZKvy8f1FyWLYrLTchB5Qz216Lm92wfbq0A==",
  1079 + "dev": true,
  1080 + "license": "MIT",
  1081 + "dependencies": {
  1082 + "@vue/devtools-kit": "^8.1.1",
  1083 + "@vue/devtools-shared": "^8.1.1"
  1084 + },
  1085 + "peerDependencies": {
  1086 + "vue": "^3.0.0"
  1087 + }
  1088 + },
  1089 + "node_modules/@vue/devtools-kit": {
  1090 + "version": "8.1.1",
  1091 + "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-8.1.1.tgz",
  1092 + "integrity": "sha512-gVBaBv++i+adg4JpH71k9ppl4soyR7Y2McEqO5YNgv0BI1kMZ7BDX5gnwkZ5COYgiCyhejZG+yGNrBAjj6Coqg==",
  1093 + "dev": true,
  1094 + "license": "MIT",
  1095 + "dependencies": {
  1096 + "@vue/devtools-shared": "^8.1.1",
  1097 + "birpc": "^2.6.1",
  1098 + "hookable": "^5.5.3",
  1099 + "perfect-debounce": "^2.0.0"
  1100 + }
  1101 + },
  1102 + "node_modules/@vue/devtools-shared": {
  1103 + "version": "8.1.1",
  1104 + "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-8.1.1.tgz",
  1105 + "integrity": "sha512-+h4ttmJYl/txpxHKaoZcaKpC+pvckgLzIDiSQlaQ7kKthKh8KuwoLW2D8hPJEnqKzXOvu15UHEoGyngAXCz0EQ==",
  1106 + "dev": true,
  1107 + "license": "MIT"
  1108 + },
  1109 + "node_modules/@vue/reactivity": {
  1110 + "version": "3.5.33",
  1111 + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.33.tgz",
  1112 + "integrity": "sha512-p8UfIqyIhb0rYGlSgSBV+lPhF2iUSBcRy7enhTmPqKWadHy9kcOFYF1AejYBP9P+avnd3OBbD49DU4pLWX/94A==",
  1113 + "license": "MIT",
  1114 + "dependencies": {
  1115 + "@vue/shared": "3.5.33"
  1116 + }
  1117 + },
  1118 + "node_modules/@vue/runtime-core": {
  1119 + "version": "3.5.33",
  1120 + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.33.tgz",
  1121 + "integrity": "sha512-UpFF45RI9//a7rvq7RdOQblb4tup7hHG9QsmIrxkFQLzQ7R8/iNQ5LE15NhLZ1/WcHMU2b47u6P33CPUelHyIQ==",
  1122 + "license": "MIT",
  1123 + "dependencies": {
  1124 + "@vue/reactivity": "3.5.33",
  1125 + "@vue/shared": "3.5.33"
  1126 + }
  1127 + },
  1128 + "node_modules/@vue/runtime-dom": {
  1129 + "version": "3.5.33",
  1130 + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.33.tgz",
  1131 + "integrity": "sha512-IOxMsAOwquhfITgmOgaPYl7/j8gKUxUFoflRc+u4LxyD3+783xne8vNta1PONVCvCV9A0w7hkyEepINDqfO0tw==",
  1132 + "license": "MIT",
  1133 + "dependencies": {
  1134 + "@vue/reactivity": "3.5.33",
  1135 + "@vue/runtime-core": "3.5.33",
  1136 + "@vue/shared": "3.5.33",
  1137 + "csstype": "^3.2.3"
  1138 + }
  1139 + },
  1140 + "node_modules/@vue/server-renderer": {
  1141 + "version": "3.5.33",
  1142 + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.33.tgz",
  1143 + "integrity": "sha512-0xylq/8/h44lVG0pZFknv1XIdEgymq2E9n59uTWJBG+dIgiT0TMCSsxrN7nO16Z0MU0MPjFcguBbZV8Itk52Hw==",
  1144 + "license": "MIT",
  1145 + "dependencies": {
  1146 + "@vue/compiler-ssr": "3.5.33",
  1147 + "@vue/shared": "3.5.33"
  1148 + },
  1149 + "peerDependencies": {
  1150 + "vue": "3.5.33"
  1151 + }
  1152 + },
  1153 + "node_modules/@vue/shared": {
  1154 + "version": "3.5.33",
  1155 + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.33.tgz",
  1156 + "integrity": "sha512-5vR2QIlmaLG77Ygd4pMP6+SGQ5yox9VhtnbDWTy9DzMzdmeLxZ1QqxrywEZ9sa1AVubfIJyaCG3ytyWU81ufcQ==",
  1157 + "license": "MIT"
  1158 + },
  1159 + "node_modules/@vueuse/core": {
  1160 + "version": "12.0.0",
  1161 + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-12.0.0.tgz",
  1162 + "integrity": "sha512-C12RukhXiJCbx4MGhjmd/gH52TjJsc3G0E0kQj/kb19H3Nt6n1CA4DRWuTdWWcaFRdlTe0npWDS942mvacvNBw==",
  1163 + "license": "MIT",
  1164 + "dependencies": {
  1165 + "@types/web-bluetooth": "^0.0.20",
  1166 + "@vueuse/metadata": "12.0.0",
  1167 + "@vueuse/shared": "12.0.0",
  1168 + "vue": "^3.5.13"
  1169 + },
  1170 + "funding": {
  1171 + "url": "https://github.com/sponsors/antfu"
  1172 + }
  1173 + },
  1174 + "node_modules/@vueuse/metadata": {
  1175 + "version": "12.0.0",
  1176 + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-12.0.0.tgz",
  1177 + "integrity": "sha512-Yzimd1D3sjxTDOlF05HekU5aSGdKjxhuhRFHA7gDWLn57PRbBIh+SF5NmjhJ0WRgF3my7T8LBucyxdFJjIfRJQ==",
  1178 + "license": "MIT",
  1179 + "funding": {
  1180 + "url": "https://github.com/sponsors/antfu"
  1181 + }
  1182 + },
  1183 + "node_modules/@vueuse/shared": {
  1184 + "version": "12.0.0",
  1185 + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-12.0.0.tgz",
  1186 + "integrity": "sha512-3i6qtcq2PIio5i/vVYidkkcgvmTjCqrf26u+Fd4LhnbBmIT6FN8y6q/GJERp8lfcB9zVEfjdV0Br0443qZuJpw==",
  1187 + "license": "MIT",
  1188 + "dependencies": {
  1189 + "vue": "^3.5.13"
  1190 + },
  1191 + "funding": {
  1192 + "url": "https://github.com/sponsors/antfu"
  1193 + }
  1194 + },
  1195 + "node_modules/ansis": {
  1196 + "version": "4.2.0",
  1197 + "resolved": "https://registry.npmmirror.com/ansis/-/ansis-4.2.0.tgz",
  1198 + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==",
  1199 + "dev": true,
  1200 + "license": "ISC",
  1201 + "engines": {
  1202 + "node": ">=14"
  1203 + }
  1204 + },
  1205 + "node_modules/async-validator": {
  1206 + "version": "4.2.5",
  1207 + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
  1208 + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
  1209 + "license": "MIT"
  1210 + },
  1211 + "node_modules/baseline-browser-mapping": {
  1212 + "version": "2.10.23",
  1213 + "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.23.tgz",
  1214 + "integrity": "sha512-xwVXGqevyKPsiuQdLj+dZMVjidjJV508TBqexND5HrF89cGdCYCJFB3qhcxRHSeMctdCfbR1jrxBajhDy7o29g==",
  1215 + "dev": true,
  1216 + "license": "Apache-2.0",
  1217 + "bin": {
  1218 + "baseline-browser-mapping": "dist/cli.cjs"
  1219 + },
  1220 + "engines": {
  1221 + "node": ">=6.0.0"
  1222 + }
  1223 + },
  1224 + "node_modules/birpc": {
  1225 + "version": "2.9.0",
  1226 + "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.9.0.tgz",
  1227 + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==",
  1228 + "dev": true,
  1229 + "license": "MIT",
  1230 + "funding": {
  1231 + "url": "https://github.com/sponsors/antfu"
  1232 + }
  1233 + },
  1234 + "node_modules/browserslist": {
  1235 + "version": "4.28.2",
  1236 + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.2.tgz",
  1237 + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
  1238 + "dev": true,
  1239 + "funding": [
  1240 + {
  1241 + "type": "opencollective",
  1242 + "url": "https://opencollective.com/browserslist"
  1243 + },
  1244 + {
  1245 + "type": "tidelift",
  1246 + "url": "https://tidelift.com/funding/github/npm/browserslist"
  1247 + },
  1248 + {
  1249 + "type": "github",
  1250 + "url": "https://github.com/sponsors/ai"
  1251 + }
  1252 + ],
  1253 + "license": "MIT",
  1254 + "dependencies": {
  1255 + "baseline-browser-mapping": "^2.10.12",
  1256 + "caniuse-lite": "^1.0.30001782",
  1257 + "electron-to-chromium": "^1.5.328",
  1258 + "node-releases": "^2.0.36",
  1259 + "update-browserslist-db": "^1.2.3"
  1260 + },
  1261 + "bin": {
  1262 + "browserslist": "cli.js"
  1263 + },
  1264 + "engines": {
  1265 + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
  1266 + }
  1267 + },
  1268 + "node_modules/bundle-name": {
  1269 + "version": "4.1.0",
  1270 + "resolved": "https://registry.npmmirror.com/bundle-name/-/bundle-name-4.1.0.tgz",
  1271 + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
  1272 + "dev": true,
  1273 + "license": "MIT",
  1274 + "dependencies": {
  1275 + "run-applescript": "^7.0.0"
  1276 + },
  1277 + "engines": {
  1278 + "node": ">=18"
  1279 + },
  1280 + "funding": {
  1281 + "url": "https://github.com/sponsors/sindresorhus"
  1282 + }
  1283 + },
  1284 + "node_modules/caniuse-lite": {
  1285 + "version": "1.0.30001791",
  1286 + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001791.tgz",
  1287 + "integrity": "sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==",
  1288 + "dev": true,
  1289 + "funding": [
  1290 + {
  1291 + "type": "opencollective",
  1292 + "url": "https://opencollective.com/browserslist"
  1293 + },
  1294 + {
  1295 + "type": "tidelift",
  1296 + "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
  1297 + },
  1298 + {
  1299 + "type": "github",
  1300 + "url": "https://github.com/sponsors/ai"
  1301 + }
  1302 + ],
  1303 + "license": "CC-BY-4.0"
  1304 + },
  1305 + "node_modules/convert-source-map": {
  1306 + "version": "2.0.0",
  1307 + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz",
  1308 + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
  1309 + "dev": true,
  1310 + "license": "MIT"
  1311 + },
  1312 + "node_modules/csstype": {
  1313 + "version": "3.2.3",
  1314 + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
  1315 + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
  1316 + "license": "MIT"
  1317 + },
  1318 + "node_modules/dayjs": {
  1319 + "version": "1.11.20",
  1320 + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.20.tgz",
  1321 + "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==",
  1322 + "license": "MIT"
  1323 + },
  1324 + "node_modules/debug": {
  1325 + "version": "4.4.3",
  1326 + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
  1327 + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
  1328 + "dev": true,
  1329 + "license": "MIT",
  1330 + "dependencies": {
  1331 + "ms": "^2.1.3"
  1332 + },
  1333 + "engines": {
  1334 + "node": ">=6.0"
  1335 + },
  1336 + "peerDependenciesMeta": {
  1337 + "supports-color": {
  1338 + "optional": true
  1339 + }
  1340 + }
  1341 + },
  1342 + "node_modules/default-browser": {
  1343 + "version": "5.5.0",
  1344 + "resolved": "https://registry.npmmirror.com/default-browser/-/default-browser-5.5.0.tgz",
  1345 + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==",
  1346 + "dev": true,
  1347 + "license": "MIT",
  1348 + "dependencies": {
  1349 + "bundle-name": "^4.1.0",
  1350 + "default-browser-id": "^5.0.0"
  1351 + },
  1352 + "engines": {
  1353 + "node": ">=18"
  1354 + },
  1355 + "funding": {
  1356 + "url": "https://github.com/sponsors/sindresorhus"
  1357 + }
  1358 + },
  1359 + "node_modules/default-browser-id": {
  1360 + "version": "5.0.1",
  1361 + "resolved": "https://registry.npmmirror.com/default-browser-id/-/default-browser-id-5.0.1.tgz",
  1362 + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==",
  1363 + "dev": true,
  1364 + "license": "MIT",
  1365 + "engines": {
  1366 + "node": ">=18"
  1367 + },
  1368 + "funding": {
  1369 + "url": "https://github.com/sponsors/sindresorhus"
  1370 + }
  1371 + },
  1372 + "node_modules/define-lazy-prop": {
  1373 + "version": "3.0.0",
  1374 + "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
  1375 + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
  1376 + "dev": true,
  1377 + "license": "MIT",
  1378 + "engines": {
  1379 + "node": ">=12"
  1380 + },
  1381 + "funding": {
  1382 + "url": "https://github.com/sponsors/sindresorhus"
  1383 + }
  1384 + },
  1385 + "node_modules/detect-libc": {
  1386 + "version": "2.1.2",
  1387 + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz",
  1388 + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
  1389 + "dev": true,
  1390 + "license": "Apache-2.0",
  1391 + "engines": {
  1392 + "node": ">=8"
  1393 + }
  1394 + },
  1395 + "node_modules/electron-to-chromium": {
  1396 + "version": "1.5.344",
  1397 + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz",
  1398 + "integrity": "sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg==",
  1399 + "dev": true,
  1400 + "license": "ISC"
  1401 + },
  1402 + "node_modules/element-plus": {
  1403 + "version": "2.13.7",
  1404 + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.13.7.tgz",
  1405 + "integrity": "sha512-XdHATFZOyzVFL1DaHQ90IOJQSg9UnSAV+bhDW+YB5UoZ0Hxs50mwqjqfwXkuwpSag+VXXizVcErBR6Movo5daw==",
  1406 + "license": "MIT",
  1407 + "dependencies": {
  1408 + "@ctrl/tinycolor": "^4.2.0",
  1409 + "@element-plus/icons-vue": "^2.3.2",
  1410 + "@floating-ui/dom": "^1.0.1",
  1411 + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
  1412 + "@types/lodash": "^4.17.20",
  1413 + "@types/lodash-es": "^4.17.12",
  1414 + "@vueuse/core": "12.0.0",
  1415 + "async-validator": "^4.2.5",
  1416 + "dayjs": "^1.11.19",
  1417 + "lodash": "^4.17.23",
  1418 + "lodash-es": "^4.17.23",
  1419 + "lodash-unified": "^1.0.3",
  1420 + "memoize-one": "^6.0.0",
  1421 + "normalize-wheel-es": "^1.2.0",
  1422 + "vue-component-type-helpers": "^3.2.4"
  1423 + },
  1424 + "peerDependencies": {
  1425 + "vue": "^3.3.0"
  1426 + }
  1427 + },
  1428 + "node_modules/entities": {
  1429 + "version": "7.0.1",
  1430 + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz",
  1431 + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
  1432 + "license": "BSD-2-Clause",
  1433 + "engines": {
  1434 + "node": ">=0.12"
  1435 + },
  1436 + "funding": {
  1437 + "url": "https://github.com/fb55/entities?sponsor=1"
  1438 + }
  1439 + },
  1440 + "node_modules/error-stack-parser-es": {
  1441 + "version": "1.0.5",
  1442 + "resolved": "https://registry.npmmirror.com/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz",
  1443 + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==",
  1444 + "dev": true,
  1445 + "license": "MIT",
  1446 + "funding": {
  1447 + "url": "https://github.com/sponsors/antfu"
  1448 + }
  1449 + },
  1450 + "node_modules/escalade": {
  1451 + "version": "3.2.0",
  1452 + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
  1453 + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
  1454 + "dev": true,
  1455 + "license": "MIT",
  1456 + "engines": {
  1457 + "node": ">=6"
  1458 + }
  1459 + },
  1460 + "node_modules/estree-walker": {
  1461 + "version": "2.0.2",
  1462 + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
  1463 + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
  1464 + "license": "MIT"
  1465 + },
  1466 + "node_modules/fdir": {
  1467 + "version": "6.5.0",
  1468 + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
  1469 + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
  1470 + "dev": true,
  1471 + "license": "MIT",
  1472 + "engines": {
  1473 + "node": ">=12.0.0"
  1474 + },
  1475 + "peerDependencies": {
  1476 + "picomatch": "^3 || ^4"
  1477 + },
  1478 + "peerDependenciesMeta": {
  1479 + "picomatch": {
  1480 + "optional": true
  1481 + }
  1482 + }
  1483 + },
  1484 + "node_modules/fsevents": {
  1485 + "version": "2.3.3",
  1486 + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
  1487 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
  1488 + "dev": true,
  1489 + "hasInstallScript": true,
  1490 + "license": "MIT",
  1491 + "optional": true,
  1492 + "os": [
  1493 + "darwin"
  1494 + ],
  1495 + "engines": {
  1496 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
  1497 + }
  1498 + },
  1499 + "node_modules/gensync": {
  1500 + "version": "1.0.0-beta.2",
  1501 + "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
  1502 + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
  1503 + "dev": true,
  1504 + "license": "MIT",
  1505 + "engines": {
  1506 + "node": ">=6.9.0"
  1507 + }
  1508 + },
  1509 + "node_modules/hookable": {
  1510 + "version": "5.5.3",
  1511 + "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
  1512 + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
  1513 + "dev": true,
  1514 + "license": "MIT"
  1515 + },
  1516 + "node_modules/is-docker": {
  1517 + "version": "3.0.0",
  1518 + "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz",
  1519 + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
  1520 + "dev": true,
  1521 + "license": "MIT",
  1522 + "bin": {
  1523 + "is-docker": "cli.js"
  1524 + },
  1525 + "engines": {
  1526 + "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
  1527 + },
  1528 + "funding": {
  1529 + "url": "https://github.com/sponsors/sindresorhus"
  1530 + }
  1531 + },
  1532 + "node_modules/is-inside-container": {
  1533 + "version": "1.0.0",
  1534 + "resolved": "https://registry.npmmirror.com/is-inside-container/-/is-inside-container-1.0.0.tgz",
  1535 + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
  1536 + "dev": true,
  1537 + "license": "MIT",
  1538 + "dependencies": {
  1539 + "is-docker": "^3.0.0"
  1540 + },
  1541 + "bin": {
  1542 + "is-inside-container": "cli.js"
  1543 + },
  1544 + "engines": {
  1545 + "node": ">=14.16"
  1546 + },
  1547 + "funding": {
  1548 + "url": "https://github.com/sponsors/sindresorhus"
  1549 + }
  1550 + },
  1551 + "node_modules/is-wsl": {
  1552 + "version": "3.1.1",
  1553 + "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-3.1.1.tgz",
  1554 + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==",
  1555 + "dev": true,
  1556 + "license": "MIT",
  1557 + "dependencies": {
  1558 + "is-inside-container": "^1.0.0"
  1559 + },
  1560 + "engines": {
  1561 + "node": ">=16"
  1562 + },
  1563 + "funding": {
  1564 + "url": "https://github.com/sponsors/sindresorhus"
  1565 + }
  1566 + },
  1567 + "node_modules/js-tokens": {
  1568 + "version": "4.0.0",
  1569 + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
  1570 + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
  1571 + "dev": true,
  1572 + "license": "MIT"
  1573 + },
  1574 + "node_modules/jsesc": {
  1575 + "version": "3.1.0",
  1576 + "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz",
  1577 + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
  1578 + "dev": true,
  1579 + "license": "MIT",
  1580 + "bin": {
  1581 + "jsesc": "bin/jsesc"
  1582 + },
  1583 + "engines": {
  1584 + "node": ">=6"
  1585 + }
  1586 + },
  1587 + "node_modules/json5": {
  1588 + "version": "2.2.3",
  1589 + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
  1590 + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
  1591 + "dev": true,
  1592 + "license": "MIT",
  1593 + "bin": {
  1594 + "json5": "lib/cli.js"
  1595 + },
  1596 + "engines": {
  1597 + "node": ">=6"
  1598 + }
  1599 + },
  1600 + "node_modules/kolorist": {
  1601 + "version": "1.8.0",
  1602 + "resolved": "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz",
  1603 + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==",
  1604 + "dev": true,
  1605 + "license": "MIT"
  1606 + },
  1607 + "node_modules/lightningcss": {
  1608 + "version": "1.32.0",
  1609 + "resolved": "https://registry.npmmirror.com/lightningcss/-/lightningcss-1.32.0.tgz",
  1610 + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
  1611 + "dev": true,
  1612 + "license": "MPL-2.0",
  1613 + "dependencies": {
  1614 + "detect-libc": "^2.0.3"
  1615 + },
  1616 + "engines": {
  1617 + "node": ">= 12.0.0"
  1618 + },
  1619 + "funding": {
  1620 + "type": "opencollective",
  1621 + "url": "https://opencollective.com/parcel"
  1622 + },
  1623 + "optionalDependencies": {
  1624 + "lightningcss-android-arm64": "1.32.0",
  1625 + "lightningcss-darwin-arm64": "1.32.0",
  1626 + "lightningcss-darwin-x64": "1.32.0",
  1627 + "lightningcss-freebsd-x64": "1.32.0",
  1628 + "lightningcss-linux-arm-gnueabihf": "1.32.0",
  1629 + "lightningcss-linux-arm64-gnu": "1.32.0",
  1630 + "lightningcss-linux-arm64-musl": "1.32.0",
  1631 + "lightningcss-linux-x64-gnu": "1.32.0",
  1632 + "lightningcss-linux-x64-musl": "1.32.0",
  1633 + "lightningcss-win32-arm64-msvc": "1.32.0",
  1634 + "lightningcss-win32-x64-msvc": "1.32.0"
  1635 + }
  1636 + },
  1637 + "node_modules/lightningcss-android-arm64": {
  1638 + "version": "1.32.0",
  1639 + "resolved": "https://registry.npmmirror.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
  1640 + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
  1641 + "cpu": [
  1642 + "arm64"
  1643 + ],
  1644 + "dev": true,
  1645 + "license": "MPL-2.0",
  1646 + "optional": true,
  1647 + "os": [
  1648 + "android"
  1649 + ],
  1650 + "engines": {
  1651 + "node": ">= 12.0.0"
  1652 + },
  1653 + "funding": {
  1654 + "type": "opencollective",
  1655 + "url": "https://opencollective.com/parcel"
  1656 + }
  1657 + },
  1658 + "node_modules/lightningcss-darwin-arm64": {
  1659 + "version": "1.32.0",
  1660 + "resolved": "https://registry.npmmirror.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
  1661 + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
  1662 + "cpu": [
  1663 + "arm64"
  1664 + ],
  1665 + "dev": true,
  1666 + "license": "MPL-2.0",
  1667 + "optional": true,
  1668 + "os": [
  1669 + "darwin"
  1670 + ],
  1671 + "engines": {
  1672 + "node": ">= 12.0.0"
  1673 + },
  1674 + "funding": {
  1675 + "type": "opencollective",
  1676 + "url": "https://opencollective.com/parcel"
  1677 + }
  1678 + },
  1679 + "node_modules/lightningcss-darwin-x64": {
  1680 + "version": "1.32.0",
  1681 + "resolved": "https://registry.npmmirror.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
  1682 + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
  1683 + "cpu": [
  1684 + "x64"
  1685 + ],
  1686 + "dev": true,
  1687 + "license": "MPL-2.0",
  1688 + "optional": true,
  1689 + "os": [
  1690 + "darwin"
  1691 + ],
  1692 + "engines": {
  1693 + "node": ">= 12.0.0"
  1694 + },
  1695 + "funding": {
  1696 + "type": "opencollective",
  1697 + "url": "https://opencollective.com/parcel"
  1698 + }
  1699 + },
  1700 + "node_modules/lightningcss-freebsd-x64": {
  1701 + "version": "1.32.0",
  1702 + "resolved": "https://registry.npmmirror.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
  1703 + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
  1704 + "cpu": [
  1705 + "x64"
  1706 + ],
  1707 + "dev": true,
  1708 + "license": "MPL-2.0",
  1709 + "optional": true,
  1710 + "os": [
  1711 + "freebsd"
  1712 + ],
  1713 + "engines": {
  1714 + "node": ">= 12.0.0"
  1715 + },
  1716 + "funding": {
  1717 + "type": "opencollective",
  1718 + "url": "https://opencollective.com/parcel"
  1719 + }
  1720 + },
  1721 + "node_modules/lightningcss-linux-arm-gnueabihf": {
  1722 + "version": "1.32.0",
  1723 + "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
  1724 + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
  1725 + "cpu": [
  1726 + "arm"
  1727 + ],
  1728 + "dev": true,
  1729 + "license": "MPL-2.0",
  1730 + "optional": true,
  1731 + "os": [
  1732 + "linux"
  1733 + ],
  1734 + "engines": {
  1735 + "node": ">= 12.0.0"
  1736 + },
  1737 + "funding": {
  1738 + "type": "opencollective",
  1739 + "url": "https://opencollective.com/parcel"
  1740 + }
  1741 + },
  1742 + "node_modules/lightningcss-linux-arm64-gnu": {
  1743 + "version": "1.32.0",
  1744 + "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
  1745 + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
  1746 + "cpu": [
  1747 + "arm64"
  1748 + ],
  1749 + "dev": true,
  1750 + "license": "MPL-2.0",
  1751 + "optional": true,
  1752 + "os": [
  1753 + "linux"
  1754 + ],
  1755 + "engines": {
  1756 + "node": ">= 12.0.0"
  1757 + },
  1758 + "funding": {
  1759 + "type": "opencollective",
  1760 + "url": "https://opencollective.com/parcel"
  1761 + }
  1762 + },
  1763 + "node_modules/lightningcss-linux-arm64-musl": {
  1764 + "version": "1.32.0",
  1765 + "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
  1766 + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
  1767 + "cpu": [
  1768 + "arm64"
  1769 + ],
  1770 + "dev": true,
  1771 + "license": "MPL-2.0",
  1772 + "optional": true,
  1773 + "os": [
  1774 + "linux"
  1775 + ],
  1776 + "engines": {
  1777 + "node": ">= 12.0.0"
  1778 + },
  1779 + "funding": {
  1780 + "type": "opencollective",
  1781 + "url": "https://opencollective.com/parcel"
  1782 + }
  1783 + },
  1784 + "node_modules/lightningcss-linux-x64-gnu": {
  1785 + "version": "1.32.0",
  1786 + "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
  1787 + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
  1788 + "cpu": [
  1789 + "x64"
  1790 + ],
  1791 + "dev": true,
  1792 + "license": "MPL-2.0",
  1793 + "optional": true,
  1794 + "os": [
  1795 + "linux"
  1796 + ],
  1797 + "engines": {
  1798 + "node": ">= 12.0.0"
  1799 + },
  1800 + "funding": {
  1801 + "type": "opencollective",
  1802 + "url": "https://opencollective.com/parcel"
  1803 + }
  1804 + },
  1805 + "node_modules/lightningcss-linux-x64-musl": {
  1806 + "version": "1.32.0",
  1807 + "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
  1808 + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
  1809 + "cpu": [
  1810 + "x64"
  1811 + ],
  1812 + "dev": true,
  1813 + "license": "MPL-2.0",
  1814 + "optional": true,
  1815 + "os": [
  1816 + "linux"
  1817 + ],
  1818 + "engines": {
  1819 + "node": ">= 12.0.0"
  1820 + },
  1821 + "funding": {
  1822 + "type": "opencollective",
  1823 + "url": "https://opencollective.com/parcel"
  1824 + }
  1825 + },
  1826 + "node_modules/lightningcss-win32-arm64-msvc": {
  1827 + "version": "1.32.0",
  1828 + "resolved": "https://registry.npmmirror.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
  1829 + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
  1830 + "cpu": [
  1831 + "arm64"
  1832 + ],
  1833 + "dev": true,
  1834 + "license": "MPL-2.0",
  1835 + "optional": true,
  1836 + "os": [
  1837 + "win32"
  1838 + ],
  1839 + "engines": {
  1840 + "node": ">= 12.0.0"
  1841 + },
  1842 + "funding": {
  1843 + "type": "opencollective",
  1844 + "url": "https://opencollective.com/parcel"
  1845 + }
  1846 + },
  1847 + "node_modules/lightningcss-win32-x64-msvc": {
  1848 + "version": "1.32.0",
  1849 + "resolved": "https://registry.npmmirror.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
  1850 + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
  1851 + "cpu": [
  1852 + "x64"
  1853 + ],
  1854 + "dev": true,
  1855 + "license": "MPL-2.0",
  1856 + "optional": true,
  1857 + "os": [
  1858 + "win32"
  1859 + ],
  1860 + "engines": {
  1861 + "node": ">= 12.0.0"
  1862 + },
  1863 + "funding": {
  1864 + "type": "opencollective",
  1865 + "url": "https://opencollective.com/parcel"
  1866 + }
  1867 + },
  1868 + "node_modules/lodash": {
  1869 + "version": "4.18.1",
  1870 + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz",
  1871 + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
  1872 + "license": "MIT"
  1873 + },
  1874 + "node_modules/lodash-es": {
  1875 + "version": "4.18.1",
  1876 + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz",
  1877 + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
  1878 + "license": "MIT"
  1879 + },
  1880 + "node_modules/lodash-unified": {
  1881 + "version": "1.0.3",
  1882 + "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
  1883 + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
  1884 + "license": "MIT",
  1885 + "peerDependencies": {
  1886 + "@types/lodash-es": "*",
  1887 + "lodash": "*",
  1888 + "lodash-es": "*"
  1889 + }
  1890 + },
  1891 + "node_modules/lru-cache": {
  1892 + "version": "5.1.1",
  1893 + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz",
  1894 + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
  1895 + "dev": true,
  1896 + "license": "ISC",
  1897 + "dependencies": {
  1898 + "yallist": "^3.0.2"
  1899 + }
  1900 + },
  1901 + "node_modules/magic-string": {
  1902 + "version": "0.30.21",
  1903 + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
  1904 + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
  1905 + "license": "MIT",
  1906 + "dependencies": {
  1907 + "@jridgewell/sourcemap-codec": "^1.5.5"
  1908 + }
  1909 + },
  1910 + "node_modules/memoize-one": {
  1911 + "version": "6.0.0",
  1912 + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
  1913 + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
  1914 + "license": "MIT"
  1915 + },
  1916 + "node_modules/mrmime": {
  1917 + "version": "2.0.1",
  1918 + "resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.1.tgz",
  1919 + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
  1920 + "dev": true,
  1921 + "license": "MIT",
  1922 + "engines": {
  1923 + "node": ">=10"
  1924 + }
  1925 + },
  1926 + "node_modules/ms": {
  1927 + "version": "2.1.3",
  1928 + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
  1929 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
  1930 + "dev": true,
  1931 + "license": "MIT"
  1932 + },
  1933 + "node_modules/nanoid": {
  1934 + "version": "3.3.11",
  1935 + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
  1936 + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
  1937 + "funding": [
  1938 + {
  1939 + "type": "github",
  1940 + "url": "https://github.com/sponsors/ai"
  1941 + }
  1942 + ],
  1943 + "license": "MIT",
  1944 + "bin": {
  1945 + "nanoid": "bin/nanoid.cjs"
  1946 + },
  1947 + "engines": {
  1948 + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
  1949 + }
  1950 + },
  1951 + "node_modules/node-releases": {
  1952 + "version": "2.0.38",
  1953 + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.38.tgz",
  1954 + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==",
  1955 + "dev": true,
  1956 + "license": "MIT"
  1957 + },
  1958 + "node_modules/normalize-wheel-es": {
  1959 + "version": "1.2.0",
  1960 + "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
  1961 + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
  1962 + "license": "BSD-3-Clause"
  1963 + },
  1964 + "node_modules/ohash": {
  1965 + "version": "2.0.11",
  1966 + "resolved": "https://registry.npmmirror.com/ohash/-/ohash-2.0.11.tgz",
  1967 + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
  1968 + "dev": true,
  1969 + "license": "MIT"
  1970 + },
  1971 + "node_modules/open": {
  1972 + "version": "10.2.0",
  1973 + "resolved": "https://registry.npmmirror.com/open/-/open-10.2.0.tgz",
  1974 + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==",
  1975 + "dev": true,
  1976 + "license": "MIT",
  1977 + "dependencies": {
  1978 + "default-browser": "^5.2.1",
  1979 + "define-lazy-prop": "^3.0.0",
  1980 + "is-inside-container": "^1.0.0",
  1981 + "wsl-utils": "^0.1.0"
  1982 + },
  1983 + "engines": {
  1984 + "node": ">=18"
  1985 + },
  1986 + "funding": {
  1987 + "url": "https://github.com/sponsors/sindresorhus"
  1988 + }
  1989 + },
  1990 + "node_modules/pathe": {
  1991 + "version": "2.0.3",
  1992 + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz",
  1993 + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
  1994 + "dev": true,
  1995 + "license": "MIT"
  1996 + },
  1997 + "node_modules/perfect-debounce": {
  1998 + "version": "2.1.0",
  1999 + "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-2.1.0.tgz",
  2000 + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==",
  2001 + "dev": true,
  2002 + "license": "MIT"
  2003 + },
  2004 + "node_modules/picocolors": {
  2005 + "version": "1.1.1",
  2006 + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
  2007 + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
  2008 + "license": "ISC"
  2009 + },
  2010 + "node_modules/picomatch": {
  2011 + "version": "4.0.4",
  2012 + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz",
  2013 + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
  2014 + "dev": true,
  2015 + "license": "MIT",
  2016 + "engines": {
  2017 + "node": ">=12"
  2018 + },
  2019 + "funding": {
  2020 + "url": "https://github.com/sponsors/jonschlinkert"
  2021 + }
  2022 + },
  2023 + "node_modules/postcss": {
  2024 + "version": "8.5.12",
  2025 + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.12.tgz",
  2026 + "integrity": "sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==",
  2027 + "funding": [
  2028 + {
  2029 + "type": "opencollective",
  2030 + "url": "https://opencollective.com/postcss/"
  2031 + },
  2032 + {
  2033 + "type": "tidelift",
  2034 + "url": "https://tidelift.com/funding/github/npm/postcss"
  2035 + },
  2036 + {
  2037 + "type": "github",
  2038 + "url": "https://github.com/sponsors/ai"
  2039 + }
  2040 + ],
  2041 + "license": "MIT",
  2042 + "dependencies": {
  2043 + "nanoid": "^3.3.11",
  2044 + "picocolors": "^1.1.1",
  2045 + "source-map-js": "^1.2.1"
  2046 + },
  2047 + "engines": {
  2048 + "node": "^10 || ^12 || >=14"
  2049 + }
  2050 + },
  2051 + "node_modules/rolldown": {
  2052 + "version": "1.0.0-rc.17",
  2053 + "resolved": "https://registry.npmmirror.com/rolldown/-/rolldown-1.0.0-rc.17.tgz",
  2054 + "integrity": "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==",
  2055 + "dev": true,
  2056 + "license": "MIT",
  2057 + "dependencies": {
  2058 + "@oxc-project/types": "=0.127.0",
  2059 + "@rolldown/pluginutils": "1.0.0-rc.17"
  2060 + },
  2061 + "bin": {
  2062 + "rolldown": "bin/cli.mjs"
  2063 + },
  2064 + "engines": {
  2065 + "node": "^20.19.0 || >=22.12.0"
  2066 + },
  2067 + "optionalDependencies": {
  2068 + "@rolldown/binding-android-arm64": "1.0.0-rc.17",
  2069 + "@rolldown/binding-darwin-arm64": "1.0.0-rc.17",
  2070 + "@rolldown/binding-darwin-x64": "1.0.0-rc.17",
  2071 + "@rolldown/binding-freebsd-x64": "1.0.0-rc.17",
  2072 + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17",
  2073 + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17",
  2074 + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17",
  2075 + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17",
  2076 + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17",
  2077 + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17",
  2078 + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17",
  2079 + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17",
  2080 + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17",
  2081 + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17",
  2082 + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17"
  2083 + }
  2084 + },
  2085 + "node_modules/rolldown/node_modules/@rolldown/pluginutils": {
  2086 + "version": "1.0.0-rc.17",
  2087 + "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.17.tgz",
  2088 + "integrity": "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==",
  2089 + "dev": true,
  2090 + "license": "MIT"
  2091 + },
  2092 + "node_modules/run-applescript": {
  2093 + "version": "7.1.0",
  2094 + "resolved": "https://registry.npmmirror.com/run-applescript/-/run-applescript-7.1.0.tgz",
  2095 + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==",
  2096 + "dev": true,
  2097 + "license": "MIT",
  2098 + "engines": {
  2099 + "node": ">=18"
  2100 + },
  2101 + "funding": {
  2102 + "url": "https://github.com/sponsors/sindresorhus"
  2103 + }
  2104 + },
  2105 + "node_modules/semver": {
  2106 + "version": "6.3.1",
  2107 + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
  2108 + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
  2109 + "dev": true,
  2110 + "license": "ISC",
  2111 + "bin": {
  2112 + "semver": "bin/semver.js"
  2113 + }
  2114 + },
  2115 + "node_modules/sirv": {
  2116 + "version": "3.0.2",
  2117 + "resolved": "https://registry.npmmirror.com/sirv/-/sirv-3.0.2.tgz",
  2118 + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==",
  2119 + "dev": true,
  2120 + "license": "MIT",
  2121 + "dependencies": {
  2122 + "@polka/url": "^1.0.0-next.24",
  2123 + "mrmime": "^2.0.0",
  2124 + "totalist": "^3.0.0"
  2125 + },
  2126 + "engines": {
  2127 + "node": ">=18"
  2128 + }
  2129 + },
  2130 + "node_modules/source-map-js": {
  2131 + "version": "1.2.1",
  2132 + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
  2133 + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
  2134 + "license": "BSD-3-Clause",
  2135 + "engines": {
  2136 + "node": ">=0.10.0"
  2137 + }
  2138 + },
  2139 + "node_modules/tinyglobby": {
  2140 + "version": "0.2.16",
  2141 + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.16.tgz",
  2142 + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
  2143 + "dev": true,
  2144 + "license": "MIT",
  2145 + "dependencies": {
  2146 + "fdir": "^6.5.0",
  2147 + "picomatch": "^4.0.4"
  2148 + },
  2149 + "engines": {
  2150 + "node": ">=12.0.0"
  2151 + },
  2152 + "funding": {
  2153 + "url": "https://github.com/sponsors/SuperchupuDev"
  2154 + }
  2155 + },
  2156 + "node_modules/totalist": {
  2157 + "version": "3.0.1",
  2158 + "resolved": "https://registry.npmmirror.com/totalist/-/totalist-3.0.1.tgz",
  2159 + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
  2160 + "dev": true,
  2161 + "license": "MIT",
  2162 + "engines": {
  2163 + "node": ">=6"
  2164 + }
  2165 + },
  2166 + "node_modules/tslib": {
  2167 + "version": "2.8.1",
  2168 + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
  2169 + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
  2170 + "dev": true,
  2171 + "license": "0BSD",
  2172 + "optional": true
  2173 + },
  2174 + "node_modules/unplugin-utils": {
  2175 + "version": "0.3.1",
  2176 + "resolved": "https://registry.npmmirror.com/unplugin-utils/-/unplugin-utils-0.3.1.tgz",
  2177 + "integrity": "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==",
  2178 + "dev": true,
  2179 + "license": "MIT",
  2180 + "dependencies": {
  2181 + "pathe": "^2.0.3",
  2182 + "picomatch": "^4.0.3"
  2183 + },
  2184 + "engines": {
  2185 + "node": ">=20.19.0"
  2186 + },
  2187 + "funding": {
  2188 + "url": "https://github.com/sponsors/sxzz"
  2189 + }
  2190 + },
  2191 + "node_modules/update-browserslist-db": {
  2192 + "version": "1.2.3",
  2193 + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
  2194 + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
  2195 + "dev": true,
  2196 + "funding": [
  2197 + {
  2198 + "type": "opencollective",
  2199 + "url": "https://opencollective.com/browserslist"
  2200 + },
  2201 + {
  2202 + "type": "tidelift",
  2203 + "url": "https://tidelift.com/funding/github/npm/browserslist"
  2204 + },
  2205 + {
  2206 + "type": "github",
  2207 + "url": "https://github.com/sponsors/ai"
  2208 + }
  2209 + ],
  2210 + "license": "MIT",
  2211 + "dependencies": {
  2212 + "escalade": "^3.2.0",
  2213 + "picocolors": "^1.1.1"
  2214 + },
  2215 + "bin": {
  2216 + "update-browserslist-db": "cli.js"
  2217 + },
  2218 + "peerDependencies": {
  2219 + "browserslist": ">= 4.21.0"
  2220 + }
  2221 + },
  2222 + "node_modules/vite": {
  2223 + "version": "8.0.10",
  2224 + "resolved": "https://registry.npmmirror.com/vite/-/vite-8.0.10.tgz",
  2225 + "integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==",
  2226 + "dev": true,
  2227 + "license": "MIT",
  2228 + "dependencies": {
  2229 + "lightningcss": "^1.32.0",
  2230 + "picomatch": "^4.0.4",
  2231 + "postcss": "^8.5.10",
  2232 + "rolldown": "1.0.0-rc.17",
  2233 + "tinyglobby": "^0.2.16"
  2234 + },
  2235 + "bin": {
  2236 + "vite": "bin/vite.js"
  2237 + },
  2238 + "engines": {
  2239 + "node": "^20.19.0 || >=22.12.0"
  2240 + },
  2241 + "funding": {
  2242 + "url": "https://github.com/vitejs/vite?sponsor=1"
  2243 + },
  2244 + "optionalDependencies": {
  2245 + "fsevents": "~2.3.3"
  2246 + },
  2247 + "peerDependencies": {
  2248 + "@types/node": "^20.19.0 || >=22.12.0",
  2249 + "@vitejs/devtools": "^0.1.0",
  2250 + "esbuild": "^0.27.0 || ^0.28.0",
  2251 + "jiti": ">=1.21.0",
  2252 + "less": "^4.0.0",
  2253 + "sass": "^1.70.0",
  2254 + "sass-embedded": "^1.70.0",
  2255 + "stylus": ">=0.54.8",
  2256 + "sugarss": "^5.0.0",
  2257 + "terser": "^5.16.0",
  2258 + "tsx": "^4.8.1",
  2259 + "yaml": "^2.4.2"
  2260 + },
  2261 + "peerDependenciesMeta": {
  2262 + "@types/node": {
  2263 + "optional": true
  2264 + },
  2265 + "@vitejs/devtools": {
  2266 + "optional": true
  2267 + },
  2268 + "esbuild": {
  2269 + "optional": true
  2270 + },
  2271 + "jiti": {
  2272 + "optional": true
  2273 + },
  2274 + "less": {
  2275 + "optional": true
  2276 + },
  2277 + "sass": {
  2278 + "optional": true
  2279 + },
  2280 + "sass-embedded": {
  2281 + "optional": true
  2282 + },
  2283 + "stylus": {
  2284 + "optional": true
  2285 + },
  2286 + "sugarss": {
  2287 + "optional": true
  2288 + },
  2289 + "terser": {
  2290 + "optional": true
  2291 + },
  2292 + "tsx": {
  2293 + "optional": true
  2294 + },
  2295 + "yaml": {
  2296 + "optional": true
  2297 + }
  2298 + }
  2299 + },
  2300 + "node_modules/vite-plugin-vue-devtools": {
  2301 + "version": "8.1.1",
  2302 + "resolved": "https://registry.npmmirror.com/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.1.1.tgz",
  2303 + "integrity": "sha512-9qTpOmZ2vHpvlI9hdVXAQ1Ry4I8GcBArU7aPi0qfIaV7fQIXy0L1nb6X4mFY2Gw0dYshHuLbIl0Ulb572SCjsQ==",
  2304 + "dev": true,
  2305 + "license": "MIT",
  2306 + "dependencies": {
  2307 + "@vue/devtools-core": "^8.1.1",
  2308 + "@vue/devtools-kit": "^8.1.1",
  2309 + "@vue/devtools-shared": "^8.1.1",
  2310 + "sirv": "^3.0.2",
  2311 + "vite-plugin-inspect": "^11.3.3",
  2312 + "vite-plugin-vue-inspector": "^5.3.2"
  2313 + },
  2314 + "engines": {
  2315 + "node": ">=v14.21.3"
  2316 + },
  2317 + "peerDependencies": {
  2318 + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
  2319 + }
  2320 + },
  2321 + "node_modules/vite-plugin-vue-devtools/node_modules/vite-plugin-inspect": {
  2322 + "version": "11.3.3",
  2323 + "resolved": "https://registry.npmmirror.com/vite-plugin-inspect/-/vite-plugin-inspect-11.3.3.tgz",
  2324 + "integrity": "sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==",
  2325 + "dev": true,
  2326 + "license": "MIT",
  2327 + "dependencies": {
  2328 + "ansis": "^4.1.0",
  2329 + "debug": "^4.4.1",
  2330 + "error-stack-parser-es": "^1.0.5",
  2331 + "ohash": "^2.0.11",
  2332 + "open": "^10.2.0",
  2333 + "perfect-debounce": "^2.0.0",
  2334 + "sirv": "^3.0.1",
  2335 + "unplugin-utils": "^0.3.0",
  2336 + "vite-dev-rpc": "^1.1.0"
  2337 + },
  2338 + "engines": {
  2339 + "node": ">=14"
  2340 + },
  2341 + "funding": {
  2342 + "url": "https://github.com/sponsors/antfu"
  2343 + },
  2344 + "peerDependencies": {
  2345 + "vite": "^6.0.0 || ^7.0.0-0"
  2346 + },
  2347 + "peerDependenciesMeta": {
  2348 + "@nuxt/kit": {
  2349 + "optional": true
  2350 + }
  2351 + }
  2352 + },
  2353 + "node_modules/vite-plugin-vue-devtools/node_modules/vite-plugin-inspect/node_modules/vite-dev-rpc": {
  2354 + "version": "1.1.0",
  2355 + "resolved": "https://registry.npmmirror.com/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz",
  2356 + "integrity": "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==",
  2357 + "dev": true,
  2358 + "license": "MIT",
  2359 + "dependencies": {
  2360 + "birpc": "^2.4.0",
  2361 + "vite-hot-client": "^2.1.0"
  2362 + },
  2363 + "funding": {
  2364 + "url": "https://github.com/sponsors/antfu"
  2365 + },
  2366 + "peerDependencies": {
  2367 + "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0"
  2368 + }
  2369 + },
  2370 + "node_modules/vite-plugin-vue-devtools/node_modules/vite-plugin-inspect/node_modules/vite-dev-rpc/node_modules/vite-hot-client": {
  2371 + "version": "2.1.0",
  2372 + "resolved": "https://registry.npmmirror.com/vite-hot-client/-/vite-hot-client-2.1.0.tgz",
  2373 + "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==",
  2374 + "dev": true,
  2375 + "license": "MIT",
  2376 + "funding": {
  2377 + "url": "https://github.com/sponsors/antfu"
  2378 + },
  2379 + "peerDependencies": {
  2380 + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0"
  2381 + }
  2382 + },
  2383 + "node_modules/vite-plugin-vue-inspector": {
  2384 + "version": "5.4.0",
  2385 + "resolved": "https://registry.npmmirror.com/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.4.0.tgz",
  2386 + "integrity": "sha512-Iq/024CydcE46FZqWPU4t4lw4uYOdLnFSO1RNxJVt2qY9zxIjmnkBqhHnYaReWM82kmNnaXs7OkfgRrV2GEjyw==",
  2387 + "dev": true,
  2388 + "license": "MIT",
  2389 + "dependencies": {
  2390 + "@babel/core": "^7.23.0",
  2391 + "@babel/plugin-proposal-decorators": "^7.23.0",
  2392 + "@babel/plugin-syntax-import-attributes": "^7.22.5",
  2393 + "@babel/plugin-syntax-import-meta": "^7.10.4",
  2394 + "@babel/plugin-transform-typescript": "^7.22.15",
  2395 + "@vue/babel-plugin-jsx": "^1.1.5",
  2396 + "@vue/compiler-dom": "^3.3.4",
  2397 + "kolorist": "^1.8.0",
  2398 + "magic-string": "^0.30.4"
  2399 + },
  2400 + "peerDependencies": {
  2401 + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
  2402 + }
  2403 + },
  2404 + "node_modules/vue": {
  2405 + "version": "3.5.33",
  2406 + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.33.tgz",
  2407 + "integrity": "sha512-1AgChhx5w3ALgT4oK3acm2Es/7jyZhWSVUfs3rOBlGQC0rjEDkS7G4lWlJJGGNQD+BV3reCwbQrOe1mPNwKHBQ==",
  2408 + "license": "MIT",
  2409 + "dependencies": {
  2410 + "@vue/compiler-dom": "3.5.33",
  2411 + "@vue/compiler-sfc": "3.5.33",
  2412 + "@vue/runtime-dom": "3.5.33",
  2413 + "@vue/server-renderer": "3.5.33",
  2414 + "@vue/shared": "3.5.33"
  2415 + },
  2416 + "peerDependencies": {
  2417 + "typescript": "*"
  2418 + },
  2419 + "peerDependenciesMeta": {
  2420 + "typescript": {
  2421 + "optional": true
  2422 + }
  2423 + }
  2424 + },
  2425 + "node_modules/vue-component-type-helpers": {
  2426 + "version": "3.2.7",
  2427 + "resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.2.7.tgz",
  2428 + "integrity": "sha512-+gPp5YGmhfsj1IN+xUo7y0fb4clfnOiiUA39y07yW1VzCRjzVgwLbtmdWlghh7mXrPsEaYc7rrIir/HT6C8vYQ==",
  2429 + "license": "MIT"
  2430 + },
  2431 + "node_modules/vue-router": {
  2432 + "version": "4.6.4",
  2433 + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz",
  2434 + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
  2435 + "license": "MIT",
  2436 + "dependencies": {
  2437 + "@vue/devtools-api": "^6.6.4"
  2438 + },
  2439 + "funding": {
  2440 + "url": "https://github.com/sponsors/posva"
  2441 + },
  2442 + "peerDependencies": {
  2443 + "vue": "^3.5.0"
  2444 + }
  2445 + },
  2446 + "node_modules/wsl-utils": {
  2447 + "version": "0.1.0",
  2448 + "resolved": "https://registry.npmmirror.com/wsl-utils/-/wsl-utils-0.1.0.tgz",
  2449 + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==",
  2450 + "dev": true,
  2451 + "license": "MIT",
  2452 + "dependencies": {
  2453 + "is-wsl": "^3.1.0"
  2454 + },
  2455 + "engines": {
  2456 + "node": ">=18"
  2457 + },
  2458 + "funding": {
  2459 + "url": "https://github.com/sponsors/sindresorhus"
  2460 + }
  2461 + },
  2462 + "node_modules/yallist": {
  2463 + "version": "3.1.1",
  2464 + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
  2465 + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
  2466 + "dev": true,
  2467 + "license": "ISC"
  2468 + }
  2469 + }
  2470 +}
  1 +{
  2 + "name": "iot-bridge-ui",
  3 + "version": "0.0.0",
  4 + "private": true,
  5 + "type": "module",
  6 + "scripts": {
  7 + "dev": "vite",
  8 + "build": "vite build",
  9 + "preview": "vite preview"
  10 + },
  11 + "dependencies": {
  12 + "@element-plus/icons-vue": "^2.3.2",
  13 + "element-plus": "^2.13.7",
  14 + "vue": "^3.5.32",
  15 + "vue-router": "^4.6.4"
  16 + },
  17 + "devDependencies": {
  18 + "@vitejs/plugin-vue": "^6.0.6",
  19 + "vite": "^8.0.8",
  20 + "vite-plugin-vue-devtools": "^8.1.1"
  21 + },
  22 + "engines": {
  23 + "node": "^20.19.0 || >=22.12.0"
  24 + }
  25 +}
No preview for this file type
  1 +<template>
  2 + <div class="app-container">
  3 + <el-container>
  4 + <el-aside width="180px" class="sidebar">
  5 + <div class="logo-area">
  6 + <span>云物联网平台</span>
  7 + </div>
  8 + <el-menu
  9 + :default-active="currentRoute"
  10 + class="sidebar-menu"
  11 + background-color="#304156"
  12 + text-color="#bfcbd9"
  13 + active-text-color="#409eff"
  14 + :router="true"
  15 + >
  16 + <el-menu-item index="/smart-light">
  17 + <el-icon><Monitor /></el-icon>
  18 + <span>智能灯</span>
  19 + </el-menu-item>
  20 + <el-menu-item index="/energy">
  21 + <el-icon><Lightning /></el-icon>
  22 + <span>能耗</span>
  23 + </el-menu-item>
  24 + </el-menu>
  25 + </el-aside>
  26 + <el-main class="main-content">
  27 + <router-view />
  28 + </el-main>
  29 + </el-container>
  30 + </div>
  31 +</template>
  32 +
  33 +<script setup>
  34 +import { computed } from 'vue'
  35 +import { useRoute } from 'vue-router'
  36 +
  37 +const route = useRoute()
  38 +const currentRoute = computed(() => route.path)
  39 +</script>
  40 +
  41 +<style scoped>
  42 +.app-container {
  43 + height: 100vh;
  44 + overflow: hidden;
  45 +}
  46 +.sidebar {
  47 + background-color: #304156;
  48 + color: #fff;
  49 +}
  50 +.logo-area {
  51 + padding: 18px 16px;
  52 + color: #fff;
  53 + font-size: 15px;
  54 + font-weight: bold;
  55 + text-align: center;
  56 + border-bottom: 1px solid rgba(255,255,255,0.08);
  57 + background-color: #263445;
  58 +}
  59 +.sidebar-menu {
  60 + border-right: none !important;
  61 + padding-top: 8px;
  62 +}
  63 +.main-content {
  64 + background-color: #f0f2f5;
  65 + padding: 0;
  66 + overflow-y: auto;
  67 +}
  68 +</style>
  1 +/* color palette from <https://github.com/vuejs/theme> */
  2 +:root {
  3 + --vt-c-white: #ffffff;
  4 + --vt-c-white-soft: #f8f8f8;
  5 + --vt-c-white-mute: #f2f2f2;
  6 +
  7 + --vt-c-black: #181818;
  8 + --vt-c-black-soft: #222222;
  9 + --vt-c-black-mute: #282828;
  10 +
  11 + --vt-c-indigo: #2c3e50;
  12 +
  13 + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
  14 + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
  15 + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
  16 + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
  17 +
  18 + --vt-c-text-light-1: var(--vt-c-indigo);
  19 + --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
  20 + --vt-c-text-dark-1: var(--vt-c-white);
  21 + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
  22 +}
  23 +
  24 +/* semantic color variables for this project */
  25 +:root {
  26 + --color-background: var(--vt-c-white);
  27 + --color-background-soft: var(--vt-c-white-soft);
  28 + --color-background-mute: var(--vt-c-white-mute);
  29 +
  30 + --color-border: var(--vt-c-divider-light-2);
  31 + --color-border-hover: var(--vt-c-divider-light-1);
  32 +
  33 + --color-heading: var(--vt-c-text-light-1);
  34 + --color-text: var(--vt-c-text-light-1);
  35 +
  36 + --section-gap: 160px;
  37 +}
  38 +
  39 +@media (prefers-color-scheme: dark) {
  40 + :root {
  41 + --color-background: var(--vt-c-black);
  42 + --color-background-soft: var(--vt-c-black-soft);
  43 + --color-background-mute: var(--vt-c-black-mute);
  44 +
  45 + --color-border: var(--vt-c-divider-dark-2);
  46 + --color-border-hover: var(--vt-c-divider-dark-1);
  47 +
  48 + --color-heading: var(--vt-c-text-dark-1);
  49 + --color-text: var(--vt-c-text-dark-2);
  50 + }
  51 +}
  52 +
  53 +*,
  54 +*::before,
  55 +*::after {
  56 + box-sizing: border-box;
  57 + margin: 0;
  58 + font-weight: normal;
  59 +}
  60 +
  61 +body {
  62 + min-height: 100vh;
  63 + color: var(--color-text);
  64 + background: var(--color-background);
  65 + transition:
  66 + color 0.5s,
  67 + background-color 0.5s;
  68 + line-height: 1.6;
  69 + font-family:
  70 + Inter,
  71 + -apple-system,
  72 + BlinkMacSystemFont,
  73 + 'Segoe UI',
  74 + Roboto,
  75 + Oxygen,
  76 + Ubuntu,
  77 + Cantarell,
  78 + 'Fira Sans',
  79 + 'Droid Sans',
  80 + 'Helvetica Neue',
  81 + sans-serif;
  82 + font-size: 15px;
  83 + text-rendering: optimizeLegibility;
  84 + -webkit-font-smoothing: antialiased;
  85 + -moz-osx-font-smoothing: grayscale;
  86 +}
  1 +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
  1 +* {
  2 + margin: 0;
  3 + padding: 0;
  4 + box-sizing: border-box;
  5 +}
  6 +
  7 +html, body {
  8 + width: 100%;
  9 + height: 100%;
  10 + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  11 +}
  12 +
  13 +#app {
  14 + width: 100%;
  15 + height: 100vh;
  16 + max-width: none;
  17 + margin: 0;
  18 + padding: 0;
  19 +}
  1 +<template>
  2 + <el-dialog
  3 + :model-value="visible"
  4 + @update:model-value="$emit('update:visible', $event)"
  5 + title=""
  6 + width="calc(100vw - 40px)"
  7 + :style="{ maxWidth: '1400px' }"
  8 + top="3vh"
  9 + destroy-on-close
  10 + class="count-dialog"
  11 + >
  12 + <template #header>
  13 + <div class="dialog-header">
  14 + <span class="title-text">中速纸杯机24号机 计数明细</span>
  15 + <span class="query-label">查询方式:</span>
  16 + <div class="header-center">
  17 + <el-radio-group v-model="queryMode" size="small">
  18 + <el-radio-button value="day">日查询</el-radio-button>
  19 + <el-radio-button value="week">周查询</el-radio-button>
  20 + <el-radio-button value="month">月查询</el-radio-button>
  21 + </el-radio-group>
  22 + <el-date-picker v-model="dateRange" type="daterange" size="small" range-separator="-"
  23 + start-placeholder="2026-04-21" end-placeholder="2026-04-28" style="width: 240px; margin-left: 8px;" />
  24 + </div>
  25 + <div class="header-right">
  26 + </div>
  27 + </div>
  28 + </template>
  29 +
  30 + <div class="count-body">
  31 + <!-- 折线图 -->
  32 + <div class="chart-section">
  33 + <svg viewBox="0 0 900 250" xmlns="http://www.w3.org/2000/svg">
  34 + <!-- Y轴 -->
  35 + <g font-size="11" fill="#999" text-anchor="end">
  36 + <text x="35" y="215">0</text>
  37 + <text x="35" y="175">0.2</text>
  38 + <text x="35" y="135">0.4</text>
  39 + <text x="35" y="95">0.6</text>
  40 + <text x="35" y="55">0.8</text>
  41 + <text x="35" y="18">1</text>
  42 + </g>
  43 + <!-- 网格横线 -->
  44 + <g stroke="#f0f0f0" stroke-width="1">
  45 + <line x1="45" y1="213" x2="880" y2="213"/>
  46 + <line x1="45" y1="173" x2="880" y2="173"/>
  47 + <line x1="45" y1="133" x2="880" y2="133"/>
  48 + <line x1="45" y1="93" x2="880" y2="93"/>
  49 + <line x1="45" y1="53" x2="880" y2="53"/>
  50 + <line x1="45" y1="16" x2="880" y2="16"/>
  51 + </g>
  52 + <!-- X轴日期 -->
  53 + <g font-size="11" fill="#666" text-anchor="middle">
  54 + <text x="105" y="235">2026-04-21</text>
  55 + <text x="225" y="235">2026-04-22</text>
  56 + <text x="345" y="235">2026-04-23</text>
  57 + <text x="465" y="235">2026-04-24</text>
  58 + <text x="585" y="235">2026-04-25</text>
  59 + <text x="705" y="235">2026-04-26</text>
  60 + <text x="825" y="235">2026-04-27</text>
  61 + </g>
  62 + <!-- 数据点(全部为0) -->
  63 + <g fill="#409eff">
  64 + <circle cx="105" cy="213" r="3"/><text x="105" y="205" text-anchor="middle" font-size="11" fill="#409eff">0</text>
  65 + <circle cx="225" cy="213" r="3"/><text x="225" y="205" text-anchor="middle" font-size="11" fill="#409eff">0</text>
  66 + <circle cx="345" cy="213" r="3"/><text x="345" y="205" text-anchor="middle" font-size="11" fill="#409eff">0</text>
  67 + <circle cx="465" cy="213" r="3"/><text x="465" y="205" text-anchor="middle" font-size="11" fill="#409eff">0</text>
  68 + <circle cx="585" cy="213" r="3"/><text x="585" y="205" text-anchor="middle" font-size="11" fill="#409eff">0</text>
  69 + <circle cx="705" cy="213" r="3"/><text x="705" y="205" text-anchor="middle" font-size="11" fill="#409eff">0</text>
  70 + <circle cx="825" cy="213" r="3"/><text x="825" y="205" text-anchor="middle" font-size="11" fill="#409eff">0</text>
  71 + </g>
  72 + <!-- 连接线 -->
  73 + <polyline points="105,213 225,213 345,213 465,213 585,213 705,213 825,213"
  74 + fill="none" stroke="#409eff" stroke-width="2"/>
  75 + <!-- 坐标轴线 -->
  76 + <line x1="45" y1="213" x2="880" y2="213" stroke="#ccc" stroke-width="1"/>
  77 + </svg>
  78 + </div>
  79 +
  80 + <!-- 表格 -->
  81 + <div class="table-section">
  82 + <el-table :data="[]" size="small" stripe border style="width: 100%; font-size: 12px;" empty-text="暂无数据">
  83 + <el-table-column prop="date" label="日期" width="140" align="center" />
  84 + <el-table-column prop="totalCount" label="总个数" align="center" />
  85 + <el-table-column prop="lightOnDuration" label="亮灯时长" align="center" />
  86 + <el-table-column prop="avgDuration" label="平均时长" align="center" />
  87 + <el-table-column prop="maxDuration" label="理论时长" align="center" />
  88 + <el-table-column prop="efficiency" label="生产效率" align="center" />
  89 + <el-table-column prop="detail" label="详情" align="center" />
  90 + <el-table-column prop="remark" label="备注" align="center" />
  91 + </el-table>
  92 + <div class="empty-hint">暂无数据</div>
  93 + </div>
  94 + </div>
  95 + </el-dialog>
  96 +</template>
  97 +
  98 +<script setup>
  99 +import { ref } from 'vue'
  100 +
  101 +defineProps({ visible: Boolean, device: Object })
  102 +defineEmits(['update:visible'])
  103 +const queryMode = ref('day')
  104 +const dateRange = ref(null)
  105 +</script>
  106 +
  107 +<style scoped>
  108 +.count-dialog :deep(.el-dialog) {
  109 + max-height: 92vh;
  110 + display: flex;
  111 + flex-direction: column;
  112 +}
  113 +.count-dialog :deep(.el-dialog__header) {
  114 + padding: 10px 20px;
  115 + border-bottom: 1px solid #e8e8e8;
  116 + margin: 0;
  117 + flex-shrink: 0;
  118 +}
  119 +.count-dialog :deep(.el-dialog__body) {
  120 + overflow-y: auto;
  121 + flex: 1;
  122 +}
  123 +.dialog-header {
  124 + display: flex;
  125 + align-items: center;
  126 + gap: 12px;
  127 +}
  128 +.title-text {
  129 + font-size: 14px;
  130 + font-weight: bold;
  131 + color: #333;
  132 + white-space: nowrap;
  133 +}
  134 +.query-label {
  135 + font-size: 13px;
  136 + color: #666;
  137 +}
  138 +.header-center {
  139 + display: flex;
  140 + align-items: center;
  141 + flex: 1;
  142 +}
  143 +.header-right {
  144 + display: flex;
  145 + align-items: center;
  146 + gap: 8px;
  147 +}
  148 +
  149 +.count-body {
  150 + padding: 0;
  151 +}
  152 +.chart-section {
  153 + background: #fff;
  154 + border: 1px solid #ebeef5;
  155 + border-radius: 4px;
  156 + padding: 16px 20px;
  157 + margin-bottom: 16px;
  158 +}
  159 +.chart-section svg {
  160 + width: 100%;
  161 + height: auto;
  162 + display: block;
  163 +}
  164 +
  165 +.table-section {
  166 + background: #fff;
  167 + border: 1px solid #ebeef5;
  168 + border-radius: 4px;
  169 + overflow: hidden;
  170 +}
  171 +.empty-hint {
  172 + text-align: center;
  173 + padding: 30px;
  174 + color: #999;
  175 + font-size: 13px;
  176 +}
  177 +</style>
  1 +<template>
  2 + <el-dialog
  3 + :model-value="visible"
  4 + @update:model-value="$emit('update:visible', $event)"
  5 + title=""
  6 + width="calc(100vw - 40px)"
  7 + :style="{ maxWidth: '1400px' }"
  8 + top="3vh"
  9 + destroy-on-close
  10 + class="ereport-dialog"
  11 + >
  12 + <template #header>
  13 + <div class="dialog-header">
  14 + <span class="title-text">{{ device?.name || '能耗设备1' }} 能耗报表</span>
  15 + <div class="header-right">
  16 + <el-icon :size="16" style="cursor:pointer;color:#409eff;"><FullScreen /></el-icon>
  17 + <el-icon :size="16" style="cursor:pointer;color:#409eff;margin-left:8px;" @click="$emit('update:visible', false)"><Close /></el-icon>
  18 + </div>
  19 + </div>
  20 + </template>
  21 +
  22 + <div class="report-body">
  23 + <!-- 上排:6个能耗卡片 + 碳排放统计 -->
  24 + <div class="top-section">
  25 + <div class="energy-cards-grid">
  26 + <div v-for="(card, idx) in energyCards" :key="idx" :class="['energy-card-item', card.color]">
  27 + <span class="card-label">{{ card.label }}</span>
  28 + <span class="card-val">{{ card.value }}<small>{{ card.unit }}</small></span>
  29 + </div>
  30 + </div>
  31 + <div class="carbon-panel">
  32 + <div class="carbon-title">碳排放统计 <i style="font-size:12px;">▼</i></div>
  33 + <div class="carbon-sub">碳排放系数0</div>
  34 + <div v-for="item in carbonItems" :key="item.label" :class="['carbon-row', item.color]">
  35 + {{ item.label }}{{ item.val }}
  36 + </div>
  37 + </div>
  38 + </div>
  39 +
  40 + <!-- 下排:3个图表 -->
  41 + <div class="charts-grid">
  42 + <!-- 时能耗 -->
  43 + <div class="chart-card">
  44 + <div class="chart-header">
  45 + <span class="chart-title">时能耗</span>
  46 + <div class="chart-tools">
  47 + <label><input type="radio" name="t1" checked /> 2025-04-28</label>&nbsp;
  48 + <label><input type="radio" name="t2" checked /> 昨日日期</label>
  49 + <el-icon :size="14"><ZoomIn /></el-icon>
  50 + </div>
  51 + </div>
  52 + <div class="chart-body">
  53 + <svg viewBox="0 0 500 220">
  54 + <g font-size="10" fill="#999" text-anchor="end">
  55 + <text x="24" y="20">1</text><text x="24" y="60">0.8</text><text x="24" y="100">0.6</text>
  56 + <text x="24" y="140">0.4</text><text x="24" y="180">0.2</text><text x="24" y="210">0</text>
  57 + </g>
  58 + <line x1="30" y1="206" x2="490" y2="206" stroke="#ddd"/>
  59 + <g font-size="9" fill="#666" text-anchor="middle">
  60 + <template v-for="i in 25" :key="'th'+i"><text :x="36+i*18" y="218">{{ i-1 }}</text></template>
  61 + </g>
  62 + <polyline points="36,206 54,206 72,206 90,206 108,206 126,206 144,206 162,206 180,206 198,206 216,206 234,206 252,206 270,206 288,206 306,206 324,206 342,206 360,206 378,206 396,206 414,206 432,206 450,206 468,206 486,206"
  63 + fill="none" stroke="#409eff" stroke-width="1.5"/>
  64 + </svg>
  65 + </div>
  66 + </div>
  67 +
  68 + <!-- 日能耗 -->
  69 + <div class="chart-card">
  70 + <div class="chart-header">
  71 + <span class="chart-title">日能耗</span>
  72 + <div class="chart-tools">
  73 + <label><input type="radio" checked/> 2025-04</label>&nbsp;
  74 + <label><input type="radio" checked/> 昨日日期</label>
  75 + <el-icon :size="14"><ZoomIn /></el-icon>
  76 + </div>
  77 + </div>
  78 + <div class="chart-body">
  79 + <svg viewBox="0 0 500 220">
  80 + <g font-size="10" fill="#999" text-anchor="end">
  81 + <text x="24" y="20">1</text><text x="24" y="60">0.8</text><text x="24" y="100">0.6</text>
  82 + <text x="24" y="140">0.4</text><text x="24" y="180">0.2</text><text x="24" y="210">0</text>
  83 + </g>
  84 + <line x1="30" y1="206" x2="490" y2="206" stroke="#ddd"/>
  85 + <g font-size="9" fill="#666" text-anchor="middle">
  86 + <template v-for="i in 31" :key="'dh'+i"><text :x="32+(i-1)*15" y="218">{{ i }}</text></template>
  87 + </g>
  88 + <polyline fill="none" stroke="#67c23a" stroke-width="1.5"/>
  89 + </svg>
  90 + </div>
  91 + </div>
  92 +
  93 + <!-- 月能耗 -->
  94 + <div class="chart-card full-width">
  95 + <div class="chart-header">
  96 + <span class="chart-title">月能耗</span>
  97 + <div class="chart-tools">
  98 + <label><input type="radio" checked/> 2025</label>
  99 + <el-icon :size="14"><ZoomIn /></el-icon>
  100 + </div>
  101 + </div>
  102 + <div class="chart-body">
  103 + <svg viewBox="0 0 500 180">
  104 + <g font-size="10" fill="#999" text-anchor="end">
  105 + <text x="22" y="18">1</text><text x="22" y="53">0.8</text><text x="22" y="88">0.6</text>
  106 + <text x="22" y="123">0.4</text><text x="22" y="158">0.2</text>
  107 + </g>
  108 + <line x1="28" y1="164" x2="488" y2="164" stroke="#ddd"/>
  109 + <g font-size="9" fill="#666" text-anchor="middle">
  110 + <template v-for="i in 12" :key="'mh'+i"><text :x="34+(i-1)*39" y="177">{{ i }}</text></template>
  111 + </g>
  112 + </svg>
  113 + </div>
  114 + </div>
  115 + </div>
  116 + </div>
  117 + </el-dialog>
  118 +</template>
  119 +
  120 +<script setup>
  121 +import { ref } from 'vue'
  122 +import { FullScreen, Close, ZoomIn } from '@element-plus/icons-vue'
  123 +
  124 +defineProps({ visible: Boolean, device: Object })
  125 +defineEmits(['update:visible'])
  126 +
  127 +const energyCards = [
  128 + { label: '本小时能耗', value: '0', unit: 'kw·h', color: 'orange' },
  129 + { label: '本日能耗', value: '0', unit: 'kw·h', color: 'green' },
  130 + { label: '本月能耗', value: '0', unit: 'kw·h', color: 'blue' },
  131 + { label: '上小时能耗', value: '0', unit: 'kw·h', color: 'orange' },
  132 + { label: '昨日能耗', value: '0', unit: 'kw·h', color: 'green' },
  133 + { label: '上月能耗', value: '0', unit: 'kw·h', color: 'blue' }
  134 +]
  135 +const carbonItems = [
  136 + { label: '累计碳排放:', val: '0', color: 'blue' },
  137 + { label: '时:', val: '0.00', color: 'blue' },
  138 + { label: '日:', val: '0.00', color: 'blue' },
  139 + { label: '月:', val: '0.00', color: 'blue' }
  140 +]
  141 +</script>
  142 +
  143 +<style scoped>
  144 +.ereport-dialog :deep(.el-dialog) {
  145 + max-height: 92vh;
  146 + display: flex; flex-direction: column;
  147 +}
  148 +.ereport-dialog :deep(.el-dialog__header) { padding: 10px 20px; border-bottom: 1px solid #e8e8e8; margin: 0; flex-shrink: 0; }
  149 +.ereport-dialog :deep(.el-dialog__body) { overflow-y: auto; flex: 1; }
  150 +.dialog-header { display: flex; align-items: center; justify-content: space-between; }
  151 +.title-text { font-size: 15px; font-weight: bold; color: #333; }
  152 +.header-right { display: flex; align-items: center; }
  153 +
  154 +.report-body { padding: 12px 0; }
  155 +
  156 +.top-section { display: grid; grid-template-columns: 1fr 200px; gap: 14px; margin-bottom: 14px; padding: 0 16px; }
  157 +.energy-cards-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
  158 +.energy-card-item {
  159 + border-radius: 6px; padding: 16px 12px; display: flex; flex-direction: column;
  160 + align-items: center; justify-content: center; color: #fff;
  161 +}
  162 +.energy-card-item.orange { background: linear-gradient(135deg, #f56c6c, #e74c3c); }
  163 +.energy-card-item.green { background: linear-gradient(135deg, #67c23a, #52c41a); }
  164 +.energy-card-item.blue { background: linear-gradient(135deg, #409eff, #1890ff); }
  165 +.card-label { font-size: 13px; opacity: 0.9; }
  166 +.card-val { font-size: 26px; font-weight: bold; margin-top: 6px; }
  167 +.card-val small { font-size: 13px; font-weight: normal; margin-left: 2px; }
  168 +
  169 +.carbon-panel { background: linear-gradient(160deg, #5b9bd5 0%, #2e75b6 100%); border-radius: 6px; padding: 14px; color: #fff; }
  170 +.carbon-title { font-size: 13px; font-weight: bold; margin-bottom: 8px; }
  171 +.carbon-sub { font-size: 11px; opacity: 0.85; margin-bottom: 10px; text-align: right; }
  172 +.carbon-row { padding: 7px 12px; border-radius: 4px; margin-bottom: 4px; font-size: 12px; background: rgba(255,255,255,0.18); }
  173 +.carbon-row.blue { background: rgba(64,158,255,0.35); }
  174 +
  175 +.charts-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; padding: 0 16px; }
  176 +.chart-card { background: #fff; border: 1px solid #eee; border-radius: 6px; overflow: hidden; }
  177 +.chart-card.full-width { grid-column: 1 / -1; }
  178 +.chart-header { padding: 10px 14px; border-bottom: 1px solid #f0f0f0; display: flex; justify-content: space-between; align-items: center; }
  179 +.chart-title { font-size: 13px; font-weight: bold; color: #333; }
  180 +.chart-tools { display: flex; align-items: center; gap: 6px; font-size: 11px; color: #666; }
  181 +.chart-tools label { cursor: pointer; display: flex; align-items: center; gap: 2px; }
  182 +.chart-body { padding: 10px 14px; }
  183 +.chart-body svg { width: 100%; height: auto; }
  184 +</style>
  1 +<script setup>
  2 +defineProps({
  3 + msg: {
  4 + type: String,
  5 + required: true,
  6 + },
  7 +})
  8 +</script>
  9 +
  10 +<template>
  11 + <div class="greetings">
  12 + <h1 class="green">{{ msg }}</h1>
  13 + <h3>
  14 + You’ve successfully created a project with
  15 + <a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
  16 + <a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
  17 + </h3>
  18 + </div>
  19 +</template>
  20 +
  21 +<style scoped>
  22 +h1 {
  23 + font-weight: 500;
  24 + font-size: 2.6rem;
  25 + position: relative;
  26 + top: -10px;
  27 +}
  28 +
  29 +h3 {
  30 + font-size: 1.2rem;
  31 +}
  32 +
  33 +.greetings h1,
  34 +.greetings h3 {
  35 + text-align: center;
  36 +}
  37 +
  38 +@media (min-width: 1024px) {
  39 + .greetings h1,
  40 + .greetings h3 {
  41 + text-align: left;
  42 + }
  43 +}
  44 +</style>
  1 +<template>
  2 + <el-dialog
  3 + :model-value="visible"
  4 + @update:model-value="$emit('update:visible', $event)"
  5 + :title="dialogTitle"
  6 + width="calc(100vw - 40px)"
  7 + :style="{ maxWidth: '1400px' }"
  8 + top="3vh"
  9 + destroy-on-close
  10 + class="oee-dialog"
  11 + >
  12 + <template #header>
  13 + <div class="dialog-header">
  14 + <div class="header-left">
  15 + <span class="title-text">{{ dialogTitle }}</span>
  16 + <span class="query-label">查询方式:</span>
  17 + <el-radio-group v-model="queryType" size="small">
  18 + <el-radio-button value="day">日查询</el-radio-button>
  19 + </el-radio-group>
  20 + <el-date-picker v-model="queryDate" type="date" placeholder="选择日期" size="small"
  21 + style="width: 160px; margin-left: 8px;" @change="fetchLampData" />
  22 + </div>
  23 + </div>
  24 + </template>
  25 +
  26 + <div class="oee-body">
  27 + <!-- OEE时序图 -->
  28 + <div class="chart-section">
  29 + <h4 class="section-title">OEE时序</h4>
  30 + <div class="timeline-chart" ref="timelineRef" @wheel.prevent="onWheel">
  31 + <canvas ref="canvasRef" :width="canvasW" :height="canvasH"
  32 + @mousemove="onCanvasMouseMove" @mouseleave="hoverSeg = null"></canvas>
  33 + <!-- 自定义悬浮提示框 -->
  34 + <div v-if="hoverSeg" class="hover-tooltip" :style="{ left: tooltipPos.x + 'px', top: tooltipPos.y + 'px' }">
  35 + <div class="tip-row"><span class="tip-label">开始时间:</span>{{ hoverSeg.startTimeText }}</div>
  36 + <div class="tip-row"><span class="tip-label">结束时间:</span>{{ hoverSeg.endTimeText }}</div>
  37 + <div class="tip-row"><span class="tip-label">状态:</span><span :style="{ color: stateColorMap[hoverSeg.state] }">{{ stateNameMap[hoverSeg.state] || '未知' }}</span></div>
  38 + <div class="tip-row"><span class="tip-label">持续时长:</span>{{ formatDuration(hoverSeg.duration) }}</div>
  39 + </div>
  40 + </div>
  41 + </div>
  42 +
  43 + <!-- 底部两栏 -->
  44 + <div class="bottom-grid">
  45 + <!-- 左侧:OEE时序详情表格 -->
  46 + <div class="table-panel">
  47 + <div class="panel-header">
  48 + <h4 class="panel-title">OEE时序详情</h4>
  49 + <div class="panel-actions">
  50 + <el-select v-model="durationFilter" placeholder="请选择" size="small" style="width: 140px;">
  51 + <el-option v-for="n in 60" :key="n" :label="`>${n}分`" :value="n"/>
  52 + </el-select>
  53 + </div>
  54 + </div>
  55 + <el-table :data="filteredTableData" size="small" stripe max-height="400" style="font-size: 12px;">
  56 + <el-table-column prop="startTime" label="开始时间" width="170" />
  57 + <el-table-column prop="status" label="状态" width="80">
  58 + <template #default="{ row }">
  59 + <el-tag :type="statusTagType(row.statusName)" size="small">{{ row.statusName }}</el-tag>
  60 + </template>
  61 + </el-table-column>
  62 + <el-table-column prop="durationText" label="运行时长" sortable width="100" />
  63 + <el-table-column prop="reason" label="原因" />
  64 + <el-table-column prop="operator" label="操作人" width="120" />
  65 + </el-table>
  66 + </div>
  67 +
  68 + <!-- 右侧:双图表(左右布局) -->
  69 + <div class="chart-panel">
  70 + <!-- 当日时长分布 — 实心饼图 -->
  71 + <div class="sub-chart">
  72 + <h4 class="panel-title">当日时长分布</h4>
  73 + <div class="legend-list">
  74 + <div class="legend-item"><span class="dot green"></span>绿灯</div>
  75 + <div class="legend-item"><span class="dot red"></span>红灯</div>
  76 + <div class="legend-item"><span class="dot yellow"></span>黄灯</div>
  77 + </div>
  78 + <div class="pie-canvas-wrap">
  79 + <canvas ref="pieCanvasRef" width="320" height="320" class="pie-canvas"
  80 + @mousemove="onPieMouseMove" @mouseleave="pieHoverItem = null"></canvas>
  81 + <!-- 饼图悬浮提示框 -->
  82 + <div v-if="pieHoverItem" class="pie-tooltip" :style="{ left: pieTooltipPos.x + 'px', top: pieTooltipPos.y + 'px' }">
  83 + <div class="pie-tip-title">时长详情</div>
  84 + <div class="pie-tip-row"><span class="dot" :style="{ background: pieHoverItem.color }"></span>{{ pieHoverItem.key }}:{{ formatDuration(pieHoverItem.sec) }}</div>
  85 + </div>
  86 + </div>
  87 + </div>
  88 + <!-- 异常原因分布 — 环形图 -->
  89 + <div class="sub-chart">
  90 + <h4 class="panel-title">异常原因分布</h4>
  91 + <div class="legend-list">
  92 + <div class="legend-item"><span class="dot" style="background:#f56c6c"></span>红灯未知原因</div>
  93 + <div class="legend-item"><span class="dot" style="background:#f5a623"></span>黄灯未知原因</div>
  94 + </div>
  95 + <div class="pie-canvas-wrap">
  96 + <canvas ref="reasonCanvasRef" width="320" height="320" class="pie-canvas"
  97 + @mousemove="onReasonMouseMove" @mouseleave="reasonHoverItem = null"></canvas>
  98 + <!-- 异常原因 hover 提示框 -->
  99 + <div v-if="reasonHoverItem" class="pie-tooltip" :style="{ left: reasonTooltipPos.x + 'px', top: reasonTooltipPos.y + 'px' }">
  100 + <div class="pie-tip-title">时长占比</div>
  101 + <div v-for="(row, i) in reasonHoverItem.rows" :key="i" class="pie-tip-row">{{ row.key }}总时长 {{ formatDuration(row.sec) }}</div>
  102 + <div class="pie-tip-row">时长占比 {{ reasonHoverItem.pct }}%</div>
  103 + </div>
  104 + </div>
  105 + </div>
  106 + </div>
  107 + </div>
  108 + </div>
  109 + </el-dialog>
  110 +</template>
  111 +
  112 +<script setup>
  113 +import { ref, reactive, computed, watch, onMounted, nextTick } from 'vue'
  114 +
  115 +const props = defineProps({
  116 + visible: Boolean,
  117 + device: Object
  118 +})
  119 +const emit = defineEmits(['update:visible'])
  120 +
  121 +const queryType = ref('day')
  122 +const queryDate = ref(new Date())
  123 +const durationFilter = ref(null)
  124 +
  125 +// 状态映射
  126 +const stateColorMap = { 0: '#909399', 1: '#c0392b', 2: '#e67e22', 3: '#67c23a', 4: '#2463aa' }
  127 +const stateNameMap = { '0': '灭灯', '1': '红灯', '2': '黄灯', '3': '绿灯', '4': '蓝灯' }
  128 +
  129 +// 数据
  130 +const lampData = ref([])
  131 +const stats = reactive({ off: '0秒', red: '0秒', yellow: '0秒', green: '0秒', blue: '0秒' })
  132 +
  133 +// 标题
  134 +const dialogTitle = computed(() => {
  135 + const name = props.device?.name || props.device?._raw?.deviceName || '设备'
  136 + return `${name} OEE时序`
  137 +})
  138 +
  139 +// 格式化日期 YYYY-MM-DD
  140 +function formatDate(d) {
  141 + if (!d) return new Date().toISOString().slice(0, 10)
  142 + const dt = new Date(d)
  143 + const y = dt.getFullYear()
  144 + const m = String(dt.getMonth() + 1).padStart(2, '0')
  145 + const dd = String(dt.getDate()).padStart(2, '0')
  146 + return `${y}-${m}-${dd}`
  147 +}
  148 +
  149 +// 秒数 → X分Y秒 / X时X分X秒
  150 +function formatDuration(seconds) {
  151 + if (!seconds || seconds <= 0) return '0秒'
  152 + seconds = Number(seconds)
  153 + const h = Math.floor(seconds / 3600)
  154 + const m = Math.floor((seconds % 3600) / 60)
  155 + const s = Math.round(seconds % 60)
  156 + if (h > 0) return `${h}时${m}分${s}秒`
  157 + if (m > 0) return `${m}分${s}秒`
  158 + return `${s}秒`
  159 +}
  160 +
  161 +// 解析时长字符串为秒数(用于筛选)
  162 +function parseDurationToSec(str) {
  163 + if (!str) return 0
  164 + let total = 0
  165 + const hMatch = str.match(/(\d+)时/)
  166 + const mMatch = str.match(/(\d+)分/)
  167 + const sMatch = str.match(/(\d+)秒/)
  168 + if (hMatch) total += parseInt(hMatch[1]) * 3600
  169 + if (mMatch) total += parseInt(mMatch[1]) * 60
  170 + if (sMatch) total += parseInt(sMatch[1])
  171 + return total
  172 +}
  173 +
  174 +// 表格数据
  175 +const tableData = computed(() => {
  176 + return lampData.value.map(item => ({
  177 + startTime: item.startTime,
  178 + status: item.lampState,
  179 + statusName: stateNameMap[String(item.lampState)] || '未知',
  180 + duration: item.duration,
  181 + durationText: formatDuration(item.duration),
  182 + reason: '无',
  183 + operator: '设备上传',
  184 + }))
  185 +})
  186 +
  187 +// 时长筛选后的表格数据
  188 +const filteredTableData = computed(() => {
  189 + if (!durationFilter.value) return tableData.value
  190 + const threshold = durationFilter.value * 60 // 分 → 秒
  191 + return tableData.value.filter(row => parseDurationToSec(row.durationText) >= threshold)
  192 +})
  193 +
  194 +// ========== 时序图 Canvas 绘制 ==========
  195 +const CANVAS_H = 100
  196 +const timelineRef = ref(null)
  197 +const canvasRef = ref(null)
  198 +const zoomLevel = ref(1)
  199 +const minZoom = 0.001
  200 +const maxZoom = 1
  201 +const hoverSeg = ref(null)
  202 +const tooltipPos = reactive({ x: 0, y: 0 })
  203 +const containerW = ref(900) // 容器 CSS 宽度
  204 +const canvasW = ref(900) // canvas 像素宽(=容器宽,1:1映射)
  205 +const canvasH = ref(CANVAS_H) // canvas 像素高
  206 +const viewOffsetX = ref(0) // 视口偏移(数据空间)
  207 +
  208 +// 格式化时间字符串 (用于tooltip)
  209 +function formatTimeStr(isoStr) {
  210 + if (!isoStr) return ''
  211 + const d = new Date(isoStr)
  212 + const m = String(d.getMonth() + 1).padStart(2, '0')
  213 + const dd = String(d.getDate()).padStart(2, '0')
  214 + const h = String(d.getHours()).padStart(2, '0')
  215 + const min = String(d.getMinutes()).padStart(2, '0')
  216 + const s = String(d.getSeconds()).padStart(2, '0')
  217 + return `${m}/${dd} ${h}:${min}:${s}`
  218 +}
  219 +
  220 +// 计算结束时间
  221 +function calcEndTime(startTime, durationSec) {
  222 + if (!startTime) return ''
  223 + const d = new Date(startTime)
  224 + d.setSeconds(d.getSeconds() + (durationSec || 0))
  225 + return formatTimeStr(d.toISOString())
  226 +}
  227 +
  228 +function onWheel(e) {
  229 + const container = timelineRef.value
  230 + if (!container) return
  231 + const rect = container.getBoundingClientRect()
  232 + const mx = e.clientX - rect.left
  233 +
  234 + const mouseDataX = mx * zoomLevel.value + viewOffsetX.value
  235 + // 向上滚动(deltaY < 0)缩小,向下(deltaY > 0)放大
  236 + const delta = e.deltaY < 0 ? 0.8 : 1.25
  237 + const nextZ = Math.max(minZoom, Math.min(maxZoom, zoomLevel.value * delta))
  238 + viewOffsetX.value = mouseDataX - mx * nextZ
  239 + zoomLevel.value = nextZ
  240 +}
  241 +
  242 +// 数据空间:24h → plotW 像素(zoom=1时),左侧留 offset 像素放标签
  243 +const rawSegments = computed(() => {
  244 + if (!lampData.value.length) return []
  245 + const dayStr = formatDate(queryDate.value)
  246 + const [y, m, d] = dayStr.split('-').map(Number)
  247 + const dayStartMs = new Date(y, m - 1, d).getTime()
  248 + const plotLeft = 55
  249 + const plotW = canvasW.value - plotLeft - 10
  250 +
  251 + return lampData.value.map(item => {
  252 + const startMs = new Date(item.startTime).getTime()
  253 + const durSec = item.duration || 0
  254 + const endMs = startMs + durSec * 1000
  255 +
  256 + const startX = ((startMs - dayStartMs) / 86400000) * plotW + plotLeft
  257 + const endX = ((endMs - dayStartMs) / 86400000) * plotW + plotLeft
  258 + const x = Math.max(plotLeft, startX)
  259 + const w = Math.max(1, endX - x)
  260 +
  261 + return { x, w,
  262 + state: String(item.lampState),
  263 + startTime: item.startTime,
  264 + duration: item.duration,
  265 + startTimeText: formatTimeStr(item.startTime),
  266 + endTimeText: calcEndTime(item.startTime, item.duration),
  267 + }
  268 + })
  269 +})
  270 +
  271 +// Canvas 绘制 —— 数据坐标 → 屏幕坐标: screenX = (dataX - viewOffsetX) / zoomLevel
  272 +function drawTimeline() {
  273 + const canvas = canvasRef.value
  274 + if (!canvas) return
  275 + const ctx = canvas.getContext('2d')
  276 + const W = canvasW.value
  277 + const H = canvasH.value
  278 + const z = zoomLevel.value
  279 + const vo = viewOffsetX.value
  280 +
  281 + // 布局参数(参考目标样式:时刻左上、条带居中、时间轴底部)
  282 + const labelLeft = 50 // "时刻" 标签 X 偏移
  283 + const plotLeft = 55 // 数据区起点 X
  284 + const plotW = W - plotLeft - 10 // 数据区宽度
  285 + const barY = 24 // 条带顶部 Y
  286 + const barH = 46 // 条带高度
  287 + const axisY = barY + barH + 8 // 分隔线 Y
  288 + const timeLabelY = H - 4 // 时间标签 Y
  289 +
  290 + ctx.clearRect(0, 0, W, H)
  291 +
  292 + // "时刻" 标签
  293 + ctx.fillStyle = '#999'
  294 + ctx.font = '12px sans-serif'
  295 + ctx.fillText('时刻', labelLeft - vo / z, 16)
  296 +
  297 + // 时间轴标签 — 整数刻度对齐
  298 + const totalSec = 24 * 3600
  299 + // 视口可见时间跨度(秒)
  300 + const visSpanSec = Math.max(60, (W * z / plotW) * totalSec)
  301 + // 根据可见跨度选漂亮步长:确保屏幕上约显示 6~10 个标签
  302 + let stepSec = 14400 // 默认 4 小时
  303 + if (visSpanSec <= 120) stepSec = 30 // <2分钟 → 每30秒
  304 + else if (visSpanSec <= 300) stepSec = 60 // <5分钟 → 每分钟
  305 + else if (visSpanSec <= 600) stepSec = 300 // <10分钟 → 每5分钟
  306 + else if (visSpanSec <= 1800) stepSec = 600 // <30分钟 → 每10分钟
  307 + else if (visSpanSec <= 3600) stepSec = 900 // <1小时 → 每15分钟
  308 + else if (visSpanSec <= 7200) stepSec = 1800// <2小时 → 每30分钟
  309 + else if (visSpanSec <= 28800) stepSec = 3600 // <8小时 → 每小时
  310 + else stepSec = 7200 // >=8小时 → 每2小时
  311 +
  312 + ctx.font = '11px sans-serif'
  313 + ctx.fillStyle = '#666'
  314 +
  315 + // 视口左边界对应的时间(秒)
  316 + const leftSec = ((vo - plotLeft) / plotW) * totalSec
  317 + // 对齐到 stepSec 边界(向下取整),找第一个标签
  318 + let firstSec = Math.floor(leftSec / stepSec) * stepSec
  319 + if (firstSec < 0) firstSec = 0
  320 +
  321 + // 整数循环,只画整数刻度
  322 + for (let s = firstSec; s <= totalSec + stepSec * 2; s += stepSec) {
  323 + const dataPx = plotLeft + (s / totalSec) * plotW
  324 + const screenPx = (dataPx - vo) / z
  325 + if (screenPx < -50 || screenPx > W + 50) continue
  326 +
  327 + const h = Math.floor(s / 3600)
  328 + const mm = Math.floor((s % 3600) / 60)
  329 + const ss = s % 60
  330 +
  331 + if (stepSec < 60) {
  332 + ctx.fillText(`${String(h).padStart(2,'0')}:${String(mm).padStart(2,'0')}:${String(ss).padStart(2,'0')}`, screenPx, timeLabelY)
  333 + } else {
  334 + ctx.fillText(`${String(h).padStart(2,'0')}:${String(mm).padStart(2,'0')}`, screenPx, timeLabelY)
  335 + }
  336 + }
  337 +
  338 + // 分隔线(条带与时间轴之间)
  339 + ctx.strokeStyle = '#ddd'
  340 + ctx.lineWidth = 1
  341 + ctx.beginPath()
  342 + ctx.moveTo((plotLeft - vo) / z, axisY)
  343 + ctx.lineTo(((plotLeft + plotW) - vo) / z, axisY)
  344 + ctx.stroke()
  345 +
  346 + // 条带
  347 + const hoveredIdx = hoverSeg.value ? rawSegments.value.indexOf(hoverSeg.value) : -1
  348 +
  349 + rawSegments.value.forEach((seg, idx) => {
  350 + const sx = (seg.x - vo) / z
  351 + const sw = seg.w / z
  352 + if (sx + sw < -1 || sx > W + 1) return
  353 +
  354 + ctx.fillStyle = stateColorMap[seg.state] || '#909399'
  355 + ctx.globalAlpha = idx === hoveredIdx ? 0.7 : 1
  356 +
  357 + // 纯矩形,无圆角
  358 + ctx.fillRect(sx, barY, sw, barH)
  359 + })
  360 +
  361 + ctx.globalAlpha = 1
  362 +}
  363 +
  364 +// 鼠标 hit test
  365 +function onCanvasMouseMove(e) {
  366 + const container = timelineRef.value
  367 + if (!container) return
  368 + const rect = container.getBoundingClientRect()
  369 + const mx = e.clientX - rect.left
  370 + const my = e.clientY - rect.top
  371 + const z = zoomLevel.value
  372 + const vo = viewOffsetX.value
  373 + const dataX = mx * z + vo
  374 +
  375 + // 与 drawTimeline 中一致的条带位置
  376 + const barY = 24
  377 + const barH = 46
  378 + let found = null
  379 +
  380 + for (let i = rawSegments.value.length - 1; i >= 0; i--) {
  381 + const seg = rawSegments.value[i]
  382 + if (dataX >= seg.x && dataX <= seg.x + seg.w && my >= barY && my <= barY + barH) {
  383 + found = seg
  384 + break
  385 + }
  386 + }
  387 +
  388 + hoverSeg.value = found
  389 + if (found) {
  390 + tooltipPos.x = Math.min(Math.max(mx + 12, 12), rect.width - 190)
  391 + tooltipPos.y = Math.max(my - 80, 6)
  392 + }
  393 +}
  394 +
  395 +// ========== 监听容器尺寸变化 ==========
  396 +function updateCanvasSize() {
  397 + if (!timelineRef.value) return
  398 + // 减去 padding (左右各 6px ≈ 12px)
  399 + containerW.value = timelineRef.value.clientWidth - 12
  400 + canvasW.value = containerW.value
  401 + canvasH.value = CANVAS_H
  402 +}
  403 +
  404 +// ========== 饼图 Canvas ==========
  405 +const pieCanvasRef = ref(null)
  406 +const reasonCanvasRef = ref(null)
  407 +const pieHoverItem = ref(null)
  408 +const pieTooltipPos = reactive({ x: 0, y: 0 })
  409 +const reasonHoverItem = ref(null)
  410 +const reasonTooltipPos = reactive({ x: 0, y: 0 })
  411 +// 存储饼图扇区角度范围用于 hover 检测
  412 +let pieAngleRanges = []
  413 +let reasonAngleRanges = []
  414 +
  415 +// 当日时长分布 — 各状态秒数
  416 +const stateSeconds = computed(() => ({
  417 + green: parseDurationToSec(stats.green),
  418 + red: parseDurationToSec(stats.red),
  419 + yellow: parseDurationToSec(stats.yellow)
  420 +}))
  421 +
  422 +const totalSeconds = computed(() => {
  423 + return stateSeconds.value.green + stateSeconds.value.red + stateSeconds.value.yellow || 1
  424 +})
  425 +
  426 +// 异常原因分布 — 只用 lampDurationStats 中红灯 + 黄灯的数据
  427 +const reasonStats = computed(() => {
  428 + const redSec = parseDurationToSec(stats.red)
  429 + const yellowSec = parseDurationToSec(stats.yellow)
  430 + const items = []
  431 + if (redSec > 0) items.push({ key: '红灯', sec: redSec, color: '#f56c6c' })
  432 + if (yellowSec > 0) items.push({ key: '黄灯', sec: yellowSec, color: '#f5a623' })
  433 + return items
  434 +})
  435 +
  436 +function drawPieChart(canvasRefKey, items, options = {}) {
  437 + const canvas = canvasRefKey?.value
  438 + if (!canvas) return
  439 + const ctx = canvas.getContext('2d')
  440 + const W = canvas.width, H = canvas.height
  441 + const cx = W / 2, cy = H / 2
  442 + const r = Math.min(W, H) / 2 - 8
  443 + const solid = !!options.solid // 实心饼图(无内圆)
  444 + const innerR = solid ? 0 : r * 0.55
  445 +
  446 + ctx.clearRect(0, 0, W, H)
  447 +
  448 + if (!items || items.length === 0) {
  449 + ctx.beginPath()
  450 + ctx.arc(cx, cy, r, 0, Math.PI * 2)
  451 + if (!solid) { ctx.arc(cx, cy, innerR, 0, Math.PI * 2, true) }
  452 + ctx.fillStyle = '#eee'
  453 + ctx.fill()
  454 + ctx.fillStyle = '#999'
  455 + ctx.font = '12px sans-serif'
  456 + ctx.textAlign = 'center'
  457 + ctx.textBaseline = 'middle'
  458 + ctx.fillText('暂无数据', cx, cy)
  459 + // 清空角度范围
  460 + if (canvas === pieCanvasRef.value) pieAngleRanges = []
  461 + if (canvas === reasonCanvasRef.value) reasonAngleRanges = []
  462 + return
  463 + }
  464 +
  465 + const total = items.reduce((s, i) => s + i.sec, 0) || 1
  466 + let startAngle = -Math.PI / 2
  467 +
  468 + // 重置对应画布的角度范围
  469 + if (canvas === pieCanvasRef.value) pieAngleRanges = []
  470 + if (canvas === reasonCanvasRef.value) reasonAngleRanges = []
  471 +
  472 + items.forEach(item => {
  473 + const angle = (item.sec / total) * Math.PI * 2
  474 + const endAngle = startAngle + angle
  475 + const midAngle = startAngle + angle / 2
  476 +
  477 + // 扇区路径
  478 + ctx.beginPath()
  479 + if (solid) {
  480 + ctx.moveTo(cx, cy)
  481 + ctx.arc(cx, cy, r, startAngle, endAngle)
  482 + ctx.closePath()
  483 + } else {
  484 + ctx.moveTo(cx + innerR * Math.cos(startAngle), cy + innerR * Math.sin(startAngle))
  485 + ctx.arc(cx, cy, r, startAngle, endAngle)
  486 + ctx.arc(cx, cy, innerR, endAngle, startAngle, true)
  487 + ctx.closePath()
  488 + }
  489 + ctx.fillStyle = item.color
  490 + ctx.fill()
  491 +
  492 + // 记录角度范围用于 hover 检测
  493 + if (canvas === pieCanvasRef.value) {
  494 + pieAngleRanges.push({ ...item, startAngle, endAngle, cx, cy, r, innerR, total })
  495 + } else if (canvas === reasonCanvasRef.value) {
  496 + reasonAngleRanges.push({ ...item, startAngle, endAngle, cx, cy, r, innerR, total })
  497 + }
  498 +
  499 + // 标签
  500 + if (angle > 0.25) {
  501 + const labelR = solid ? r * 0.65 : (r + innerR) / 2
  502 + const lx = cx + labelR * Math.cos(midAngle)
  503 + const ly = cy + labelR * Math.sin(midAngle)
  504 + const pct = (item.sec / total * 100).toFixed(2)
  505 +
  506 + ctx.fillStyle = '#fff'
  507 + // canvas 分辨率 320,字体需放大以匹配显示尺寸
  508 + ctx.font = solid ? 'bold 18px sans-serif' : 'bold 16px sans-serif'
  509 + ctx.textAlign = 'center'
  510 + ctx.textBaseline = 'middle'
  511 + ctx.fillText(`${pct}%`, lx, ly - (solid ? 11 : 8))
  512 +
  513 + ctx.font = solid ? '14px sans-serif' : '12px sans-serif'
  514 + if (solid) {
  515 + const h = Math.floor(item.sec / 3600)
  516 + const m = Math.floor((item.sec % 3600) / 60)
  517 + let durText = ''
  518 + if (h > 0) durText = `${item.key}:${h}.${String(m).padStart(2,'0')}时`
  519 + else if (m > 0) durText = `${item.key}:${m}分`
  520 + else durText = `${item.key}:${Math.round(item.sec % 60)}秒`
  521 + ctx.fillText(durText, lx, ly + 11)
  522 + } else {
  523 + ctx.fillText(item.key, lx, ly + (solid ? 12 : 10))
  524 + }
  525 + }
  526 +
  527 + startAngle = endAngle
  528 + })
  529 +}
  530 +
  531 +// 饼图 hover 检测
  532 +function onPieMouseMove(e) {
  533 + const canvas = pieCanvasRef.value
  534 + if (!canvas) return
  535 + const rect = canvas.getBoundingClientRect()
  536 + const mx = e.clientX - rect.left
  537 + const my = e.clientY - rect.top
  538 + // 转换为 canvas 内部坐标(考虑 CSS 缩放)
  539 + const scaleX = canvas.width / rect.width
  540 + const scaleY = canvas.height / rect.height
  541 + const px = mx * scaleX
  542 + const py = my * scaleY
  543 +
  544 + let found = null
  545 + for (let i = pieAngleRanges.length - 1; i >= 0; i--) {
  546 + const seg = pieAngleRanges[i]
  547 + const dx = px - seg.cx
  548 + const dy = py - seg.cy
  549 + const dist = Math.sqrt(dx * dx + dy * dy)
  550 +
  551 + // 判断是否在扇区内(实心:dist <= r;环形:innerR < dist <= r)
  552 + const inRadius = dist <= seg.r && dist >= seg.innerR
  553 + if (!inRadius) continue
  554 +
  555 + // 计算鼠标角度,与扇区角度比较
  556 + let mouseAngle = Math.atan2(dy, dx)
  557 + // 归一化角度到 [-PI, PI],然后统一到 startAngle~endAngle 的范围
  558 + // 简化处理:直接比较,考虑跨 -PI 边界的情况
  559 + let a = mouseAngle
  560 + let sa = seg.startAngle
  561 + let ea = seg.endAngle
  562 +
  563 + // 处理跨边界情况
  564 + function inRange(a, sa, ea) {
  565 + // 标准化为 [0, 2PI)
  566 + const norm = v => { let x = v % (Math.PI * 2); if (x < 0) x += Math.PI * 2; return x }
  567 + const na = norm(a), nsa = norm(sa), nea = norm(ea)
  568 + if (nea >= nsa) return na >= nsa && na <= nea
  569 + else return na >= nsa || na <= nea
  570 + }
  571 +
  572 + if (inRange(a, sa, ea)) {
  573 + found = seg
  574 + break
  575 + }
  576 + }
  577 +
  578 + pieHoverItem.value = found
  579 + if (found) {
  580 + pieTooltipPos.x = Math.min(Math.max(mx + 12, 12), rect.width - 160)
  581 + pieTooltipPos.y = Math.max(my - 60, 6)
  582 + }
  583 +}
  584 +
  585 +// 异常原因分布 hover 检测 — tooltip 显示"时长占比"格式
  586 +function onReasonMouseMove(e) {
  587 + const canvas = reasonCanvasRef.value
  588 + if (!canvas) return
  589 + const rect = canvas.getBoundingClientRect()
  590 + const mx = e.clientX - rect.left
  591 + const my = e.clientY - rect.top
  592 + const scaleX = canvas.width / rect.width
  593 + const scaleY = canvas.height / rect.height
  594 + const px = mx * scaleX
  595 + const py = my * scaleY
  596 +
  597 + let found = null
  598 + for (let i = reasonAngleRanges.length - 1; i >= 0; i--) {
  599 + const seg = reasonAngleRanges[i]
  600 + const dx = px - seg.cx
  601 + const dy = py - seg.cy
  602 + const dist = Math.sqrt(dx * dx + dy * dy)
  603 + const inRadius = dist <= seg.r && dist >= seg.innerR
  604 + if (!inRadius) continue
  605 +
  606 + const mouseAngle = Math.atan2(dy, dx)
  607 + function inRange(a, sa, ea) {
  608 + const norm = v => { let x = v % (Math.PI * 2); if (x < 0) x += Math.PI * 2; return x }
  609 + const na = norm(a), nsa = norm(sa), nea = norm(ea)
  610 + if (nea >= nsa) return na >= nsa && na <= nea
  611 + else return na >= nsa || na <= nea
  612 + }
  613 +
  614 + if (inRange(mouseAngle, seg.startAngle, seg.endAngle)) {
  615 + found = seg
  616 + break
  617 + }
  618 + }
  619 +
  620 + // 构造 tooltip 数据:显示所有项 + 总占比
  621 + if (found || reasonAngleRanges.length > 0) {
  622 + const total = reasonAngleRanges.reduce((s, r) => s + r.sec, 0) || 1
  623 + const pct = (found ? found.sec / total : total > 0 ? 1 : 0) * 100
  624 + reasonHoverItem.value = found ? {
  625 + rows: [{ key: found.key, sec: found.sec }],
  626 + pct: pct.toFixed(2)
  627 + } : {
  628 + rows: reasonAngleRanges.map(r => ({ key: r.key, sec: r.sec })),
  629 + pct: '100.00'
  630 + }
  631 + if (!found) {
  632 + // 悬浮在空白区域显示所有数据
  633 + reasonHoverItem.value = {
  634 + rows: reasonAngleRanges.map(r => ({ key: r.key, sec: r.sec })),
  635 + pct: '100.00'
  636 + }
  637 + }
  638 + } else {
  639 + reasonHoverItem.value = null
  640 + }
  641 +
  642 + if (reasonHoverItem.value) {
  643 + reasonTooltipPos.x = Math.min(Math.max(mx + 12, 12), rect.width - 180)
  644 + reasonTooltipPos.y = Math.max(my - 70, 6)
  645 + }
  646 +}
  647 +
  648 +// 绘制当日时长分布饼图(实心)
  649 +function drawDurationPie() {
  650 + const { green, red, yellow } = stateSeconds.value
  651 + const items = []
  652 + if (green > 0) items.push({ key: '绿灯', sec: green, color: '#67c23a' })
  653 + if (red > 0) items.push({ key: '红灯', sec: red, color: '#f56c6c' })
  654 + if (yellow > 0) items.push({ key: '黄灯', sec: yellow, color: '#f5a623' })
  655 + drawPieChart(pieCanvasRef, items, { solid: true })
  656 +}
  657 +
  658 +// 绘制异常原因分布饼图(环形)
  659 +function drawReasonPie() {
  660 + drawPieChart(reasonCanvasRef, reasonStats.value)
  661 +}
  662 +
  663 +// ========== 接口调用 ==========
  664 +async function fetchLampData() {
  665 + const dtuSn = props.device?._raw?.dtuSn || ''
  666 + const date = formatDate(queryDate.value)
  667 + if (!dtuSn) return
  668 + try {
  669 + const res = await fetch(`/api/device/lampData?dtuSn=${dtuSn}&date=${date}`)
  670 + const data = await res.json()
  671 + // list 中只有一个元素,取其 lampData
  672 + const entry = (data.list && data.list[0]) || {}
  673 + lampData.value = (entry.lampData || []).sort((a, b) =>
  674 + new Date(b.startTime) - new Date(a.startTime)
  675 + )
  676 + // 统计
  677 + const s = data.lampDurationStats || {}
  678 + stats.off = s.off || '0秒'
  679 + stats.red = s.red || '0秒'
  680 + stats.yellow = s.yellow || '0秒'
  681 + stats.green = s.green || '0秒'
  682 + stats.blue = s.blue || '0秒'
  683 + } catch (err) {
  684 + console.error('获取灯数据失败:', err)
  685 + }
  686 +}
  687 +
  688 +function statusTagType(status) {
  689 + const map = { '绿灯': '', '黄灯': 'warning', '红灯': 'danger', '蓝灯': '', '灭灯': 'info' }
  690 + return map[status] || ''
  691 +}
  692 +
  693 +// 弹窗打开时自动请求
  694 +watch(() => props.visible, (val) => {
  695 + if (val) {
  696 + fetchLampData()
  697 + // 等 Vue DOM 更新后获取正确尺寸,再等 dialog 动画结束再次确认
  698 + nextTick(() => {
  699 + updateCanvasSize()
  700 + setTimeout(updateCanvasSize, 350)
  701 + })
  702 + }
  703 +})
  704 +
  705 +// 数据或视口变化时重绘
  706 +watch([lampData, zoomLevel, viewOffsetX, canvasW], () => {
  707 + nextTick(drawTimeline)
  708 +}, { deep: true })
  709 +
  710 +// 饼图数据变化时重绘
  711 +watch([stats, lampData], () => {
  712 + nextTick(() => {
  713 + drawDurationPie()
  714 + drawReasonPie()
  715 + })
  716 +}, { deep: true })
  717 +
  718 +onMounted(() => {
  719 + updateCanvasSize()
  720 + const el = timelineRef.value
  721 + if (!el) return
  722 + const ro = new ResizeObserver(updateCanvasSize)
  723 + ro.observe(el)
  724 + // 初始绘制饼图
  725 + nextTick(() => { drawDurationPie(); drawReasonPie() })
  726 +})
  727 +</script>
  728 +
  729 +<style scoped>
  730 +.oee-dialog :deep(.el-dialog) {
  731 + max-height: 92vh;
  732 + display: flex;
  733 + flex-direction: column;
  734 +}
  735 +.oee-dialog :deep(.el-dialog__header) {
  736 + padding: 12px 20px;
  737 + border-bottom: 1px solid #e8e8e8;
  738 + margin: 0;
  739 + flex-shrink: 0;
  740 +}
  741 +.oee-dialog :deep(.el-dialog__body) {
  742 + overflow-y: auto;
  743 + flex: 1;
  744 +}
  745 +.dialog-header {
  746 + display: flex;
  747 + align-items: center;
  748 +}
  749 +.header-left {
  750 + display: flex;
  751 + align-items: center;
  752 + gap: 8px;
  753 +}
  754 +.title-text {
  755 + font-size: 15px;
  756 + font-weight: bold;
  757 + color: #333;
  758 +}
  759 +.query-label {
  760 + font-size: 13px;
  761 + color: #666;
  762 + white-space: nowrap;
  763 +}
  764 +
  765 +.oee-body { padding: 0; }
  766 +.chart-section {
  767 + border-bottom: 1px solid #ebeef5;
  768 + padding: 12px 16px;
  769 +}
  770 +.section-title {
  771 + font-size: 14px;
  772 + font-weight: bold;
  773 + color: #333;
  774 + margin: 0 0 8px 0;
  775 +}
  776 +.timeline-chart {
  777 + background: #fff;
  778 + border: 1px solid #e0e0e0;
  779 + border-radius: 4px;
  780 + padding: 6px;
  781 + overflow: hidden;
  782 + position: relative;
  783 +}
  784 +.timeline-chart canvas {
  785 + display: block;
  786 +}
  787 +
  788 +.hover-tooltip {
  789 + position: absolute;
  790 + background: rgba(32, 40, 52, 0.92);
  791 + color: #fff;
  792 + font-size: 12px;
  793 + padding: 10px 14px;
  794 + border-radius: 6px;
  795 + pointer-events: none;
  796 + z-index: 100;
  797 + white-space: nowrap;
  798 + box-shadow: 0 4px 16px rgba(0,0,0,0.25);
  799 + line-height: 1.7;
  800 +}
  801 +.tip-row { white-space: nowrap; }
  802 +.tip-label { color: #aaa; }
  803 +
  804 +.bottom-grid {
  805 + display: grid;
  806 + grid-template-columns: 1fr 1fr;
  807 + gap: 12px;
  808 +}
  809 +.table-panel {
  810 + border: 1px solid #ebeef5;
  811 + border-radius: 4px;
  812 + overflow: hidden;
  813 +}
  814 +.panel-header {
  815 + display: flex;
  816 + justify-content: space-between;
  817 + align-items: center;
  818 + padding: 12px 16px;
  819 + border-bottom: 1px solid #ebeef5;
  820 + background: #fafafa;
  821 +}
  822 +.panel-title {
  823 + font-size: 14px;
  824 + font-weight: bold;
  825 + color: #333;
  826 + margin: 0;
  827 +}
  828 +.panel-actions { display: flex; gap: 8px; }
  829 +
  830 +.chart-panel {
  831 + border: 1px solid #ebeef5;
  832 + border-radius: 4px;
  833 + padding: 16px;
  834 + background: #fafafa;
  835 + display: flex;
  836 + flex-direction: row;
  837 + align-items: center;
  838 + justify-content: center;
  839 + gap: 56px;
  840 +}
  841 +.sub-chart {
  842 + display: flex;
  843 + flex-direction: column;
  844 + align-items: center;
  845 + gap: 8px;
  846 + flex: 0 0 auto;
  847 +}
  848 +.sub-chart .panel-title {
  849 + font-size: 13px;
  850 + font-weight: bold;
  851 + color: #333;
  852 + margin: 0;
  853 +}
  854 +.legend-list {
  855 + display: flex;
  856 + flex-wrap: wrap;
  857 + gap: 12px;
  858 + justify-content: center;
  859 + font-size: 12px;
  860 + color: #666;
  861 +}
  862 +.legend-item {
  863 + display: flex;
  864 + align-items: center;
  865 + gap: 4px;
  866 +}
  867 +.dot {
  868 + width: 10px;
  869 + height: 10px;
  870 + border-radius: 50%;
  871 +}
  872 +.dot.blue { background: #409eff; }
  873 +.dot.red { background: #f56c6c; }
  874 +.dot.yellow { background: #f5a623; }
  875 +.dot.green { background: #67c23a; }
  876 +.dot.gray { background: #909399; }
  877 +
  878 +.pie-canvas-wrap {
  879 + position: relative;
  880 + display: flex;
  881 + align-items: center;
  882 + justify-content: center;
  883 +}
  884 +.pie-canvas {
  885 + width: 200px;
  886 + height: 200px;
  887 +}
  888 +.pie-tooltip {
  889 + position: absolute;
  890 + background: rgba(255, 255, 255, 0.96);
  891 + color: #333;
  892 + font-size: 12px;
  893 + padding: 8px 14px;
  894 + border-radius: 6px;
  895 + pointer-events: none;
  896 + z-index: 100;
  897 + box-shadow: 0 2px 12px rgba(0,0,0,0.15);
  898 + border: 1px solid #e4e7ed;
  899 + white-space: nowrap;
  900 +}
  901 +.pie-tip-title {
  902 + font-weight: bold;
  903 + margin-bottom: 4px;
  904 + color: #333;
  905 + border-bottom: 1px solid #ebeef5;
  906 + padding-bottom: 4px;
  907 +}
  908 +.pie-tip-row {
  909 + display: flex;
  910 + align-items: center;
  911 + gap: 6px;
  912 +}
  913 +</style>
  1 +<template>
  2 + <el-dialog
  3 + :model-value="visible"
  4 + @update:model-value="$emit('update:visible', $event)"
  5 + title=""
  6 + width="calc(100vw - 40px)"
  7 + :style="{ maxWidth: '1400px' }"
  8 + top="3vh"
  9 + destroy-on-close
  10 + class="param-dialog"
  11 + >
  12 + <template #header>
  13 + <div class="dialog-header">
  14 + <span class="title-text">{{ device?.name || '能耗设备1' }}</span>
  15 + <div class="header-right">
  16 + <el-icon :size="16" style="cursor:pointer;color:#409eff;"><Refresh /></el-icon>
  17 + <el-icon :size="16" style="cursor:pointer;color:#409eff;margin-left:6px;"><Grid /></el-icon>
  18 + <el-icon :size="16" style="cursor:pointer;color:#409eff;margin-left:6px;"><List /></el-icon>
  19 + <el-icon :size="16" style="cursor:pointer;color:#409eff;margin-left:6px;" @click="$emit('update:visible', false)"><Close /></el-icon>
  20 + </div>
  21 + </div>
  22 + </template>
  23 +
  24 + <div class="param-body">
  25 + <!-- 相位标签 -->
  26 + <div class="phase-tabs">
  27 + <div v-for="p in phases" :key="p" :class="['phase-tab', { active: activePhase === p }]"
  28 + @click="activePhase = p">{{ p }}:0</div>
  29 + </div>
  30 +
  31 + <!-- 主内容区:左侧数据表 + 右侧统计 -->
  32 + <div class="main-grid">
  33 + <!-- 左侧:电压电流功率温度表格 + 曲线 -->
  34 + <div class="left-panel">
  35 + <div class="data-table-area">
  36 + <table class="param-table">
  37 + <thead>
  38 + <tr><th></th><th>电压</th><th>电流</th><th>功率</th><th>温度</th></tr>
  39 + </thead>
  40 + <tbody>
  41 + <tr v-for="row in tableRows" :key="row.label">
  42 + <td class="row-label">{{ row.label }}</td>
  43 + <td>{{ row.voltage }}</td>
  44 + <td>{{ row.current }}</td>
  45 + <td>{{ row.power }}</td>
  46 + <td>{{ row.temp }}</td>
  47 + </tr>
  48 + </tbody>
  49 + </table>
  50 + <!-- 右侧额外信息 -->
  51 + <div class="extra-info">
  52 + <div v-for="(info, i) in extraInfos" :key="i" class="ei-item">{{ info }}:0</div>
  53 + </div>
  54 + </div>
  55 +
  56 + <!-- 电流均值/峰值曲线 -->
  57 + <div class="curve-section">
  58 + <div class="curve-header">
  59 + <span class="curve-title">电流均值/峰值曲线 ▼</span>
  60 + <el-date-picker v-model="curveDate" type="date" size="small" placeholder="2026-04-28" />
  61 + </div>
  62 + <div class="curve-chart">
  63 + <svg viewBox="0 0 700 180">
  64 + <g font-size="10" fill="#999" text-anchor="end">
  65 + <text x="24" y="18">5</text><text x="24" y="53">4</text><text x="24" y="88">3</text>
  66 + <text x="24" y="123">2</text><text x="24" y="158">1</text>
  67 + </g>
  68 + <line x1="30" y1="154" x2="680" y2="154" stroke="#ddd"/>
  69 + <polyline points="36,154 56,154 76,154 ... 660,154" fill="none" stroke="#f5a623" stroke-width="1.2"/>
  70 + <g font-size="8" fill="#666" text-anchor="middle">
  71 + <text x="46" y="168">00:00</text><text x="130" y="168">04:00</text>
  72 + <text x="220" y="168">08:00</text><text x="310" y="168">12:00</text>
  73 + <text x="400" y="168">16:00</text><text x="490" y="168">20:00</text><text x="580" y="168">24:00</text>
  74 + </g>
  75 + </svg>
  76 + </div>
  77 + <div class="curve-legend">
  78 + <span class="leg"><i class="dot y"/>电流最大值</span>
  79 + <span class="leg"><i class="dot g"/>电流最小值</span>
  80 + <span class="leg"><i class="dot r"/>电流瞬时平均值</span>
  81 + </div>
  82 + </div>
  83 +
  84 + <!-- 电能 & 相位角 -->
  85 + <div class="bottom-row">
  86 + <div class="power-card">
  87 + <div class="pc-title">电能</div>
  88 + <div class="pc-list">
  89 + <div v-for="(p, i) in powerItems" :key="i" :class="['pc-item', p.color]">
  90 + <span class="pc-dot"></span> {{ p.label }}
  91 + <span class="pc-val">{{ p.val }}</span>
  92 + </div>
  93 + </div>
  94 + </div>
  95 + <div class="angle-card">
  96 + <div class="ac-title">相位角</div>
  97 + <div class="ac-charts">
  98 + <div class="ac-pie-wrap">
  99 + <svg viewBox="0 0 120 120"><circle cx="60" cy="60" r="48" fill="#e8f4fd"/><text x="60" y="55" text-anchor="middle" font-size="11" fill="#333">电压相位角</text>
  100 + <g font-size="10" fill="#666"><text x="45" y="72">A相 0</text><text x="75" y="72">B相 0</text><text x="60" y="86">C相 0</text></g>
  101 + <circle cx="35" cy="90" r="3" fill="#e74c3c"/><circle cx="60" cy="93" r="3" fill="#67c23a"/><circle cx="85" cy="90" r="3" fill="#409eff"/>
  102 + </svg>
  103 + </div>
  104 + <div class="ac-pie-wrap">
  105 + <svg viewBox="0 0 120 120"><circle cx="60" cy="60" r="48" fill="#e8f4fd"/><text x="60" y="55" text-anchor="middle" font-size="11" fill="#333">电流相位角</text>
  106 + <g font-size="10" fill="#666"><text x="42" y="70">A相 0</text><text x="78" y="70">B相 0</text><text x="60" y="84">C相 0</text></g>
  107 + <circle cx="32" cy="92" r="3" fill="#e74c3c"/><circle cx="58" cy="95" r="3" fill="#67c23a"/><circle cx="84" cy="92" r="3" fill="#409eff"/>
  108 + </svg>
  109 + </div>
  110 + </div>
  111 + <div class="ac-ref">参考值: A相 120 &nbsp; B相 120 &nbsp; C相 240</div>
  112 + </div>
  113 + </div>
  114 + </div>
  115 +
  116 + <!-- 右侧:功率统计 -->
  117 + <div class="right-panel">
  118 + <div class="rp-title">功率</div>
  119 + <div class="power-stats">
  120 + <div v-for="(ps, i) in powerStats" :key="i" :class="['ps-item', 'ps-'+ps.color]">
  121 + <div class="ps-circle">
  122 + <svg viewBox="0 0 50 50"><circle cx="25" cy="25" r="20" fill="none" stroke="#eee" stroke-width="5"/>
  123 + <text x="25" y="28" text-anchor="middle" font-size="13" font-weight="bold" fill="#333">{{ ps.val }}</text>
  124 + </svg>
  125 + </div>
  126 + <div class="ps-info">
  127 + <div class="ps-bars">
  128 + <span :class="'ps-bar '+pb.color" v-for="(pb, j) in ps.bars" :key="j">
  129 + {{ pb.label }}{{ pb.val }}
  130 + </span>
  131 + </div>
  132 + <div class="ps-result">视在功率 &nbsp;&nbsp; {{ ps.result }}</div>
  133 + </div>
  134 + </div>
  135 + </div>
  136 +
  137 + <!-- 温度图表 -->
  138 + <div class="temp-card">
  139 + <div class="temp-header">温度 <b>▼</b></div>
  140 + <div class="temp-chart">
  141 + <svg viewBox="0 0 280 140">
  142 + <g font-size="9" fill="#999" text-anchor="end">
  143 + <text x="22" y="15">1</text><text x="22" y="43">0.8</text><text x="22" y="71">0.6</text>
  144 + <text x="22" y="99">0.4</text><text x="22" y="127">0.2</text>
  145 + </g>
  146 + <line x1="28" y1="124" x2="268" y2="124" stroke="#ddd"/>
  147 + <g font-size="7" fill="#666" text-anchor="middle">
  148 + <text x="38" y="136">温度TA</text><text x="68" y="136">温度TB</text>
  149 + <text x="98" y="136">温度TC</text><text x="128" y="136">温度TN</text>
  150 + <text x="158" y="136">温度TE</text>
  151 + </g>
  152 + </svg>
  153 + </div>
  154 + </div>
  155 + </div>
  156 + </div>
  157 + </div>
  158 + </el-dialog>
  159 +</template>
  160 +
  161 +<script setup>
  162 +import { ref } from 'vue'
  163 +import { Refresh, Grid, List, Close } from '@element-plus/icons-vue'
  164 +
  165 +defineProps({ visible: Boolean, device: Object })
  166 +defineEmits(['update:visible'])
  167 +
  168 +const phases = ['UA', 'UB', 'UC', 'UAB', 'UBC', 'UAC', 'UF']
  169 +const activePhase = ref('UA')
  170 +const curveDate = ref('')
  171 +
  172 +const tableRows = [
  173 + { label: '极大值', voltage: 0, current: 0, power: 0, temp: 0 },
  174 + { label: '平均值', voltage: 0, current: 0, power: 0, temp: 0 },
  175 + { label: '极小值', voltage: 0, current: 0, power: 0, temp: 0 }
  176 +]
  177 +const extraInfos = ['IA', 'IB', 'IC']
  178 +const powerItems = [
  179 + { label: 'A相', val: 0, color: 'o' },
  180 + { label: 'B相', val: 0, color: 'g' },
  181 + { label: 'C相', val: 0, color: 'r' },
  182 + { label: '合相', val: 0, color: 'b' }
  183 +]
  184 +const powerStats = [
  185 + {
  186 + color: 'o', val: 0,
  187 + bars: [
  188 + { label: '有功功率', val: 0, color: '' },
  189 + { label: 'A相 ', val: '', color: 'o' }, { label: '无功功率', val: 0, color: '' }
  190 + ],
  191 + result: 0
  192 + },
  193 + {
  194 + color: 'g', val: 0,
  195 + bars: [
  196 + { label: '有功功率', val: 0, color: '' },
  197 + { label: 'B相 ', val: '', color: 'g' }, { label: '无功功率', val: 0, color: '' }
  198 + ],
  199 + result: 0
  200 + },
  201 + {
  202 + color: 'r', val: 0,
  203 + bars: [
  204 + { label: '有功功率', val: 0, color: '' },
  205 + { label: 'C相 ', val: '', color: 'r' }, { label: '无功功率', val: 0, color: '' }
  206 + ],
  207 + result: 0
  208 + },
  209 + {
  210 + color: 'b', val: 0,
  211 + bars: [
  212 + { label: '有功功率', val: 0, color: '' },
  213 + { label: '合相 ', val: '', color: 'b' }, { label: '无功功率', val: 0, color: '' }
  214 + ],
  215 + result: 0
  216 + }
  217 +]
  218 +</script>
  219 +
  220 +<style scoped>
  221 +.param-dialog :deep(.el-dialog){max-height:92vh;display:flex;flex-direction:column;}
  222 +.param-dialog :deep(.el-dialog__header){padding:10px 20px;border-bottom:1px solid #e8e8e8;margin:0;flex-shrink:0;}
  223 +.param-dialog :deep(.el-dialog__body){overflow-y:auto;flex:1;padding:12px;}
  224 +.dialog-header{display:flex;align-items:center;justify-content:space-between;}
  225 +.title-text{font-size:15px;font-weight:bold;color:#333;}
  226 +.header-right{display:flex;align-items:center;}
  227 +
  228 +.phase-tabs{display:flex;gap:4px;background:#fff;border:1px solid #eee;border-radius:6px 6px 0 0;padding:8px 14px;}
  229 +.phase-tab{padding:6px 14px;font-size:12px;cursor:pointer;color:#666;border-radius:4px;}
  230 +.phase-tab.active{background:#409eff;color:#fff;font-weight:bold;}
  231 +
  232 +.main-grid{display:flex;gap:14px;background:#fff;border:1px solid #eee;border-top:none;border-radius:0 0 6px 6px;padding:14px;}
  233 +
  234 +.left-panel{flex:1;min-width:0;}
  235 +.data-table-area{background:#408aff;border-radius:6px;padding:14px;display:flex;gap:16px;margin-bottom:12px;color:#fff;}
  236 +.param-table{border-collapse:collapse;font-size:13px;}
  237 +.param-table th{padding:6px 16px;text-align:center;font-weight:normal;opacity:0.85;border-bottom:1px solid rgba(255,255,255,0.2);}
  238 +.param-table td{padding:6px 16px;text-align:center;}
  239 +.row-label{text-align:left!important;font-weight:bold;}
  240 +.extra-info{font-size:12px;opacity:0.85;line-height:2;}
  241 +
  242 +.curve-section{border:1px solid #eee;border-radius:6px;padding:12px;margin-bottom:12px;}
  243 +.curve-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;}
  244 +.curve-title{font-size:13px;font-weight:bold;color:#333;}
  245 +.curve-legend{display:flex;gap:14px;font-size:11px;color:#666;margin-top:6px;}
  246 +.curve-chart svg{width:100%;height:auto;}
  247 +
  248 +.bottom-row{display:flex;gap:12px;}
  249 +.power-card,.angle-card{flex:1;border:1px solid #eee;border-radius:6px;padding:12px;}
  250 +.pc-title,.ac-title{font-size:13px;font-weight:bold;color:#333;margin-bottom:8px;}
  251 +.pc-list{display:flex;flex-direction:column;gap:6px;}
  252 +.pc-item{display:flex;align-items:center;gap:6px;font-size:12px;color:#666;}
  253 +.pc-dot{width:10px;height:10px;border-radius:2px;}
  254 +.pc-dot.o{background:#f56c6c;}.pc-dot.g{background:#67c23a;}
  255 +.pc-dot.r{background:#e74c3c;}.pc-dot.b{background:#409eff;}
  256 +.pc-val{margin-left:auto;font-weight:bold;color:#333;}
  257 +
  258 +.ac-charts{display:flex;gap:12px;justify-content:center;}
  259 +.ac-pie-wrap svg{width:110px;height:110px;}
  260 +.ac-ref{text-align:center;font-size:11px;color:#999;margin-top:6px;}
  261 +
  262 +.right-panel{width:260px;flex-shrink:0;}
  263 +.rp-title{font-size:14px;font-weight:bold;color:#333;margin-bottom:10px;}
  264 +.power-stats{display:flex;flex-direction:column;gap:10px;margin-bottom:14px;}
  265 +.ps-item{display:flex;align-items:center;gap:8px;}
  266 +.ps-circle svg{width:44px;height:44px;flex-shrink:0;}
  267 +.ps-info{flex:1;font-size:10px;color:#666;}
  268 +.ps-bar{display:inline-block;padding:2px 4px;border-radius:2px;margin-right:4px;}
  269 +.ps-bar.o{background:#fff3e0;color:#e65100;}.ps-bar.g{background:#e8f5e9;color:#2e7d32;}
  270 +.ps-bar.r{background:#ffebee;color:#c62828;}.ps-bar.b{background:#e3f2fd;color:#1565c0;}
  271 +.ps-result{margin-top:2px;}
  272 +
  273 +.temp-card{border:1px solid #eee;border-radius:6px;padding:12px;}
  274 +.temp-header{font-size:13px;font-weight:bold;color:#333;margin-bottom:8px;}
  275 +.temp-chart svg{width:100%;height:auto;}
  276 +
  277 +.leg{display:flex;align-items:center;gap:3px;}
  278 +.dot{display:inline-block;width:10px;height:10px;border-radius:2px;}
  279 +.dot.y{background:#f5a623;}.dot.g{background:#67c23a;}.dot.r{background:#f56c6c;}
  280 +</style>
  1 +<template>
  2 + <el-dialog
  3 + :model-value="visible"
  4 + @update:model-value="$emit('update:visible', $event)"
  5 + title=""
  6 + width="calc(100vw - 40px)"
  7 + :style="{ maxWidth: '1400px' }"
  8 + top="3vh"
  9 + destroy-on-close
  10 + class="safety-dialog"
  11 + >
  12 + <template #header>
  13 + <div class="dialog-header">
  14 + <span class="title-text">{{ device?.name || '能耗设备1' }}</span>
  15 + <div class="header-right">
  16 + <el-icon :size="16" style="cursor:pointer;color:#409eff;"><Refresh /></el-icon>
  17 + <el-icon :size="16" style="cursor:pointer;color:#409eff;margin-left:6px;"><FullScreen /></el-icon>
  18 + <el-icon :size="16" style="cursor:pointer;color:#409eff;margin-left:6px;" @click="$emit('update:visible', false)"><Close /></el-icon>
  19 + </div>
  20 + </div>
  21 + </template>
  22 +
  23 + <div class="safety-body">
  24 + <!-- 设备运行状态 -->
  25 + <div class="panel">
  26 + <div class="panel-title">设备运行状态:</div>
  27 + <div class="status-chart-area">
  28 + <div class="status-bar-chart">
  29 + <svg viewBox="0 0 700 100">
  30 + <g font-size="10" fill="#999" text-anchor="middle">
  31 + <text x="50" y="85">04:00</text><text x="180" y="85">08:00</text><text x="310" y="85">12:00</text><text x="440" y="85">16:00</text><text x="570" y="85">20:00</text><text x="650" y="85">25:00</text>
  32 + </g>
  33 + <rect x="200" y="15" width="90" height="55" rx="3" fill="#999" opacity="0.7"/>
  34 + </svg>
  35 + </div>
  36 + <el-date-picker v-model="runDate" type="date" size="small" placeholder="2026-04-28" />
  37 + </div>
  38 + </div>
  39 +
  40 + <!-- 运行状态能耗产量复合 -->
  41 + <div class="panel">
  42 + <div class="panel-title">运行状态能耗产量复合</div>
  43 + <div class="composite-row">
  44 + <div class="composite-left">
  45 + <div class="pie-wrap">
  46 + <svg viewBox="0 0 120 120"><circle cx="60" cy="60" r="48" fill="#e8f4fd" stroke="#ddd"/>
  47 + <circle cx="60" cy="60" r="38" fill="none" stroke="#409eff" stroke-width="12"
  48 + stroke-dasharray="239 239" transform="rotate(-90 60 60)"/>
  49 + <text x="60" y="58" text-anchor="middle" font-size="11" fill="#333">正常</text>
  50 + <text x="60" y="72" text-anchor="middle" font-size="9" fill="#666">100%</text>
  51 + </svg>
  52 + </div>
  53 + <div class="composite-info">
  54 + <div class="ci-row"><span class="ci-dot b"></span>本月耗电</div>
  55 + <div class="ci-row"><span class="ci-dot g"></span>日产量</div>
  56 + </div>
  57 + </div>
  58 + <div class="composite-right">
  59 + <div>待机电能范围:<b>0.00A ≤ I ≤ 0.00A</b></div>
  60 + <div>运行电能范围:<b>I ≥ 0.00A</b></div>
  61 + </div>
  62 + </div>
  63 + </div>
  64 +
  65 + <!-- 运行时长统计 + 健康度/能效统计 -->
  66 + <div class="two-col-row">
  67 + <div class="panel flex-1">
  68 + <div class="panel-title">运行时长统计:</div>
  69 + <div class="bar-legend">
  70 + <span class="leg"><i class="dot o"/>停机</span>
  71 + <span class="leg"><i class="dot g"/>待机</span>
  72 + <span class="leg"><i class="dot b"/>运行</span>
  73 + <span class="leg"><i class="dot gy"/>离线</span>
  74 + </div>
  75 + <div class="runtime-bar-chart">
  76 + <svg viewBox="0 0 600 160">
  77 + <g font-size="9" fill="#999" text-anchor="end">
  78 + <text x="24" y="18">24</text><text x="24" y="46">18</text><text x="24" y="74">12</text>
  79 + <text x="24" y="102">6</text><text x="24" y="130">0</text>
  80 + </g>
  81 + <line x1="30" y1="126" x2="580" y2="126" stroke="#ddd"/>
  82 + <rect x="36" y="86" width="14" height="40" fill="#999" rx="1"/><text x="43" y="141" text-anchor="middle" font-size="7">03-13</text>
  83 + <rect x="54" y="106" width="14" height="20" fill="#999" rx="1"/><text x="61" y="141" text-anchor="middle" font-size="7">03-14</text>
  84 + <rect x="72" y="126" width="14" height="0" rx="1"/><text x="79" y="141" text-anchor="middle" font-size="7">03-15</text>
  85 + <rect x="90" y="126" width="14" height="0" rx="1"/><text x="97" y="141" text-anchor="middle" font-size="7">03-16</text>
  86 + <rect x="108" y="126" width="14" height="0" rx="1"/><text x="115" y="141" text-anchor="middle" font-size="7">03-17</text>
  87 + <rect x="126" y="126" width="14" height="0" rx="1"/><text x="133" y="141" text-anchor="middle" font-size="7">03-18</text>
  88 + <rect x="144" y="126" width="14" height="0" rx="1"/><text x="151" y="141" text-anchor="middle" font-size="7">03-19</text>
  89 + <rect x="162" y="126" width="14" height="0" rx="1"/><text x="169" y="141" text-anchor="middle" font-size="7">03-20</text>
  90 + <rect x="180" y="126" width="14" height="0" rx="1"/><text x="187" y="141" text-anchor="middle" font-size="7">03-21</text>
  91 + <rect x="198" y="126" width="14" height="0" rx="1"/><text x="205" y="141" text-anchor="middle" font-size="7">03-22</text>
  92 + <rect x="216" y="116" width="14" height="10" fill="#999" rx="1"/><text x="223" y="141" text-anchor="middle" font-size="7">03-23</text>
  93 + <rect x="234" y="56" width="14" height="70" fill="#999" rx="1"/><text x="241" y="141" text-anchor="middle" font-size="7">03-24</text>
  94 + <rect x="252" y="46" width="14" height="80" fill="#999" rx="1"/><text x="259" y="141" text-anchor="middle" font-size="7">03-25</text>
  95 + <rect x="270" y="46" width="14" height="80" fill="#999" rx="1"/><text x="277" y="141" text-anchor="middle" font-size="7">03-26</text>
  96 + <rect x="288" y="76" width="14" height="50" fill="#999" rx="1"/><text x="295" y="141" text-anchor="middle" font-size="7">03-27</text>
  97 + <rect x="306" y="96" width="14" height="30" fill="#999" rx="1"/><text x="313" y="141" text-anchor="middle" font-size="7">03-28</text>
  98 + <line x1="330" y1="10" x2="330" y2="130" stroke="#eee" stroke-dasharray="3,3"/>
  99 + <text x="380" y="75" text-anchor="middle" font-size="11" fill="#666" opacity="0.6">2026-04-13 — 2026-04-28</text>
  100 + </svg>
  101 + </div>
  102 + </div>
  103 +
  104 + <div class="right-stats">
  105 + <!-- 健康度 -->
  106 + <div class="stat-card">
  107 + <div class="sc-header">健康度:</div>
  108 + <div class="sc-content">
  109 + <div class="score-circle">
  110 + <svg viewBox="0 0 100 100"><circle cx="50" cy="50" r="42" fill="none" stroke="#eee" stroke-width="8"/>
  111 + <circle cx="50" cy="50" r="42" fill="none" stroke="#e6a23c" stroke-width="8" stroke-dasharray="2 262" transform="rotate(-90 50 50)"/>
  112 + <text x="50" y="53" text-anchor="middle" font-size="18" font-weight="bold" fill="#333">0.00</text>
  113 + </svg>
  114 + </div>
  115 + <div class="sc-detail">
  116 + <div class="sd-row"><span class="sd-label">总评分:</span><span class="sd-val">0.00</span></div>
  117 + <div class="sd-row"><span class="sd-label">月最大需量</span></div>
  118 + <div class="sd-big"><b>0.00Kw</b></div>
  119 + </div>
  120 + <div class="sc-bars">
  121 + <div v-for="(item, i) in healthBars" :key="i" :class="['hb-item', 'hb-'+item.color]">
  122 + {{ item.pct }}% {{ item.label }}
  123 + </div>
  124 + </div>
  125 + </div>
  126 + </div>
  127 +
  128 + <!-- 能效统计 -->
  129 + <div class="stat-card">
  130 + <div class="sc-header">能效统计:</div>
  131 + <div class="sc-content">
  132 + <div class="score-circle small">
  133 + <svg viewBox="0 0 100 100"><circle cx="50" cy="50" r="42" fill="none" stroke="#eee" stroke-width="8"/>
  134 + <text x="50" y="53" text-anchor="middle" font-size="18" font-weight="bold" fill="#333">0</text>
  135 + </svg>
  136 + </div>
  137 + <div class="ef-bars">
  138 + <div v-for="(item, i) in effBars" :key="i" class="eb-item">
  139 + <div class="eb-bar-wrap"><div :class="['eb-fill', 'fill-' + item.color]" :style="{width:item.val+'%'}"></div></div>
  140 + <div class="eb-label">{{ item.val }}<br/>{{ item.label }}</div>
  141 + </div>
  142 + </div>
  143 + <div class="ef-bottom">日能效曲线</div>
  144 + </div>
  145 + </div>
  146 + </div>
  147 + </div>
  148 +
  149 + <!-- 产量分析 + 日投入产出 -->
  150 + <div class="two-col-row">
  151 + <div class="panel flex-1">
  152 + <div class="panel-title">产量分析:</div>
  153 + <div class="prod-bars">
  154 + <div v-for="(item, i) in prodData" :key="i" class="prod-item">
  155 + <div :class="['pb-dot', item.color]"></div>
  156 + <div>{{ item.label }}</div>
  157 + <div class="pb-val">{{ item.val }}</div>
  158 + </div>
  159 + </div>
  160 + <div class="prod-line">日产量曲线</div>
  161 + </div>
  162 + <div class="panel flex-1">
  163 + <div class="panel-title">日投入产出、日生产效率</div>
  164 + <div class="io-legend">
  165 + <span class="leg"><i class="dot b"/>收入产出比</span>
  166 + <span class="leg"><i class="dot g"/>生产效率</span>
  167 + </div>
  168 + </div>
  169 + </div>
  170 + </div>
  171 + </el-dialog>
  172 +</template>
  173 +
  174 +<script setup>
  175 +import { ref } from 'vue'
  176 +import { Refresh, FullScreen, Close } from '@element-plus/icons-vue'
  177 +
  178 +defineProps({ visible: Boolean, device: Object })
  179 +defineEmits(['update:visible'])
  180 +
  181 +const runDate = ref('')
  182 +const healthBars = [
  183 + { pct: 0.00, label: '自愈率', color: 'orange' },
  184 + { pct: 0.00, label: '电平平衡率', color: 'green' },
  185 + { pct: 0.00, label: '总故障数', color: 'red' },
  186 + { pct: 0.00, label: '电压不平衡', color: 'blue' }
  187 +]
  188 +const effBars = [
  189 + { val: 0.00, label: '日累计运行时长', color: 'orange' },
  190 + { val: 0.00, label: '日累计能耗', color: 'green' },
  191 + { val: 0.00, label: '月累计运行时长', color: 'red' },
  192 + { val: 0.00, label: '月累计能耗', color: 'blue' }
  193 +]
  194 +const prodData = [
  195 + { label: '日累计产量', val: '0.00', color: 'o' },
  196 + { label: '月累计产量', val: '0.00', color: 'g' },
  197 + { label: '日投入产出', val: '0.00', color: 'r' },
  198 + { label: '日生产效率', val: '0.00', color: 'b' }
  199 +]
  200 +</script>
  201 +
  202 +<style scoped>
  203 +.safety-dialog :deep(.el-dialog) { max-height: 92vh; display:flex;flex-direction:column; }
  204 +.safety-dialog :deep(.el-dialog__header){padding:10px 20px;border-bottom:1px solid #e8e8e8;margin:0;flex-shrink:0; }
  205 +.safety-dialog :deep(.el-dialog__body){overflow-y:auto;flex:1;padding:12px;}
  206 +.dialog-header{display:flex;align-items:center;justify-content:space-between;}
  207 +.title-text{font-size:15px;font-weight:bold;color:#333;}
  208 +.header-right{display:flex;align-items:center;}
  209 +
  210 +.safety-body .panel{background:#fff;border:1px solid #eee;border-radius:6px;padding:14px;margin-bottom:12px;}
  211 +.panel-title{font-size:13px;font-weight:bold;color:#333;margin-bottom:10px;}
  212 +.flex-1{flex:1;}
  213 +.two-col-row{display:flex;gap:12px;}
  214 +
  215 +.status-chart-area{display:flex;align-items:center;justify-content:space-between;gap:12px;}
  216 +.status-bar-chart{flex:1;}
  217 +.status-bar-chart svg{width:100%;height:auto;}
  218 +
  219 +.composite-row{display:flex;justify-content:space-between;align-items:center;gap:16px;}
  220 +.composite-left{display:flex;align-items:center;gap:16px;}
  221 +.pie-wrap svg{width:120px;height:120px;}
  222 +.composite-info{font-size:12px;color:#666;display:flex;gap:16px;}
  223 +.ci-row{display:flex;align-items:center;gap:4px;}
  224 +.ci-dot{display:inline-block;width:10px;height:10px;border-radius:2px;}
  225 +.ci-dot.b{background:#409eff;}.ci-dot.g{background:#67c23a;}
  226 +.composite-right{font-size:12px;color:#666;line-height:2;}
  227 +
  228 +.bar-legend{display:flex;gap:14px;font-size:11px;color:#666;margin-bottom:6px;}
  229 +.leg{display:flex;align-items:center;gap:3px;}
  230 +.dot{display:inline-block;width:10px;height:10px;border-radius:2px;}
  231 +.dot.o{background:#f56c6c;}.dot.g{background:#67c23a;}.dot.b{background:#409eff;}.dot.gy{background:#909399;}
  232 +.runtime-bar-chart{overflow-x:auto;}
  233 +
  234 +.right-stats{width:280px;display:flex;flex-direction:column;gap:12px;}
  235 +.stat-card{background:#fff;border:1px solid #eee;border-radius:6px;padding:12px;}
  236 +.sc-header{font-size:13px;font-weight:bold;color:#333;margin-bottom:8px;}
  237 +.sc-content{display:flex;align-items:flex-start;gap:10px;}
  238 +.score-circle svg{width:90px;height:90px;flex-shrink:0;}
  239 +.score-circle.small svg{width:76px;height:76px;}
  240 +.sc-detail{flex:1;font-size:11px;color:#666;}
  241 +.sd-row{margin-bottom:2px;}
  242 +.sd-val{color:#e6a23c;font-weight:bold;font-size:13px;}
  243 +.sd-big{margin-top:4px;color:#409eff;font-size:16px;}
  244 +.sc-bars,.ef-bars{flex:1;display:flex;flex-direction:column;gap:4px;}
  245 +.hb-item{font-size:10px;padding:3px 6px;border-radius:3px;text-align:center;}
  246 +.hb-orange{background:#fff3e0;color:#e65100;}
  247 +.hb-green{background:#e8f5e9;color:#2e7d32;}
  248 +.hb-red{background:#ffebee;color:#c62828;}
  249 +.hb-blue{background:#e3f2fd;color:#1565c0;}
  250 +.eb-item{display:flex;align-items:center;gap:6px;font-size:10px;}
  251 +.eb-bar-wrap{width:50px;height:8px;background:#f0f0f0;border-radius:2px;overflow:hidden;}
  252 +.eb-fill{height:100%;border-radius:2px;}
  253 +.fill-orange{background:#f56c6c;}.fill-green{background:#67c23a;}
  254 +.fill-red{background:#f56c6c;}.fill-blue{background:#409eff;}
  255 +.eb-label{color:#666;white-space:nowrap;}
  256 +.ef-bottom{text-align:center;font-size:11px;color:#999;margin-top:4px;}
  257 +
  258 +.prod-bars{display:flex;gap:24px;margin-bottom:8px;}
  259 +.pb-dot{width:12px;height:12px;border-radius:2px;margin-right:4px;}
  260 +.pb-dot.o{background:#f56c6c;}.pb-dot.g{background:#67c23a;}.pb-dot.r{background:#e74c3c;}.pb-dot.b{background:#409eff;}
  261 +.prod-item{display:flex;align-items:center;gap:4px;font-size:12px;color:#666;}
  262 +.pb-val{font-weight:bold;color:#333;margin-left:4px;}
  263 +.prod-line{text-align:center;font-size:11px;color:#999;}
  264 +.io-legend{display:flex;gap:14px;font-size:11px;color:#666;}
  265 +</style>
  1 +<template>
  2 + <el-dialog
  3 + :model-value="visible"
  4 + @update:model-value="$emit('update:visible', $event)"
  5 + title=""
  6 + width="calc(100vw - 40px)"
  7 + :style="{ maxWidth: '1400px' }"
  8 + top="3vh"
  9 + destroy-on-close
  10 + class="setting-dialog"
  11 + >
  12 + <template #header>
  13 + <div class="dialog-header">
  14 + <div class="left-tabs">
  15 + <span :class="['tab-item', { active: activeTab === 'trigger' }]" @click="activeTab = 'trigger'">触发器设置</span>
  16 + <span :class="['tab-item', { active: activeTab === 'history' }]" @click="activeTab = 'history'">原因列表查看</span>
  17 + <span :class="['tab-item', { active: activeTab === 'setting' }]" @click="activeTab = 'setting'">设置</span>
  18 + </div>
  19 + <div class="header-right">
  20 + <span class="device-name">中速纸杯机24号机</span>
  21 + </div>
  22 + </div>
  23 + </template>
  24 +
  25 + <div class="setting-body">
  26 + <div class="sub-tabs">
  27 + <span
  28 + v-for="st in subTabs" :key="st.key"
  29 + :class="['sub-tab', { active: activeSub === st.key }]"
  30 + @click="activeSub = st.key"
  31 + >{{ st.label }}</span>
  32 + <el-button size="small" type="primary" plain class="add-trigger-btn">添加触发条件</el-button>
  33 + </div>
  34 +
  35 + <el-table :data="triggerTableData" size="small" stripe border style="width: 100%; font-size: 12px;">
  36 + <el-table-column prop="name" label="触发器名称" min-width="120" fixed>
  37 + <template #default="{ row }">
  38 + <span class="link-text">{{ row.name }}</span>
  39 + </template>
  40 + </el-table-column>
  41 + <el-table-column prop="condition" label="触发条件" min-width="100" />
  42 + <el-table-column prop="threshold" label="静默阈值" min-width="100" />
  43 + <el-table-column prop="duration" label="累管时间" min-width="110">
  44 + <template #default="{ row }">
  45 + <span class="link-text">{{ row.duration }}</span>
  46 + </template>
  47 + </el-table-column>
  48 + <el-table-column prop="operator" label="接收人员" min-width="100" />
  49 + <el-table-column prop="alertTime" label="触发时间" min-width="110">
  50 + <template #default="{ row }">
  51 + <span class="link-text">{{ row.alertTime }}</span>
  52 + </template>
  53 + </el-table-column>
  54 + <el-table-column prop="receiveMethod" label="接收方式" min-width="90" />
  55 + <el-table-column prop="part" label="部件" min-width="80" />
  56 + <el-table-column prop="contactGroup" label="联系组" min-width="90" />
  57 + <el-table-column prop="config" label="配置" min-width="200" />
  58 + </el-table>
  59 +
  60 + <div class="footer-bar">
  61 + <span>共 1 条</span>
  62 + <el-pagination layout="prev, pager, next" :total="1" :page-size="10" small />
  63 + <span>前往 <el-input-number :min="1" :max="1" :controls="false" size="small" style="width: 46px;" /> 页</span>
  64 + </div>
  65 + </div>
  66 + </el-dialog>
  67 +</template>
  68 +
  69 +<script setup>
  70 +import { ref } from 'vue'
  71 +
  72 +defineProps({
  73 + visible: Boolean,
  74 + device: Object
  75 +})
  76 +defineEmits(['update:visible'])
  77 +
  78 +const activeTab = ref('trigger')
  79 +const activeSub = ref('light')
  80 +
  81 +const subTabs = [
  82 + { key: 'light', label: '绿灯' },
  83 + { key: 'yellow', label: '黄灯' },
  84 + { key: 'offline', label: '离线' },
  85 + { key: 'lightOff', label: '灭灯' },
  86 + { key: 'counter', label: '计数' },
  87 + { key: 'blue', label: '蓝灯' },
  88 + { key: 'reason', label: '原因码' },
  89 + { key: 'safe', label: '安灯' },
  90 +]
  91 +
  92 +const triggerTableData = [
  93 + { name: '红灯即时', condition: '>6秒', threshold: '0分', duration: '00:00:24:00', operator: '', alertTime: '', receiveMethod: '', part: '', contactGroup: '', config: '启用 / 禁用 / 删除 / 添加联系人 / 编辑联系组' }
  94 +]
  95 +</script>
  96 +
  97 +<style scoped>
  98 +.setting-dialog :deep(.el-dialog) {
  99 + max-height: 92vh;
  100 + display: flex;
  101 + flex-direction: column;
  102 +}
  103 +.setting-dialog :deep(.el-dialog__header) {
  104 + padding: 0;
  105 + margin: 0;
  106 + border-bottom: 1px solid #e8e8e8;
  107 + flex-shrink: 0;
  108 +}
  109 +.setting-dialog :deep(.el-dialog__body) {
  110 + overflow-y: auto;
  111 + flex: 1;
  112 +}
  113 +.dialog-header {
  114 + display: flex;
  115 + justify-content: space-between;
  116 + align-items: center;
  117 + height: 48px;
  118 + padding: 0 20px;
  119 +}
  120 +.left-tabs {
  121 + display: flex;
  122 + gap: 0;
  123 + height: 100%;
  124 + align-items: center;
  125 +}
  126 +.tab-item {
  127 + padding: 0 18px;
  128 + height: 100%;
  129 + display: flex;
  130 + align-items: center;
  131 + font-size: 13px;
  132 + color: #666;
  133 + cursor: pointer;
  134 + border-bottom: 2px solid transparent;
  135 + transition: all 0.2s;
  136 +}
  137 +.tab-item.active {
  138 + color: #409eff;
  139 + font-weight: bold;
  140 + border-bottom-color: #409eff;
  141 +}
  142 +.header-right {
  143 + display: flex;
  144 + align-items: center;
  145 + gap: 12px;
  146 +}
  147 +.device-name {
  148 + font-size: 13px;
  149 + color: #333;
  150 + font-weight: 500;
  151 +}
  152 +
  153 +.setting-body {
  154 + padding: 0;
  155 +}
  156 +.sub-tabs {
  157 + display: flex;
  158 + align-items: center;
  159 + gap: 4px;
  160 + padding: 12px 20px;
  161 + border-bottom: 1px solid #e8e8e8;
  162 + background: #fafafa;
  163 +}
  164 +.sub-tab {
  165 + padding: 6px 18px;
  166 + font-size: 13px;
  167 + color: #333;
  168 + cursor: pointer;
  169 + border-radius: 4px;
  170 + transition: all 0.2s;
  171 +}
  172 +.sub-tab:hover {
  173 + color: #409eff;
  174 +}
  175 +.sub-tab.active {
  176 + background: #409eff;
  177 + color: #fff;
  178 + font-weight: bold;
  179 +}
  180 +.add-trigger-btn {
  181 + margin-left: auto;
  182 +}
  183 +
  184 +.link-text {
  185 + color: #409eff;
  186 + cursor: pointer;
  187 +}
  188 +.link-text:hover {
  189 + text-decoration: underline;
  190 +}
  191 +
  192 +.footer-bar {
  193 + display: flex;
  194 + align-items: center;
  195 + justify-content: space-between;
  196 + padding: 12px 20px;
  197 + border-top: 1px solid #e8e8e8;
  198 + background: #fafafa;
  199 + font-size: 12px;
  200 + color: #999;
  201 + gap: 16px;
  202 +}
  203 +</style>
  1 +<script setup>
  2 +import WelcomeItem from './WelcomeItem.vue'
  3 +import DocumentationIcon from './icons/IconDocumentation.vue'
  4 +import ToolingIcon from './icons/IconTooling.vue'
  5 +import EcosystemIcon from './icons/IconEcosystem.vue'
  6 +import CommunityIcon from './icons/IconCommunity.vue'
  7 +import SupportIcon from './icons/IconSupport.vue'
  8 +
  9 +const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
  10 +</script>
  11 +
  12 +<template>
  13 + <WelcomeItem>
  14 + <template #icon>
  15 + <DocumentationIcon />
  16 + </template>
  17 + <template #heading>Documentation</template>
  18 +
  19 + Vue’s
  20 + <a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
  21 + provides you with all information you need to get started.
  22 + </WelcomeItem>
  23 +
  24 + <WelcomeItem>
  25 + <template #icon>
  26 + <ToolingIcon />
  27 + </template>
  28 + <template #heading>Tooling</template>
  29 +
  30 + This project is served and bundled with
  31 + <a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
  32 + recommended IDE setup is
  33 + <a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>
  34 + +
  35 + <a href="https://github.com/vuejs/language-tools" target="_blank" rel="noopener"
  36 + >Vue - Official</a
  37 + >. If you need to test your components and web pages, check out
  38 + <a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
  39 + and
  40 + <a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
  41 + /
  42 + <a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>.
  43 +
  44 + <br />
  45 +
  46 + More instructions are available in
  47 + <a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a
  48 + >.
  49 + </WelcomeItem>
  50 +
  51 + <WelcomeItem>
  52 + <template #icon>
  53 + <EcosystemIcon />
  54 + </template>
  55 + <template #heading>Ecosystem</template>
  56 +
  57 + Get official tools and libraries for your project:
  58 + <a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
  59 + <a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
  60 + <a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
  61 + <a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
  62 + you need more resources, we suggest paying
  63 + <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
  64 + a visit.
  65 + </WelcomeItem>
  66 +
  67 + <WelcomeItem>
  68 + <template #icon>
  69 + <CommunityIcon />
  70 + </template>
  71 + <template #heading>Community</template>
  72 +
  73 + Got stuck? Ask your question on
  74 + <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
  75 + (our official Discord server), or
  76 + <a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
  77 + >StackOverflow</a
  78 + >. You should also follow the official
  79 + <a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a>
  80 + Bluesky account or the
  81 + <a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
  82 + X account for latest news in the Vue world.
  83 + </WelcomeItem>
  84 +
  85 + <WelcomeItem>
  86 + <template #icon>
  87 + <SupportIcon />
  88 + </template>
  89 + <template #heading>Support Vue</template>
  90 +
  91 + As an independent project, Vue relies on community backing for its sustainability. You can help
  92 + us by
  93 + <a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
  94 + </WelcomeItem>
  95 +</template>