wanghao 2 weeks ago
parent
commit
02c2757732
63 changed files with 14126 additions and 371 deletions
  1. 7 4
      .env
  2. 2 1
      .env.test
  3. 3 0
      eslint.config.js
  4. 5 0
      package.json
  5. 9107 0
      pnpm-lock.yaml
  6. 0 1
      public/favicon.svg
  7. BIN
      public/logo.png
  8. BIN
      src/assets/home/app_logo.png
  9. BIN
      src/assets/home/home.mp4
  10. 2 2
      src/constants/reg.ts
  11. 31 33
      src/hooks/common/table.ts
  12. 1 1
      src/locales/langs/en-us.ts
  13. 2 2
      src/locales/langs/zh-cn.ts
  14. 6 0
      src/router/elegant/imports.ts
  15. 77 0
      src/router/elegant/routes.ts
  16. 8 0
      src/router/elegant/transform.ts
  17. 7 7
      src/service/api/auth.ts
  18. 24 0
      src/service/api/home.ts
  19. 1 0
      src/service/api/index.ts
  20. 3 2
      src/service/api/route.ts
  21. 46 39
      src/service/api/system-manage.ts
  22. 178 18
      src/service/request/index.ts
  23. 15 15
      src/store/modules/auth/index.ts
  24. 63 0
      src/store/modules/route/custom.ts
  25. 2 3
      src/store/modules/route/index.ts
  26. 58 32
      src/typings/api.d.ts
  27. 1 1
      src/typings/app.d.ts
  28. 8 0
      src/typings/components.d.ts
  29. 17 0
      src/typings/elegant-router.d.ts
  30. 24 1
      src/typings/storage.d.ts
  31. 52 28
      src/views/_builtin/login/modules/pwd-login.vue
  32. 162 0
      src/views/admin/sys-dept/index.vue
  33. 105 0
      src/views/admin/sys-dept/modules/m-search.vue
  34. 248 0
      src/views/admin/sys-dept/modules/user-operate-drawer.vue
  35. 65 0
      src/views/admin/sys-dept/modules/user-resetpwd-dialog.vue
  36. 237 0
      src/views/admin/sys-menu/index.vue
  37. 615 0
      src/views/admin/sys-menu/modules/menu-operate-modal.vue
  38. 78 0
      src/views/admin/sys-menu/modules/menu-search.vue
  39. 79 0
      src/views/admin/sys-menu/modules/shared.ts
  40. 207 0
      src/views/admin/sys-role/index.vue
  41. 85 0
      src/views/admin/sys-role/modules/button-auth-modal.vue
  42. 149 0
      src/views/admin/sys-role/modules/menu-auth-modal.vue
  43. 132 0
      src/views/admin/sys-role/modules/role-modifypermis-modal.vue
  44. 206 0
      src/views/admin/sys-role/modules/role-operate-drawer.vue
  45. 80 0
      src/views/admin/sys-role/modules/role-search.vue
  46. 220 0
      src/views/admin/sys-user/index.vue
  47. 248 0
      src/views/admin/sys-user/modules/user-operate-drawer.vue
  48. 65 0
      src/views/admin/sys-user/modules/user-resetpwd-dialog.vue
  49. 137 0
      src/views/admin/sys-user/modules/user-search.vue
  50. 494 0
      src/views/business-analysis/system-space/index.vue
  51. 54 34
      src/views/manage/menu/index.vue
  52. 27 18
      src/views/manage/menu/modules/menu-operate-modal.vue
  53. 13 9
      src/views/manage/menu/modules/menu-search.vue
  54. 37 33
      src/views/manage/role/index.vue
  55. 7 7
      src/views/manage/role/modules/role-modifypermis-modal.vue
  56. 15 15
      src/views/manage/role/modules/role-operate-drawer.vue
  57. 11 5
      src/views/manage/role/modules/role-search.vue
  58. 41 31
      src/views/manage/user/index.vue
  59. 20 18
      src/views/manage/user/modules/user-operate-drawer.vue
  60. 4 4
      src/views/manage/user/modules/user-resetpwd-dialog.vue
  61. 6 6
      src/views/manage/user/modules/user-search.vue
  62. 529 0
      src/views/new-home/index.vue
  63. 0 1
      vite.config.ts

+ 7 - 4
.env

@@ -12,7 +12,7 @@ VITE_ICON_PREFIX=icon
 VITE_ICON_LOCAL_PREFIX=icon-local
 
 # auth route mode: static | dynamic
-VITE_AUTH_ROUTE_MODE=static
+VITE_AUTH_ROUTE_MODE=dynamic
 
 # static auth route home
 VITE_ROUTE_HOME=home
@@ -27,13 +27,16 @@ VITE_HTTP_PROXY=N
 VITE_ROUTER_HISTORY_MODE=history
 
 # success code of backend service, when the code is received, the request is successful
-VITE_SERVICE_SUCCESS_CODE=0000
+# VITE_SERVICE_SUCCESS_CODE=0000
+VITE_SERVICE_SUCCESS_CODE=200
 
 # logout codes of backend service, when the code is received, the user will be logged out and redirected to login page
-VITE_SERVICE_LOGOUT_CODES=8888,8889
+# VITE_SERVICE_LOGOUT_CODES=8888,8889
+VITE_SERVICE_LOGOUT_CODES=401
 
 # modal logout codes of backend service, when the code is received, the user will be logged out by displaying a modal
-VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
+# VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
+VITE_SERVICE_MODAL_LOGOUT_CODES=401
 
 # token expired codes of backend service, when the code is received, it will refresh the token and resend the request
 VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998

+ 2 - 1
.env.test

@@ -3,7 +3,8 @@ VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default
 
 # other backend service base url, test environment
 VITE_OTHER_SERVICE_BASE_URL= `{
-  "demo": "http://observe-server.cestong.com.cn"
+  "demo": "http://observe-server.cestong.com.cn",
+  "core": "http://observe-front.cestong.com.cn/core"
 }`
 
 # whether to enable http proxy when is dev mode

+ 3 - 0
eslint.config.js

@@ -20,5 +20,8 @@ export default defineConfig(
       ],
       'unocss/order-attributify': 'off'
     }
+  },
+  {
+    ignores: ['src']
   }
 );

+ 5 - 0
package.json

@@ -40,6 +40,7 @@
     "clipboard": "2.0.11",
     "dayjs": "1.11.11",
     "echarts": "5.5.0",
+    "jsencrypt": "^3.3.2",
     "lodash-es": "4.17.21",
     "nprogress": "0.2.0",
     "pinia": "2.1.7",
@@ -89,5 +90,9 @@
   "lint-staged": {
     "*": "eslint --fix"
   },
+  "volta": {
+    "node": "18.20.5",
+    "pnpm": "8.15.9"
+  },
   "website": "http://observe-front.cestong.com.cn/#/home"
 }

+ 9107 - 0
pnpm-lock.yaml

@@ -0,0 +1,9107 @@
+lockfileVersion: '6.0'
+
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
+importers:
+
+  .:
+    dependencies:
+      '@better-scroll/core':
+        specifier: 2.5.1
+        version: 2.5.1
+      '@iconify/vue':
+        specifier: 4.1.2
+        version: 4.1.2(vue@3.4.29)
+      '@sa/axios':
+        specifier: workspace:*
+        version: link:packages/axios
+      '@sa/color':
+        specifier: workspace:*
+        version: link:packages/color
+      '@sa/fetch':
+        specifier: workspace:*
+        version: link:packages/ofetch
+      '@sa/hooks':
+        specifier: workspace:*
+        version: link:packages/hooks
+      '@sa/materials':
+        specifier: workspace:*
+        version: link:packages/materials
+      '@sa/utils':
+        specifier: workspace:*
+        version: link:packages/utils
+      '@vueuse/core':
+        specifier: 10.11.0
+        version: 10.11.0(vue@3.4.29)
+      ant-design-vue:
+        specifier: 4.2.3
+        version: 4.2.3(vue@3.4.29)
+      clipboard:
+        specifier: 2.0.11
+        version: 2.0.11
+      dayjs:
+        specifier: 1.11.11
+        version: 1.11.11
+      echarts:
+        specifier: 5.5.0
+        version: 5.5.0
+      jsencrypt:
+        specifier: ^3.3.2
+        version: 3.3.2
+      lodash-es:
+        specifier: 4.17.21
+        version: 4.17.21
+      nprogress:
+        specifier: 0.2.0
+        version: 0.2.0
+      pinia:
+        specifier: 2.1.7
+        version: 2.1.7(typescript@5.4.5)(vue@3.4.29)
+      tailwind-merge:
+        specifier: 2.3.0
+        version: 2.3.0
+      vue:
+        specifier: 3.4.29
+        version: 3.4.29(typescript@5.4.5)
+      vue-draggable-plus:
+        specifier: 0.5.0
+        version: 0.5.0(@types/sortablejs@1.15.8)
+      vue-i18n:
+        specifier: 9.13.1
+        version: 9.13.1(vue@3.4.29)
+      vue-router:
+        specifier: 4.3.3
+        version: 4.3.3(vue@3.4.29)
+    devDependencies:
+      '@elegant-router/vue':
+        specifier: 0.3.7
+        version: 0.3.7
+      '@iconify/json':
+        specifier: 2.2.220
+        version: 2.2.220
+      '@sa/scripts':
+        specifier: workspace:*
+        version: link:packages/scripts
+      '@sa/uno-preset':
+        specifier: workspace:*
+        version: link:packages/uno-preset
+      '@soybeanjs/eslint-config':
+        specifier: 1.3.7
+        version: 1.3.7(@unocss/eslint-config@0.61.0)(eslint-plugin-vue@9.26.0)(eslint@9.5.0)(typescript@5.4.5)(vue-eslint-parser@9.4.3)
+      '@types/lodash-es':
+        specifier: 4.17.12
+        version: 4.17.12
+      '@types/node':
+        specifier: 20.14.6
+        version: 20.14.6
+      '@types/nprogress':
+        specifier: 0.2.3
+        version: 0.2.3
+      '@unocss/eslint-config':
+        specifier: 0.61.0
+        version: 0.61.0(eslint@9.5.0)(typescript@5.4.5)
+      '@unocss/preset-icons':
+        specifier: 0.61.0
+        version: 0.61.0
+      '@unocss/preset-uno':
+        specifier: 0.61.0
+        version: 0.61.0
+      '@unocss/transformer-directives':
+        specifier: 0.61.0
+        version: 0.61.0
+      '@unocss/transformer-variant-group':
+        specifier: 0.61.0
+        version: 0.61.0
+      '@unocss/vite':
+        specifier: 0.61.0
+        version: 0.61.0(vite@5.3.1)
+      '@vitejs/plugin-vue':
+        specifier: 5.0.5
+        version: 5.0.5(vite@5.3.1)(vue@3.4.29)
+      '@vitejs/plugin-vue-jsx':
+        specifier: 4.0.0
+        version: 4.0.0(vite@5.3.1)(vue@3.4.29)
+      eslint:
+        specifier: 9.5.0
+        version: 9.5.0
+      eslint-plugin-vue:
+        specifier: 9.26.0
+        version: 9.26.0(eslint@9.5.0)
+      lint-staged:
+        specifier: 15.2.7
+        version: 15.2.7
+      sass:
+        specifier: 1.77.6
+        version: 1.77.6
+      simple-git-hooks:
+        specifier: 2.11.1
+        version: 2.11.1
+      tsx:
+        specifier: 4.15.6
+        version: 4.15.6
+      typescript:
+        specifier: 5.4.5
+        version: 5.4.5
+      unplugin-icons:
+        specifier: 0.19.0
+        version: 0.19.0
+      unplugin-vue-components:
+        specifier: 0.27.0
+        version: 0.27.0(vue@3.4.29)
+      vite:
+        specifier: 5.3.1
+        version: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+      vite-plugin-progress:
+        specifier: 0.0.7
+        version: 0.0.7(vite@5.3.1)
+      vite-plugin-svg-icons:
+        specifier: 2.0.1
+        version: 2.0.1(vite@5.3.1)
+      vite-plugin-vue-devtools:
+        specifier: 7.3.2
+        version: 7.3.2(vite@5.3.1)(vue@3.4.29)
+      vue-eslint-parser:
+        specifier: 9.4.3
+        version: 9.4.3(eslint@9.5.0)
+      vue-tsc:
+        specifier: 2.0.21
+        version: 2.0.21(typescript@5.4.5)
+
+  packages/axios:
+    dependencies:
+      '@sa/utils':
+        specifier: workspace:*
+        version: link:../utils
+      axios:
+        specifier: 1.7.2
+        version: 1.7.2
+      axios-retry:
+        specifier: 4.4.0
+        version: 4.4.0(axios@1.7.2)
+      qs:
+        specifier: 6.12.1
+        version: 6.12.1
+    devDependencies:
+      '@types/qs':
+        specifier: 6.9.15
+        version: 6.9.15
+
+  packages/color:
+    dependencies:
+      '@sa/utils':
+        specifier: workspace:*
+        version: link:../utils
+      colord:
+        specifier: 2.9.3
+        version: 2.9.3
+
+  packages/hooks:
+    dependencies:
+      '@sa/axios':
+        specifier: workspace:*
+        version: link:../axios
+
+  packages/materials:
+    dependencies:
+      '@sa/utils':
+        specifier: workspace:*
+        version: link:../utils
+      '@simonwep/pickr':
+        specifier: 1.9.1
+        version: 1.9.1
+      simplebar-vue:
+        specifier: 2.3.5
+        version: 2.3.5(vue@3.4.29)
+    devDependencies:
+      typed-css-modules:
+        specifier: 0.9.1
+        version: 0.9.1
+
+  packages/ofetch:
+    dependencies:
+      ofetch:
+        specifier: 1.3.4
+        version: 1.3.4
+
+  packages/scripts:
+    devDependencies:
+      '@soybeanjs/changelog':
+        specifier: 0.3.24
+        version: 0.3.24(@unocss/eslint-config@0.61.0)(eslint-plugin-vue@9.26.0)(eslint@9.0.0-rc.0)(typescript@5.4.5)(vue-eslint-parser@9.4.3)
+      bumpp:
+        specifier: 9.4.1
+        version: 9.4.1
+      c12:
+        specifier: 1.11.1
+        version: 1.11.1
+      cac:
+        specifier: 6.7.14
+        version: 6.7.14
+      consola:
+        specifier: 3.2.3
+        version: 3.2.3
+      enquirer:
+        specifier: 2.4.1
+        version: 2.4.1
+      execa:
+        specifier: 9.2.0
+        version: 9.2.0
+      kolorist:
+        specifier: 1.8.0
+        version: 1.8.0
+      npm-check-updates:
+        specifier: 16.14.20
+        version: 16.14.20
+      rimraf:
+        specifier: 5.0.7
+        version: 5.0.7
+
+  packages/uno-preset: {}
+
+  packages/utils:
+    dependencies:
+      colord:
+        specifier: 2.9.3
+        version: 2.9.3
+      crypto-js:
+        specifier: 4.2.0
+        version: 4.2.0
+      localforage:
+        specifier: 1.10.0
+        version: 1.10.0
+      nanoid:
+        specifier: 5.0.7
+        version: 5.0.7
+    devDependencies:
+      '@types/crypto-js':
+        specifier: 4.2.2
+        version: 4.2.2
+
+packages:
+
+  /@ampproject/remapping@2.3.0:
+    resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
+    engines: {node: '>=6.0.0'}
+    dependencies:
+      '@jridgewell/gen-mapping': 0.3.5
+      '@jridgewell/trace-mapping': 0.3.25
+    dev: true
+
+  /@ant-design/colors@6.0.0:
+    resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==}
+    dependencies:
+      '@ctrl/tinycolor': 3.6.1
+    dev: false
+
+  /@ant-design/icons-svg@4.4.2:
+    resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==}
+    dev: false
+
+  /@ant-design/icons-vue@7.0.1(vue@3.4.29):
+    resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==}
+    peerDependencies:
+      vue: '>=3.0.3'
+    dependencies:
+      '@ant-design/colors': 6.0.0
+      '@ant-design/icons-svg': 4.4.2
+      vue: 3.4.29(typescript@5.4.5)
+    dev: false
+
+  /@antfu/eslint-define-config@1.23.0-2:
+    resolution: {integrity: sha512-LvxY21+ZhpuBf/aHeBUtGQhSEfad4PkNKXKvDOSvukaM3XVTfBhwmHX2EKwAsdq5DlfjbT3qqYyMiueBIO5iDQ==}
+    engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>= 8.6.0'}
+    dev: true
+
+  /@antfu/install-pkg@0.1.1:
+    resolution: {integrity: sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==}
+    dependencies:
+      execa: 5.1.1
+      find-up: 5.0.0
+    dev: true
+
+  /@antfu/install-pkg@0.3.3:
+    resolution: {integrity: sha512-nHHsk3NXQ6xkCfiRRC8Nfrg8pU5kkr3P3Y9s9dKqiuRmBD0Yap7fymNDjGFKeWhZQHqqbCS5CfeMy9wtExM24w==}
+    dependencies:
+      '@jsdevtools/ez-spawn': 3.0.4
+    dev: true
+
+  /@antfu/utils@0.7.10:
+    resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==}
+    dev: true
+
+  /@babel/code-frame@7.24.7:
+    resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/highlight': 7.24.7
+      picocolors: 1.0.1
+    dev: true
+
+  /@babel/compat-data@7.24.7:
+    resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==}
+    engines: {node: '>=6.9.0'}
+    dev: true
+
+  /@babel/core@7.24.7:
+    resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@ampproject/remapping': 2.3.0
+      '@babel/code-frame': 7.24.7
+      '@babel/generator': 7.24.7
+      '@babel/helper-compilation-targets': 7.24.7
+      '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7)
+      '@babel/helpers': 7.24.7
+      '@babel/parser': 7.24.7
+      '@babel/template': 7.24.7
+      '@babel/traverse': 7.24.7
+      '@babel/types': 7.24.7
+      convert-source-map: 2.0.0
+      debug: 4.3.5
+      gensync: 1.0.0-beta.2
+      json5: 2.2.3
+      semver: 6.3.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/generator@7.24.7:
+    resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/types': 7.24.7
+      '@jridgewell/gen-mapping': 0.3.5
+      '@jridgewell/trace-mapping': 0.3.25
+      jsesc: 2.5.2
+    dev: true
+
+  /@babel/helper-annotate-as-pure@7.24.7:
+    resolution: {integrity: sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/types': 7.24.7
+    dev: true
+
+  /@babel/helper-compilation-targets@7.24.7:
+    resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/compat-data': 7.24.7
+      '@babel/helper-validator-option': 7.24.7
+      browserslist: 4.23.1
+      lru-cache: 5.1.1
+      semver: 6.3.1
+    dev: true
+
+  /@babel/helper-create-class-features-plugin@7.24.7(@babel/core@7.24.7):
+    resolution: {integrity: sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-annotate-as-pure': 7.24.7
+      '@babel/helper-environment-visitor': 7.24.7
+      '@babel/helper-function-name': 7.24.7
+      '@babel/helper-member-expression-to-functions': 7.24.7
+      '@babel/helper-optimise-call-expression': 7.24.7
+      '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.7)
+      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
+      '@babel/helper-split-export-declaration': 7.24.7
+      semver: 6.3.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/helper-environment-visitor@7.24.7:
+    resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/types': 7.24.7
+    dev: true
+
+  /@babel/helper-function-name@7.24.7:
+    resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/template': 7.24.7
+      '@babel/types': 7.24.7
+    dev: true
+
+  /@babel/helper-hoist-variables@7.24.7:
+    resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/types': 7.24.7
+    dev: true
+
+  /@babel/helper-member-expression-to-functions@7.24.7:
+    resolution: {integrity: sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/traverse': 7.24.7
+      '@babel/types': 7.24.7
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/helper-module-imports@7.22.15:
+    resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/types': 7.24.7
+    dev: true
+
+  /@babel/helper-module-imports@7.24.7:
+    resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/traverse': 7.24.7
+      '@babel/types': 7.24.7
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7):
+    resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-environment-visitor': 7.24.7
+      '@babel/helper-module-imports': 7.24.7
+      '@babel/helper-simple-access': 7.24.7
+      '@babel/helper-split-export-declaration': 7.24.7
+      '@babel/helper-validator-identifier': 7.24.7
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/helper-optimise-call-expression@7.24.7:
+    resolution: {integrity: sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/types': 7.24.7
+    dev: true
+
+  /@babel/helper-plugin-utils@7.24.7:
+    resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==}
+    engines: {node: '>=6.9.0'}
+    dev: true
+
+  /@babel/helper-replace-supers@7.24.7(@babel/core@7.24.7):
+    resolution: {integrity: sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-environment-visitor': 7.24.7
+      '@babel/helper-member-expression-to-functions': 7.24.7
+      '@babel/helper-optimise-call-expression': 7.24.7
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/helper-simple-access@7.24.7:
+    resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/traverse': 7.24.7
+      '@babel/types': 7.24.7
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/helper-skip-transparent-expression-wrappers@7.24.7:
+    resolution: {integrity: sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/traverse': 7.24.7
+      '@babel/types': 7.24.7
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/helper-split-export-declaration@7.24.7:
+    resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/types': 7.24.7
+    dev: true
+
+  /@babel/helper-string-parser@7.24.7:
+    resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==}
+    engines: {node: '>=6.9.0'}
+
+  /@babel/helper-validator-identifier@7.24.7:
+    resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==}
+    engines: {node: '>=6.9.0'}
+
+  /@babel/helper-validator-option@7.24.7:
+    resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==}
+    engines: {node: '>=6.9.0'}
+    dev: true
+
+  /@babel/helpers@7.24.7:
+    resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/template': 7.24.7
+      '@babel/types': 7.24.7
+    dev: true
+
+  /@babel/highlight@7.24.7:
+    resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/helper-validator-identifier': 7.24.7
+      chalk: 2.4.2
+      js-tokens: 4.0.0
+      picocolors: 1.0.1
+    dev: true
+
+  /@babel/parser@7.24.7:
+    resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+    dependencies:
+      '@babel/types': 7.24.7
+
+  /@babel/plugin-proposal-decorators@7.24.7(@babel/core@7.24.7):
+    resolution: {integrity: sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7)
+      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.24.7)
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.24.7):
+    resolution: {integrity: sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+    dev: true
+
+  /@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.24.7):
+    resolution: {integrity: sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+    dev: true
+
+  /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.7):
+    resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+    dev: true
+
+  /@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.7):
+    resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+    dev: true
+
+  /@babel/plugin-syntax-typescript@7.24.7(@babel/core@7.24.7):
+    resolution: {integrity: sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-plugin-utils': 7.24.7
+    dev: true
+
+  /@babel/plugin-transform-typescript@7.24.7(@babel/core@7.24.7):
+    resolution: {integrity: sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-annotate-as-pure': 7.24.7
+      '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7)
+      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.24.7)
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/runtime@7.24.7:
+    resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      regenerator-runtime: 0.14.1
+    dev: false
+
+  /@babel/template@7.24.7:
+    resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/code-frame': 7.24.7
+      '@babel/parser': 7.24.7
+      '@babel/types': 7.24.7
+    dev: true
+
+  /@babel/traverse@7.24.7:
+    resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/code-frame': 7.24.7
+      '@babel/generator': 7.24.7
+      '@babel/helper-environment-visitor': 7.24.7
+      '@babel/helper-function-name': 7.24.7
+      '@babel/helper-hoist-variables': 7.24.7
+      '@babel/helper-split-export-declaration': 7.24.7
+      '@babel/parser': 7.24.7
+      '@babel/types': 7.24.7
+      debug: 4.3.5
+      globals: 11.12.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@babel/types@7.24.7:
+    resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/helper-string-parser': 7.24.7
+      '@babel/helper-validator-identifier': 7.24.7
+      to-fast-properties: 2.0.0
+
+  /@better-scroll/core@2.5.1:
+    resolution: {integrity: sha512-koKOuYA55dQ04FJRIVUpMGDr1hbCfWmfX0MGp1hKagkQSWSRpwblqACiwtggVauoj9aaJRJZ9hDsTM4weaavlg==}
+    dependencies:
+      '@better-scroll/shared-utils': 2.5.1
+    dev: false
+
+  /@better-scroll/shared-utils@2.5.1:
+    resolution: {integrity: sha512-AplkfSjXVYP9LZiD6JsKgmgQJ/mG4uuLmBuwLz8W5OsYc7AYTfN8kw6GqZ5OwCGoXkVhBGyd8NeC4xwYItp0aw==}
+    dev: false
+
+  /@colors/colors@1.5.0:
+    resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
+    engines: {node: '>=0.1.90'}
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@ctrl/tinycolor@3.6.1:
+    resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
+    engines: {node: '>=10'}
+    dev: false
+
+  /@elegant-router/core@0.3.7:
+    resolution: {integrity: sha512-iNj+ZGage9w6vnZyAvZzrRX+yQX7Tr02PJZjwX92ShdEEDnDkM71UnUOv94X6z6T1y4QQo+v1/z6MNP0fJl5mw==}
+    dependencies:
+      chokidar: 3.6.0
+      consola: 3.2.3
+      fast-glob: 3.3.2
+      kolorist: 1.8.0
+      micromatch: 4.0.5
+    dev: true
+
+  /@elegant-router/vue@0.3.7:
+    resolution: {integrity: sha512-nw1M62SIlvyVE+BsHoOVntJzib2Ch1uz1U8QLJygNMuKfltb9VmWhZzEpKr8ZSIWLQt3ibK6wsla2T4h67mxGQ==}
+    dependencies:
+      '@elegant-router/core': 0.3.7
+      consola: 3.2.3
+      kolorist: 1.8.0
+      magic-string: 0.30.10
+      magicast: 0.3.4
+      prettier: 3.2.5
+      recast: 0.23.7
+      unplugin: 1.10.1
+    dev: true
+
+  /@emotion/hash@0.9.1:
+    resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==}
+    dev: false
+
+  /@emotion/unitless@0.8.1:
+    resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==}
+    dev: false
+
+  /@esbuild/aix-ppc64@0.21.5:
+    resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [aix]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/android-arm64@0.21.5:
+    resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/android-arm@0.21.5:
+    resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/android-x64@0.21.5:
+    resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/darwin-arm64@0.21.5:
+    resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/darwin-x64@0.21.5:
+    resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/freebsd-arm64@0.21.5:
+    resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [freebsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/freebsd-x64@0.21.5:
+    resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [freebsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-arm64@0.21.5:
+    resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-arm@0.21.5:
+    resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-ia32@0.21.5:
+    resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-loong64@0.21.5:
+    resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
+    engines: {node: '>=12'}
+    cpu: [loong64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-mips64el@0.21.5:
+    resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
+    engines: {node: '>=12'}
+    cpu: [mips64el]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-ppc64@0.21.5:
+    resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-riscv64@0.21.5:
+    resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
+    engines: {node: '>=12'}
+    cpu: [riscv64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-s390x@0.21.5:
+    resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
+    engines: {node: '>=12'}
+    cpu: [s390x]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-x64@0.21.5:
+    resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/netbsd-x64@0.21.5:
+    resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [netbsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/openbsd-x64@0.21.5:
+    resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [openbsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/sunos-x64@0.21.5:
+    resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [sunos]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/win32-arm64@0.21.5:
+    resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/win32-ia32@0.21.5:
+    resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/win32-x64@0.21.5:
+    resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@eslint-community/eslint-utils@4.4.0(eslint@9.0.0-rc.0):
+    resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+    dependencies:
+      eslint: 9.0.0-rc.0
+      eslint-visitor-keys: 3.4.3
+    dev: true
+
+  /@eslint-community/eslint-utils@4.4.0(eslint@9.5.0):
+    resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+    dependencies:
+      eslint: 9.5.0
+      eslint-visitor-keys: 3.4.3
+    dev: true
+
+  /@eslint-community/regexpp@4.11.0:
+    resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==}
+    engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+    dev: true
+
+  /@eslint/config-array@0.16.0:
+    resolution: {integrity: sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    dependencies:
+      '@eslint/object-schema': 2.1.4
+      debug: 4.3.5
+      minimatch: 3.1.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@eslint/eslintrc@3.1.0:
+    resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    dependencies:
+      ajv: 6.12.6
+      debug: 4.3.5
+      espree: 10.1.0
+      globals: 14.0.0
+      ignore: 5.3.1
+      import-fresh: 3.3.0
+      js-yaml: 4.1.0
+      minimatch: 3.1.2
+      strip-json-comments: 3.1.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@eslint/js@9.0.0-rc.0:
+    resolution: {integrity: sha512-xKe0bSy6LRzfoibzCo7QcpdspzLOm80hLUtVdtLMYGjGioELbRizJIxMLZb6jl0BOmIexLtOBr3Tgdtj4eGaEQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    dev: true
+
+  /@eslint/js@9.4.0:
+    resolution: {integrity: sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    dev: true
+
+  /@eslint/js@9.5.0:
+    resolution: {integrity: sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    dev: true
+
+  /@eslint/object-schema@2.1.4:
+    resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    dev: true
+
+  /@gar/promisify@1.1.3:
+    resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
+    dev: true
+
+  /@humanwhocodes/config-array@0.11.14:
+    resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
+    engines: {node: '>=10.10.0'}
+    deprecated: Use @eslint/config-array instead
+    dependencies:
+      '@humanwhocodes/object-schema': 2.0.3
+      debug: 4.3.5
+      minimatch: 3.1.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@humanwhocodes/module-importer@1.0.1:
+    resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+    engines: {node: '>=12.22'}
+    dev: true
+
+  /@humanwhocodes/object-schema@2.0.3:
+    resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
+    deprecated: Use @eslint/object-schema instead
+    dev: true
+
+  /@humanwhocodes/retry@0.3.0:
+    resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
+    engines: {node: '>=18.18'}
+    dev: true
+
+  /@iconify/json@2.2.220:
+    resolution: {integrity: sha512-EpKZAK99E5qmgeOS5XOxzlzPaYXOkhLneypLFvbKIU3/KGmxGS/k6pgaEX6wTId4oF2HPGBDJnXyvckHiOHQiA==}
+    dependencies:
+      '@iconify/types': 2.0.0
+      pathe: 1.1.2
+    dev: true
+
+  /@iconify/types@2.0.0:
+    resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
+
+  /@iconify/utils@2.1.25:
+    resolution: {integrity: sha512-Y+iGko8uv/Fz5bQLLJyNSZGOdMW0G7cnlEX1CiNcKsRXX9cq/y/vwxrIAtLCZhKHr3m0VJmsjVPsvnM4uX8YLg==}
+    dependencies:
+      '@antfu/install-pkg': 0.1.1
+      '@antfu/utils': 0.7.10
+      '@iconify/types': 2.0.0
+      debug: 4.3.5
+      kolorist: 1.8.0
+      local-pkg: 0.5.0
+      mlly: 1.7.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@iconify/vue@4.1.2(vue@3.4.29):
+    resolution: {integrity: sha512-CQnYqLiQD5LOAaXhBrmj1mdL2/NCJvwcC4jtW2Z8ukhThiFkLDkutarTOV2trfc9EXqUqRs0KqXOL9pZ/IyysA==}
+    peerDependencies:
+      vue: '>=3'
+    dependencies:
+      '@iconify/types': 2.0.0
+      vue: 3.4.29(typescript@5.4.5)
+    dev: false
+
+  /@intlify/core-base@9.13.1:
+    resolution: {integrity: sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==}
+    engines: {node: '>= 16'}
+    dependencies:
+      '@intlify/message-compiler': 9.13.1
+      '@intlify/shared': 9.13.1
+    dev: false
+
+  /@intlify/message-compiler@9.13.1:
+    resolution: {integrity: sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==}
+    engines: {node: '>= 16'}
+    dependencies:
+      '@intlify/shared': 9.13.1
+      source-map-js: 1.2.0
+    dev: false
+
+  /@intlify/shared@9.13.1:
+    resolution: {integrity: sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==}
+    engines: {node: '>= 16'}
+    dev: false
+
+  /@isaacs/cliui@8.0.2:
+    resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+    engines: {node: '>=12'}
+    dependencies:
+      string-width: 5.1.2
+      string-width-cjs: /string-width@4.2.3
+      strip-ansi: 7.1.0
+      strip-ansi-cjs: /strip-ansi@6.0.1
+      wrap-ansi: 8.1.0
+      wrap-ansi-cjs: /wrap-ansi@7.0.0
+    dev: true
+
+  /@jridgewell/gen-mapping@0.3.5:
+    resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
+    engines: {node: '>=6.0.0'}
+    dependencies:
+      '@jridgewell/set-array': 1.2.1
+      '@jridgewell/sourcemap-codec': 1.4.15
+      '@jridgewell/trace-mapping': 0.3.25
+    dev: true
+
+  /@jridgewell/resolve-uri@3.1.2:
+    resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+    engines: {node: '>=6.0.0'}
+    dev: true
+
+  /@jridgewell/set-array@1.2.1:
+    resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
+    engines: {node: '>=6.0.0'}
+    dev: true
+
+  /@jridgewell/sourcemap-codec@1.4.15:
+    resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+
+  /@jridgewell/trace-mapping@0.3.25:
+    resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+    dependencies:
+      '@jridgewell/resolve-uri': 3.1.2
+      '@jridgewell/sourcemap-codec': 1.4.15
+    dev: true
+
+  /@jsdevtools/ez-spawn@3.0.4:
+    resolution: {integrity: sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==}
+    engines: {node: '>=10'}
+    dependencies:
+      call-me-maybe: 1.0.2
+      cross-spawn: 7.0.3
+      string-argv: 0.3.2
+      type-detect: 4.0.8
+    dev: true
+
+  /@nodelib/fs.scandir@2.1.5:
+    resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+    engines: {node: '>= 8'}
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      run-parallel: 1.2.0
+    dev: true
+
+  /@nodelib/fs.stat@2.0.5:
+    resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+    engines: {node: '>= 8'}
+    dev: true
+
+  /@nodelib/fs.walk@1.2.8:
+    resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+    engines: {node: '>= 8'}
+    dependencies:
+      '@nodelib/fs.scandir': 2.1.5
+      fastq: 1.17.1
+    dev: true
+
+  /@npmcli/fs@2.1.2:
+    resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    dependencies:
+      '@gar/promisify': 1.1.3
+      semver: 7.6.2
+    dev: true
+
+  /@npmcli/fs@3.1.1:
+    resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      semver: 7.6.2
+    dev: true
+
+  /@npmcli/git@4.1.0:
+    resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      '@npmcli/promise-spawn': 6.0.2
+      lru-cache: 7.18.3
+      npm-pick-manifest: 8.0.2
+      proc-log: 3.0.0
+      promise-inflight: 1.0.1
+      promise-retry: 2.0.1
+      semver: 7.6.2
+      which: 3.0.1
+    transitivePeerDependencies:
+      - bluebird
+    dev: true
+
+  /@npmcli/installed-package-contents@2.1.0:
+    resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    hasBin: true
+    dependencies:
+      npm-bundled: 3.0.1
+      npm-normalize-package-bin: 3.0.1
+    dev: true
+
+  /@npmcli/move-file@2.0.1:
+    resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    deprecated: This functionality has been moved to @npmcli/fs
+    dependencies:
+      mkdirp: 1.0.4
+      rimraf: 3.0.2
+    dev: true
+
+  /@npmcli/node-gyp@3.0.0:
+    resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dev: true
+
+  /@npmcli/promise-spawn@6.0.2:
+    resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      which: 3.0.1
+    dev: true
+
+  /@npmcli/run-script@6.0.2:
+    resolution: {integrity: sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      '@npmcli/node-gyp': 3.0.0
+      '@npmcli/promise-spawn': 6.0.2
+      node-gyp: 9.4.1
+      read-package-json-fast: 3.0.2
+      which: 3.0.1
+    transitivePeerDependencies:
+      - bluebird
+      - supports-color
+    dev: true
+
+  /@pkgjs/parseargs@0.11.0:
+    resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+    engines: {node: '>=14'}
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@pkgr/core@0.1.1:
+    resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
+    engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+    dev: true
+
+  /@pnpm/config.env-replace@1.1.0:
+    resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==}
+    engines: {node: '>=12.22.0'}
+    dev: true
+
+  /@pnpm/network.ca-file@1.0.2:
+    resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==}
+    engines: {node: '>=12.22.0'}
+    dependencies:
+      graceful-fs: 4.2.10
+    dev: true
+
+  /@pnpm/npm-conf@2.2.2:
+    resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==}
+    engines: {node: '>=12'}
+    dependencies:
+      '@pnpm/config.env-replace': 1.1.0
+      '@pnpm/network.ca-file': 1.0.2
+      config-chain: 1.1.13
+    dev: true
+
+  /@polka/url@1.0.0-next.25:
+    resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
+    dev: true
+
+  /@rollup/pluginutils@5.1.0:
+    resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
+    engines: {node: '>=14.0.0'}
+    peerDependencies:
+      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+    peerDependenciesMeta:
+      rollup:
+        optional: true
+    dependencies:
+      '@types/estree': 1.0.5
+      estree-walker: 2.0.2
+      picomatch: 2.3.1
+    dev: true
+
+  /@rollup/rollup-android-arm-eabi@4.18.0:
+    resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==}
+    cpu: [arm]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-android-arm64@4.18.0:
+    resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==}
+    cpu: [arm64]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-darwin-arm64@4.18.0:
+    resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==}
+    cpu: [arm64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-darwin-x64@4.18.0:
+    resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==}
+    cpu: [x64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-arm-gnueabihf@4.18.0:
+    resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==}
+    cpu: [arm]
+    os: [linux]
+    libc: [glibc]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-arm-musleabihf@4.18.0:
+    resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==}
+    cpu: [arm]
+    os: [linux]
+    libc: [musl]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-arm64-gnu@4.18.0:
+    resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-arm64-musl@4.18.0:
+    resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-powerpc64le-gnu@4.18.0:
+    resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==}
+    cpu: [ppc64]
+    os: [linux]
+    libc: [glibc]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-riscv64-gnu@4.18.0:
+    resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==}
+    cpu: [riscv64]
+    os: [linux]
+    libc: [glibc]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-s390x-gnu@4.18.0:
+    resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==}
+    cpu: [s390x]
+    os: [linux]
+    libc: [glibc]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-x64-gnu@4.18.0:
+    resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-x64-musl@4.18.0:
+    resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-win32-arm64-msvc@4.18.0:
+    resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==}
+    cpu: [arm64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-win32-ia32-msvc@4.18.0:
+    resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==}
+    cpu: [ia32]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-win32-x64-msvc@4.18.0:
+    resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==}
+    cpu: [x64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@sec-ant/readable-stream@0.4.1:
+    resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
+    dev: true
+
+  /@sigstore/bundle@1.1.0:
+    resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      '@sigstore/protobuf-specs': 0.2.1
+    dev: true
+
+  /@sigstore/protobuf-specs@0.2.1:
+    resolution: {integrity: sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dev: true
+
+  /@sigstore/sign@1.0.0:
+    resolution: {integrity: sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      '@sigstore/bundle': 1.1.0
+      '@sigstore/protobuf-specs': 0.2.1
+      make-fetch-happen: 11.1.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@sigstore/tuf@1.0.3:
+    resolution: {integrity: sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      '@sigstore/protobuf-specs': 0.2.1
+      tuf-js: 1.1.7
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@simonwep/pickr@1.8.2:
+    resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==}
+    dependencies:
+      core-js: 3.37.1
+      nanopop: 2.4.2
+    dev: false
+
+  /@simonwep/pickr@1.9.1:
+    resolution: {integrity: sha512-fR3qmfAcPf/HSFS7GEnTmZLM3+xERv1+jyMBbzT63ilRRM8veYjI7ELvkHHKk0/du3lHp7uh/FqatjM3646X1g==}
+    dependencies:
+      core-js: 3.37.0
+      nanopop: 2.4.2
+    dev: false
+
+  /@sindresorhus/is@5.6.0:
+    resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
+    engines: {node: '>=14.16'}
+    dev: true
+
+  /@sindresorhus/merge-streams@4.0.0:
+    resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /@soybeanjs/changelog@0.3.24(@unocss/eslint-config@0.61.0)(eslint-plugin-vue@9.26.0)(eslint@9.0.0-rc.0)(typescript@5.4.5)(vue-eslint-parser@9.4.3):
+    resolution: {integrity: sha512-QQVDFOsAdrYkyE5eEXuwtEi3poIOptkZhA0NxV2dfZoU3ChfFo0pkkuDplgpXaZvx09Omu2i04fdNKxFftAC3w==}
+    engines: {node: '>=16', pnpm: '>=9'}
+    dependencies:
+      '@soybeanjs/eslint-config': 1.3.7(@unocss/eslint-config@0.61.0)(eslint-plugin-vue@9.26.0)(eslint@9.0.0-rc.0)(typescript@5.4.5)(vue-eslint-parser@9.4.3)
+      cli-progress: 3.12.0
+      convert-gitmoji: 0.1.5
+      dayjs: 1.11.11
+      execa: 9.1.0
+      ofetch: 1.3.4
+      semver: 7.6.2
+    transitivePeerDependencies:
+      - '@toml-tools/parser'
+      - '@types/eslint'
+      - '@unocss/eslint-config'
+      - eslint
+      - eslint-plugin-astro
+      - eslint-plugin-react
+      - eslint-plugin-react-hooks
+      - eslint-plugin-react-native
+      - eslint-plugin-react-refresh
+      - eslint-plugin-solid
+      - eslint-plugin-svelte
+      - eslint-plugin-vue
+      - prettier-plugin-astro
+      - prettier-plugin-svelte
+      - prettier-plugin-toml
+      - supports-color
+      - typescript
+      - vue-eslint-parser
+    dev: true
+
+  /@soybeanjs/eslint-config@1.3.7(@unocss/eslint-config@0.61.0)(eslint-plugin-vue@9.26.0)(eslint@9.0.0-rc.0)(typescript@5.4.5)(vue-eslint-parser@9.4.3):
+    resolution: {integrity: sha512-+VyWKjM5McbzBKA3ptqoWgHKDtE/UuXqU7GhciZS2x8YT4ORDFfqGvEgCGaGMVE6jMuh0i8aEskZjnnv3GtT8A==}
+    peerDependencies:
+      '@toml-tools/parser': '*'
+      '@unocss/eslint-config': '>=0.58.0'
+      eslint: '>=8.40.0'
+      eslint-plugin-astro: '>=0.30.0'
+      eslint-plugin-react: '>=7.0.0'
+      eslint-plugin-react-hooks: '>=4.0.0'
+      eslint-plugin-react-native: '>=4.0.0'
+      eslint-plugin-react-refresh: '>=0.4.0'
+      eslint-plugin-solid: '>=0.10.0'
+      eslint-plugin-svelte: '>=2.0.0'
+      eslint-plugin-vue: '>=9.19.0'
+      prettier-plugin-astro: '>=0.12.0'
+      prettier-plugin-svelte: '>=3.0.0'
+      prettier-plugin-toml: '>=2.0.0'
+      typescript: '>=5.0.0'
+      vue-eslint-parser: '>=9.3.2'
+    peerDependenciesMeta:
+      '@toml-tools/parser':
+        optional: true
+      '@unocss/eslint-config':
+        optional: true
+      eslint-plugin-astro:
+        optional: true
+      eslint-plugin-react:
+        optional: true
+      eslint-plugin-react-hooks:
+        optional: true
+      eslint-plugin-react-native:
+        optional: true
+      eslint-plugin-react-refresh:
+        optional: true
+      eslint-plugin-solid:
+        optional: true
+      eslint-plugin-svelte:
+        optional: true
+      eslint-plugin-vue:
+        optional: true
+      prettier-plugin-astro:
+        optional: true
+      prettier-plugin-svelte:
+        optional: true
+      prettier-plugin-toml:
+        optional: true
+      vue-eslint-parser:
+        optional: true
+    dependencies:
+      '@antfu/eslint-define-config': 1.23.0-2
+      '@antfu/install-pkg': 0.3.3
+      '@eslint/eslintrc': 3.1.0
+      '@eslint/js': 9.4.0
+      '@typescript-eslint/eslint-plugin': 7.13.0(@typescript-eslint/parser@7.13.0)(eslint@9.0.0-rc.0)(typescript@5.4.5)
+      '@typescript-eslint/parser': 7.13.0(eslint@9.0.0-rc.0)(typescript@5.4.5)
+      '@unocss/eslint-config': 0.61.0(eslint@9.5.0)(typescript@5.4.5)
+      eslint: 9.0.0-rc.0
+      eslint-config-prettier: 9.1.0(eslint@9.0.0-rc.0)
+      eslint-parser-plain: 0.1.0
+      eslint-plugin-import-x: 0.5.1(eslint@9.0.0-rc.0)(typescript@5.4.5)
+      eslint-plugin-n: 17.8.1(eslint@9.0.0-rc.0)
+      eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0)(eslint@9.0.0-rc.0)(prettier@3.3.2)
+      eslint-plugin-unicorn: 53.0.0(eslint@9.0.0-rc.0)
+      eslint-plugin-vue: 9.26.0(eslint@9.5.0)
+      globals: 15.4.0
+      local-pkg: 0.5.0
+      prettier: 3.3.2
+      prettier-plugin-jsdoc: 1.3.0(prettier@3.3.2)
+      prettier-plugin-json-sort: 0.0.2(prettier@3.3.2)
+      prompts: 2.4.2
+      typescript: 5.4.5
+      vue-eslint-parser: 9.4.3(eslint@9.5.0)
+    transitivePeerDependencies:
+      - '@types/eslint'
+      - supports-color
+    dev: true
+
+  /@soybeanjs/eslint-config@1.3.7(@unocss/eslint-config@0.61.0)(eslint-plugin-vue@9.26.0)(eslint@9.5.0)(typescript@5.4.5)(vue-eslint-parser@9.4.3):
+    resolution: {integrity: sha512-+VyWKjM5McbzBKA3ptqoWgHKDtE/UuXqU7GhciZS2x8YT4ORDFfqGvEgCGaGMVE6jMuh0i8aEskZjnnv3GtT8A==}
+    peerDependencies:
+      '@toml-tools/parser': '*'
+      '@unocss/eslint-config': '>=0.58.0'
+      eslint: '>=8.40.0'
+      eslint-plugin-astro: '>=0.30.0'
+      eslint-plugin-react: '>=7.0.0'
+      eslint-plugin-react-hooks: '>=4.0.0'
+      eslint-plugin-react-native: '>=4.0.0'
+      eslint-plugin-react-refresh: '>=0.4.0'
+      eslint-plugin-solid: '>=0.10.0'
+      eslint-plugin-svelte: '>=2.0.0'
+      eslint-plugin-vue: '>=9.19.0'
+      prettier-plugin-astro: '>=0.12.0'
+      prettier-plugin-svelte: '>=3.0.0'
+      prettier-plugin-toml: '>=2.0.0'
+      typescript: '>=5.0.0'
+      vue-eslint-parser: '>=9.3.2'
+    peerDependenciesMeta:
+      '@toml-tools/parser':
+        optional: true
+      '@unocss/eslint-config':
+        optional: true
+      eslint-plugin-astro:
+        optional: true
+      eslint-plugin-react:
+        optional: true
+      eslint-plugin-react-hooks:
+        optional: true
+      eslint-plugin-react-native:
+        optional: true
+      eslint-plugin-react-refresh:
+        optional: true
+      eslint-plugin-solid:
+        optional: true
+      eslint-plugin-svelte:
+        optional: true
+      eslint-plugin-vue:
+        optional: true
+      prettier-plugin-astro:
+        optional: true
+      prettier-plugin-svelte:
+        optional: true
+      prettier-plugin-toml:
+        optional: true
+      vue-eslint-parser:
+        optional: true
+    dependencies:
+      '@antfu/eslint-define-config': 1.23.0-2
+      '@antfu/install-pkg': 0.3.3
+      '@eslint/eslintrc': 3.1.0
+      '@eslint/js': 9.4.0
+      '@typescript-eslint/eslint-plugin': 7.13.0(@typescript-eslint/parser@7.13.0)(eslint@9.5.0)(typescript@5.4.5)
+      '@typescript-eslint/parser': 7.13.0(eslint@9.5.0)(typescript@5.4.5)
+      '@unocss/eslint-config': 0.61.0(eslint@9.5.0)(typescript@5.4.5)
+      eslint: 9.5.0
+      eslint-config-prettier: 9.1.0(eslint@9.5.0)
+      eslint-parser-plain: 0.1.0
+      eslint-plugin-import-x: 0.5.1(eslint@9.5.0)(typescript@5.4.5)
+      eslint-plugin-n: 17.8.1(eslint@9.5.0)
+      eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0)(eslint@9.5.0)(prettier@3.3.2)
+      eslint-plugin-unicorn: 53.0.0(eslint@9.5.0)
+      eslint-plugin-vue: 9.26.0(eslint@9.5.0)
+      globals: 15.4.0
+      local-pkg: 0.5.0
+      prettier: 3.3.2
+      prettier-plugin-jsdoc: 1.3.0(prettier@3.3.2)
+      prettier-plugin-json-sort: 0.0.2(prettier@3.3.2)
+      prompts: 2.4.2
+      typescript: 5.4.5
+      vue-eslint-parser: 9.4.3(eslint@9.5.0)
+    transitivePeerDependencies:
+      - '@types/eslint'
+      - supports-color
+    dev: true
+
+  /@szmarczak/http-timer@5.0.1:
+    resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==}
+    engines: {node: '>=14.16'}
+    dependencies:
+      defer-to-connect: 2.0.1
+    dev: true
+
+  /@tootallnate/once@2.0.0:
+    resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
+    engines: {node: '>= 10'}
+    dev: true
+
+  /@trysound/sax@0.2.0:
+    resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
+    engines: {node: '>=10.13.0'}
+    dev: true
+
+  /@tufjs/canonical-json@1.0.0:
+    resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dev: true
+
+  /@tufjs/models@1.0.4:
+    resolution: {integrity: sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      '@tufjs/canonical-json': 1.0.0
+      minimatch: 9.0.5
+    dev: true
+
+  /@types/crypto-js@4.2.2:
+    resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==}
+    dev: true
+
+  /@types/debug@4.1.12:
+    resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+    dependencies:
+      '@types/ms': 0.7.34
+    dev: true
+
+  /@types/estree@1.0.5:
+    resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+    dev: true
+
+  /@types/http-cache-semantics@4.0.4:
+    resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==}
+    dev: true
+
+  /@types/lodash-es@4.17.12:
+    resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
+    dependencies:
+      '@types/lodash': 4.17.6
+
+  /@types/lodash@4.17.6:
+    resolution: {integrity: sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==}
+
+  /@types/mdast@4.0.4:
+    resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+    dependencies:
+      '@types/unist': 3.0.2
+    dev: true
+
+  /@types/ms@0.7.34:
+    resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
+    dev: true
+
+  /@types/node@10.17.60:
+    resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==}
+    dev: true
+
+  /@types/node@20.14.6:
+    resolution: {integrity: sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==}
+    dependencies:
+      undici-types: 5.26.5
+    dev: true
+
+  /@types/normalize-package-data@2.4.4:
+    resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
+    dev: true
+
+  /@types/nprogress@0.2.3:
+    resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==}
+    dev: true
+
+  /@types/qs@6.9.15:
+    resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==}
+    dev: true
+
+  /@types/semver-utils@1.1.3:
+    resolution: {integrity: sha512-T+YwkslhsM+CeuhYUxyAjWm7mJ5am/K10UX40RuA6k6Lc7eGtq8iY2xOzy7Vq0GOqhl/xZl5l2FwURZMTPTUww==}
+    dev: true
+
+  /@types/sortablejs@1.15.8:
+    resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==}
+    dev: false
+
+  /@types/svgo@2.6.4:
+    resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==}
+    dependencies:
+      '@types/node': 20.14.6
+    dev: true
+
+  /@types/unist@3.0.2:
+    resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==}
+    dev: true
+
+  /@types/web-bluetooth@0.0.20:
+    resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
+    dev: false
+
+  /@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0)(eslint@9.0.0-rc.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      '@typescript-eslint/parser': ^7.0.0
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@eslint-community/regexpp': 4.11.0
+      '@typescript-eslint/parser': 7.13.0(eslint@9.0.0-rc.0)(typescript@5.4.5)
+      '@typescript-eslint/scope-manager': 7.13.0
+      '@typescript-eslint/type-utils': 7.13.0(eslint@9.0.0-rc.0)(typescript@5.4.5)
+      '@typescript-eslint/utils': 7.13.0(eslint@9.0.0-rc.0)(typescript@5.4.5)
+      '@typescript-eslint/visitor-keys': 7.13.0
+      eslint: 9.0.0-rc.0
+      graphemer: 1.4.0
+      ignore: 5.3.1
+      natural-compare: 1.4.0
+      ts-api-utils: 1.3.0(typescript@5.4.5)
+      typescript: 5.4.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0)(eslint@9.5.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      '@typescript-eslint/parser': ^7.0.0
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@eslint-community/regexpp': 4.11.0
+      '@typescript-eslint/parser': 7.13.0(eslint@9.5.0)(typescript@5.4.5)
+      '@typescript-eslint/scope-manager': 7.13.0
+      '@typescript-eslint/type-utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5)
+      '@typescript-eslint/utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5)
+      '@typescript-eslint/visitor-keys': 7.13.0
+      eslint: 9.5.0
+      graphemer: 1.4.0
+      ignore: 5.3.1
+      natural-compare: 1.4.0
+      ts-api-utils: 1.3.0(typescript@5.4.5)
+      typescript: 5.4.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/parser@7.13.0(eslint@9.0.0-rc.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@typescript-eslint/scope-manager': 7.13.0
+      '@typescript-eslint/types': 7.13.0
+      '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5)
+      '@typescript-eslint/visitor-keys': 7.13.0
+      debug: 4.3.5
+      eslint: 9.0.0-rc.0
+      typescript: 5.4.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/parser@7.13.0(eslint@9.5.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@typescript-eslint/scope-manager': 7.13.0
+      '@typescript-eslint/types': 7.13.0
+      '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5)
+      '@typescript-eslint/visitor-keys': 7.13.0
+      debug: 4.3.5
+      eslint: 9.5.0
+      typescript: 5.4.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/scope-manager@7.13.0:
+    resolution: {integrity: sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    dependencies:
+      '@typescript-eslint/types': 7.13.0
+      '@typescript-eslint/visitor-keys': 7.13.0
+    dev: true
+
+  /@typescript-eslint/scope-manager@7.15.0:
+    resolution: {integrity: sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    dependencies:
+      '@typescript-eslint/types': 7.15.0
+      '@typescript-eslint/visitor-keys': 7.15.0
+    dev: true
+
+  /@typescript-eslint/type-utils@7.13.0(eslint@9.0.0-rc.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5)
+      '@typescript-eslint/utils': 7.13.0(eslint@9.0.0-rc.0)(typescript@5.4.5)
+      debug: 4.3.5
+      eslint: 9.0.0-rc.0
+      ts-api-utils: 1.3.0(typescript@5.4.5)
+      typescript: 5.4.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/type-utils@7.13.0(eslint@9.5.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5)
+      '@typescript-eslint/utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5)
+      debug: 4.3.5
+      eslint: 9.5.0
+      ts-api-utils: 1.3.0(typescript@5.4.5)
+      typescript: 5.4.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/types@7.13.0:
+    resolution: {integrity: sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    dev: true
+
+  /@typescript-eslint/types@7.15.0:
+    resolution: {integrity: sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    dev: true
+
+  /@typescript-eslint/typescript-estree@7.13.0(typescript@5.4.5):
+    resolution: {integrity: sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@typescript-eslint/types': 7.13.0
+      '@typescript-eslint/visitor-keys': 7.13.0
+      debug: 4.3.5
+      globby: 11.1.0
+      is-glob: 4.0.3
+      minimatch: 9.0.5
+      semver: 7.6.2
+      ts-api-utils: 1.3.0(typescript@5.4.5)
+      typescript: 5.4.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/typescript-estree@7.15.0(typescript@5.4.5):
+    resolution: {integrity: sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@typescript-eslint/types': 7.15.0
+      '@typescript-eslint/visitor-keys': 7.15.0
+      debug: 4.3.5
+      globby: 11.1.0
+      is-glob: 4.0.3
+      minimatch: 9.0.5
+      semver: 7.6.2
+      ts-api-utils: 1.3.0(typescript@5.4.5)
+      typescript: 5.4.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/utils@7.13.0(eslint@9.0.0-rc.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0-rc.0)
+      '@typescript-eslint/scope-manager': 7.13.0
+      '@typescript-eslint/types': 7.13.0
+      '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5)
+      eslint: 9.0.0-rc.0
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+    dev: true
+
+  /@typescript-eslint/utils@7.13.0(eslint@9.5.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0)
+      '@typescript-eslint/scope-manager': 7.13.0
+      '@typescript-eslint/types': 7.13.0
+      '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5)
+      eslint: 9.5.0
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+    dev: true
+
+  /@typescript-eslint/utils@7.15.0(eslint@9.0.0-rc.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0-rc.0)
+      '@typescript-eslint/scope-manager': 7.15.0
+      '@typescript-eslint/types': 7.15.0
+      '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.4.5)
+      eslint: 9.0.0-rc.0
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+    dev: true
+
+  /@typescript-eslint/utils@7.15.0(eslint@9.5.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0)
+      '@typescript-eslint/scope-manager': 7.15.0
+      '@typescript-eslint/types': 7.15.0
+      '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.4.5)
+      eslint: 9.5.0
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+    dev: true
+
+  /@typescript-eslint/visitor-keys@7.13.0:
+    resolution: {integrity: sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    dependencies:
+      '@typescript-eslint/types': 7.13.0
+      eslint-visitor-keys: 3.4.3
+    dev: true
+
+  /@typescript-eslint/visitor-keys@7.15.0:
+    resolution: {integrity: sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    dependencies:
+      '@typescript-eslint/types': 7.15.0
+      eslint-visitor-keys: 3.4.3
+    dev: true
+
+  /@unocss/config@0.61.0:
+    resolution: {integrity: sha512-k8uV4n8eMti4S6BFeAkc9QBXJefDIlPyOWrdKykUMOHLIWVAIS53JixW9FJNgJRw0RVI6B7UR+rOznWwKpORPA==}
+    engines: {node: '>=14'}
+    dependencies:
+      '@unocss/core': 0.61.0
+      unconfig: 0.3.13
+    dev: true
+
+  /@unocss/core@0.61.0:
+    resolution: {integrity: sha512-Y/Ly3LPIAzOBlWCdKBVzVzIaaWDsf+oWPIUZlaW7DL++WWypVBCghmxXIT5dyuMGXE560Hj92st4AkXfuVdxGQ==}
+    dev: true
+
+  /@unocss/eslint-config@0.61.0(eslint@9.5.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-X5PqMToLtIaNCWjim3ZReBPxUYDVeGCoUEW/kydsAp4uIZb7rwS49tMGZZg12GLYPg/AUw5Rdk13t1MFF1aclQ==}
+    engines: {node: '>=14'}
+    dependencies:
+      '@unocss/eslint-plugin': 0.61.0(eslint@9.5.0)(typescript@5.4.5)
+    transitivePeerDependencies:
+      - eslint
+      - supports-color
+      - typescript
+    dev: true
+
+  /@unocss/eslint-plugin@0.61.0(eslint@9.5.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-iZzERoVNTC/RJ4KUkhWDRu3LYYOeJmi7+AnuM2QGjkhNV5nHWb7fl7gVQvujK6xk+Kcy+f26k40tTKA9cCkuEg==}
+    engines: {node: '>=14'}
+    dependencies:
+      '@typescript-eslint/utils': 7.15.0(eslint@9.5.0)(typescript@5.4.5)
+      '@unocss/config': 0.61.0
+      '@unocss/core': 0.61.0
+      magic-string: 0.30.10
+      synckit: 0.9.0
+    transitivePeerDependencies:
+      - eslint
+      - supports-color
+      - typescript
+    dev: true
+
+  /@unocss/extractor-arbitrary-variants@0.61.0:
+    resolution: {integrity: sha512-9ru/UR4kZ1+jGXpMawV9T8kpL54FrJBmWKMuFlDTEDIwtzDyyfLbt/buoXdzKDLmil9hOXH3IH8+dah/OiiDoA==}
+    dependencies:
+      '@unocss/core': 0.61.0
+    dev: true
+
+  /@unocss/inspector@0.61.0:
+    resolution: {integrity: sha512-gpL2RNw6Cp145kTxWN0BG/tWd4x3LVbgkZfyUlh5IAZHWKAq9MWA0jIifV2RU94h4rbSBNHxz50bodYtkzeM8A==}
+    dependencies:
+      '@unocss/core': 0.61.0
+      '@unocss/rule-utils': 0.61.0
+      gzip-size: 6.0.0
+      sirv: 2.0.4
+    dev: true
+
+  /@unocss/preset-icons@0.61.0:
+    resolution: {integrity: sha512-xI7isKu1fQbyGee1lcJBLwvUlmubYbPN4ymepUamfprNPlWrzb5Gj2+SROERlzzrTaI8C0YdBxsYMGyOV94dXQ==}
+    dependencies:
+      '@iconify/utils': 2.1.25
+      '@unocss/core': 0.61.0
+      ofetch: 1.3.4
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@unocss/preset-mini@0.61.0:
+    resolution: {integrity: sha512-P+DdMtPtzAQ2aQ1/WWPoO3X/qvky+Fqq4eKXIvbqXOQ9c2oem7/dnsPeT08zzLIqxVJnuykymPwRT85EumS0gg==}
+    dependencies:
+      '@unocss/core': 0.61.0
+      '@unocss/extractor-arbitrary-variants': 0.61.0
+      '@unocss/rule-utils': 0.61.0
+    dev: true
+
+  /@unocss/preset-uno@0.61.0:
+    resolution: {integrity: sha512-mkKOra3dQEc3uI7aPIqa3t8MJXlmpLSgGaPfEJK52xkFe991ex6CiUunYMMWbh6ZSzmdxkO31IwQIH9lcmj/Uw==}
+    dependencies:
+      '@unocss/core': 0.61.0
+      '@unocss/preset-mini': 0.61.0
+      '@unocss/preset-wind': 0.61.0
+      '@unocss/rule-utils': 0.61.0
+    dev: true
+
+  /@unocss/preset-wind@0.61.0:
+    resolution: {integrity: sha512-PooyLVAF4wH9KvW4OKfDxYFuM4qmnlU+Ci6O6RGgVsKyQMq76crRqqK76lbnehg7jOoZJVxmWfQ6k5gT3aQeXQ==}
+    dependencies:
+      '@unocss/core': 0.61.0
+      '@unocss/preset-mini': 0.61.0
+      '@unocss/rule-utils': 0.61.0
+    dev: true
+
+  /@unocss/rule-utils@0.61.0:
+    resolution: {integrity: sha512-MCdmfhE6Q9HSWjWqi2sx5/nnKyOEhfhoo+pVumHIqkHQICQ/LuKioFf7Y7e5ycqjFE/7dC2hKGZJ8WTMGIOMwA==}
+    engines: {node: '>=14'}
+    dependencies:
+      '@unocss/core': 0.61.0
+      magic-string: 0.30.10
+    dev: true
+
+  /@unocss/scope@0.61.0:
+    resolution: {integrity: sha512-uDk84LX2meZHskSvy0Mad7jgF0Be6el16F9DKYYvxlUxlzu/mCj6PQpQrXi8uZ2+O3akneHFqAbO6ewYShKdQA==}
+    dev: true
+
+  /@unocss/transformer-directives@0.61.0:
+    resolution: {integrity: sha512-15nIynJPYFYnW/TUQu0NyZ5uxTDcrRyY8sB3axcYZOqqlu1hgPFotVukl6jqCZgGUR1AbfbnJwuDlcBQeT8xpA==}
+    dependencies:
+      '@unocss/core': 0.61.0
+      '@unocss/rule-utils': 0.61.0
+      css-tree: 2.3.1
+    dev: true
+
+  /@unocss/transformer-variant-group@0.61.0:
+    resolution: {integrity: sha512-5DHEram3iv+c9jPQW8p629aFyptyzdP5yNnRSMLBZcwyJ672VAKzPUZLYHh5UOUb69eaet3og1cU8uxpHhGKtQ==}
+    dependencies:
+      '@unocss/core': 0.61.0
+    dev: true
+
+  /@unocss/vite@0.61.0(vite@5.3.1):
+    resolution: {integrity: sha512-gjxLJrja1hqDwdd8z3QvzfMCcKppGqiL2+A6aHwG/AXfEmZMydA50U7VvJK7Wx8/Enm26G6JQrtGrpu+kK3QpQ==}
+    peerDependencies:
+      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0
+    dependencies:
+      '@ampproject/remapping': 2.3.0
+      '@rollup/pluginutils': 5.1.0
+      '@unocss/config': 0.61.0
+      '@unocss/core': 0.61.0
+      '@unocss/inspector': 0.61.0
+      '@unocss/scope': 0.61.0
+      '@unocss/transformer-directives': 0.61.0
+      chokidar: 3.6.0
+      fast-glob: 3.3.2
+      magic-string: 0.30.10
+      vite: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+    transitivePeerDependencies:
+      - rollup
+    dev: true
+
+  /@vitejs/plugin-vue-jsx@4.0.0(vite@5.3.1)(vue@3.4.29):
+    resolution: {integrity: sha512-A+6wL2AdQhDsLsDnY+2v4rRDI1HLJGIMc97a8FURO9tqKsH5QvjWrzsa5DH3NlZsM742W2wODl2fF+bfcTWtXw==}
+    engines: {node: ^18.0.0 || >=20.0.0}
+    peerDependencies:
+      vite: ^5.0.0
+      vue: ^3.0.0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/plugin-transform-typescript': 7.24.7(@babel/core@7.24.7)
+      '@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.24.7)
+      vite: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+      vue: 3.4.29(typescript@5.4.5)
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@vitejs/plugin-vue@5.0.5(vite@5.3.1)(vue@3.4.29):
+    resolution: {integrity: sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==}
+    engines: {node: ^18.0.0 || >=20.0.0}
+    peerDependencies:
+      vite: ^5.0.0
+      vue: ^3.2.25
+    dependencies:
+      vite: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+      vue: 3.4.29(typescript@5.4.5)
+    dev: true
+
+  /@volar/language-core@2.3.4:
+    resolution: {integrity: sha512-wXBhY11qG6pCDAqDnbBRFIDSIwbqkWI7no+lj5+L7IlA7HRIjRP7YQLGzT0LF4lS6eHkMSsclXqy9DwYJasZTQ==}
+    dependencies:
+      '@volar/source-map': 2.3.4
+    dev: true
+
+  /@volar/source-map@2.3.4:
+    resolution: {integrity: sha512-C+t63nwcblqLIVTYXaVi/+gC8NukDaDIQI72J3R7aXGvtgaVB16c+J8Iz7/VfOy7kjYv7lf5GhBny6ACw9fTGQ==}
+    dev: true
+
+  /@volar/typescript@2.3.4:
+    resolution: {integrity: sha512-acCvt7dZECyKcvO5geNybmrqOsu9u8n5XP1rfiYsOLYGPxvHRav9BVmEdRyZ3vvY6mNyQ1wLL5Hday4IShe17w==}
+    dependencies:
+      '@volar/language-core': 2.3.4
+      path-browserify: 1.0.1
+      vscode-uri: 3.0.8
+    dev: true
+
+  /@vue/babel-helper-vue-transform-on@1.2.2:
+    resolution: {integrity: sha512-nOttamHUR3YzdEqdM/XXDyCSdxMA9VizUKoroLX6yTyRtggzQMHXcmwh8a7ZErcJttIBIc9s68a1B8GZ+Dmvsw==}
+    dev: true
+
+  /@vue/babel-plugin-jsx@1.2.2(@babel/core@7.24.7):
+    resolution: {integrity: sha512-nYTkZUVTu4nhP199UoORePsql0l+wj7v/oyQjtThUVhJl1U+6qHuoVhIvR3bf7eVKjbCK+Cs2AWd7mi9Mpz9rA==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    peerDependenciesMeta:
+      '@babel/core':
+        optional: true
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/helper-module-imports': 7.22.15
+      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.7)
+      '@babel/template': 7.24.7
+      '@babel/traverse': 7.24.7
+      '@babel/types': 7.24.7
+      '@vue/babel-helper-vue-transform-on': 1.2.2
+      '@vue/babel-plugin-resolve-type': 1.2.2(@babel/core@7.24.7)
+      camelcase: 6.3.0
+      html-tags: 3.3.1
+      svg-tags: 1.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@vue/babel-plugin-resolve-type@1.2.2(@babel/core@7.24.7):
+    resolution: {integrity: sha512-EntyroPwNg5IPVdUJupqs0CFzuf6lUrVvCspmv2J1FITLeGnUCuoGNNk78dgCusxEiYj6RMkTJflGSxk5aIC4A==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    dependencies:
+      '@babel/code-frame': 7.24.7
+      '@babel/core': 7.24.7
+      '@babel/helper-module-imports': 7.22.15
+      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/parser': 7.24.7
+      '@vue/compiler-sfc': 3.4.31
+    dev: true
+
+  /@vue/compiler-core@3.4.29:
+    resolution: {integrity: sha512-TFKiRkKKsRCKvg/jTSSKK7mYLJEQdUiUfykbG49rubC9SfDyvT2JrzTReopWlz2MxqeLyxh9UZhvxEIBgAhtrg==}
+    dependencies:
+      '@babel/parser': 7.24.7
+      '@vue/shared': 3.4.29
+      entities: 4.5.0
+      estree-walker: 2.0.2
+      source-map-js: 1.2.0
+
+  /@vue/compiler-core@3.4.31:
+    resolution: {integrity: sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==}
+    dependencies:
+      '@babel/parser': 7.24.7
+      '@vue/shared': 3.4.31
+      entities: 4.5.0
+      estree-walker: 2.0.2
+      source-map-js: 1.2.0
+    dev: true
+
+  /@vue/compiler-dom@3.4.29:
+    resolution: {integrity: sha512-A6+iZ2fKIEGnfPJejdB7b1FlJzgiD+Y/sxxKwJWg1EbJu6ZPgzaPQQ51ESGNv0CP6jm6Z7/pO6Ia8Ze6IKrX7w==}
+    dependencies:
+      '@vue/compiler-core': 3.4.29
+      '@vue/shared': 3.4.29
+
+  /@vue/compiler-dom@3.4.31:
+    resolution: {integrity: sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==}
+    dependencies:
+      '@vue/compiler-core': 3.4.31
+      '@vue/shared': 3.4.31
+    dev: true
+
+  /@vue/compiler-sfc@3.4.29:
+    resolution: {integrity: sha512-zygDcEtn8ZimDlrEQyLUovoWgKQic6aEQqRXce2WXBvSeHbEbcAsXyCk9oG33ZkyWH4sl9D3tkYc1idoOkdqZQ==}
+    dependencies:
+      '@babel/parser': 7.24.7
+      '@vue/compiler-core': 3.4.29
+      '@vue/compiler-dom': 3.4.29
+      '@vue/compiler-ssr': 3.4.29
+      '@vue/shared': 3.4.29
+      estree-walker: 2.0.2
+      magic-string: 0.30.10
+      postcss: 8.4.39
+      source-map-js: 1.2.0
+
+  /@vue/compiler-sfc@3.4.31:
+    resolution: {integrity: sha512-einJxqEw8IIJxzmnxmJBuK2usI+lJonl53foq+9etB2HAzlPjAS/wa7r0uUpXw5ByX3/0uswVSrjNb17vJm1kQ==}
+    dependencies:
+      '@babel/parser': 7.24.7
+      '@vue/compiler-core': 3.4.31
+      '@vue/compiler-dom': 3.4.31
+      '@vue/compiler-ssr': 3.4.31
+      '@vue/shared': 3.4.31
+      estree-walker: 2.0.2
+      magic-string: 0.30.10
+      postcss: 8.4.39
+      source-map-js: 1.2.0
+    dev: true
+
+  /@vue/compiler-ssr@3.4.29:
+    resolution: {integrity: sha512-rFbwCmxJ16tDp3N8XCx5xSQzjhidYjXllvEcqX/lopkoznlNPz3jyy0WGJCyhAaVQK677WWFt3YO/WUEkMMUFQ==}
+    dependencies:
+      '@vue/compiler-dom': 3.4.29
+      '@vue/shared': 3.4.29
+
+  /@vue/compiler-ssr@3.4.31:
+    resolution: {integrity: sha512-RtefmITAje3fJ8FSg1gwgDhdKhZVntIVbwupdyZDSifZTRMiWxWehAOTCc8/KZDnBOcYQ4/9VWxsTbd3wT0hAA==}
+    dependencies:
+      '@vue/compiler-dom': 3.4.31
+      '@vue/shared': 3.4.31
+    dev: true
+
+  /@vue/devtools-api@6.6.3:
+    resolution: {integrity: sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==}
+    dev: false
+
+  /@vue/devtools-core@7.3.5(vite@5.3.1)(vue@3.4.29):
+    resolution: {integrity: sha512-uSC3IkIp6MtyJYSh5xzY99sgqlAXLq+peE2KKXTi6JeRHOtMngFWFWENXi70IJ1EVGYztiFQoHhI9WZcgKBz8g==}
+    peerDependencies:
+      vue: ^3.0.0
+    dependencies:
+      '@vue/devtools-kit': 7.3.5
+      '@vue/devtools-shared': 7.3.5
+      mitt: 3.0.1
+      nanoid: 3.3.7
+      pathe: 1.1.2
+      vite-hot-client: 0.2.3(vite@5.3.1)
+      vue: 3.4.29(typescript@5.4.5)
+    transitivePeerDependencies:
+      - vite
+    dev: true
+
+  /@vue/devtools-kit@7.3.5:
+    resolution: {integrity: sha512-wwfi10gJ1HMtjzcd8aIOnzBHlIRqsYDgcDyrKvkeyc0Gbcoe7UrkXRVHZUOtcxxoplHA0PwpT6wFg0uUCmi8Ww==}
+    dependencies:
+      '@vue/devtools-shared': 7.3.5
+      birpc: 0.2.17
+      hookable: 5.5.3
+      mitt: 3.0.1
+      perfect-debounce: 1.0.0
+      speakingurl: 14.0.1
+      superjson: 2.2.1
+    dev: true
+
+  /@vue/devtools-shared@7.3.5:
+    resolution: {integrity: sha512-Rqii3VazmWTi67a86rYopi61n5Ved05EybJCwyrfoO9Ok3MaS/4yRFl706ouoISMlyrASJFEzM0/AiDA6w4f9A==}
+    dependencies:
+      rfdc: 1.4.1
+    dev: true
+
+  /@vue/language-core@2.0.21(typescript@5.4.5):
+    resolution: {integrity: sha512-vjs6KwnCK++kIXT+eI63BGpJHfHNVJcUCr3RnvJsccT3vbJnZV5IhHR2puEkoOkIbDdp0Gqi1wEnv3hEd3WsxQ==}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@volar/language-core': 2.3.4
+      '@vue/compiler-dom': 3.4.31
+      '@vue/shared': 3.4.31
+      computeds: 0.0.1
+      minimatch: 9.0.5
+      path-browserify: 1.0.1
+      typescript: 5.4.5
+      vue-template-compiler: 2.7.16
+    dev: true
+
+  /@vue/reactivity@3.4.29:
+    resolution: {integrity: sha512-w8+KV+mb1a8ornnGQitnMdLfE0kXmteaxLdccm2XwdFxXst4q/Z7SEboCV5SqJNpZbKFeaRBBJBhW24aJyGINg==}
+    dependencies:
+      '@vue/shared': 3.4.29
+
+  /@vue/runtime-core@3.4.29:
+    resolution: {integrity: sha512-s8fmX3YVR/Rk5ig0ic0NuzTNjK2M7iLuVSZyMmCzN/+Mjuqqif1JasCtEtmtoJWF32pAtUjyuT2ljNKNLeOmnQ==}
+    dependencies:
+      '@vue/reactivity': 3.4.29
+      '@vue/shared': 3.4.29
+
+  /@vue/runtime-dom@3.4.29:
+    resolution: {integrity: sha512-gI10atCrtOLf/2MPPMM+dpz3NGulo9ZZR9d1dWo4fYvm+xkfvRrw1ZmJ7mkWtiJVXSsdmPbcK1p5dZzOCKDN0g==}
+    dependencies:
+      '@vue/reactivity': 3.4.29
+      '@vue/runtime-core': 3.4.29
+      '@vue/shared': 3.4.29
+      csstype: 3.1.3
+
+  /@vue/server-renderer@3.4.29(vue@3.4.29):
+    resolution: {integrity: sha512-HMLCmPI2j/k8PVkSBysrA2RxcxC5DgBiCdj7n7H2QtR8bQQPqKAe8qoaxLcInzouBmzwJ+J0x20ygN/B5mYBng==}
+    peerDependencies:
+      vue: 3.4.29
+    dependencies:
+      '@vue/compiler-ssr': 3.4.29
+      '@vue/shared': 3.4.29
+      vue: 3.4.29(typescript@5.4.5)
+
+  /@vue/shared@3.4.29:
+    resolution: {integrity: sha512-hQ2gAQcBO/CDpC82DCrinJNgOHI2v+FA7BDW4lMSPeBpQ7sRe2OLHWe5cph1s7D8DUQAwRt18dBDfJJ220APEA==}
+
+  /@vue/shared@3.4.31:
+    resolution: {integrity: sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==}
+    dev: true
+
+  /@vueuse/core@10.11.0(vue@3.4.29):
+    resolution: {integrity: sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==}
+    dependencies:
+      '@types/web-bluetooth': 0.0.20
+      '@vueuse/metadata': 10.11.0
+      '@vueuse/shared': 10.11.0(vue@3.4.29)
+      vue-demi: 0.14.8(vue@3.4.29)
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+      - vue
+    dev: false
+
+  /@vueuse/metadata@10.11.0:
+    resolution: {integrity: sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==}
+    dev: false
+
+  /@vueuse/shared@10.11.0(vue@3.4.29):
+    resolution: {integrity: sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==}
+    dependencies:
+      vue-demi: 0.14.8(vue@3.4.29)
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+      - vue
+    dev: false
+
+  /abbrev@1.1.1:
+    resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
+    dev: true
+
+  /acorn-jsx@5.3.2(acorn@8.12.1):
+    resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+    peerDependencies:
+      acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+    dependencies:
+      acorn: 8.12.1
+    dev: true
+
+  /acorn@8.12.1:
+    resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
+    engines: {node: '>=0.4.0'}
+    hasBin: true
+    dev: true
+
+  /agent-base@6.0.2:
+    resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
+    engines: {node: '>= 6.0.0'}
+    dependencies:
+      debug: 4.3.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /agentkeepalive@4.5.0:
+    resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==}
+    engines: {node: '>= 8.0.0'}
+    dependencies:
+      humanize-ms: 1.2.1
+    dev: true
+
+  /aggregate-error@3.1.0:
+    resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
+    engines: {node: '>=8'}
+    dependencies:
+      clean-stack: 2.2.0
+      indent-string: 4.0.0
+    dev: true
+
+  /ajv@6.12.6:
+    resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+    dependencies:
+      fast-deep-equal: 3.1.3
+      fast-json-stable-stringify: 2.1.0
+      json-schema-traverse: 0.4.1
+      uri-js: 4.4.1
+    dev: true
+
+  /ansi-align@3.0.1:
+    resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
+    dependencies:
+      string-width: 4.2.3
+    dev: true
+
+  /ansi-colors@4.1.3:
+    resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /ansi-escapes@6.2.1:
+    resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==}
+    engines: {node: '>=14.16'}
+    dev: true
+
+  /ansi-regex@2.1.1:
+    resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /ansi-regex@5.0.1:
+    resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /ansi-regex@6.0.1:
+    resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /ansi-styles@2.2.1:
+    resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /ansi-styles@3.2.1:
+    resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+    engines: {node: '>=4'}
+    dependencies:
+      color-convert: 1.9.3
+    dev: true
+
+  /ansi-styles@4.3.0:
+    resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+    engines: {node: '>=8'}
+    dependencies:
+      color-convert: 2.0.1
+    dev: true
+
+  /ansi-styles@6.2.1:
+    resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /ant-design-vue@4.2.3(vue@3.4.29):
+    resolution: {integrity: sha512-kqGyWvZtFlSInFP93Ow6wS8LzEsxxUgpI+ZY5jQQkuX8WAcqdwXCA7IcHMpECW6JB89DZMo2Bw85jUg2SjlgQA==}
+    engines: {node: '>=12.22.0'}
+    peerDependencies:
+      vue: '>=3.2.0'
+    dependencies:
+      '@ant-design/colors': 6.0.0
+      '@ant-design/icons-vue': 7.0.1(vue@3.4.29)
+      '@babel/runtime': 7.24.7
+      '@ctrl/tinycolor': 3.6.1
+      '@emotion/hash': 0.9.1
+      '@emotion/unitless': 0.8.1
+      '@simonwep/pickr': 1.8.2
+      array-tree-filter: 2.1.0
+      async-validator: 4.2.5
+      csstype: 3.1.3
+      dayjs: 1.11.11
+      dom-align: 1.12.4
+      dom-scroll-into-view: 2.0.1
+      lodash: 4.17.21
+      lodash-es: 4.17.21
+      resize-observer-polyfill: 1.5.1
+      scroll-into-view-if-needed: 2.2.31
+      shallow-equal: 1.2.1
+      stylis: 4.3.2
+      throttle-debounce: 5.0.2
+      vue: 3.4.29(typescript@5.4.5)
+      vue-types: 3.0.2(vue@3.4.29)
+      warning: 4.0.3
+    dev: false
+
+  /anymatch@3.1.3:
+    resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+    engines: {node: '>= 8'}
+    dependencies:
+      normalize-path: 3.0.0
+      picomatch: 2.3.1
+    dev: true
+
+  /aproba@2.0.0:
+    resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
+    dev: true
+
+  /are-we-there-yet@3.0.1:
+    resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    deprecated: This package is no longer supported.
+    dependencies:
+      delegates: 1.0.0
+      readable-stream: 3.6.2
+    dev: true
+
+  /argparse@2.0.1:
+    resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+    dev: true
+
+  /arr-diff@4.0.0:
+    resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /arr-flatten@1.1.0:
+    resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /arr-union@3.1.0:
+    resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /array-buffer-byte-length@1.0.1:
+    resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      is-array-buffer: 3.0.4
+    dev: true
+
+  /array-tree-filter@2.1.0:
+    resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==}
+    dev: false
+
+  /array-union@2.1.0:
+    resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /array-unique@0.3.2:
+    resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /arraybuffer.prototype.slice@1.0.3:
+    resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      array-buffer-byte-length: 1.0.1
+      call-bind: 1.0.7
+      define-properties: 1.2.1
+      es-abstract: 1.23.3
+      es-errors: 1.3.0
+      get-intrinsic: 1.2.4
+      is-array-buffer: 3.0.4
+      is-shared-array-buffer: 1.0.3
+    dev: true
+
+  /assign-symbols@1.0.0:
+    resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /ast-types@0.16.1:
+    resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
+    engines: {node: '>=4'}
+    dependencies:
+      tslib: 2.6.3
+    dev: true
+
+  /async-validator@4.2.5:
+    resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
+    dev: false
+
+  /asynckit@0.4.0:
+    resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+    dev: false
+
+  /atob@2.1.2:
+    resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==}
+    engines: {node: '>= 4.5.0'}
+    hasBin: true
+    dev: true
+
+  /available-typed-arrays@1.0.7:
+    resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      possible-typed-array-names: 1.0.0
+    dev: true
+
+  /axios-retry@4.4.0(axios@1.7.2):
+    resolution: {integrity: sha512-yewTKjzl6jSgc+2M7FCJ3LxRGgL1iiXHcj+E6h6xie6H1mTHr7yqaUroWIvVXG1UKSPwGDXxV05YxtGvrD6Paw==}
+    peerDependencies:
+      axios: 0.x || 1.x
+    dependencies:
+      axios: 1.7.2
+      is-retry-allowed: 2.2.0
+    dev: false
+
+  /axios@1.7.2:
+    resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==}
+    dependencies:
+      follow-redirects: 1.15.6
+      form-data: 4.0.0
+      proxy-from-env: 1.1.0
+    transitivePeerDependencies:
+      - debug
+    dev: false
+
+  /balanced-match@1.0.2:
+    resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+    dev: true
+
+  /base@0.11.2:
+    resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      cache-base: 1.0.1
+      class-utils: 0.3.6
+      component-emitter: 1.3.1
+      define-property: 1.0.0
+      isobject: 3.0.1
+      mixin-deep: 1.3.2
+      pascalcase: 0.1.1
+    dev: true
+
+  /big.js@5.2.2:
+    resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==}
+    dev: true
+
+  /binary-extensions@2.3.0:
+    resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /binary-searching@2.0.5:
+    resolution: {integrity: sha512-v4N2l3RxL+m4zDxyxz3Ne2aTmiPn8ZUpKFpdPtO+ItW1NcTCXA7JeHG5GMBSvoKSkQZ9ycS+EouDVxYB9ufKWA==}
+    dev: true
+
+  /birpc@0.2.17:
+    resolution: {integrity: sha512-+hkTxhot+dWsLpp3gia5AkVHIsKlZybNT5gIYiDlNzJrmYPcTM9k5/w2uaj3IPpd7LlEYpmCj4Jj1nC41VhDFg==}
+    dev: true
+
+  /bluebird@3.7.2:
+    resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
+    dev: true
+
+  /boolbase@1.0.0:
+    resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+    dev: true
+
+  /boxen@7.1.1:
+    resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==}
+    engines: {node: '>=14.16'}
+    dependencies:
+      ansi-align: 3.0.1
+      camelcase: 7.0.1
+      chalk: 5.3.0
+      cli-boxes: 3.0.0
+      string-width: 5.1.2
+      type-fest: 2.19.0
+      widest-line: 4.0.1
+      wrap-ansi: 8.1.0
+    dev: true
+
+  /brace-expansion@1.1.11:
+    resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+    dependencies:
+      balanced-match: 1.0.2
+      concat-map: 0.0.1
+    dev: true
+
+  /brace-expansion@2.0.1:
+    resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+    dependencies:
+      balanced-match: 1.0.2
+    dev: true
+
+  /braces@2.3.2:
+    resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      arr-flatten: 1.1.0
+      array-unique: 0.3.2
+      extend-shallow: 2.0.1
+      fill-range: 4.0.0
+      isobject: 3.0.1
+      repeat-element: 1.1.4
+      snapdragon: 0.8.2
+      snapdragon-node: 2.1.1
+      split-string: 3.1.0
+      to-regex: 3.0.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /braces@3.0.3:
+    resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+    engines: {node: '>=8'}
+    dependencies:
+      fill-range: 7.1.1
+    dev: true
+
+  /browserslist@4.23.1:
+    resolution: {integrity: sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==}
+    engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+    hasBin: true
+    dependencies:
+      caniuse-lite: 1.0.30001640
+      electron-to-chromium: 1.4.816
+      node-releases: 2.0.14
+      update-browserslist-db: 1.1.0(browserslist@4.23.1)
+    dev: true
+
+  /buffer-from@1.1.2:
+    resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+    dev: true
+
+  /builtin-modules@3.3.0:
+    resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /bumpp@9.4.1:
+    resolution: {integrity: sha512-kzhp/LpNX0HkUpEyLd7sU2LTN/mbAVgcxJ1Zi2cAJTE/tul6rypSKGpH8UywDpzKWItL8LVdKsIFnwmylw0+7g==}
+    engines: {node: '>=10'}
+    hasBin: true
+    dependencies:
+      '@jsdevtools/ez-spawn': 3.0.4
+      c12: 1.11.1
+      cac: 6.7.14
+      escalade: 3.1.2
+      fast-glob: 3.3.2
+      js-yaml: 4.1.0
+      prompts: 2.4.2
+      semver: 7.6.2
+    transitivePeerDependencies:
+      - magicast
+    dev: true
+
+  /bundle-name@4.1.0:
+    resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
+    engines: {node: '>=18'}
+    dependencies:
+      run-applescript: 7.0.0
+    dev: true
+
+  /c12@1.11.1:
+    resolution: {integrity: sha512-KDU0TvSvVdaYcQKQ6iPHATGz/7p/KiVjPg4vQrB6Jg/wX9R0yl5RZxWm9IoZqaIHD2+6PZd81+KMGwRr/lRIUg==}
+    peerDependencies:
+      magicast: ^0.3.4
+    peerDependenciesMeta:
+      magicast:
+        optional: true
+    dependencies:
+      chokidar: 3.6.0
+      confbox: 0.1.7
+      defu: 6.1.4
+      dotenv: 16.4.5
+      giget: 1.2.3
+      jiti: 1.21.6
+      mlly: 1.7.1
+      ohash: 1.1.3
+      pathe: 1.1.2
+      perfect-debounce: 1.0.0
+      pkg-types: 1.1.3
+      rc9: 2.1.2
+    dev: true
+
+  /cac@6.7.14:
+    resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /cacache@16.1.3:
+    resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    dependencies:
+      '@npmcli/fs': 2.1.2
+      '@npmcli/move-file': 2.0.1
+      chownr: 2.0.0
+      fs-minipass: 2.1.0
+      glob: 8.1.0
+      infer-owner: 1.0.4
+      lru-cache: 7.18.3
+      minipass: 3.3.6
+      minipass-collect: 1.0.2
+      minipass-flush: 1.0.5
+      minipass-pipeline: 1.2.4
+      mkdirp: 1.0.4
+      p-map: 4.0.0
+      promise-inflight: 1.0.1
+      rimraf: 3.0.2
+      ssri: 9.0.1
+      tar: 6.2.1
+      unique-filename: 2.0.1
+    transitivePeerDependencies:
+      - bluebird
+    dev: true
+
+  /cacache@17.1.4:
+    resolution: {integrity: sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      '@npmcli/fs': 3.1.1
+      fs-minipass: 3.0.3
+      glob: 10.4.2
+      lru-cache: 7.18.3
+      minipass: 7.1.2
+      minipass-collect: 1.0.2
+      minipass-flush: 1.0.5
+      minipass-pipeline: 1.2.4
+      p-map: 4.0.0
+      ssri: 10.0.6
+      tar: 6.2.1
+      unique-filename: 3.0.0
+    dev: true
+
+  /cache-base@1.0.1:
+    resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      collection-visit: 1.0.0
+      component-emitter: 1.3.1
+      get-value: 2.0.6
+      has-value: 1.0.0
+      isobject: 3.0.1
+      set-value: 2.0.1
+      to-object-path: 0.3.0
+      union-value: 1.0.1
+      unset-value: 1.0.0
+    dev: true
+
+  /cacheable-lookup@7.0.0:
+    resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==}
+    engines: {node: '>=14.16'}
+    dev: true
+
+  /cacheable-request@10.2.14:
+    resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==}
+    engines: {node: '>=14.16'}
+    dependencies:
+      '@types/http-cache-semantics': 4.0.4
+      get-stream: 6.0.1
+      http-cache-semantics: 4.1.1
+      keyv: 4.5.4
+      mimic-response: 4.0.0
+      normalize-url: 8.0.1
+      responselike: 3.0.0
+    dev: true
+
+  /call-bind@1.0.7:
+    resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      es-define-property: 1.0.0
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+      get-intrinsic: 1.2.4
+      set-function-length: 1.2.2
+
+  /call-me-maybe@1.0.2:
+    resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==}
+    dev: true
+
+  /callsites@3.1.0:
+    resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /camelcase@6.3.0:
+    resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /camelcase@7.0.1:
+    resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
+    engines: {node: '>=14.16'}
+    dev: true
+
+  /caniuse-lite@1.0.30001640:
+    resolution: {integrity: sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==}
+    dev: true
+
+  /chalk@1.1.3:
+    resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      ansi-styles: 2.2.1
+      escape-string-regexp: 1.0.5
+      has-ansi: 2.0.0
+      strip-ansi: 3.0.1
+      supports-color: 2.0.0
+    dev: true
+
+  /chalk@2.4.2:
+    resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+    engines: {node: '>=4'}
+    dependencies:
+      ansi-styles: 3.2.1
+      escape-string-regexp: 1.0.5
+      supports-color: 5.5.0
+    dev: true
+
+  /chalk@4.1.2:
+    resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+    engines: {node: '>=10'}
+    dependencies:
+      ansi-styles: 4.3.0
+      supports-color: 7.2.0
+    dev: true
+
+  /chalk@5.3.0:
+    resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
+    engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+    dev: true
+
+  /character-entities@2.0.2:
+    resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+    dev: true
+
+  /chokidar@3.6.0:
+    resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+    engines: {node: '>= 8.10.0'}
+    dependencies:
+      anymatch: 3.1.3
+      braces: 3.0.3
+      glob-parent: 5.1.2
+      is-binary-path: 2.1.0
+      is-glob: 4.0.3
+      normalize-path: 3.0.0
+      readdirp: 3.6.0
+    optionalDependencies:
+      fsevents: 2.3.3
+    dev: true
+
+  /chownr@2.0.0:
+    resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /ci-info@3.9.0:
+    resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /ci-info@4.0.0:
+    resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /citty@0.1.6:
+    resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
+    dependencies:
+      consola: 3.2.3
+    dev: true
+
+  /class-utils@0.3.6:
+    resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      arr-union: 3.1.0
+      define-property: 0.2.5
+      isobject: 3.0.1
+      static-extend: 0.1.2
+    dev: true
+
+  /clean-regexp@1.0.0:
+    resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==}
+    engines: {node: '>=4'}
+    dependencies:
+      escape-string-regexp: 1.0.5
+    dev: true
+
+  /clean-stack@2.2.0:
+    resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /cli-boxes@3.0.0:
+    resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /cli-cursor@4.0.0:
+    resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    dependencies:
+      restore-cursor: 4.0.0
+    dev: true
+
+  /cli-progress@3.12.0:
+    resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==}
+    engines: {node: '>=4'}
+    dependencies:
+      string-width: 4.2.3
+    dev: true
+
+  /cli-table3@0.6.5:
+    resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
+    engines: {node: 10.* || >= 12.*}
+    dependencies:
+      string-width: 4.2.3
+    optionalDependencies:
+      '@colors/colors': 1.5.0
+    dev: true
+
+  /cli-truncate@4.0.0:
+    resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
+    engines: {node: '>=18'}
+    dependencies:
+      slice-ansi: 5.0.0
+      string-width: 7.2.0
+    dev: true
+
+  /clipboard@2.0.11:
+    resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==}
+    dependencies:
+      good-listener: 1.2.2
+      select: 1.1.2
+      tiny-emitter: 2.1.0
+    dev: false
+
+  /cliui@8.0.1:
+    resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 7.0.0
+    dev: true
+
+  /clone@2.1.2:
+    resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
+    engines: {node: '>=0.8'}
+    dev: true
+
+  /collection-visit@1.0.0:
+    resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      map-visit: 1.0.0
+      object-visit: 1.0.1
+    dev: true
+
+  /color-convert@1.9.3:
+    resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+    dependencies:
+      color-name: 1.1.3
+    dev: true
+
+  /color-convert@2.0.1:
+    resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+    engines: {node: '>=7.0.0'}
+    dependencies:
+      color-name: 1.1.4
+    dev: true
+
+  /color-name@1.1.3:
+    resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+    dev: true
+
+  /color-name@1.1.4:
+    resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+    dev: true
+
+  /color-support@1.1.3:
+    resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
+    hasBin: true
+    dev: true
+
+  /colord@2.9.3:
+    resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
+    dev: false
+
+  /colorette@2.0.20:
+    resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
+    dev: true
+
+  /combined-stream@1.0.8:
+    resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+    engines: {node: '>= 0.8'}
+    dependencies:
+      delayed-stream: 1.0.0
+    dev: false
+
+  /commander@10.0.1:
+    resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
+    engines: {node: '>=14'}
+    dev: true
+
+  /commander@12.1.0:
+    resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /commander@7.2.0:
+    resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+    engines: {node: '>= 10'}
+    dev: true
+
+  /comment-parser@1.4.1:
+    resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==}
+    engines: {node: '>= 12.0.0'}
+    dev: true
+
+  /component-emitter@1.3.1:
+    resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
+    dev: true
+
+  /compute-scroll-into-view@1.0.20:
+    resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
+    dev: false
+
+  /computeds@0.0.1:
+    resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==}
+    dev: true
+
+  /concat-map@0.0.1:
+    resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+    dev: true
+
+  /confbox@0.1.7:
+    resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==}
+    dev: true
+
+  /config-chain@1.1.13:
+    resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
+    dependencies:
+      ini: 1.3.8
+      proto-list: 1.2.4
+    dev: true
+
+  /configstore@6.0.0:
+    resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==}
+    engines: {node: '>=12'}
+    dependencies:
+      dot-prop: 6.0.1
+      graceful-fs: 4.2.11
+      unique-string: 3.0.0
+      write-file-atomic: 3.0.3
+      xdg-basedir: 5.1.0
+    dev: true
+
+  /consola@3.2.3:
+    resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==}
+    engines: {node: ^14.18.0 || >=16.10.0}
+    dev: true
+
+  /console-control-strings@1.1.0:
+    resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
+    dev: true
+
+  /convert-gitmoji@0.1.5:
+    resolution: {integrity: sha512-4wqOafJdk2tqZC++cjcbGcaJ13BZ3kwldf06PTiAQRAB76Z1KJwZNL1SaRZMi2w1FM9RYTgZ6QErS8NUl/GBmQ==}
+    dev: true
+
+  /convert-source-map@2.0.0:
+    resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+    dev: true
+
+  /copy-anything@3.0.5:
+    resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
+    engines: {node: '>=12.13'}
+    dependencies:
+      is-what: 4.1.16
+    dev: true
+
+  /copy-descriptor@0.1.1:
+    resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /core-js-compat@3.37.1:
+    resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==}
+    dependencies:
+      browserslist: 4.23.1
+    dev: true
+
+  /core-js@3.37.0:
+    resolution: {integrity: sha512-fu5vHevQ8ZG4og+LXug8ulUtVxjOcEYvifJr7L5Bfq9GOztVqsKd9/59hUk2ZSbCrS3BqUr3EpaYGIYzq7g3Ug==}
+    requiresBuild: true
+    dev: false
+
+  /core-js@3.37.1:
+    resolution: {integrity: sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==}
+    requiresBuild: true
+    dev: false
+
+  /cors@2.8.5:
+    resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
+    engines: {node: '>= 0.10'}
+    dependencies:
+      object-assign: 4.1.1
+      vary: 1.1.2
+    dev: true
+
+  /cross-spawn@7.0.3:
+    resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+    engines: {node: '>= 8'}
+    dependencies:
+      path-key: 3.1.1
+      shebang-command: 2.0.0
+      which: 2.0.2
+    dev: true
+
+  /crypto-js@4.2.0:
+    resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
+    dev: false
+
+  /crypto-random-string@4.0.0:
+    resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==}
+    engines: {node: '>=12'}
+    dependencies:
+      type-fest: 1.4.0
+    dev: true
+
+  /css-select@4.3.0:
+    resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==}
+    dependencies:
+      boolbase: 1.0.0
+      css-what: 6.1.0
+      domhandler: 4.3.1
+      domutils: 2.8.0
+      nth-check: 2.1.1
+    dev: true
+
+  /css-tree@1.1.3:
+    resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==}
+    engines: {node: '>=8.0.0'}
+    dependencies:
+      mdn-data: 2.0.14
+      source-map: 0.6.1
+    dev: true
+
+  /css-tree@2.3.1:
+    resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
+    engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+    dependencies:
+      mdn-data: 2.0.30
+      source-map-js: 1.2.0
+    dev: true
+
+  /css-what@6.1.0:
+    resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
+    engines: {node: '>= 6'}
+    dev: true
+
+  /cssesc@3.0.0:
+    resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+    engines: {node: '>=4'}
+    hasBin: true
+    dev: true
+
+  /csso@4.2.0:
+    resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==}
+    engines: {node: '>=8.0.0'}
+    dependencies:
+      css-tree: 1.1.3
+    dev: true
+
+  /csstype@3.1.3:
+    resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+  /data-view-buffer@1.0.1:
+    resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      es-errors: 1.3.0
+      is-data-view: 1.0.1
+    dev: true
+
+  /data-view-byte-length@1.0.1:
+    resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      es-errors: 1.3.0
+      is-data-view: 1.0.1
+    dev: true
+
+  /data-view-byte-offset@1.0.0:
+    resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      es-errors: 1.3.0
+      is-data-view: 1.0.1
+    dev: true
+
+  /dayjs@1.11.11:
+    resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==}
+
+  /de-indent@1.0.2:
+    resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
+    dev: true
+
+  /debug@2.6.9:
+    resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+    dependencies:
+      ms: 2.0.0
+    dev: true
+
+  /debug@3.2.7:
+    resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+    dependencies:
+      ms: 2.1.3
+    dev: true
+
+  /debug@4.3.5:
+    resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==}
+    engines: {node: '>=6.0'}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+    dependencies:
+      ms: 2.1.2
+    dev: true
+
+  /decode-named-character-reference@1.0.2:
+    resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
+    dependencies:
+      character-entities: 2.0.2
+    dev: true
+
+  /decode-uri-component@0.2.2:
+    resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==}
+    engines: {node: '>=0.10'}
+    dev: true
+
+  /decompress-response@6.0.0:
+    resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      mimic-response: 3.1.0
+    dev: true
+
+  /deep-extend@0.6.0:
+    resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
+    engines: {node: '>=4.0.0'}
+    dev: true
+
+  /deep-is@0.1.4:
+    resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+    dev: true
+
+  /default-browser-id@5.0.0:
+    resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /default-browser@5.2.1:
+    resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==}
+    engines: {node: '>=18'}
+    dependencies:
+      bundle-name: 4.1.0
+      default-browser-id: 5.0.0
+    dev: true
+
+  /defer-to-connect@2.0.1:
+    resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /define-data-property@1.1.4:
+    resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      es-define-property: 1.0.0
+      es-errors: 1.3.0
+      gopd: 1.0.1
+
+  /define-lazy-prop@3.0.0:
+    resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /define-properties@1.2.1:
+    resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      define-data-property: 1.1.4
+      has-property-descriptors: 1.0.2
+      object-keys: 1.1.1
+    dev: true
+
+  /define-property@0.2.5:
+    resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-descriptor: 0.1.7
+    dev: true
+
+  /define-property@1.0.0:
+    resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-descriptor: 1.0.3
+    dev: true
+
+  /define-property@2.0.2:
+    resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-descriptor: 1.0.3
+      isobject: 3.0.1
+    dev: true
+
+  /defu@6.1.4:
+    resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
+    dev: true
+
+  /delayed-stream@1.0.0:
+    resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+    engines: {node: '>=0.4.0'}
+    dev: false
+
+  /delegate@3.2.0:
+    resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==}
+    dev: false
+
+  /delegates@1.0.0:
+    resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
+    dev: true
+
+  /dequal@2.0.3:
+    resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /destr@2.0.3:
+    resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==}
+
+  /devlop@1.1.0:
+    resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+    dependencies:
+      dequal: 2.0.3
+    dev: true
+
+  /dir-glob@3.0.1:
+    resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+    engines: {node: '>=8'}
+    dependencies:
+      path-type: 4.0.0
+    dev: true
+
+  /doctrine@3.0.0:
+    resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+    engines: {node: '>=6.0.0'}
+    dependencies:
+      esutils: 2.0.3
+    dev: true
+
+  /dom-align@1.12.4:
+    resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==}
+    dev: false
+
+  /dom-scroll-into-view@2.0.1:
+    resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==}
+    dev: false
+
+  /dom-serializer@0.2.2:
+    resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==}
+    dependencies:
+      domelementtype: 2.3.0
+      entities: 2.2.0
+    dev: true
+
+  /dom-serializer@1.4.1:
+    resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
+    dependencies:
+      domelementtype: 2.3.0
+      domhandler: 4.3.1
+      entities: 2.2.0
+    dev: true
+
+  /domelementtype@1.3.1:
+    resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==}
+    dev: true
+
+  /domelementtype@2.3.0:
+    resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+    dev: true
+
+  /domhandler@2.4.2:
+    resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==}
+    dependencies:
+      domelementtype: 1.3.1
+    dev: true
+
+  /domhandler@4.3.1:
+    resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==}
+    engines: {node: '>= 4'}
+    dependencies:
+      domelementtype: 2.3.0
+    dev: true
+
+  /domutils@1.7.0:
+    resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==}
+    dependencies:
+      dom-serializer: 0.2.2
+      domelementtype: 1.3.1
+    dev: true
+
+  /domutils@2.8.0:
+    resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
+    dependencies:
+      dom-serializer: 1.4.1
+      domelementtype: 2.3.0
+      domhandler: 4.3.1
+    dev: true
+
+  /dot-prop@6.0.1:
+    resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==}
+    engines: {node: '>=10'}
+    dependencies:
+      is-obj: 2.0.0
+    dev: true
+
+  /dotenv@16.4.5:
+    resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /duplexer@0.1.2:
+    resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
+    dev: true
+
+  /eastasianwidth@0.2.0:
+    resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+    dev: true
+
+  /echarts@5.5.0:
+    resolution: {integrity: sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw==}
+    dependencies:
+      tslib: 2.3.0
+      zrender: 5.5.0
+    dev: false
+
+  /electron-to-chromium@1.4.816:
+    resolution: {integrity: sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw==}
+    dev: true
+
+  /emoji-regex@10.3.0:
+    resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==}
+    dev: true
+
+  /emoji-regex@8.0.0:
+    resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+    dev: true
+
+  /emoji-regex@9.2.2:
+    resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+    dev: true
+
+  /emojis-list@3.0.0:
+    resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==}
+    engines: {node: '>= 4'}
+    dev: true
+
+  /encoding@0.1.13:
+    resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
+    requiresBuild: true
+    dependencies:
+      iconv-lite: 0.6.3
+    dev: true
+    optional: true
+
+  /enhanced-resolve@5.17.0:
+    resolution: {integrity: sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==}
+    engines: {node: '>=10.13.0'}
+    dependencies:
+      graceful-fs: 4.2.11
+      tapable: 2.2.1
+    dev: true
+
+  /enquirer@2.4.1:
+    resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
+    engines: {node: '>=8.6'}
+    dependencies:
+      ansi-colors: 4.1.3
+      strip-ansi: 6.0.1
+    dev: true
+
+  /entities@1.1.2:
+    resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==}
+    dev: true
+
+  /entities@2.2.0:
+    resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
+    dev: true
+
+  /entities@4.5.0:
+    resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+    engines: {node: '>=0.12'}
+
+  /env-paths@2.2.1:
+    resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /err-code@2.0.3:
+    resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
+    dev: true
+
+  /error-ex@1.3.2:
+    resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
+    dependencies:
+      is-arrayish: 0.2.1
+    dev: true
+
+  /error-stack-parser-es@0.1.4:
+    resolution: {integrity: sha512-l0uy0kAoo6toCgVOYaAayqtPa2a1L15efxUMEnQebKwLQX2X0OpS6wMMQdc4juJXmxd9i40DuaUHq+mjIya9TQ==}
+    dev: true
+
+  /es-abstract@1.23.3:
+    resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      array-buffer-byte-length: 1.0.1
+      arraybuffer.prototype.slice: 1.0.3
+      available-typed-arrays: 1.0.7
+      call-bind: 1.0.7
+      data-view-buffer: 1.0.1
+      data-view-byte-length: 1.0.1
+      data-view-byte-offset: 1.0.0
+      es-define-property: 1.0.0
+      es-errors: 1.3.0
+      es-object-atoms: 1.0.0
+      es-set-tostringtag: 2.0.3
+      es-to-primitive: 1.2.1
+      function.prototype.name: 1.1.6
+      get-intrinsic: 1.2.4
+      get-symbol-description: 1.0.2
+      globalthis: 1.0.4
+      gopd: 1.0.1
+      has-property-descriptors: 1.0.2
+      has-proto: 1.0.3
+      has-symbols: 1.0.3
+      hasown: 2.0.2
+      internal-slot: 1.0.7
+      is-array-buffer: 3.0.4
+      is-callable: 1.2.7
+      is-data-view: 1.0.1
+      is-negative-zero: 2.0.3
+      is-regex: 1.1.4
+      is-shared-array-buffer: 1.0.3
+      is-string: 1.0.7
+      is-typed-array: 1.1.13
+      is-weakref: 1.0.2
+      object-inspect: 1.13.2
+      object-keys: 1.1.1
+      object.assign: 4.1.5
+      regexp.prototype.flags: 1.5.2
+      safe-array-concat: 1.1.2
+      safe-regex-test: 1.0.3
+      string.prototype.trim: 1.2.9
+      string.prototype.trimend: 1.0.8
+      string.prototype.trimstart: 1.0.8
+      typed-array-buffer: 1.0.2
+      typed-array-byte-length: 1.0.1
+      typed-array-byte-offset: 1.0.2
+      typed-array-length: 1.0.6
+      unbox-primitive: 1.0.2
+      which-typed-array: 1.1.15
+    dev: true
+
+  /es-define-property@1.0.0:
+    resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      get-intrinsic: 1.2.4
+
+  /es-errors@1.3.0:
+    resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+    engines: {node: '>= 0.4'}
+
+  /es-object-atoms@1.0.0:
+    resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      es-errors: 1.3.0
+    dev: true
+
+  /es-set-tostringtag@2.0.3:
+    resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      get-intrinsic: 1.2.4
+      has-tostringtag: 1.0.2
+      hasown: 2.0.2
+    dev: true
+
+  /es-to-primitive@1.2.1:
+    resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      is-callable: 1.2.7
+      is-date-object: 1.0.5
+      is-symbol: 1.0.4
+    dev: true
+
+  /esbuild@0.21.5:
+    resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
+    engines: {node: '>=12'}
+    hasBin: true
+    requiresBuild: true
+    optionalDependencies:
+      '@esbuild/aix-ppc64': 0.21.5
+      '@esbuild/android-arm': 0.21.5
+      '@esbuild/android-arm64': 0.21.5
+      '@esbuild/android-x64': 0.21.5
+      '@esbuild/darwin-arm64': 0.21.5
+      '@esbuild/darwin-x64': 0.21.5
+      '@esbuild/freebsd-arm64': 0.21.5
+      '@esbuild/freebsd-x64': 0.21.5
+      '@esbuild/linux-arm': 0.21.5
+      '@esbuild/linux-arm64': 0.21.5
+      '@esbuild/linux-ia32': 0.21.5
+      '@esbuild/linux-loong64': 0.21.5
+      '@esbuild/linux-mips64el': 0.21.5
+      '@esbuild/linux-ppc64': 0.21.5
+      '@esbuild/linux-riscv64': 0.21.5
+      '@esbuild/linux-s390x': 0.21.5
+      '@esbuild/linux-x64': 0.21.5
+      '@esbuild/netbsd-x64': 0.21.5
+      '@esbuild/openbsd-x64': 0.21.5
+      '@esbuild/sunos-x64': 0.21.5
+      '@esbuild/win32-arm64': 0.21.5
+      '@esbuild/win32-ia32': 0.21.5
+      '@esbuild/win32-x64': 0.21.5
+    dev: true
+
+  /escalade@3.1.2:
+    resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /escape-goat@4.0.0:
+    resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /escape-string-regexp@1.0.5:
+    resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+    engines: {node: '>=0.8.0'}
+    dev: true
+
+  /escape-string-regexp@4.0.0:
+    resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /eslint-compat-utils@0.5.1(eslint@9.0.0-rc.0):
+    resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==}
+    engines: {node: '>=12'}
+    peerDependencies:
+      eslint: '>=6.0.0'
+    dependencies:
+      eslint: 9.0.0-rc.0
+      semver: 7.6.2
+    dev: true
+
+  /eslint-compat-utils@0.5.1(eslint@9.5.0):
+    resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==}
+    engines: {node: '>=12'}
+    peerDependencies:
+      eslint: '>=6.0.0'
+    dependencies:
+      eslint: 9.5.0
+      semver: 7.6.2
+    dev: true
+
+  /eslint-config-prettier@9.1.0(eslint@9.0.0-rc.0):
+    resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
+    hasBin: true
+    peerDependencies:
+      eslint: '>=7.0.0'
+    dependencies:
+      eslint: 9.0.0-rc.0
+    dev: true
+
+  /eslint-config-prettier@9.1.0(eslint@9.5.0):
+    resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
+    hasBin: true
+    peerDependencies:
+      eslint: '>=7.0.0'
+    dependencies:
+      eslint: 9.5.0
+    dev: true
+
+  /eslint-import-resolver-node@0.3.9:
+    resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
+    dependencies:
+      debug: 3.2.7
+      is-core-module: 2.14.0
+      resolve: 1.22.8
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /eslint-parser-plain@0.1.0:
+    resolution: {integrity: sha512-oOeA6FWU0UJT/Rxc3XF5Cq0nbIZbylm7j8+plqq0CZoE6m4u32OXJrR+9iy4srGMmF6v6pmgvP1zPxSRIGh3sg==}
+    dev: true
+
+  /eslint-plugin-es-x@7.8.0(eslint@9.0.0-rc.0):
+    resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    peerDependencies:
+      eslint: '>=8'
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0-rc.0)
+      '@eslint-community/regexpp': 4.11.0
+      eslint: 9.0.0-rc.0
+      eslint-compat-utils: 0.5.1(eslint@9.0.0-rc.0)
+    dev: true
+
+  /eslint-plugin-es-x@7.8.0(eslint@9.5.0):
+    resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    peerDependencies:
+      eslint: '>=8'
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0)
+      '@eslint-community/regexpp': 4.11.0
+      eslint: 9.5.0
+      eslint-compat-utils: 0.5.1(eslint@9.5.0)
+    dev: true
+
+  /eslint-plugin-import-x@0.5.1(eslint@9.0.0-rc.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-2JK8bbFOLes+gG6tgdnM8safCxMAj4u2wjX8X1BRFPfnY7Ct2hFYESoIcVwABX/DDcdpQFLGtKmzbNEWJZD9iQ==}
+    engines: {node: '>=16'}
+    peerDependencies:
+      eslint: ^8.56.0 || ^9.0.0-0
+    dependencies:
+      '@typescript-eslint/utils': 7.15.0(eslint@9.0.0-rc.0)(typescript@5.4.5)
+      debug: 4.3.5
+      doctrine: 3.0.0
+      eslint: 9.0.0-rc.0
+      eslint-import-resolver-node: 0.3.9
+      get-tsconfig: 4.7.5
+      is-glob: 4.0.3
+      minimatch: 9.0.5
+      semver: 7.6.2
+      tslib: 2.6.3
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+    dev: true
+
+  /eslint-plugin-import-x@0.5.1(eslint@9.5.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-2JK8bbFOLes+gG6tgdnM8safCxMAj4u2wjX8X1BRFPfnY7Ct2hFYESoIcVwABX/DDcdpQFLGtKmzbNEWJZD9iQ==}
+    engines: {node: '>=16'}
+    peerDependencies:
+      eslint: ^8.56.0 || ^9.0.0-0
+    dependencies:
+      '@typescript-eslint/utils': 7.15.0(eslint@9.5.0)(typescript@5.4.5)
+      debug: 4.3.5
+      doctrine: 3.0.0
+      eslint: 9.5.0
+      eslint-import-resolver-node: 0.3.9
+      get-tsconfig: 4.7.5
+      is-glob: 4.0.3
+      minimatch: 9.0.5
+      semver: 7.6.2
+      tslib: 2.6.3
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+    dev: true
+
+  /eslint-plugin-n@17.8.1(eslint@9.0.0-rc.0):
+    resolution: {integrity: sha512-KdG0h0voZms8UhndNu8DeWx1eM4sY+A4iXtsNo6kOfJLYHNeTGPacGalJ9GcvrbmOL3r/7QOMwVZDSw+1SqsrA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      eslint: '>=8.23.0'
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0-rc.0)
+      enhanced-resolve: 5.17.0
+      eslint: 9.0.0-rc.0
+      eslint-plugin-es-x: 7.8.0(eslint@9.0.0-rc.0)
+      get-tsconfig: 4.7.5
+      globals: 15.4.0
+      ignore: 5.3.1
+      minimatch: 9.0.5
+      semver: 7.6.2
+    dev: true
+
+  /eslint-plugin-n@17.8.1(eslint@9.5.0):
+    resolution: {integrity: sha512-KdG0h0voZms8UhndNu8DeWx1eM4sY+A4iXtsNo6kOfJLYHNeTGPacGalJ9GcvrbmOL3r/7QOMwVZDSw+1SqsrA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      eslint: '>=8.23.0'
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0)
+      enhanced-resolve: 5.17.0
+      eslint: 9.5.0
+      eslint-plugin-es-x: 7.8.0(eslint@9.5.0)
+      get-tsconfig: 4.7.5
+      globals: 15.4.0
+      ignore: 5.3.1
+      minimatch: 9.0.5
+      semver: 7.6.2
+    dev: true
+
+  /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@9.0.0-rc.0)(prettier@3.3.2):
+    resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    peerDependencies:
+      '@types/eslint': '>=8.0.0'
+      eslint: '>=8.0.0'
+      eslint-config-prettier: '*'
+      prettier: '>=3.0.0'
+    peerDependenciesMeta:
+      '@types/eslint':
+        optional: true
+      eslint-config-prettier:
+        optional: true
+    dependencies:
+      eslint: 9.0.0-rc.0
+      eslint-config-prettier: 9.1.0(eslint@9.0.0-rc.0)
+      prettier: 3.3.2
+      prettier-linter-helpers: 1.0.0
+      synckit: 0.8.8
+    dev: true
+
+  /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@9.5.0)(prettier@3.3.2):
+    resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    peerDependencies:
+      '@types/eslint': '>=8.0.0'
+      eslint: '>=8.0.0'
+      eslint-config-prettier: '*'
+      prettier: '>=3.0.0'
+    peerDependenciesMeta:
+      '@types/eslint':
+        optional: true
+      eslint-config-prettier:
+        optional: true
+    dependencies:
+      eslint: 9.5.0
+      eslint-config-prettier: 9.1.0(eslint@9.5.0)
+      prettier: 3.3.2
+      prettier-linter-helpers: 1.0.0
+      synckit: 0.8.8
+    dev: true
+
+  /eslint-plugin-unicorn@53.0.0(eslint@9.0.0-rc.0):
+    resolution: {integrity: sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw==}
+    engines: {node: '>=18.18'}
+    peerDependencies:
+      eslint: '>=8.56.0'
+    dependencies:
+      '@babel/helper-validator-identifier': 7.24.7
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0-rc.0)
+      '@eslint/eslintrc': 3.1.0
+      ci-info: 4.0.0
+      clean-regexp: 1.0.0
+      core-js-compat: 3.37.1
+      eslint: 9.0.0-rc.0
+      esquery: 1.5.0
+      indent-string: 4.0.0
+      is-builtin-module: 3.2.1
+      jsesc: 3.0.2
+      pluralize: 8.0.0
+      read-pkg-up: 7.0.1
+      regexp-tree: 0.1.27
+      regjsparser: 0.10.0
+      semver: 7.6.2
+      strip-indent: 3.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /eslint-plugin-unicorn@53.0.0(eslint@9.5.0):
+    resolution: {integrity: sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw==}
+    engines: {node: '>=18.18'}
+    peerDependencies:
+      eslint: '>=8.56.0'
+    dependencies:
+      '@babel/helper-validator-identifier': 7.24.7
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0)
+      '@eslint/eslintrc': 3.1.0
+      ci-info: 4.0.0
+      clean-regexp: 1.0.0
+      core-js-compat: 3.37.1
+      eslint: 9.5.0
+      esquery: 1.5.0
+      indent-string: 4.0.0
+      is-builtin-module: 3.2.1
+      jsesc: 3.0.2
+      pluralize: 8.0.0
+      read-pkg-up: 7.0.1
+      regexp-tree: 0.1.27
+      regjsparser: 0.10.0
+      semver: 7.6.2
+      strip-indent: 3.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /eslint-plugin-vue@9.26.0(eslint@9.5.0):
+    resolution: {integrity: sha512-eTvlxXgd4ijE1cdur850G6KalZqk65k1JKoOI2d1kT3hr8sPD07j1q98FRFdNnpxBELGPWxZmInxeHGF/GxtqQ==}
+    engines: {node: ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0)
+      eslint: 9.5.0
+      globals: 13.24.0
+      natural-compare: 1.4.0
+      nth-check: 2.1.1
+      postcss-selector-parser: 6.1.0
+      semver: 7.6.2
+      vue-eslint-parser: 9.4.3(eslint@9.5.0)
+      xml-name-validator: 4.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /eslint-scope@7.2.2:
+    resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    dependencies:
+      esrecurse: 4.3.0
+      estraverse: 5.3.0
+    dev: true
+
+  /eslint-scope@8.0.1:
+    resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    dependencies:
+      esrecurse: 4.3.0
+      estraverse: 5.3.0
+    dev: true
+
+  /eslint-visitor-keys@3.4.3:
+    resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    dev: true
+
+  /eslint-visitor-keys@4.0.0:
+    resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    dev: true
+
+  /eslint@9.0.0-rc.0:
+    resolution: {integrity: sha512-Xc4DSm5oJZyv/KFk3yoUhZNTyTsbXZTtyIGjhle0QSC9J/QPhdCC0U9c1RRmWqAoqZWVDnctWqFhaHVHJ1II2g==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    hasBin: true
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0-rc.0)
+      '@eslint-community/regexpp': 4.11.0
+      '@eslint/eslintrc': 3.1.0
+      '@eslint/js': 9.0.0-rc.0
+      '@humanwhocodes/config-array': 0.11.14
+      '@humanwhocodes/module-importer': 1.0.1
+      '@nodelib/fs.walk': 1.2.8
+      ajv: 6.12.6
+      chalk: 4.1.2
+      cross-spawn: 7.0.3
+      debug: 4.3.5
+      escape-string-regexp: 4.0.0
+      eslint-scope: 8.0.1
+      eslint-visitor-keys: 4.0.0
+      espree: 10.1.0
+      esquery: 1.5.0
+      esutils: 2.0.3
+      fast-deep-equal: 3.1.3
+      file-entry-cache: 8.0.0
+      find-up: 5.0.0
+      glob-parent: 6.0.2
+      graphemer: 1.4.0
+      ignore: 5.3.1
+      imurmurhash: 0.1.4
+      is-glob: 4.0.3
+      is-path-inside: 3.0.3
+      json-stable-stringify-without-jsonify: 1.0.1
+      levn: 0.4.1
+      lodash.merge: 4.6.2
+      minimatch: 3.1.2
+      natural-compare: 1.4.0
+      optionator: 0.9.4
+      strip-ansi: 6.0.1
+      text-table: 0.2.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /eslint@9.5.0:
+    resolution: {integrity: sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    hasBin: true
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0)
+      '@eslint-community/regexpp': 4.11.0
+      '@eslint/config-array': 0.16.0
+      '@eslint/eslintrc': 3.1.0
+      '@eslint/js': 9.5.0
+      '@humanwhocodes/module-importer': 1.0.1
+      '@humanwhocodes/retry': 0.3.0
+      '@nodelib/fs.walk': 1.2.8
+      ajv: 6.12.6
+      chalk: 4.1.2
+      cross-spawn: 7.0.3
+      debug: 4.3.5
+      escape-string-regexp: 4.0.0
+      eslint-scope: 8.0.1
+      eslint-visitor-keys: 4.0.0
+      espree: 10.1.0
+      esquery: 1.5.0
+      esutils: 2.0.3
+      fast-deep-equal: 3.1.3
+      file-entry-cache: 8.0.0
+      find-up: 5.0.0
+      glob-parent: 6.0.2
+      ignore: 5.3.1
+      imurmurhash: 0.1.4
+      is-glob: 4.0.3
+      is-path-inside: 3.0.3
+      json-stable-stringify-without-jsonify: 1.0.1
+      levn: 0.4.1
+      lodash.merge: 4.6.2
+      minimatch: 3.1.2
+      natural-compare: 1.4.0
+      optionator: 0.9.4
+      strip-ansi: 6.0.1
+      text-table: 0.2.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /espree@10.1.0:
+    resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    dependencies:
+      acorn: 8.12.1
+      acorn-jsx: 5.3.2(acorn@8.12.1)
+      eslint-visitor-keys: 4.0.0
+    dev: true
+
+  /espree@9.6.1:
+    resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    dependencies:
+      acorn: 8.12.1
+      acorn-jsx: 5.3.2(acorn@8.12.1)
+      eslint-visitor-keys: 3.4.3
+    dev: true
+
+  /esprima@4.0.1:
+    resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+    engines: {node: '>=4'}
+    hasBin: true
+    dev: true
+
+  /esquery@1.5.0:
+    resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
+    engines: {node: '>=0.10'}
+    dependencies:
+      estraverse: 5.3.0
+    dev: true
+
+  /esrecurse@4.3.0:
+    resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+    engines: {node: '>=4.0'}
+    dependencies:
+      estraverse: 5.3.0
+    dev: true
+
+  /estraverse@5.3.0:
+    resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+    engines: {node: '>=4.0'}
+    dev: true
+
+  /estree-walker@2.0.2:
+    resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+  /esutils@2.0.3:
+    resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /etag@1.8.1:
+    resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+    engines: {node: '>= 0.6'}
+    dev: true
+
+  /eventemitter3@5.0.1:
+    resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
+    dev: true
+
+  /execa@5.1.1:
+    resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+    engines: {node: '>=10'}
+    dependencies:
+      cross-spawn: 7.0.3
+      get-stream: 6.0.1
+      human-signals: 2.1.0
+      is-stream: 2.0.1
+      merge-stream: 2.0.0
+      npm-run-path: 4.0.1
+      onetime: 5.1.2
+      signal-exit: 3.0.7
+      strip-final-newline: 2.0.0
+    dev: true
+
+  /execa@8.0.1:
+    resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
+    engines: {node: '>=16.17'}
+    dependencies:
+      cross-spawn: 7.0.3
+      get-stream: 8.0.1
+      human-signals: 5.0.0
+      is-stream: 3.0.0
+      merge-stream: 2.0.0
+      npm-run-path: 5.3.0
+      onetime: 6.0.0
+      signal-exit: 4.1.0
+      strip-final-newline: 3.0.0
+    dev: true
+
+  /execa@9.1.0:
+    resolution: {integrity: sha512-lSgHc4Elo2m6bUDhc3Hl/VxvUDJdQWI40RZ4KMY9bKRc+hgMOT7II/JjbNDhI8VnMtrCb7U/fhpJIkLORZozWw==}
+    engines: {node: '>=18'}
+    dependencies:
+      '@sindresorhus/merge-streams': 4.0.0
+      cross-spawn: 7.0.3
+      figures: 6.1.0
+      get-stream: 9.0.1
+      human-signals: 7.0.0
+      is-plain-obj: 4.1.0
+      is-stream: 4.0.1
+      npm-run-path: 5.3.0
+      pretty-ms: 9.0.0
+      signal-exit: 4.1.0
+      strip-final-newline: 4.0.0
+      yoctocolors: 2.1.1
+    dev: true
+
+  /execa@9.2.0:
+    resolution: {integrity: sha512-vpOyYg7UAVKLAWWtRS2gAdgkT7oJbCn0me3gmUmxZih4kd3MF/oo8kNTBTIbkO3yuuF5uB4ZCZfn8BOolITYhg==}
+    engines: {node: ^18.19.0 || >=20.5.0}
+    dependencies:
+      '@sindresorhus/merge-streams': 4.0.0
+      cross-spawn: 7.0.3
+      figures: 6.1.0
+      get-stream: 9.0.1
+      human-signals: 7.0.0
+      is-plain-obj: 4.1.0
+      is-stream: 4.0.1
+      npm-run-path: 5.3.0
+      pretty-ms: 9.0.0
+      signal-exit: 4.1.0
+      strip-final-newline: 4.0.0
+      yoctocolors: 2.1.1
+    dev: true
+
+  /expand-brackets@2.1.4:
+    resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      debug: 2.6.9
+      define-property: 0.2.5
+      extend-shallow: 2.0.1
+      posix-character-classes: 0.1.1
+      regex-not: 1.0.2
+      snapdragon: 0.8.2
+      to-regex: 3.0.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /exponential-backoff@3.1.1:
+    resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==}
+    dev: true
+
+  /extend-shallow@2.0.1:
+    resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-extendable: 0.1.1
+    dev: true
+
+  /extend-shallow@3.0.2:
+    resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      assign-symbols: 1.0.0
+      is-extendable: 1.0.1
+    dev: true
+
+  /extglob@2.0.4:
+    resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      array-unique: 0.3.2
+      define-property: 1.0.0
+      expand-brackets: 2.1.4
+      extend-shallow: 2.0.1
+      fragment-cache: 0.2.1
+      regex-not: 1.0.2
+      snapdragon: 0.8.2
+      to-regex: 3.0.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /fast-deep-equal@3.1.3:
+    resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+    dev: true
+
+  /fast-diff@1.3.0:
+    resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
+    dev: true
+
+  /fast-glob@3.3.2:
+    resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+    engines: {node: '>=8.6.0'}
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      '@nodelib/fs.walk': 1.2.8
+      glob-parent: 5.1.2
+      merge2: 1.4.1
+      micromatch: 4.0.7
+    dev: true
+
+  /fast-json-stable-stringify@2.1.0:
+    resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+    dev: true
+
+  /fast-levenshtein@2.0.6:
+    resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+    dev: true
+
+  /fast-memoize@2.5.2:
+    resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==}
+    dev: true
+
+  /fastq@1.17.1:
+    resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
+    dependencies:
+      reusify: 1.0.4
+    dev: true
+
+  /figures@6.1.0:
+    resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
+    engines: {node: '>=18'}
+    dependencies:
+      is-unicode-supported: 2.0.0
+    dev: true
+
+  /file-entry-cache@8.0.0:
+    resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
+    engines: {node: '>=16.0.0'}
+    dependencies:
+      flat-cache: 4.0.1
+    dev: true
+
+  /fill-range@4.0.0:
+    resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      extend-shallow: 2.0.1
+      is-number: 3.0.0
+      repeat-string: 1.6.1
+      to-regex-range: 2.1.1
+    dev: true
+
+  /fill-range@7.1.1:
+    resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+    engines: {node: '>=8'}
+    dependencies:
+      to-regex-range: 5.0.1
+    dev: true
+
+  /find-up@4.1.0:
+    resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+    engines: {node: '>=8'}
+    dependencies:
+      locate-path: 5.0.0
+      path-exists: 4.0.0
+    dev: true
+
+  /find-up@5.0.0:
+    resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+    engines: {node: '>=10'}
+    dependencies:
+      locate-path: 6.0.0
+      path-exists: 4.0.0
+    dev: true
+
+  /flat-cache@4.0.1:
+    resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
+    engines: {node: '>=16'}
+    dependencies:
+      flatted: 3.3.1
+      keyv: 4.5.4
+    dev: true
+
+  /flatted@3.3.1:
+    resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
+    dev: true
+
+  /follow-redirects@1.15.6:
+    resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
+    engines: {node: '>=4.0'}
+    peerDependencies:
+      debug: '*'
+    peerDependenciesMeta:
+      debug:
+        optional: true
+    dev: false
+
+  /for-each@0.3.3:
+    resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
+    dependencies:
+      is-callable: 1.2.7
+    dev: true
+
+  /for-in@1.0.2:
+    resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /foreground-child@3.2.1:
+    resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==}
+    engines: {node: '>=14'}
+    dependencies:
+      cross-spawn: 7.0.3
+      signal-exit: 4.1.0
+    dev: true
+
+  /form-data-encoder@2.1.4:
+    resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==}
+    engines: {node: '>= 14.17'}
+    dev: true
+
+  /form-data@4.0.0:
+    resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+    engines: {node: '>= 6'}
+    dependencies:
+      asynckit: 0.4.0
+      combined-stream: 1.0.8
+      mime-types: 2.1.35
+    dev: false
+
+  /fp-and-or@0.1.4:
+    resolution: {integrity: sha512-+yRYRhpnFPWXSly/6V4Lw9IfOV26uu30kynGJ03PW+MnjOEQe45RZ141QcS0aJehYBYA50GfCDnsRbFJdhssRw==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /fragment-cache@0.2.1:
+    resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      map-cache: 0.2.2
+    dev: true
+
+  /fs-extra@10.1.0:
+    resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      graceful-fs: 4.2.11
+      jsonfile: 6.1.0
+      universalify: 2.0.1
+    dev: true
+
+  /fs-extra@11.2.0:
+    resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
+    engines: {node: '>=14.14'}
+    dependencies:
+      graceful-fs: 4.2.11
+      jsonfile: 6.1.0
+      universalify: 2.0.1
+    dev: true
+
+  /fs-minipass@2.1.0:
+    resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
+    engines: {node: '>= 8'}
+    dependencies:
+      minipass: 3.3.6
+    dev: true
+
+  /fs-minipass@3.0.3:
+    resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      minipass: 7.1.2
+    dev: true
+
+  /fs.realpath@1.0.0:
+    resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+    dev: true
+
+  /fsevents@2.3.3:
+    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /function-bind@1.1.2:
+    resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+  /function.prototype.name@1.1.6:
+    resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      define-properties: 1.2.1
+      es-abstract: 1.23.3
+      functions-have-names: 1.2.3
+    dev: true
+
+  /functions-have-names@1.2.3:
+    resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+    dev: true
+
+  /gauge@4.0.4:
+    resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    deprecated: This package is no longer supported.
+    dependencies:
+      aproba: 2.0.0
+      color-support: 1.1.3
+      console-control-strings: 1.1.0
+      has-unicode: 2.0.1
+      signal-exit: 3.0.7
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wide-align: 1.1.5
+    dev: true
+
+  /gensync@1.0.0-beta.2:
+    resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+    engines: {node: '>=6.9.0'}
+    dev: true
+
+  /get-caller-file@2.0.5:
+    resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+    engines: {node: 6.* || 8.* || >= 10.*}
+    dev: true
+
+  /get-east-asian-width@1.2.0:
+    resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /get-intrinsic@1.2.4:
+    resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+      has-proto: 1.0.3
+      has-symbols: 1.0.3
+      hasown: 2.0.2
+
+  /get-stdin@8.0.0:
+    resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /get-stream@6.0.1:
+    resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /get-stream@8.0.1:
+    resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
+    engines: {node: '>=16'}
+    dev: true
+
+  /get-stream@9.0.1:
+    resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
+    engines: {node: '>=18'}
+    dependencies:
+      '@sec-ant/readable-stream': 0.4.1
+      is-stream: 4.0.1
+    dev: true
+
+  /get-symbol-description@1.0.2:
+    resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      es-errors: 1.3.0
+      get-intrinsic: 1.2.4
+    dev: true
+
+  /get-tsconfig@4.7.5:
+    resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==}
+    dependencies:
+      resolve-pkg-maps: 1.0.0
+    dev: true
+
+  /get-value@2.0.6:
+    resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /giget@1.2.3:
+    resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==}
+    hasBin: true
+    dependencies:
+      citty: 0.1.6
+      consola: 3.2.3
+      defu: 6.1.4
+      node-fetch-native: 1.6.4
+      nypm: 0.3.9
+      ohash: 1.1.3
+      pathe: 1.1.2
+      tar: 6.2.1
+    dev: true
+
+  /glob-parent@5.1.2:
+    resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+    engines: {node: '>= 6'}
+    dependencies:
+      is-glob: 4.0.3
+    dev: true
+
+  /glob-parent@6.0.2:
+    resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+    engines: {node: '>=10.13.0'}
+    dependencies:
+      is-glob: 4.0.3
+    dev: true
+
+  /glob@10.4.2:
+    resolution: {integrity: sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==}
+    engines: {node: '>=16 || 14 >=14.18'}
+    hasBin: true
+    dependencies:
+      foreground-child: 3.2.1
+      jackspeak: 3.4.0
+      minimatch: 9.0.5
+      minipass: 7.1.2
+      package-json-from-dist: 1.0.0
+      path-scurry: 1.11.1
+    dev: true
+
+  /glob@7.2.3:
+    resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+    deprecated: Glob versions prior to v9 are no longer supported
+    dependencies:
+      fs.realpath: 1.0.0
+      inflight: 1.0.6
+      inherits: 2.0.4
+      minimatch: 3.1.2
+      once: 1.4.0
+      path-is-absolute: 1.0.1
+    dev: true
+
+  /glob@8.1.0:
+    resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
+    engines: {node: '>=12'}
+    deprecated: Glob versions prior to v9 are no longer supported
+    dependencies:
+      fs.realpath: 1.0.0
+      inflight: 1.0.6
+      inherits: 2.0.4
+      minimatch: 5.1.6
+      once: 1.4.0
+    dev: true
+
+  /global-dirs@3.0.1:
+    resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==}
+    engines: {node: '>=10'}
+    dependencies:
+      ini: 2.0.0
+    dev: true
+
+  /globals@11.12.0:
+    resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
+    engines: {node: '>=4'}
+    dev: true
+
+  /globals@13.24.0:
+    resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
+    engines: {node: '>=8'}
+    dependencies:
+      type-fest: 0.20.2
+    dev: true
+
+  /globals@14.0.0:
+    resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /globals@15.4.0:
+    resolution: {integrity: sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /globalthis@1.0.4:
+    resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      define-properties: 1.2.1
+      gopd: 1.0.1
+    dev: true
+
+  /globby@11.1.0:
+    resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+    engines: {node: '>=10'}
+    dependencies:
+      array-union: 2.1.0
+      dir-glob: 3.0.1
+      fast-glob: 3.3.2
+      ignore: 5.3.1
+      merge2: 1.4.1
+      slash: 3.0.0
+    dev: true
+
+  /good-listener@1.2.2:
+    resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==}
+    dependencies:
+      delegate: 3.2.0
+    dev: false
+
+  /gopd@1.0.1:
+    resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+    dependencies:
+      get-intrinsic: 1.2.4
+
+  /got@12.6.1:
+    resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==}
+    engines: {node: '>=14.16'}
+    dependencies:
+      '@sindresorhus/is': 5.6.0
+      '@szmarczak/http-timer': 5.0.1
+      cacheable-lookup: 7.0.0
+      cacheable-request: 10.2.14
+      decompress-response: 6.0.0
+      form-data-encoder: 2.1.4
+      get-stream: 6.0.1
+      http2-wrapper: 2.2.1
+      lowercase-keys: 3.0.0
+      p-cancelable: 3.0.0
+      responselike: 3.0.0
+    dev: true
+
+  /graceful-fs@4.2.10:
+    resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
+    dev: true
+
+  /graceful-fs@4.2.11:
+    resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+    dev: true
+
+  /graphemer@1.4.0:
+    resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+    dev: true
+
+  /gzip-size@6.0.0:
+    resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==}
+    engines: {node: '>=10'}
+    dependencies:
+      duplexer: 0.1.2
+    dev: true
+
+  /has-ansi@2.0.0:
+    resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      ansi-regex: 2.1.1
+    dev: true
+
+  /has-bigints@1.0.2:
+    resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
+    dev: true
+
+  /has-flag@1.0.0:
+    resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /has-flag@3.0.0:
+    resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+    engines: {node: '>=4'}
+    dev: true
+
+  /has-flag@4.0.0:
+    resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /has-property-descriptors@1.0.2:
+    resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+    dependencies:
+      es-define-property: 1.0.0
+
+  /has-proto@1.0.3:
+    resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
+    engines: {node: '>= 0.4'}
+
+  /has-symbols@1.0.3:
+    resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+    engines: {node: '>= 0.4'}
+
+  /has-tostringtag@1.0.2:
+    resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      has-symbols: 1.0.3
+    dev: true
+
+  /has-unicode@2.0.1:
+    resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
+    dev: true
+
+  /has-value@0.3.1:
+    resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      get-value: 2.0.6
+      has-values: 0.1.4
+      isobject: 2.1.0
+    dev: true
+
+  /has-value@1.0.0:
+    resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      get-value: 2.0.6
+      has-values: 1.0.0
+      isobject: 3.0.1
+    dev: true
+
+  /has-values@0.1.4:
+    resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /has-values@1.0.0:
+    resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-number: 3.0.0
+      kind-of: 4.0.0
+    dev: true
+
+  /has-yarn@3.0.0:
+    resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    dev: true
+
+  /hasown@2.0.2:
+    resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      function-bind: 1.1.2
+
+  /he@1.2.0:
+    resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
+    hasBin: true
+    dev: true
+
+  /hookable@5.5.3:
+    resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
+    dev: true
+
+  /hosted-git-info@2.8.9:
+    resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
+    dev: true
+
+  /hosted-git-info@5.2.1:
+    resolution: {integrity: sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    dependencies:
+      lru-cache: 7.18.3
+    dev: true
+
+  /hosted-git-info@6.1.1:
+    resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      lru-cache: 7.18.3
+    dev: true
+
+  /html-tags@3.3.1:
+    resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /htmlparser2@3.10.1:
+    resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==}
+    dependencies:
+      domelementtype: 1.3.1
+      domhandler: 2.4.2
+      domutils: 1.7.0
+      entities: 1.1.2
+      inherits: 2.0.4
+      readable-stream: 3.6.2
+    dev: true
+
+  /http-cache-semantics@4.1.1:
+    resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
+    dev: true
+
+  /http-proxy-agent@5.0.0:
+    resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==}
+    engines: {node: '>= 6'}
+    dependencies:
+      '@tootallnate/once': 2.0.0
+      agent-base: 6.0.2
+      debug: 4.3.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /http2-wrapper@2.2.1:
+    resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==}
+    engines: {node: '>=10.19.0'}
+    dependencies:
+      quick-lru: 5.1.1
+      resolve-alpn: 1.2.1
+    dev: true
+
+  /https-proxy-agent@5.0.1:
+    resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
+    engines: {node: '>= 6'}
+    dependencies:
+      agent-base: 6.0.2
+      debug: 4.3.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /human-signals@2.1.0:
+    resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+    engines: {node: '>=10.17.0'}
+    dev: true
+
+  /human-signals@5.0.0:
+    resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
+    engines: {node: '>=16.17.0'}
+    dev: true
+
+  /human-signals@7.0.0:
+    resolution: {integrity: sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==}
+    engines: {node: '>=18.18.0'}
+    dev: true
+
+  /humanize-ms@1.2.1:
+    resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
+    dependencies:
+      ms: 2.1.3
+    dev: true
+
+  /iconv-lite@0.6.3:
+    resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+    engines: {node: '>=0.10.0'}
+    requiresBuild: true
+    dependencies:
+      safer-buffer: 2.1.2
+    dev: true
+    optional: true
+
+  /icss-replace-symbols@1.1.0:
+    resolution: {integrity: sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==}
+    dev: true
+
+  /icss-utils@5.1.0(postcss@8.4.39):
+    resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==}
+    engines: {node: ^10 || ^12 || >= 14}
+    peerDependencies:
+      postcss: ^8.1.0
+    dependencies:
+      postcss: 8.4.39
+    dev: true
+
+  /ignore-walk@6.0.5:
+    resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      minimatch: 9.0.5
+    dev: true
+
+  /ignore@5.3.1:
+    resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
+    engines: {node: '>= 4'}
+    dev: true
+
+  /image-size@0.5.5:
+    resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==}
+    engines: {node: '>=0.10.0'}
+    hasBin: true
+    dev: true
+
+  /immediate@3.0.6:
+    resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
+    dev: false
+
+  /immutable@4.3.6:
+    resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==}
+    dev: true
+
+  /import-fresh@3.3.0:
+    resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+    engines: {node: '>=6'}
+    dependencies:
+      parent-module: 1.0.1
+      resolve-from: 4.0.0
+    dev: true
+
+  /import-lazy@4.0.0:
+    resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /imurmurhash@0.1.4:
+    resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+    engines: {node: '>=0.8.19'}
+    dev: true
+
+  /indent-string@4.0.0:
+    resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /infer-owner@1.0.4:
+    resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==}
+    dev: true
+
+  /inflight@1.0.6:
+    resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+    deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+    dependencies:
+      once: 1.4.0
+      wrappy: 1.0.2
+    dev: true
+
+  /inherits@2.0.4:
+    resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+    dev: true
+
+  /ini@1.3.8:
+    resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+    dev: true
+
+  /ini@2.0.0:
+    resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /ini@4.1.3:
+    resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dev: true
+
+  /internal-slot@1.0.7:
+    resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      es-errors: 1.3.0
+      hasown: 2.0.2
+      side-channel: 1.0.6
+    dev: true
+
+  /ip-address@9.0.5:
+    resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==}
+    engines: {node: '>= 12'}
+    dependencies:
+      jsbn: 1.1.0
+      sprintf-js: 1.1.3
+    dev: true
+
+  /is-accessor-descriptor@1.0.1:
+    resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==}
+    engines: {node: '>= 0.10'}
+    dependencies:
+      hasown: 2.0.2
+    dev: true
+
+  /is-array-buffer@3.0.4:
+    resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      get-intrinsic: 1.2.4
+    dev: true
+
+  /is-arrayish@0.2.1:
+    resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
+    dev: true
+
+  /is-bigint@1.0.4:
+    resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+    dependencies:
+      has-bigints: 1.0.2
+    dev: true
+
+  /is-binary-path@2.1.0:
+    resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+    engines: {node: '>=8'}
+    dependencies:
+      binary-extensions: 2.3.0
+    dev: true
+
+  /is-boolean-object@1.1.2:
+    resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      has-tostringtag: 1.0.2
+    dev: true
+
+  /is-buffer@1.1.6:
+    resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
+    dev: true
+
+  /is-builtin-module@3.2.1:
+    resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==}
+    engines: {node: '>=6'}
+    dependencies:
+      builtin-modules: 3.3.0
+    dev: true
+
+  /is-callable@1.2.7:
+    resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+    engines: {node: '>= 0.4'}
+    dev: true
+
+  /is-ci@3.0.1:
+    resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==}
+    hasBin: true
+    dependencies:
+      ci-info: 3.9.0
+    dev: true
+
+  /is-core-module@2.14.0:
+    resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      hasown: 2.0.2
+    dev: true
+
+  /is-data-descriptor@1.0.1:
+    resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      hasown: 2.0.2
+    dev: true
+
+  /is-data-view@1.0.1:
+    resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      is-typed-array: 1.1.13
+    dev: true
+
+  /is-date-object@1.0.5:
+    resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      has-tostringtag: 1.0.2
+    dev: true
+
+  /is-descriptor@0.1.7:
+    resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      is-accessor-descriptor: 1.0.1
+      is-data-descriptor: 1.0.1
+    dev: true
+
+  /is-descriptor@1.0.3:
+    resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      is-accessor-descriptor: 1.0.1
+      is-data-descriptor: 1.0.1
+    dev: true
+
+  /is-docker@3.0.0:
+    resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    hasBin: true
+    dev: true
+
+  /is-extendable@0.1.1:
+    resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /is-extendable@1.0.1:
+    resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-plain-object: 2.0.4
+    dev: true
+
+  /is-extglob@2.1.1:
+    resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /is-fullwidth-code-point@3.0.0:
+    resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /is-fullwidth-code-point@4.0.0:
+    resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /is-fullwidth-code-point@5.0.0:
+    resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==}
+    engines: {node: '>=18'}
+    dependencies:
+      get-east-asian-width: 1.2.0
+    dev: true
+
+  /is-glob@4.0.3:
+    resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-extglob: 2.1.1
+    dev: true
+
+  /is-inside-container@1.0.0:
+    resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
+    engines: {node: '>=14.16'}
+    hasBin: true
+    dependencies:
+      is-docker: 3.0.0
+    dev: true
+
+  /is-installed-globally@0.4.0:
+    resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      global-dirs: 3.0.1
+      is-path-inside: 3.0.3
+    dev: true
+
+  /is-lambda@1.0.1:
+    resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
+    dev: true
+
+  /is-negative-zero@2.0.3:
+    resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
+    engines: {node: '>= 0.4'}
+    dev: true
+
+  /is-npm@6.0.0:
+    resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    dev: true
+
+  /is-number-object@1.0.7:
+    resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      has-tostringtag: 1.0.2
+    dev: true
+
+  /is-number@3.0.0:
+    resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      kind-of: 3.2.2
+    dev: true
+
+  /is-number@7.0.0:
+    resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+    engines: {node: '>=0.12.0'}
+    dev: true
+
+  /is-obj@2.0.0:
+    resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /is-path-inside@3.0.3:
+    resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /is-plain-obj@1.1.0:
+    resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /is-plain-obj@4.1.0:
+    resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /is-plain-object@2.0.4:
+    resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      isobject: 3.0.1
+    dev: true
+
+  /is-plain-object@3.0.1:
+    resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==}
+    engines: {node: '>=0.10.0'}
+    dev: false
+
+  /is-regex@1.1.4:
+    resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      has-tostringtag: 1.0.2
+    dev: true
+
+  /is-retry-allowed@2.2.0:
+    resolution: {integrity: sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==}
+    engines: {node: '>=10'}
+    dev: false
+
+  /is-shared-array-buffer@1.0.3:
+    resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+    dev: true
+
+  /is-stream@2.0.1:
+    resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /is-stream@3.0.0:
+    resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    dev: true
+
+  /is-stream@4.0.1:
+    resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /is-string@1.0.7:
+    resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      has-tostringtag: 1.0.2
+    dev: true
+
+  /is-symbol@1.0.4:
+    resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      has-symbols: 1.0.3
+    dev: true
+
+  /is-there@4.5.1:
+    resolution: {integrity: sha512-vIZ7HTXAoRoIwYSsTnxb0sg9L6rth+JOulNcavsbskQkCIWoSM2cjFOWZs4wGziGZER+Xgs/HXiCQZgiL8ppxQ==}
+    dev: true
+
+  /is-typed-array@1.1.13:
+    resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      which-typed-array: 1.1.15
+    dev: true
+
+  /is-typedarray@1.0.0:
+    resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
+    dev: true
+
+  /is-unicode-supported@2.0.0:
+    resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /is-weakref@1.0.2:
+    resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
+    dependencies:
+      call-bind: 1.0.7
+    dev: true
+
+  /is-what@4.1.16:
+    resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
+    engines: {node: '>=12.13'}
+    dev: true
+
+  /is-windows@1.0.2:
+    resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /is-wsl@3.1.0:
+    resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
+    engines: {node: '>=16'}
+    dependencies:
+      is-inside-container: 1.0.0
+    dev: true
+
+  /is-yarn-global@0.4.1:
+    resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /isarray@1.0.0:
+    resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
+    dev: true
+
+  /isarray@2.0.5:
+    resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+    dev: true
+
+  /isexe@2.0.0:
+    resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+    dev: true
+
+  /isobject@2.1.0:
+    resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      isarray: 1.0.0
+    dev: true
+
+  /isobject@3.0.1:
+    resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /jackspeak@3.4.0:
+    resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==}
+    engines: {node: '>=14'}
+    dependencies:
+      '@isaacs/cliui': 8.0.2
+    optionalDependencies:
+      '@pkgjs/parseargs': 0.11.0
+    dev: true
+
+  /jiti@1.21.6:
+    resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==}
+    hasBin: true
+    dev: true
+
+  /jju@1.4.0:
+    resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
+    dev: true
+
+  /js-base64@2.6.4:
+    resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==}
+    dev: true
+
+  /js-tokens@4.0.0:
+    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+  /js-yaml@4.1.0:
+    resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+    hasBin: true
+    dependencies:
+      argparse: 2.0.1
+    dev: true
+
+  /jsbn@1.1.0:
+    resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==}
+    dev: true
+
+  /jsencrypt@3.3.2:
+    resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==}
+    dev: false
+
+  /jsesc@0.5.0:
+    resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==}
+    hasBin: true
+    dev: true
+
+  /jsesc@2.5.2:
+    resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
+    engines: {node: '>=4'}
+    hasBin: true
+    dev: true
+
+  /jsesc@3.0.2:
+    resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==}
+    engines: {node: '>=6'}
+    hasBin: true
+    dev: true
+
+  /json-buffer@3.0.1:
+    resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+    dev: true
+
+  /json-parse-even-better-errors@2.3.1:
+    resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+    dev: true
+
+  /json-parse-even-better-errors@3.0.2:
+    resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dev: true
+
+  /json-parse-helpfulerror@1.0.3:
+    resolution: {integrity: sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==}
+    dependencies:
+      jju: 1.4.0
+    dev: true
+
+  /json-schema-traverse@0.4.1:
+    resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+    dev: true
+
+  /json-stable-stringify-without-jsonify@1.0.1:
+    resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+    dev: true
+
+  /json5@1.0.2:
+    resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
+    hasBin: true
+    dependencies:
+      minimist: 1.2.8
+    dev: true
+
+  /json5@2.2.3:
+    resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+    engines: {node: '>=6'}
+    hasBin: true
+    dev: true
+
+  /jsonfile@6.1.0:
+    resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
+    dependencies:
+      universalify: 2.0.1
+    optionalDependencies:
+      graceful-fs: 4.2.11
+    dev: true
+
+  /jsonlines@0.1.1:
+    resolution: {integrity: sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==}
+    dev: true
+
+  /jsonparse@1.3.1:
+    resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
+    engines: {'0': node >= 0.2.0}
+    dev: true
+
+  /keyv@4.5.4:
+    resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+    dependencies:
+      json-buffer: 3.0.1
+    dev: true
+
+  /kind-of@3.2.2:
+    resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-buffer: 1.1.6
+    dev: true
+
+  /kind-of@4.0.0:
+    resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-buffer: 1.1.6
+    dev: true
+
+  /kind-of@5.1.0:
+    resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /kind-of@6.0.3:
+    resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /kleur@3.0.3:
+    resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /kleur@4.1.5:
+    resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /kolorist@1.8.0:
+    resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
+    dev: true
+
+  /latest-version@7.0.0:
+    resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==}
+    engines: {node: '>=14.16'}
+    dependencies:
+      package-json: 8.1.1
+    dev: true
+
+  /levn@0.4.1:
+    resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+    engines: {node: '>= 0.8.0'}
+    dependencies:
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+    dev: true
+
+  /lie@3.1.1:
+    resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
+    dependencies:
+      immediate: 3.0.6
+    dev: false
+
+  /lilconfig@3.1.2:
+    resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==}
+    engines: {node: '>=14'}
+    dev: true
+
+  /lines-and-columns@1.2.4:
+    resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+    dev: true
+
+  /lint-staged@15.2.7:
+    resolution: {integrity: sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==}
+    engines: {node: '>=18.12.0'}
+    hasBin: true
+    dependencies:
+      chalk: 5.3.0
+      commander: 12.1.0
+      debug: 4.3.5
+      execa: 8.0.1
+      lilconfig: 3.1.2
+      listr2: 8.2.3
+      micromatch: 4.0.7
+      pidtree: 0.6.0
+      string-argv: 0.3.2
+      yaml: 2.4.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /listr2@8.2.3:
+    resolution: {integrity: sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==}
+    engines: {node: '>=18.0.0'}
+    dependencies:
+      cli-truncate: 4.0.0
+      colorette: 2.0.20
+      eventemitter3: 5.0.1
+      log-update: 6.0.0
+      rfdc: 1.4.1
+      wrap-ansi: 9.0.0
+    dev: true
+
+  /loader-utils@1.4.2:
+    resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==}
+    engines: {node: '>=4.0.0'}
+    dependencies:
+      big.js: 5.2.2
+      emojis-list: 3.0.0
+      json5: 1.0.2
+    dev: true
+
+  /local-pkg@0.5.0:
+    resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
+    engines: {node: '>=14'}
+    dependencies:
+      mlly: 1.7.1
+      pkg-types: 1.1.3
+    dev: true
+
+  /localforage@1.10.0:
+    resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
+    dependencies:
+      lie: 3.1.1
+    dev: false
+
+  /locate-path@5.0.0:
+    resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+    engines: {node: '>=8'}
+    dependencies:
+      p-locate: 4.1.0
+    dev: true
+
+  /locate-path@6.0.0:
+    resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+    engines: {node: '>=10'}
+    dependencies:
+      p-locate: 5.0.0
+    dev: true
+
+  /lodash-es@4.17.21:
+    resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+    dev: false
+
+  /lodash.merge@4.6.2:
+    resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+    dev: true
+
+  /lodash@4.17.21:
+    resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+  /log-update@6.0.0:
+    resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==}
+    engines: {node: '>=18'}
+    dependencies:
+      ansi-escapes: 6.2.1
+      cli-cursor: 4.0.0
+      slice-ansi: 7.1.0
+      strip-ansi: 7.1.0
+      wrap-ansi: 9.0.0
+    dev: true
+
+  /loose-envify@1.4.0:
+    resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+    hasBin: true
+    dependencies:
+      js-tokens: 4.0.0
+    dev: false
+
+  /lowercase-keys@3.0.0:
+    resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    dev: true
+
+  /lru-cache@10.3.0:
+    resolution: {integrity: sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==}
+    engines: {node: 14 || >=16.14}
+    dev: true
+
+  /lru-cache@5.1.1:
+    resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+    dependencies:
+      yallist: 3.1.1
+    dev: true
+
+  /lru-cache@7.18.3:
+    resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /magic-string@0.30.10:
+    resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==}
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.4.15
+
+  /magicast@0.3.4:
+    resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==}
+    dependencies:
+      '@babel/parser': 7.24.7
+      '@babel/types': 7.24.7
+      source-map-js: 1.2.0
+    dev: true
+
+  /make-fetch-happen@10.2.1:
+    resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    dependencies:
+      agentkeepalive: 4.5.0
+      cacache: 16.1.3
+      http-cache-semantics: 4.1.1
+      http-proxy-agent: 5.0.0
+      https-proxy-agent: 5.0.1
+      is-lambda: 1.0.1
+      lru-cache: 7.18.3
+      minipass: 3.3.6
+      minipass-collect: 1.0.2
+      minipass-fetch: 2.1.2
+      minipass-flush: 1.0.5
+      minipass-pipeline: 1.2.4
+      negotiator: 0.6.3
+      promise-retry: 2.0.1
+      socks-proxy-agent: 7.0.0
+      ssri: 9.0.1
+    transitivePeerDependencies:
+      - bluebird
+      - supports-color
+    dev: true
+
+  /make-fetch-happen@11.1.1:
+    resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      agentkeepalive: 4.5.0
+      cacache: 17.1.4
+      http-cache-semantics: 4.1.1
+      http-proxy-agent: 5.0.0
+      https-proxy-agent: 5.0.1
+      is-lambda: 1.0.1
+      lru-cache: 7.18.3
+      minipass: 5.0.0
+      minipass-fetch: 3.0.5
+      minipass-flush: 1.0.5
+      minipass-pipeline: 1.2.4
+      negotiator: 0.6.3
+      promise-retry: 2.0.1
+      socks-proxy-agent: 7.0.0
+      ssri: 10.0.6
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /map-cache@0.2.2:
+    resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /map-visit@1.0.0:
+    resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      object-visit: 1.0.1
+    dev: true
+
+  /mdast-util-from-markdown@2.0.1:
+    resolution: {integrity: sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==}
+    dependencies:
+      '@types/mdast': 4.0.4
+      '@types/unist': 3.0.2
+      decode-named-character-reference: 1.0.2
+      devlop: 1.1.0
+      mdast-util-to-string: 4.0.0
+      micromark: 4.0.0
+      micromark-util-decode-numeric-character-reference: 2.0.1
+      micromark-util-decode-string: 2.0.0
+      micromark-util-normalize-identifier: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+      unist-util-stringify-position: 4.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /mdast-util-to-string@4.0.0:
+    resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
+    dependencies:
+      '@types/mdast': 4.0.4
+    dev: true
+
+  /mdn-data@2.0.14:
+    resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
+    dev: true
+
+  /mdn-data@2.0.30:
+    resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
+    dev: true
+
+  /merge-options@1.0.1:
+    resolution: {integrity: sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==}
+    engines: {node: '>=4'}
+    dependencies:
+      is-plain-obj: 1.1.0
+    dev: true
+
+  /merge-stream@2.0.0:
+    resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+    dev: true
+
+  /merge2@1.4.1:
+    resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+    engines: {node: '>= 8'}
+    dev: true
+
+  /micromark-core-commonmark@2.0.1:
+    resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==}
+    dependencies:
+      decode-named-character-reference: 1.0.2
+      devlop: 1.1.0
+      micromark-factory-destination: 2.0.0
+      micromark-factory-label: 2.0.0
+      micromark-factory-space: 2.0.0
+      micromark-factory-title: 2.0.0
+      micromark-factory-whitespace: 2.0.0
+      micromark-util-character: 2.1.0
+      micromark-util-chunked: 2.0.0
+      micromark-util-classify-character: 2.0.0
+      micromark-util-html-tag-name: 2.0.0
+      micromark-util-normalize-identifier: 2.0.0
+      micromark-util-resolve-all: 2.0.0
+      micromark-util-subtokenize: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-factory-destination@2.0.0:
+    resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==}
+    dependencies:
+      micromark-util-character: 2.1.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-factory-label@2.0.0:
+    resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==}
+    dependencies:
+      devlop: 1.1.0
+      micromark-util-character: 2.1.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-factory-space@2.0.0:
+    resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==}
+    dependencies:
+      micromark-util-character: 2.1.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-factory-title@2.0.0:
+    resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==}
+    dependencies:
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.1.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-factory-whitespace@2.0.0:
+    resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==}
+    dependencies:
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.1.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-util-character@2.1.0:
+    resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==}
+    dependencies:
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-util-chunked@2.0.0:
+    resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==}
+    dependencies:
+      micromark-util-symbol: 2.0.0
+    dev: true
+
+  /micromark-util-classify-character@2.0.0:
+    resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==}
+    dependencies:
+      micromark-util-character: 2.1.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-util-combine-extensions@2.0.0:
+    resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==}
+    dependencies:
+      micromark-util-chunked: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-util-decode-numeric-character-reference@2.0.1:
+    resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==}
+    dependencies:
+      micromark-util-symbol: 2.0.0
+    dev: true
+
+  /micromark-util-decode-string@2.0.0:
+    resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==}
+    dependencies:
+      decode-named-character-reference: 1.0.2
+      micromark-util-character: 2.1.0
+      micromark-util-decode-numeric-character-reference: 2.0.1
+      micromark-util-symbol: 2.0.0
+    dev: true
+
+  /micromark-util-encode@2.0.0:
+    resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==}
+    dev: true
+
+  /micromark-util-html-tag-name@2.0.0:
+    resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==}
+    dev: true
+
+  /micromark-util-normalize-identifier@2.0.0:
+    resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==}
+    dependencies:
+      micromark-util-symbol: 2.0.0
+    dev: true
+
+  /micromark-util-resolve-all@2.0.0:
+    resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==}
+    dependencies:
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-util-sanitize-uri@2.0.0:
+    resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==}
+    dependencies:
+      micromark-util-character: 2.1.0
+      micromark-util-encode: 2.0.0
+      micromark-util-symbol: 2.0.0
+    dev: true
+
+  /micromark-util-subtokenize@2.0.1:
+    resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==}
+    dependencies:
+      devlop: 1.1.0
+      micromark-util-chunked: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: true
+
+  /micromark-util-symbol@2.0.0:
+    resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==}
+    dev: true
+
+  /micromark-util-types@2.0.0:
+    resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==}
+    dev: true
+
+  /micromark@4.0.0:
+    resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==}
+    dependencies:
+      '@types/debug': 4.1.12
+      debug: 4.3.5
+      decode-named-character-reference: 1.0.2
+      devlop: 1.1.0
+      micromark-core-commonmark: 2.0.1
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.1.0
+      micromark-util-chunked: 2.0.0
+      micromark-util-combine-extensions: 2.0.0
+      micromark-util-decode-numeric-character-reference: 2.0.1
+      micromark-util-encode: 2.0.0
+      micromark-util-normalize-identifier: 2.0.0
+      micromark-util-resolve-all: 2.0.0
+      micromark-util-sanitize-uri: 2.0.0
+      micromark-util-subtokenize: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /micromatch@3.1.0:
+    resolution: {integrity: sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      arr-diff: 4.0.0
+      array-unique: 0.3.2
+      braces: 2.3.2
+      define-property: 1.0.0
+      extend-shallow: 2.0.1
+      extglob: 2.0.4
+      fragment-cache: 0.2.1
+      kind-of: 5.1.0
+      nanomatch: 1.2.13
+      object.pick: 1.3.0
+      regex-not: 1.0.2
+      snapdragon: 0.8.2
+      to-regex: 3.0.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /micromatch@4.0.5:
+    resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+    engines: {node: '>=8.6'}
+    dependencies:
+      braces: 3.0.3
+      picomatch: 2.3.1
+    dev: true
+
+  /micromatch@4.0.7:
+    resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==}
+    engines: {node: '>=8.6'}
+    dependencies:
+      braces: 3.0.3
+      picomatch: 2.3.1
+    dev: true
+
+  /mime-db@1.52.0:
+    resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+    engines: {node: '>= 0.6'}
+    dev: false
+
+  /mime-types@2.1.35:
+    resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+    engines: {node: '>= 0.6'}
+    dependencies:
+      mime-db: 1.52.0
+    dev: false
+
+  /mimic-fn@2.1.0:
+    resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /mimic-fn@4.0.0:
+    resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /mimic-response@3.1.0:
+    resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /mimic-response@4.0.0:
+    resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    dev: true
+
+  /min-indent@1.0.1:
+    resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+    engines: {node: '>=4'}
+    dev: true
+
+  /minimatch@3.1.2:
+    resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+    dependencies:
+      brace-expansion: 1.1.11
+    dev: true
+
+  /minimatch@5.1.6:
+    resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+    engines: {node: '>=10'}
+    dependencies:
+      brace-expansion: 2.0.1
+    dev: true
+
+  /minimatch@9.0.5:
+    resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+    engines: {node: '>=16 || 14 >=14.17'}
+    dependencies:
+      brace-expansion: 2.0.1
+    dev: true
+
+  /minimist@1.2.8:
+    resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+    dev: true
+
+  /minipass-collect@1.0.2:
+    resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
+    engines: {node: '>= 8'}
+    dependencies:
+      minipass: 3.3.6
+    dev: true
+
+  /minipass-fetch@2.1.2:
+    resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    dependencies:
+      minipass: 3.3.6
+      minipass-sized: 1.0.3
+      minizlib: 2.1.2
+    optionalDependencies:
+      encoding: 0.1.13
+    dev: true
+
+  /minipass-fetch@3.0.5:
+    resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      minipass: 7.1.2
+      minipass-sized: 1.0.3
+      minizlib: 2.1.2
+    optionalDependencies:
+      encoding: 0.1.13
+    dev: true
+
+  /minipass-flush@1.0.5:
+    resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==}
+    engines: {node: '>= 8'}
+    dependencies:
+      minipass: 3.3.6
+    dev: true
+
+  /minipass-json-stream@1.0.1:
+    resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==}
+    dependencies:
+      jsonparse: 1.3.1
+      minipass: 3.3.6
+    dev: true
+
+  /minipass-pipeline@1.2.4:
+    resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==}
+    engines: {node: '>=8'}
+    dependencies:
+      minipass: 3.3.6
+    dev: true
+
+  /minipass-sized@1.0.3:
+    resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==}
+    engines: {node: '>=8'}
+    dependencies:
+      minipass: 3.3.6
+    dev: true
+
+  /minipass@3.3.6:
+    resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
+    engines: {node: '>=8'}
+    dependencies:
+      yallist: 4.0.0
+    dev: true
+
+  /minipass@5.0.0:
+    resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /minipass@7.1.2:
+    resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+    engines: {node: '>=16 || 14 >=14.17'}
+    dev: true
+
+  /minizlib@2.1.2:
+    resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
+    engines: {node: '>= 8'}
+    dependencies:
+      minipass: 3.3.6
+      yallist: 4.0.0
+    dev: true
+
+  /mitt@3.0.1:
+    resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
+    dev: true
+
+  /mixin-deep@1.3.2:
+    resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      for-in: 1.0.2
+      is-extendable: 1.0.1
+    dev: true
+
+  /mkdirp@1.0.4:
+    resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
+    engines: {node: '>=10'}
+    hasBin: true
+    dev: true
+
+  /mkdirp@3.0.1:
+    resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
+    engines: {node: '>=10'}
+    hasBin: true
+    dev: true
+
+  /mlly@1.7.1:
+    resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
+    dependencies:
+      acorn: 8.12.1
+      pathe: 1.1.2
+      pkg-types: 1.1.3
+      ufo: 1.5.3
+    dev: true
+
+  /mrmime@2.0.0:
+    resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /ms@2.0.0:
+    resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+    dev: true
+
+  /ms@2.1.2:
+    resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+    dev: true
+
+  /ms@2.1.3:
+    resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+    dev: true
+
+  /nanoid@3.3.7:
+    resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+    engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+    hasBin: true
+
+  /nanoid@5.0.7:
+    resolution: {integrity: sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==}
+    engines: {node: ^18 || >=20}
+    hasBin: true
+    dev: false
+
+  /nanomatch@1.2.13:
+    resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      arr-diff: 4.0.0
+      array-unique: 0.3.2
+      define-property: 2.0.2
+      extend-shallow: 3.0.2
+      fragment-cache: 0.2.1
+      is-windows: 1.0.2
+      kind-of: 6.0.3
+      object.pick: 1.3.0
+      regex-not: 1.0.2
+      snapdragon: 0.8.2
+      to-regex: 3.0.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /nanopop@2.4.2:
+    resolution: {integrity: sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==}
+    dev: false
+
+  /natural-compare@1.4.0:
+    resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+    dev: true
+
+  /negotiator@0.6.3:
+    resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
+    engines: {node: '>= 0.6'}
+    dev: true
+
+  /node-fetch-native@1.6.4:
+    resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==}
+
+  /node-gyp@9.4.1:
+    resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==}
+    engines: {node: ^12.13 || ^14.13 || >=16}
+    hasBin: true
+    dependencies:
+      env-paths: 2.2.1
+      exponential-backoff: 3.1.1
+      glob: 7.2.3
+      graceful-fs: 4.2.11
+      make-fetch-happen: 10.2.1
+      nopt: 6.0.0
+      npmlog: 6.0.2
+      rimraf: 3.0.2
+      semver: 7.6.2
+      tar: 6.2.1
+      which: 2.0.2
+    transitivePeerDependencies:
+      - bluebird
+      - supports-color
+    dev: true
+
+  /node-releases@2.0.14:
+    resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
+    dev: true
+
+  /nopt@6.0.0:
+    resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    hasBin: true
+    dependencies:
+      abbrev: 1.1.1
+    dev: true
+
+  /normalize-package-data@2.5.0:
+    resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
+    dependencies:
+      hosted-git-info: 2.8.9
+      resolve: 1.22.8
+      semver: 5.7.2
+      validate-npm-package-license: 3.0.4
+    dev: true
+
+  /normalize-package-data@5.0.0:
+    resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      hosted-git-info: 6.1.1
+      is-core-module: 2.14.0
+      semver: 7.6.2
+      validate-npm-package-license: 3.0.4
+    dev: true
+
+  /normalize-path@3.0.0:
+    resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /normalize-url@8.0.1:
+    resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==}
+    engines: {node: '>=14.16'}
+    dev: true
+
+  /npm-bundled@3.0.1:
+    resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      npm-normalize-package-bin: 3.0.1
+    dev: true
+
+  /npm-check-updates@16.14.20:
+    resolution: {integrity: sha512-sYbIhun4DrjO7NFOTdvs11nCar0etEhZTsEjL47eM0TuiGMhmYughRCxG2SpGRmGAQ7AkwN7bw2lWzoE7q6yOQ==}
+    engines: {node: '>=14.14'}
+    hasBin: true
+    dependencies:
+      '@types/semver-utils': 1.1.3
+      chalk: 5.3.0
+      cli-table3: 0.6.5
+      commander: 10.0.1
+      fast-memoize: 2.5.2
+      find-up: 5.0.0
+      fp-and-or: 0.1.4
+      get-stdin: 8.0.0
+      globby: 11.1.0
+      hosted-git-info: 5.2.1
+      ini: 4.1.3
+      js-yaml: 4.1.0
+      json-parse-helpfulerror: 1.0.3
+      jsonlines: 0.1.1
+      lodash: 4.17.21
+      make-fetch-happen: 11.1.1
+      minimatch: 9.0.5
+      p-map: 4.0.0
+      pacote: 15.2.0
+      parse-github-url: 1.0.3
+      progress: 2.0.3
+      prompts-ncu: 3.0.0
+      rc-config-loader: 4.1.3
+      remote-git-tags: 3.0.0
+      rimraf: 5.0.7
+      semver: 7.6.2
+      semver-utils: 1.1.4
+      source-map-support: 0.5.21
+      spawn-please: 2.0.2
+      strip-ansi: 7.1.0
+      strip-json-comments: 5.0.1
+      untildify: 4.0.0
+      update-notifier: 6.0.2
+    transitivePeerDependencies:
+      - bluebird
+      - supports-color
+    dev: true
+
+  /npm-install-checks@6.3.0:
+    resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      semver: 7.6.2
+    dev: true
+
+  /npm-normalize-package-bin@3.0.1:
+    resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dev: true
+
+  /npm-package-arg@10.1.0:
+    resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      hosted-git-info: 6.1.1
+      proc-log: 3.0.0
+      semver: 7.6.2
+      validate-npm-package-name: 5.0.1
+    dev: true
+
+  /npm-packlist@7.0.4:
+    resolution: {integrity: sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      ignore-walk: 6.0.5
+    dev: true
+
+  /npm-pick-manifest@8.0.2:
+    resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      npm-install-checks: 6.3.0
+      npm-normalize-package-bin: 3.0.1
+      npm-package-arg: 10.1.0
+      semver: 7.6.2
+    dev: true
+
+  /npm-registry-fetch@14.0.5:
+    resolution: {integrity: sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      make-fetch-happen: 11.1.1
+      minipass: 5.0.0
+      minipass-fetch: 3.0.5
+      minipass-json-stream: 1.0.1
+      minizlib: 2.1.2
+      npm-package-arg: 10.1.0
+      proc-log: 3.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /npm-run-path@4.0.1:
+    resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+    engines: {node: '>=8'}
+    dependencies:
+      path-key: 3.1.1
+    dev: true
+
+  /npm-run-path@5.3.0:
+    resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    dependencies:
+      path-key: 4.0.0
+    dev: true
+
+  /npmlog@6.0.2:
+    resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    deprecated: This package is no longer supported.
+    dependencies:
+      are-we-there-yet: 3.0.1
+      console-control-strings: 1.1.0
+      gauge: 4.0.4
+      set-blocking: 2.0.0
+    dev: true
+
+  /nprogress@0.2.0:
+    resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==}
+    dev: false
+
+  /nth-check@2.1.1:
+    resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+    dependencies:
+      boolbase: 1.0.0
+    dev: true
+
+  /nypm@0.3.9:
+    resolution: {integrity: sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==}
+    engines: {node: ^14.16.0 || >=16.10.0}
+    hasBin: true
+    dependencies:
+      citty: 0.1.6
+      consola: 3.2.3
+      execa: 8.0.1
+      pathe: 1.1.2
+      pkg-types: 1.1.3
+      ufo: 1.5.3
+    dev: true
+
+  /object-assign@4.1.1:
+    resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /object-copy@0.1.0:
+    resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      copy-descriptor: 0.1.1
+      define-property: 0.2.5
+      kind-of: 3.2.2
+    dev: true
+
+  /object-inspect@1.13.2:
+    resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==}
+    engines: {node: '>= 0.4'}
+
+  /object-keys@1.1.1:
+    resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+    engines: {node: '>= 0.4'}
+    dev: true
+
+  /object-visit@1.0.1:
+    resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      isobject: 3.0.1
+    dev: true
+
+  /object.assign@4.1.5:
+    resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      define-properties: 1.2.1
+      has-symbols: 1.0.3
+      object-keys: 1.1.1
+    dev: true
+
+  /object.pick@1.3.0:
+    resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      isobject: 3.0.1
+    dev: true
+
+  /ofetch@1.3.4:
+    resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==}
+    dependencies:
+      destr: 2.0.3
+      node-fetch-native: 1.6.4
+      ufo: 1.5.3
+
+  /ohash@1.1.3:
+    resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==}
+    dev: true
+
+  /once@1.4.0:
+    resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+    dependencies:
+      wrappy: 1.0.2
+    dev: true
+
+  /onetime@5.1.2:
+    resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+    engines: {node: '>=6'}
+    dependencies:
+      mimic-fn: 2.1.0
+    dev: true
+
+  /onetime@6.0.0:
+    resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      mimic-fn: 4.0.0
+    dev: true
+
+  /open@10.1.0:
+    resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==}
+    engines: {node: '>=18'}
+    dependencies:
+      default-browser: 5.2.1
+      define-lazy-prop: 3.0.0
+      is-inside-container: 1.0.0
+      is-wsl: 3.1.0
+    dev: true
+
+  /optionator@0.9.4:
+    resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+    engines: {node: '>= 0.8.0'}
+    dependencies:
+      deep-is: 0.1.4
+      fast-levenshtein: 2.0.6
+      levn: 0.4.1
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+      word-wrap: 1.2.5
+    dev: true
+
+  /p-cancelable@3.0.0:
+    resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==}
+    engines: {node: '>=12.20'}
+    dev: true
+
+  /p-limit@2.3.0:
+    resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+    engines: {node: '>=6'}
+    dependencies:
+      p-try: 2.2.0
+    dev: true
+
+  /p-limit@3.1.0:
+    resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      yocto-queue: 0.1.0
+    dev: true
+
+  /p-locate@4.1.0:
+    resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+    engines: {node: '>=8'}
+    dependencies:
+      p-limit: 2.3.0
+    dev: true
+
+  /p-locate@5.0.0:
+    resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+    engines: {node: '>=10'}
+    dependencies:
+      p-limit: 3.1.0
+    dev: true
+
+  /p-map@4.0.0:
+    resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      aggregate-error: 3.1.0
+    dev: true
+
+  /p-try@2.2.0:
+    resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /package-json-from-dist@1.0.0:
+    resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==}
+    dev: true
+
+  /package-json@8.1.1:
+    resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==}
+    engines: {node: '>=14.16'}
+    dependencies:
+      got: 12.6.1
+      registry-auth-token: 5.0.2
+      registry-url: 6.0.1
+      semver: 7.6.2
+    dev: true
+
+  /pacote@15.2.0:
+    resolution: {integrity: sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    hasBin: true
+    dependencies:
+      '@npmcli/git': 4.1.0
+      '@npmcli/installed-package-contents': 2.1.0
+      '@npmcli/promise-spawn': 6.0.2
+      '@npmcli/run-script': 6.0.2
+      cacache: 17.1.4
+      fs-minipass: 3.0.3
+      minipass: 5.0.0
+      npm-package-arg: 10.1.0
+      npm-packlist: 7.0.4
+      npm-pick-manifest: 8.0.2
+      npm-registry-fetch: 14.0.5
+      proc-log: 3.0.0
+      promise-retry: 2.0.1
+      read-package-json: 6.0.4
+      read-package-json-fast: 3.0.2
+      sigstore: 1.9.0
+      ssri: 10.0.6
+      tar: 6.2.1
+    transitivePeerDependencies:
+      - bluebird
+      - supports-color
+    dev: true
+
+  /parent-module@1.0.1:
+    resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+    engines: {node: '>=6'}
+    dependencies:
+      callsites: 3.1.0
+    dev: true
+
+  /parse-github-url@1.0.3:
+    resolution: {integrity: sha512-tfalY5/4SqGaV/GIGzWyHnFjlpTPTNpENR9Ea2lLldSJ8EWXMsvacWucqY3m3I4YPtas15IxTLQVQ5NSYXPrww==}
+    engines: {node: '>= 0.10'}
+    hasBin: true
+    dev: true
+
+  /parse-json@5.2.0:
+    resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
+    engines: {node: '>=8'}
+    dependencies:
+      '@babel/code-frame': 7.24.7
+      error-ex: 1.3.2
+      json-parse-even-better-errors: 2.3.1
+      lines-and-columns: 1.2.4
+    dev: true
+
+  /parse-ms@4.0.0:
+    resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /pascalcase@0.1.1:
+    resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /path-browserify@1.0.1:
+    resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+    dev: true
+
+  /path-exists@4.0.0:
+    resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /path-is-absolute@1.0.1:
+    resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /path-key@3.1.1:
+    resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /path-key@4.0.0:
+    resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /path-parse@1.0.7:
+    resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+    dev: true
+
+  /path-scurry@1.11.1:
+    resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+    engines: {node: '>=16 || 14 >=14.18'}
+    dependencies:
+      lru-cache: 10.3.0
+      minipass: 7.1.2
+    dev: true
+
+  /path-type@4.0.0:
+    resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /pathe@0.2.0:
+    resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==}
+    dev: true
+
+  /pathe@1.1.2:
+    resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
+    dev: true
+
+  /perfect-debounce@1.0.0:
+    resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
+    dev: true
+
+  /picocolors@1.0.1:
+    resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
+
+  /picomatch@2.3.1:
+    resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+    engines: {node: '>=8.6'}
+    dev: true
+
+  /pidtree@0.6.0:
+    resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
+    engines: {node: '>=0.10'}
+    hasBin: true
+    dev: true
+
+  /pinia@2.1.7(typescript@5.4.5)(vue@3.4.29):
+    resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==}
+    peerDependencies:
+      '@vue/composition-api': ^1.4.0
+      typescript: '>=4.4.4'
+      vue: ^2.6.14 || ^3.3.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+      typescript:
+        optional: true
+    dependencies:
+      '@vue/devtools-api': 6.6.3
+      typescript: 5.4.5
+      vue: 3.4.29(typescript@5.4.5)
+      vue-demi: 0.14.8(vue@3.4.29)
+    dev: false
+
+  /pkg-types@1.1.3:
+    resolution: {integrity: sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==}
+    dependencies:
+      confbox: 0.1.7
+      mlly: 1.7.1
+      pathe: 1.1.2
+    dev: true
+
+  /pluralize@8.0.0:
+    resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
+    engines: {node: '>=4'}
+    dev: true
+
+  /posix-character-classes@0.1.1:
+    resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /possible-typed-array-names@1.0.0:
+    resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
+    engines: {node: '>= 0.4'}
+    dev: true
+
+  /postcss-modules-extract-imports@3.1.0(postcss@8.4.39):
+    resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==}
+    engines: {node: ^10 || ^12 || >= 14}
+    peerDependencies:
+      postcss: ^8.1.0
+    dependencies:
+      postcss: 8.4.39
+    dev: true
+
+  /postcss-modules-local-by-default@4.0.5(postcss@8.4.39):
+    resolution: {integrity: sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==}
+    engines: {node: ^10 || ^12 || >= 14}
+    peerDependencies:
+      postcss: ^8.1.0
+    dependencies:
+      icss-utils: 5.1.0(postcss@8.4.39)
+      postcss: 8.4.39
+      postcss-selector-parser: 6.1.0
+      postcss-value-parser: 4.2.0
+    dev: true
+
+  /postcss-modules-scope@3.2.0(postcss@8.4.39):
+    resolution: {integrity: sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==}
+    engines: {node: ^10 || ^12 || >= 14}
+    peerDependencies:
+      postcss: ^8.1.0
+    dependencies:
+      postcss: 8.4.39
+      postcss-selector-parser: 6.1.0
+    dev: true
+
+  /postcss-modules-values@4.0.0(postcss@8.4.39):
+    resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==}
+    engines: {node: ^10 || ^12 || >= 14}
+    peerDependencies:
+      postcss: ^8.1.0
+    dependencies:
+      icss-utils: 5.1.0(postcss@8.4.39)
+      postcss: 8.4.39
+    dev: true
+
+  /postcss-prefix-selector@1.16.1(postcss@5.2.18):
+    resolution: {integrity: sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==}
+    peerDependencies:
+      postcss: '>4 <9'
+    dependencies:
+      postcss: 5.2.18
+    dev: true
+
+  /postcss-selector-parser@6.1.0:
+    resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==}
+    engines: {node: '>=4'}
+    dependencies:
+      cssesc: 3.0.0
+      util-deprecate: 1.0.2
+    dev: true
+
+  /postcss-value-parser@4.2.0:
+    resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+    dev: true
+
+  /postcss@5.2.18:
+    resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==}
+    engines: {node: '>=0.12'}
+    dependencies:
+      chalk: 1.1.3
+      js-base64: 2.6.4
+      source-map: 0.5.7
+      supports-color: 3.2.3
+    dev: true
+
+  /postcss@8.4.39:
+    resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==}
+    engines: {node: ^10 || ^12 || >=14}
+    dependencies:
+      nanoid: 3.3.7
+      picocolors: 1.0.1
+      source-map-js: 1.2.0
+
+  /posthtml-parser@0.2.1:
+    resolution: {integrity: sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==}
+    dependencies:
+      htmlparser2: 3.10.1
+      isobject: 2.1.0
+    dev: true
+
+  /posthtml-rename-id@1.0.12:
+    resolution: {integrity: sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==}
+    dependencies:
+      escape-string-regexp: 1.0.5
+    dev: true
+
+  /posthtml-render@1.4.0:
+    resolution: {integrity: sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /posthtml-svg-mode@1.0.3:
+    resolution: {integrity: sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==}
+    dependencies:
+      merge-options: 1.0.1
+      posthtml: 0.9.2
+      posthtml-parser: 0.2.1
+      posthtml-render: 1.4.0
+    dev: true
+
+  /posthtml@0.9.2:
+    resolution: {integrity: sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      posthtml-parser: 0.2.1
+      posthtml-render: 1.4.0
+    dev: true
+
+  /prelude-ls@1.2.1:
+    resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+    engines: {node: '>= 0.8.0'}
+    dev: true
+
+  /prettier-linter-helpers@1.0.0:
+    resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
+    engines: {node: '>=6.0.0'}
+    dependencies:
+      fast-diff: 1.3.0
+    dev: true
+
+  /prettier-plugin-jsdoc@1.3.0(prettier@3.3.2):
+    resolution: {integrity: sha512-cQm8xIa0fN9ieJFMXACQd6JPycl+8ouOijAqUqu44EF/s4fXL3Wi9sKXuEaodsEWgCN42Xby/bNhqgM1iWx4uw==}
+    engines: {node: '>=14.13.1 || >=16.0.0'}
+    peerDependencies:
+      prettier: ^3.0.0
+    dependencies:
+      binary-searching: 2.0.5
+      comment-parser: 1.4.1
+      mdast-util-from-markdown: 2.0.1
+      prettier: 3.3.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /prettier-plugin-json-sort@0.0.2(prettier@3.3.2):
+    resolution: {integrity: sha512-xd5VVfneeUBdWhTm5uh0rAto3qnkkosbte6poO5WVTZEAiQdndMQMRPv1SROXx968zfyAlS+Z+C6rkr4jbVOgg==}
+    peerDependencies:
+      prettier: '>=2.0.0'
+    dependencies:
+      prettier: 3.3.2
+    dev: true
+
+  /prettier@3.2.5:
+    resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==}
+    engines: {node: '>=14'}
+    hasBin: true
+    dev: true
+
+  /prettier@3.3.2:
+    resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==}
+    engines: {node: '>=14'}
+    hasBin: true
+    dev: true
+
+  /pretty-ms@9.0.0:
+    resolution: {integrity: sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==}
+    engines: {node: '>=18'}
+    dependencies:
+      parse-ms: 4.0.0
+    dev: true
+
+  /proc-log@3.0.0:
+    resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dev: true
+
+  /progress@2.0.3:
+    resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
+    engines: {node: '>=0.4.0'}
+    dev: true
+
+  /promise-inflight@1.0.1:
+    resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==}
+    peerDependencies:
+      bluebird: '*'
+    peerDependenciesMeta:
+      bluebird:
+        optional: true
+    dev: true
+
+  /promise-retry@2.0.1:
+    resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
+    engines: {node: '>=10'}
+    dependencies:
+      err-code: 2.0.3
+      retry: 0.12.0
+    dev: true
+
+  /prompts-ncu@3.0.0:
+    resolution: {integrity: sha512-qyz9UxZ5MlPKWVhWrCmSZ1ahm2GVYdjLb8og2sg0IPth1KRuhcggHGuijz0e41dkx35p1t1q3GRISGH7QGALFA==}
+    engines: {node: '>= 14'}
+    dependencies:
+      kleur: 4.1.5
+      sisteransi: 1.0.5
+    dev: true
+
+  /prompts@2.4.2:
+    resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
+    engines: {node: '>= 6'}
+    dependencies:
+      kleur: 3.0.3
+      sisteransi: 1.0.5
+    dev: true
+
+  /proto-list@1.2.4:
+    resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
+    dev: true
+
+  /proxy-from-env@1.1.0:
+    resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+    dev: false
+
+  /punycode@2.3.1:
+    resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /pupa@3.1.0:
+    resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==}
+    engines: {node: '>=12.20'}
+    dependencies:
+      escape-goat: 4.0.0
+    dev: true
+
+  /qs@6.12.1:
+    resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==}
+    engines: {node: '>=0.6'}
+    dependencies:
+      side-channel: 1.0.6
+    dev: false
+
+  /query-string@4.3.4:
+    resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      object-assign: 4.1.1
+      strict-uri-encode: 1.1.0
+    dev: true
+
+  /queue-microtask@1.2.3:
+    resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+    dev: true
+
+  /quick-lru@5.1.1:
+    resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /rc-config-loader@4.1.3:
+    resolution: {integrity: sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==}
+    dependencies:
+      debug: 4.3.5
+      js-yaml: 4.1.0
+      json5: 2.2.3
+      require-from-string: 2.0.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /rc9@2.1.2:
+    resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
+    dependencies:
+      defu: 6.1.4
+      destr: 2.0.3
+    dev: true
+
+  /rc@1.2.8:
+    resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
+    hasBin: true
+    dependencies:
+      deep-extend: 0.6.0
+      ini: 1.3.8
+      minimist: 1.2.8
+      strip-json-comments: 2.0.1
+    dev: true
+
+  /rd@2.0.1:
+    resolution: {integrity: sha512-/XdKU4UazUZTXFmI0dpABt8jSXPWcEyaGdk340KdHnsEOdkTctlX23aAK7ChQDn39YGNlAJr1M5uvaKt4QnpNw==}
+    dependencies:
+      '@types/node': 10.17.60
+    dev: true
+
+  /read-package-json-fast@3.0.2:
+    resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      json-parse-even-better-errors: 3.0.2
+      npm-normalize-package-bin: 3.0.1
+    dev: true
+
+  /read-package-json@6.0.4:
+    resolution: {integrity: sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    deprecated: This package is no longer supported. Please use @npmcli/package-json instead.
+    dependencies:
+      glob: 10.4.2
+      json-parse-even-better-errors: 3.0.2
+      normalize-package-data: 5.0.0
+      npm-normalize-package-bin: 3.0.1
+    dev: true
+
+  /read-pkg-up@7.0.1:
+    resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
+    engines: {node: '>=8'}
+    dependencies:
+      find-up: 4.1.0
+      read-pkg: 5.2.0
+      type-fest: 0.8.1
+    dev: true
+
+  /read-pkg@5.2.0:
+    resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==}
+    engines: {node: '>=8'}
+    dependencies:
+      '@types/normalize-package-data': 2.4.4
+      normalize-package-data: 2.5.0
+      parse-json: 5.2.0
+      type-fest: 0.6.0
+    dev: true
+
+  /readable-stream@3.6.2:
+    resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+    engines: {node: '>= 6'}
+    dependencies:
+      inherits: 2.0.4
+      string_decoder: 1.3.0
+      util-deprecate: 1.0.2
+    dev: true
+
+  /readdirp@3.6.0:
+    resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+    engines: {node: '>=8.10.0'}
+    dependencies:
+      picomatch: 2.3.1
+    dev: true
+
+  /recast@0.23.7:
+    resolution: {integrity: sha512-MpQlLZVpqbbxYcqEjwpRWo88sGvjOYoXptySz710RuddNMHx+wPkoNX6YyLZJlXAh5VZr1qmPrTwcTuFMh0Lag==}
+    engines: {node: '>= 4'}
+    dependencies:
+      ast-types: 0.16.1
+      esprima: 4.0.1
+      source-map: 0.6.1
+      tiny-invariant: 1.3.3
+      tslib: 2.6.3
+    dev: true
+
+  /regenerator-runtime@0.14.1:
+    resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+    dev: false
+
+  /regex-not@1.0.2:
+    resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      extend-shallow: 3.0.2
+      safe-regex: 1.1.0
+    dev: true
+
+  /regexp-tree@0.1.27:
+    resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
+    hasBin: true
+    dev: true
+
+  /regexp.prototype.flags@1.5.2:
+    resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      define-properties: 1.2.1
+      es-errors: 1.3.0
+      set-function-name: 2.0.2
+    dev: true
+
+  /registry-auth-token@5.0.2:
+    resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==}
+    engines: {node: '>=14'}
+    dependencies:
+      '@pnpm/npm-conf': 2.2.2
+    dev: true
+
+  /registry-url@6.0.1:
+    resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==}
+    engines: {node: '>=12'}
+    dependencies:
+      rc: 1.2.8
+    dev: true
+
+  /regjsparser@0.10.0:
+    resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==}
+    hasBin: true
+    dependencies:
+      jsesc: 0.5.0
+    dev: true
+
+  /remote-git-tags@3.0.0:
+    resolution: {integrity: sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /repeat-element@1.1.4:
+    resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /repeat-string@1.6.1:
+    resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==}
+    engines: {node: '>=0.10'}
+    dev: true
+
+  /require-directory@2.1.1:
+    resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /require-from-string@2.0.2:
+    resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /resize-observer-polyfill@1.5.1:
+    resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
+    dev: false
+
+  /resolve-alpn@1.2.1:
+    resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
+    dev: true
+
+  /resolve-from@4.0.0:
+    resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+    engines: {node: '>=4'}
+    dev: true
+
+  /resolve-pkg-maps@1.0.0:
+    resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+    dev: true
+
+  /resolve-url@0.2.1:
+    resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==}
+    deprecated: https://github.com/lydell/resolve-url#deprecated
+    dev: true
+
+  /resolve@1.22.8:
+    resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+    hasBin: true
+    dependencies:
+      is-core-module: 2.14.0
+      path-parse: 1.0.7
+      supports-preserve-symlinks-flag: 1.0.0
+    dev: true
+
+  /responselike@3.0.0:
+    resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==}
+    engines: {node: '>=14.16'}
+    dependencies:
+      lowercase-keys: 3.0.0
+    dev: true
+
+  /restore-cursor@4.0.0:
+    resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    dependencies:
+      onetime: 5.1.2
+      signal-exit: 3.0.7
+    dev: true
+
+  /ret@0.1.15:
+    resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==}
+    engines: {node: '>=0.12'}
+    dev: true
+
+  /retry@0.12.0:
+    resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
+    engines: {node: '>= 4'}
+    dev: true
+
+  /reusify@1.0.4:
+    resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+    engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+    dev: true
+
+  /rfdc@1.4.1:
+    resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
+    dev: true
+
+  /rimraf@3.0.2:
+    resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+    deprecated: Rimraf versions prior to v4 are no longer supported
+    hasBin: true
+    dependencies:
+      glob: 7.2.3
+    dev: true
+
+  /rimraf@5.0.7:
+    resolution: {integrity: sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==}
+    engines: {node: '>=14.18'}
+    hasBin: true
+    dependencies:
+      glob: 10.4.2
+    dev: true
+
+  /rollup@4.18.0:
+    resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==}
+    engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+    hasBin: true
+    dependencies:
+      '@types/estree': 1.0.5
+    optionalDependencies:
+      '@rollup/rollup-android-arm-eabi': 4.18.0
+      '@rollup/rollup-android-arm64': 4.18.0
+      '@rollup/rollup-darwin-arm64': 4.18.0
+      '@rollup/rollup-darwin-x64': 4.18.0
+      '@rollup/rollup-linux-arm-gnueabihf': 4.18.0
+      '@rollup/rollup-linux-arm-musleabihf': 4.18.0
+      '@rollup/rollup-linux-arm64-gnu': 4.18.0
+      '@rollup/rollup-linux-arm64-musl': 4.18.0
+      '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0
+      '@rollup/rollup-linux-riscv64-gnu': 4.18.0
+      '@rollup/rollup-linux-s390x-gnu': 4.18.0
+      '@rollup/rollup-linux-x64-gnu': 4.18.0
+      '@rollup/rollup-linux-x64-musl': 4.18.0
+      '@rollup/rollup-win32-arm64-msvc': 4.18.0
+      '@rollup/rollup-win32-ia32-msvc': 4.18.0
+      '@rollup/rollup-win32-x64-msvc': 4.18.0
+      fsevents: 2.3.3
+    dev: true
+
+  /run-applescript@7.0.0:
+    resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /run-parallel@1.2.0:
+    resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+    dependencies:
+      queue-microtask: 1.2.3
+    dev: true
+
+  /safe-array-concat@1.1.2:
+    resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==}
+    engines: {node: '>=0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      get-intrinsic: 1.2.4
+      has-symbols: 1.0.3
+      isarray: 2.0.5
+    dev: true
+
+  /safe-buffer@5.2.1:
+    resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+    dev: true
+
+  /safe-regex-test@1.0.3:
+    resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      es-errors: 1.3.0
+      is-regex: 1.1.4
+    dev: true
+
+  /safe-regex@1.1.0:
+    resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==}
+    dependencies:
+      ret: 0.1.15
+    dev: true
+
+  /safer-buffer@2.1.2:
+    resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /sass@1.77.6:
+    resolution: {integrity: sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==}
+    engines: {node: '>=14.0.0'}
+    hasBin: true
+    dependencies:
+      chokidar: 3.6.0
+      immutable: 4.3.6
+      source-map-js: 1.2.0
+    dev: true
+
+  /scroll-into-view-if-needed@2.2.31:
+    resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
+    dependencies:
+      compute-scroll-into-view: 1.0.20
+    dev: false
+
+  /select@1.1.2:
+    resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==}
+    dev: false
+
+  /semver-diff@4.0.0:
+    resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==}
+    engines: {node: '>=12'}
+    dependencies:
+      semver: 7.6.2
+    dev: true
+
+  /semver-utils@1.1.4:
+    resolution: {integrity: sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==}
+    dev: true
+
+  /semver@5.7.2:
+    resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
+    hasBin: true
+    dev: true
+
+  /semver@6.3.1:
+    resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+    hasBin: true
+    dev: true
+
+  /semver@7.6.2:
+    resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
+    engines: {node: '>=10'}
+    hasBin: true
+    dev: true
+
+  /set-blocking@2.0.0:
+    resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
+    dev: true
+
+  /set-function-length@1.2.2:
+    resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      define-data-property: 1.1.4
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+      get-intrinsic: 1.2.4
+      gopd: 1.0.1
+      has-property-descriptors: 1.0.2
+
+  /set-function-name@2.0.2:
+    resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      define-data-property: 1.1.4
+      es-errors: 1.3.0
+      functions-have-names: 1.2.3
+      has-property-descriptors: 1.0.2
+    dev: true
+
+  /set-value@2.0.1:
+    resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      extend-shallow: 2.0.1
+      is-extendable: 0.1.1
+      is-plain-object: 2.0.4
+      split-string: 3.1.0
+    dev: true
+
+  /shallow-equal@1.2.1:
+    resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==}
+    dev: false
+
+  /shebang-command@2.0.0:
+    resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+    engines: {node: '>=8'}
+    dependencies:
+      shebang-regex: 3.0.0
+    dev: true
+
+  /shebang-regex@3.0.0:
+    resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /side-channel@1.0.6:
+    resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      es-errors: 1.3.0
+      get-intrinsic: 1.2.4
+      object-inspect: 1.13.2
+
+  /signal-exit@3.0.7:
+    resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+    dev: true
+
+  /signal-exit@4.1.0:
+    resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+    engines: {node: '>=14'}
+    dev: true
+
+  /sigstore@1.9.0:
+    resolution: {integrity: sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    hasBin: true
+    dependencies:
+      '@sigstore/bundle': 1.1.0
+      '@sigstore/protobuf-specs': 0.2.1
+      '@sigstore/sign': 1.0.0
+      '@sigstore/tuf': 1.0.3
+      make-fetch-happen: 11.1.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /simple-git-hooks@2.11.1:
+    resolution: {integrity: sha512-tgqwPUMDcNDhuf1Xf6KTUsyeqGdgKMhzaH4PAZZuzguOgTl5uuyeYe/8mWgAr6IBxB5V06uqEf6Dy37gIWDtDg==}
+    hasBin: true
+    requiresBuild: true
+    dev: true
+
+  /simplebar-core@1.2.6:
+    resolution: {integrity: sha512-H5NYU+O+uvqOH5VXw3+lgoc1vTI6jL8LOZJsw4xgRpV7uIPjRpmLPdz0TrouxwKHBhpVLzVIlyKhaRLelIThMw==}
+    dependencies:
+      '@types/lodash-es': 4.17.12
+      lodash: 4.17.21
+      lodash-es: 4.17.21
+    dev: false
+
+  /simplebar-vue@2.3.5(vue@3.4.29):
+    resolution: {integrity: sha512-LCRpDfJ4nNNHoZK2h5HEhu3BXoLQkQOMzzcHngCb2GN7uVu22dwXW+Kel2f3MDhZgPR2abcTMMtRrRjK3ge0Yg==}
+    peerDependencies:
+      vue: '>=2.5.17'
+    dependencies:
+      simplebar-core: 1.2.6
+      vue: 3.4.29(typescript@5.4.5)
+      vue-demi: 0.13.11(vue@3.4.29)
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+    dev: false
+
+  /sirv@2.0.4:
+    resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
+    engines: {node: '>= 10'}
+    dependencies:
+      '@polka/url': 1.0.0-next.25
+      mrmime: 2.0.0
+      totalist: 3.0.1
+    dev: true
+
+  /sisteransi@1.0.5:
+    resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+    dev: true
+
+  /slash@3.0.0:
+    resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /slice-ansi@5.0.0:
+    resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      ansi-styles: 6.2.1
+      is-fullwidth-code-point: 4.0.0
+    dev: true
+
+  /slice-ansi@7.1.0:
+    resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==}
+    engines: {node: '>=18'}
+    dependencies:
+      ansi-styles: 6.2.1
+      is-fullwidth-code-point: 5.0.0
+    dev: true
+
+  /smart-buffer@4.2.0:
+    resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
+    engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
+    dev: true
+
+  /snapdragon-node@2.1.1:
+    resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      define-property: 1.0.0
+      isobject: 3.0.1
+      snapdragon-util: 3.0.1
+    dev: true
+
+  /snapdragon-util@3.0.1:
+    resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      kind-of: 3.2.2
+    dev: true
+
+  /snapdragon@0.8.2:
+    resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      base: 0.11.2
+      debug: 2.6.9
+      define-property: 0.2.5
+      extend-shallow: 2.0.1
+      map-cache: 0.2.2
+      source-map: 0.5.7
+      source-map-resolve: 0.5.3
+      use: 3.1.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /socks-proxy-agent@7.0.0:
+    resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==}
+    engines: {node: '>= 10'}
+    dependencies:
+      agent-base: 6.0.2
+      debug: 4.3.5
+      socks: 2.8.3
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /socks@2.8.3:
+    resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==}
+    engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
+    dependencies:
+      ip-address: 9.0.5
+      smart-buffer: 4.2.0
+    dev: true
+
+  /source-map-js@1.2.0:
+    resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
+    engines: {node: '>=0.10.0'}
+
+  /source-map-resolve@0.5.3:
+    resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==}
+    deprecated: See https://github.com/lydell/source-map-resolve#deprecated
+    dependencies:
+      atob: 2.1.2
+      decode-uri-component: 0.2.2
+      resolve-url: 0.2.1
+      source-map-url: 0.4.1
+      urix: 0.1.0
+    dev: true
+
+  /source-map-support@0.5.21:
+    resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+    dependencies:
+      buffer-from: 1.1.2
+      source-map: 0.6.1
+    dev: true
+
+  /source-map-url@0.4.1:
+    resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==}
+    deprecated: See https://github.com/lydell/source-map-url#deprecated
+    dev: true
+
+  /source-map@0.5.7:
+    resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /source-map@0.6.1:
+    resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /spawn-please@2.0.2:
+    resolution: {integrity: sha512-KM8coezO6ISQ89c1BzyWNtcn2V2kAVtwIXd3cN/V5a0xPYc1F/vydrRc01wsKFEQ/p+V1a4sw4z2yMITIXrgGw==}
+    engines: {node: '>=14'}
+    dependencies:
+      cross-spawn: 7.0.3
+    dev: true
+
+  /spdx-correct@3.2.0:
+    resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
+    dependencies:
+      spdx-expression-parse: 3.0.1
+      spdx-license-ids: 3.0.18
+    dev: true
+
+  /spdx-exceptions@2.5.0:
+    resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==}
+    dev: true
+
+  /spdx-expression-parse@3.0.1:
+    resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
+    dependencies:
+      spdx-exceptions: 2.5.0
+      spdx-license-ids: 3.0.18
+    dev: true
+
+  /spdx-license-ids@3.0.18:
+    resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==}
+    dev: true
+
+  /speakingurl@14.0.1:
+    resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /split-string@3.1.0:
+    resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      extend-shallow: 3.0.2
+    dev: true
+
+  /sprintf-js@1.1.3:
+    resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
+    dev: true
+
+  /ssri@10.0.6:
+    resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      minipass: 7.1.2
+    dev: true
+
+  /ssri@9.0.1:
+    resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    dependencies:
+      minipass: 3.3.6
+    dev: true
+
+  /stable@0.1.8:
+    resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==}
+    deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
+    dev: true
+
+  /static-extend@0.1.2:
+    resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      define-property: 0.2.5
+      object-copy: 0.1.0
+    dev: true
+
+  /strict-uri-encode@1.1.0:
+    resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /string-argv@0.3.2:
+    resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
+    engines: {node: '>=0.6.19'}
+    dev: true
+
+  /string-width@4.2.3:
+    resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+    engines: {node: '>=8'}
+    dependencies:
+      emoji-regex: 8.0.0
+      is-fullwidth-code-point: 3.0.0
+      strip-ansi: 6.0.1
+    dev: true
+
+  /string-width@5.1.2:
+    resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+    engines: {node: '>=12'}
+    dependencies:
+      eastasianwidth: 0.2.0
+      emoji-regex: 9.2.2
+      strip-ansi: 7.1.0
+    dev: true
+
+  /string-width@7.2.0:
+    resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
+    engines: {node: '>=18'}
+    dependencies:
+      emoji-regex: 10.3.0
+      get-east-asian-width: 1.2.0
+      strip-ansi: 7.1.0
+    dev: true
+
+  /string.prototype.trim@1.2.9:
+    resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      define-properties: 1.2.1
+      es-abstract: 1.23.3
+      es-object-atoms: 1.0.0
+    dev: true
+
+  /string.prototype.trimend@1.0.8:
+    resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==}
+    dependencies:
+      call-bind: 1.0.7
+      define-properties: 1.2.1
+      es-object-atoms: 1.0.0
+    dev: true
+
+  /string.prototype.trimstart@1.0.8:
+    resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      define-properties: 1.2.1
+      es-object-atoms: 1.0.0
+    dev: true
+
+  /string_decoder@1.3.0:
+    resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+    dependencies:
+      safe-buffer: 5.2.1
+    dev: true
+
+  /strip-ansi@3.0.1:
+    resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      ansi-regex: 2.1.1
+    dev: true
+
+  /strip-ansi@6.0.1:
+    resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+    engines: {node: '>=8'}
+    dependencies:
+      ansi-regex: 5.0.1
+    dev: true
+
+  /strip-ansi@7.1.0:
+    resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      ansi-regex: 6.0.1
+    dev: true
+
+  /strip-final-newline@2.0.0:
+    resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /strip-final-newline@3.0.0:
+    resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /strip-final-newline@4.0.0:
+    resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /strip-indent@3.0.0:
+    resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+    engines: {node: '>=8'}
+    dependencies:
+      min-indent: 1.0.1
+    dev: true
+
+  /strip-json-comments@2.0.1:
+    resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /strip-json-comments@3.1.1:
+    resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /strip-json-comments@5.0.1:
+    resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==}
+    engines: {node: '>=14.16'}
+    dev: true
+
+  /stylis@4.3.2:
+    resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==}
+    dev: false
+
+  /superjson@2.2.1:
+    resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==}
+    engines: {node: '>=16'}
+    dependencies:
+      copy-anything: 3.0.5
+    dev: true
+
+  /supports-color@2.0.0:
+    resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==}
+    engines: {node: '>=0.8.0'}
+    dev: true
+
+  /supports-color@3.2.3:
+    resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==}
+    engines: {node: '>=0.8.0'}
+    dependencies:
+      has-flag: 1.0.0
+    dev: true
+
+  /supports-color@5.5.0:
+    resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+    engines: {node: '>=4'}
+    dependencies:
+      has-flag: 3.0.0
+    dev: true
+
+  /supports-color@7.2.0:
+    resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+    engines: {node: '>=8'}
+    dependencies:
+      has-flag: 4.0.0
+    dev: true
+
+  /supports-preserve-symlinks-flag@1.0.0:
+    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+    engines: {node: '>= 0.4'}
+    dev: true
+
+  /svg-baker@1.7.0:
+    resolution: {integrity: sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==}
+    dependencies:
+      bluebird: 3.7.2
+      clone: 2.1.2
+      he: 1.2.0
+      image-size: 0.5.5
+      loader-utils: 1.4.2
+      merge-options: 1.0.1
+      micromatch: 3.1.0
+      postcss: 5.2.18
+      postcss-prefix-selector: 1.16.1(postcss@5.2.18)
+      posthtml-rename-id: 1.0.12
+      posthtml-svg-mode: 1.0.3
+      query-string: 4.3.4
+      traverse: 0.6.9
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /svg-tags@1.0.0:
+    resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==}
+    dev: true
+
+  /svgo@2.8.0:
+    resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==}
+    engines: {node: '>=10.13.0'}
+    hasBin: true
+    dependencies:
+      '@trysound/sax': 0.2.0
+      commander: 7.2.0
+      css-select: 4.3.0
+      css-tree: 1.1.3
+      csso: 4.2.0
+      picocolors: 1.0.1
+      stable: 0.1.8
+    dev: true
+
+  /synckit@0.8.8:
+    resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    dependencies:
+      '@pkgr/core': 0.1.1
+      tslib: 2.6.3
+    dev: true
+
+  /synckit@0.9.0:
+    resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    dependencies:
+      '@pkgr/core': 0.1.1
+      tslib: 2.6.3
+    dev: true
+
+  /tailwind-merge@2.3.0:
+    resolution: {integrity: sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==}
+    dependencies:
+      '@babel/runtime': 7.24.7
+    dev: false
+
+  /tapable@2.2.1:
+    resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /tar@6.2.1:
+    resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
+    engines: {node: '>=10'}
+    dependencies:
+      chownr: 2.0.0
+      fs-minipass: 2.1.0
+      minipass: 5.0.0
+      minizlib: 2.1.2
+      mkdirp: 1.0.4
+      yallist: 4.0.0
+    dev: true
+
+  /text-table@0.2.0:
+    resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+    dev: true
+
+  /throttle-debounce@5.0.2:
+    resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==}
+    engines: {node: '>=12.22'}
+    dev: false
+
+  /tiny-emitter@2.1.0:
+    resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==}
+    dev: false
+
+  /tiny-invariant@1.3.3:
+    resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
+    dev: true
+
+  /to-fast-properties@2.0.0:
+    resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+    engines: {node: '>=4'}
+
+  /to-object-path@0.3.0:
+    resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      kind-of: 3.2.2
+    dev: true
+
+  /to-regex-range@2.1.1:
+    resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-number: 3.0.0
+      repeat-string: 1.6.1
+    dev: true
+
+  /to-regex-range@5.0.1:
+    resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+    engines: {node: '>=8.0'}
+    dependencies:
+      is-number: 7.0.0
+    dev: true
+
+  /to-regex@3.0.2:
+    resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      define-property: 2.0.2
+      extend-shallow: 3.0.2
+      regex-not: 1.0.2
+      safe-regex: 1.1.0
+    dev: true
+
+  /totalist@3.0.1:
+    resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /traverse@0.6.9:
+    resolution: {integrity: sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      gopd: 1.0.1
+      typedarray.prototype.slice: 1.0.3
+      which-typed-array: 1.1.15
+    dev: true
+
+  /ts-api-utils@1.3.0(typescript@5.4.5):
+    resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
+    engines: {node: '>=16'}
+    peerDependencies:
+      typescript: '>=4.2.0'
+    dependencies:
+      typescript: 5.4.5
+    dev: true
+
+  /tslib@2.3.0:
+    resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
+    dev: false
+
+  /tslib@2.6.3:
+    resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
+    dev: true
+
+  /tsx@4.15.6:
+    resolution: {integrity: sha512-is0VQQlfNZRHEuSSTKA6m4xw74IU4AizmuB6lAYLRt9XtuyeQnyJYexhNZOPCB59SqC4JzmSzPnHGBXxf3k0hA==}
+    engines: {node: '>=18.0.0'}
+    hasBin: true
+    dependencies:
+      esbuild: 0.21.5
+      get-tsconfig: 4.7.5
+    optionalDependencies:
+      fsevents: 2.3.3
+    dev: true
+
+  /tuf-js@1.1.7:
+    resolution: {integrity: sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      '@tufjs/models': 1.0.4
+      debug: 4.3.5
+      make-fetch-happen: 11.1.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /type-check@0.4.0:
+    resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+    engines: {node: '>= 0.8.0'}
+    dependencies:
+      prelude-ls: 1.2.1
+    dev: true
+
+  /type-detect@4.0.8:
+    resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
+    engines: {node: '>=4'}
+    dev: true
+
+  /type-fest@0.20.2:
+    resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /type-fest@0.6.0:
+    resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /type-fest@0.8.1:
+    resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /type-fest@1.4.0:
+    resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /type-fest@2.19.0:
+    resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
+    engines: {node: '>=12.20'}
+    dev: true
+
+  /typed-array-buffer@1.0.2:
+    resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      es-errors: 1.3.0
+      is-typed-array: 1.1.13
+    dev: true
+
+  /typed-array-byte-length@1.0.1:
+    resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      for-each: 0.3.3
+      gopd: 1.0.1
+      has-proto: 1.0.3
+      is-typed-array: 1.1.13
+    dev: true
+
+  /typed-array-byte-offset@1.0.2:
+    resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      available-typed-arrays: 1.0.7
+      call-bind: 1.0.7
+      for-each: 0.3.3
+      gopd: 1.0.1
+      has-proto: 1.0.3
+      is-typed-array: 1.1.13
+    dev: true
+
+  /typed-array-length@1.0.6:
+    resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      for-each: 0.3.3
+      gopd: 1.0.1
+      has-proto: 1.0.3
+      is-typed-array: 1.1.13
+      possible-typed-array-names: 1.0.0
+    dev: true
+
+  /typed-css-modules@0.9.1:
+    resolution: {integrity: sha512-W2HWKncdKd+bLWsnuWB2EyuQBzZ7KJ9Byr/67KLiiyGegcN52rOveun9JR8yAvuL5IXunRMxt0eORMtAUj5bmA==}
+    engines: {node: '>=18.0.0'}
+    hasBin: true
+    dependencies:
+      camelcase: 6.3.0
+      chalk: 4.1.2
+      chokidar: 3.6.0
+      glob: 10.4.2
+      icss-replace-symbols: 1.1.0
+      is-there: 4.5.1
+      mkdirp: 3.0.1
+      postcss: 8.4.39
+      postcss-modules-extract-imports: 3.1.0(postcss@8.4.39)
+      postcss-modules-local-by-default: 4.0.5(postcss@8.4.39)
+      postcss-modules-scope: 3.2.0(postcss@8.4.39)
+      postcss-modules-values: 4.0.0(postcss@8.4.39)
+      yargs: 17.7.2
+    dev: true
+
+  /typedarray-to-buffer@3.1.5:
+    resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==}
+    dependencies:
+      is-typedarray: 1.0.0
+    dev: true
+
+  /typedarray.prototype.slice@1.0.3:
+    resolution: {integrity: sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.7
+      define-properties: 1.2.1
+      es-abstract: 1.23.3
+      es-errors: 1.3.0
+      typed-array-buffer: 1.0.2
+      typed-array-byte-offset: 1.0.2
+    dev: true
+
+  /typescript@5.4.5:
+    resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
+    engines: {node: '>=14.17'}
+    hasBin: true
+
+  /ufo@1.5.3:
+    resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
+
+  /unbox-primitive@1.0.2:
+    resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
+    dependencies:
+      call-bind: 1.0.7
+      has-bigints: 1.0.2
+      has-symbols: 1.0.3
+      which-boxed-primitive: 1.0.2
+    dev: true
+
+  /unconfig@0.3.13:
+    resolution: {integrity: sha512-N9Ph5NC4+sqtcOjPfHrRcHekBCadCXWTBzp2VYYbySOHW0PfD9XLCeXshTXjkPYwLrBr9AtSeU0CZmkYECJhng==}
+    dependencies:
+      '@antfu/utils': 0.7.10
+      defu: 6.1.4
+      jiti: 1.21.6
+    dev: true
+
+  /undici-types@5.26.5:
+    resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+    dev: true
+
+  /union-value@1.0.1:
+    resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      arr-union: 3.1.0
+      get-value: 2.0.6
+      is-extendable: 0.1.1
+      set-value: 2.0.1
+    dev: true
+
+  /unique-filename@2.0.1:
+    resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    dependencies:
+      unique-slug: 3.0.0
+    dev: true
+
+  /unique-filename@3.0.0:
+    resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      unique-slug: 4.0.0
+    dev: true
+
+  /unique-slug@3.0.0:
+    resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==}
+    engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+    dependencies:
+      imurmurhash: 0.1.4
+    dev: true
+
+  /unique-slug@4.0.0:
+    resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dependencies:
+      imurmurhash: 0.1.4
+    dev: true
+
+  /unique-string@3.0.0:
+    resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      crypto-random-string: 4.0.0
+    dev: true
+
+  /unist-util-stringify-position@4.0.0:
+    resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+    dependencies:
+      '@types/unist': 3.0.2
+    dev: true
+
+  /universalify@2.0.1:
+    resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+    engines: {node: '>= 10.0.0'}
+    dev: true
+
+  /unplugin-icons@0.19.0:
+    resolution: {integrity: sha512-u5g/gIZPZEj1wUGEQxe9nzftOSqmblhusc+sL3cawIRoIt/xWpE6XYcPOfAeFTYNjSbRrX/3QiX89PFiazgU1w==}
+    peerDependencies:
+      '@svgr/core': '>=7.0.0'
+      '@svgx/core': ^1.0.1
+      '@vue/compiler-sfc': ^3.0.2 || ^2.7.0
+      vue-template-compiler: ^2.6.12
+      vue-template-es2015-compiler: ^1.9.0
+    peerDependenciesMeta:
+      '@svgr/core':
+        optional: true
+      '@svgx/core':
+        optional: true
+      '@vue/compiler-sfc':
+        optional: true
+      vue-template-compiler:
+        optional: true
+      vue-template-es2015-compiler:
+        optional: true
+    dependencies:
+      '@antfu/install-pkg': 0.3.3
+      '@antfu/utils': 0.7.10
+      '@iconify/utils': 2.1.25
+      debug: 4.3.5
+      kolorist: 1.8.0
+      local-pkg: 0.5.0
+      unplugin: 1.11.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /unplugin-vue-components@0.27.0(vue@3.4.29):
+    resolution: {integrity: sha512-77eTEy23sQ0UpzGWnZ9I2mY3cnmXwklz4ITcn3JfxjCoX643ghImkiZ4nFm58sxbdVcc4Fo/o4LIoFnlqEqsSg==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@babel/parser': ^7.15.8
+      '@nuxt/kit': ^3.2.2
+      vue: 2 || 3
+    peerDependenciesMeta:
+      '@babel/parser':
+        optional: true
+      '@nuxt/kit':
+        optional: true
+    dependencies:
+      '@antfu/utils': 0.7.10
+      '@rollup/pluginutils': 5.1.0
+      chokidar: 3.6.0
+      debug: 4.3.5
+      fast-glob: 3.3.2
+      local-pkg: 0.5.0
+      magic-string: 0.30.10
+      minimatch: 9.0.5
+      resolve: 1.22.8
+      unplugin: 1.11.0
+      vue: 3.4.29(typescript@5.4.5)
+    transitivePeerDependencies:
+      - rollup
+      - supports-color
+    dev: true
+
+  /unplugin@1.10.1:
+    resolution: {integrity: sha512-d6Mhq8RJeGA8UfKCu54Um4lFA0eSaRa3XxdAJg8tIdxbu1ubW0hBCZUL7yI2uGyYCRndvbK8FLHzqy2XKfeMsg==}
+    engines: {node: '>=14.0.0'}
+    dependencies:
+      acorn: 8.12.1
+      chokidar: 3.6.0
+      webpack-sources: 3.2.3
+      webpack-virtual-modules: 0.6.2
+    dev: true
+
+  /unplugin@1.11.0:
+    resolution: {integrity: sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==}
+    engines: {node: '>=14.0.0'}
+    dependencies:
+      acorn: 8.12.1
+      chokidar: 3.6.0
+      webpack-sources: 3.2.3
+      webpack-virtual-modules: 0.6.2
+    dev: true
+
+  /unset-value@1.0.0:
+    resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      has-value: 0.3.1
+      isobject: 3.0.1
+    dev: true
+
+  /untildify@4.0.0:
+    resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /update-browserslist-db@1.1.0(browserslist@4.23.1):
+    resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==}
+    hasBin: true
+    peerDependencies:
+      browserslist: '>= 4.21.0'
+    dependencies:
+      browserslist: 4.23.1
+      escalade: 3.1.2
+      picocolors: 1.0.1
+    dev: true
+
+  /update-notifier@6.0.2:
+    resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==}
+    engines: {node: '>=14.16'}
+    dependencies:
+      boxen: 7.1.1
+      chalk: 5.3.0
+      configstore: 6.0.0
+      has-yarn: 3.0.0
+      import-lazy: 4.0.0
+      is-ci: 3.0.1
+      is-installed-globally: 0.4.0
+      is-npm: 6.0.0
+      is-yarn-global: 0.4.1
+      latest-version: 7.0.0
+      pupa: 3.1.0
+      semver: 7.6.2
+      semver-diff: 4.0.0
+      xdg-basedir: 5.1.0
+    dev: true
+
+  /uri-js@4.4.1:
+    resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+    dependencies:
+      punycode: 2.3.1
+    dev: true
+
+  /urix@0.1.0:
+    resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==}
+    deprecated: Please see https://github.com/lydell/urix#deprecated
+    dev: true
+
+  /use@3.1.1:
+    resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /util-deprecate@1.0.2:
+    resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+    dev: true
+
+  /validate-npm-package-license@3.0.4:
+    resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
+    dependencies:
+      spdx-correct: 3.2.0
+      spdx-expression-parse: 3.0.1
+    dev: true
+
+  /validate-npm-package-name@5.0.1:
+    resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    dev: true
+
+  /vary@1.1.2:
+    resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+    engines: {node: '>= 0.8'}
+    dev: true
+
+  /vite-hot-client@0.2.3(vite@5.3.1):
+    resolution: {integrity: sha512-rOGAV7rUlUHX89fP2p2v0A2WWvV3QMX2UYq0fRqsWSvFvev4atHWqjwGoKaZT1VTKyLGk533ecu3eyd0o59CAg==}
+    peerDependencies:
+      vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0
+    dependencies:
+      vite: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+    dev: true
+
+  /vite-plugin-inspect@0.8.4(vite@5.3.1):
+    resolution: {integrity: sha512-G0N3rjfw+AiiwnGw50KlObIHYWfulVwaCBUBLh2xTW9G1eM9ocE5olXkEYUbwyTmX+azM8duubi+9w5awdCz+g==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@nuxt/kit': '*'
+      vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0
+    peerDependenciesMeta:
+      '@nuxt/kit':
+        optional: true
+    dependencies:
+      '@antfu/utils': 0.7.10
+      '@rollup/pluginutils': 5.1.0
+      debug: 4.3.5
+      error-stack-parser-es: 0.1.4
+      fs-extra: 11.2.0
+      open: 10.1.0
+      perfect-debounce: 1.0.0
+      picocolors: 1.0.1
+      sirv: 2.0.4
+      vite: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+    transitivePeerDependencies:
+      - rollup
+      - supports-color
+    dev: true
+
+  /vite-plugin-progress@0.0.7(vite@5.3.1):
+    resolution: {integrity: sha512-zyvKdcc/X+6hnw3J1HVV1TKrlFKC4Rh8GnDnWG/2qhRXjqytTcM++xZ+SAPnoDsSyWl8O93ymK0wZRgHAoglEQ==}
+    engines: {node: '>=14', pnpm: '>=7.0.0'}
+    peerDependencies:
+      vite: '>2.0.0-0'
+    dependencies:
+      picocolors: 1.0.1
+      progress: 2.0.3
+      rd: 2.0.1
+      vite: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+    dev: true
+
+  /vite-plugin-svg-icons@2.0.1(vite@5.3.1):
+    resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==}
+    peerDependencies:
+      vite: '>=2.0.0'
+    dependencies:
+      '@types/svgo': 2.6.4
+      cors: 2.8.5
+      debug: 4.3.5
+      etag: 1.8.1
+      fs-extra: 10.1.0
+      pathe: 0.2.0
+      svg-baker: 1.7.0
+      svgo: 2.8.0
+      vite: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /vite-plugin-vue-devtools@7.3.2(vite@5.3.1)(vue@3.4.29):
+    resolution: {integrity: sha512-ysFbLOZrTfdk+jcQzwL3vv1wNaBXxBbY3Ux0eD88adZzdrpQ/AT8ZlepWJCJ6JWsZjjU5yC/7N9s9uXD7+PQiQ==}
+    engines: {node: '>=v14.21.3'}
+    peerDependencies:
+      vite: ^3.1.0 || ^4.0.0-0 || ^5.0.0-0
+    dependencies:
+      '@vue/devtools-core': 7.3.5(vite@5.3.1)(vue@3.4.29)
+      '@vue/devtools-kit': 7.3.5
+      '@vue/devtools-shared': 7.3.5
+      execa: 8.0.1
+      sirv: 2.0.4
+      vite: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+      vite-plugin-inspect: 0.8.4(vite@5.3.1)
+      vite-plugin-vue-inspector: 5.1.2(vite@5.3.1)
+    transitivePeerDependencies:
+      - '@nuxt/kit'
+      - rollup
+      - supports-color
+      - vue
+    dev: true
+
+  /vite-plugin-vue-inspector@5.1.2(vite@5.3.1):
+    resolution: {integrity: sha512-M+yH2LlQtVNzJAljQM+61CqDXBvHim8dU5ImGaQuwlo13tMDHue5D7IC20YwDJuWDODiYc/cZBUYspVlyPf2vQ==}
+    peerDependencies:
+      vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0
+    dependencies:
+      '@babel/core': 7.24.7
+      '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.24.7)
+      '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.24.7)
+      '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.7)
+      '@babel/plugin-transform-typescript': 7.24.7(@babel/core@7.24.7)
+      '@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.24.7)
+      '@vue/compiler-dom': 3.4.31
+      kolorist: 1.8.0
+      magic-string: 0.30.10
+      vite: 5.3.1(@types/node@20.14.6)(sass@1.77.6)
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /vite@5.3.1(@types/node@20.14.6)(sass@1.77.6):
+    resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==}
+    engines: {node: ^18.0.0 || >=20.0.0}
+    hasBin: true
+    peerDependencies:
+      '@types/node': ^18.0.0 || >=20.0.0
+      less: '*'
+      lightningcss: ^1.21.0
+      sass: '*'
+      stylus: '*'
+      sugarss: '*'
+      terser: ^5.4.0
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+      less:
+        optional: true
+      lightningcss:
+        optional: true
+      sass:
+        optional: true
+      stylus:
+        optional: true
+      sugarss:
+        optional: true
+      terser:
+        optional: true
+    dependencies:
+      '@types/node': 20.14.6
+      esbuild: 0.21.5
+      postcss: 8.4.39
+      rollup: 4.18.0
+      sass: 1.77.6
+    optionalDependencies:
+      fsevents: 2.3.3
+    dev: true
+
+  /vscode-uri@3.0.8:
+    resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
+    dev: true
+
+  /vue-demi@0.13.11(vue@3.4.29):
+    resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==}
+    engines: {node: '>=12'}
+    hasBin: true
+    requiresBuild: true
+    peerDependencies:
+      '@vue/composition-api': ^1.0.0-rc.1
+      vue: ^3.0.0-0 || ^2.6.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+    dependencies:
+      vue: 3.4.29(typescript@5.4.5)
+    dev: false
+
+  /vue-demi@0.14.8(vue@3.4.29):
+    resolution: {integrity: sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==}
+    engines: {node: '>=12'}
+    hasBin: true
+    requiresBuild: true
+    peerDependencies:
+      '@vue/composition-api': ^1.0.0-rc.1
+      vue: ^3.0.0-0 || ^2.6.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+    dependencies:
+      vue: 3.4.29(typescript@5.4.5)
+    dev: false
+
+  /vue-draggable-plus@0.5.0(@types/sortablejs@1.15.8):
+    resolution: {integrity: sha512-A5TT5+M5JceROSjPO9aDZTsrSN1TetEs419czPlboomarSiGIBIxTp2WD7XH53EHMrbO7Qo+leRiHWV/rMlyjA==}
+    peerDependencies:
+      '@types/sortablejs': ^1.15.0
+      '@vue/composition-api': '*'
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+    dependencies:
+      '@types/sortablejs': 1.15.8
+    dev: false
+
+  /vue-eslint-parser@9.4.3(eslint@9.5.0):
+    resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==}
+    engines: {node: ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: '>=6.0.0'
+    dependencies:
+      debug: 4.3.5
+      eslint: 9.5.0
+      eslint-scope: 7.2.2
+      eslint-visitor-keys: 3.4.3
+      espree: 9.6.1
+      esquery: 1.5.0
+      lodash: 4.17.21
+      semver: 7.6.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /vue-i18n@9.13.1(vue@3.4.29):
+    resolution: {integrity: sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==}
+    engines: {node: '>= 16'}
+    peerDependencies:
+      vue: ^3.0.0
+    dependencies:
+      '@intlify/core-base': 9.13.1
+      '@intlify/shared': 9.13.1
+      '@vue/devtools-api': 6.6.3
+      vue: 3.4.29(typescript@5.4.5)
+    dev: false
+
+  /vue-router@4.3.3(vue@3.4.29):
+    resolution: {integrity: sha512-8Q+u+WP4N2SXY38FDcF2H1dUEbYVHVPtPCPZj/GTZx8RCbiB8AtJP9+YIxn4Vs0svMTNQcLIzka4GH7Utkx9xQ==}
+    peerDependencies:
+      vue: ^3.2.0
+    dependencies:
+      '@vue/devtools-api': 6.6.3
+      vue: 3.4.29(typescript@5.4.5)
+    dev: false
+
+  /vue-template-compiler@2.7.16:
+    resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==}
+    dependencies:
+      de-indent: 1.0.2
+      he: 1.2.0
+    dev: true
+
+  /vue-tsc@2.0.21(typescript@5.4.5):
+    resolution: {integrity: sha512-E6x1p1HaHES6Doy8pqtm7kQern79zRtIewkf9fiv7Y43Zo4AFDS5hKi+iHi2RwEhqRmuiwliB1LCEFEGwvxQnw==}
+    hasBin: true
+    peerDependencies:
+      typescript: '*'
+    dependencies:
+      '@volar/typescript': 2.3.4
+      '@vue/language-core': 2.0.21(typescript@5.4.5)
+      semver: 7.6.2
+      typescript: 5.4.5
+    dev: true
+
+  /vue-types@3.0.2(vue@3.4.29):
+    resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==}
+    engines: {node: '>=10.15.0'}
+    peerDependencies:
+      vue: ^3.0.0
+    dependencies:
+      is-plain-object: 3.0.1
+      vue: 3.4.29(typescript@5.4.5)
+    dev: false
+
+  /vue@3.4.29(typescript@5.4.5):
+    resolution: {integrity: sha512-8QUYfRcYzNlYuzKPfge1UWC6nF9ym0lx7mpGVPJYNhddxEf3DD0+kU07NTL0sXuiT2HuJuKr/iEO8WvXvT0RSQ==}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@vue/compiler-dom': 3.4.29
+      '@vue/compiler-sfc': 3.4.29
+      '@vue/runtime-dom': 3.4.29
+      '@vue/server-renderer': 3.4.29(vue@3.4.29)
+      '@vue/shared': 3.4.29
+      typescript: 5.4.5
+
+  /warning@4.0.3:
+    resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
+    dependencies:
+      loose-envify: 1.4.0
+    dev: false
+
+  /webpack-sources@3.2.3:
+    resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
+    engines: {node: '>=10.13.0'}
+    dev: true
+
+  /webpack-virtual-modules@0.6.2:
+    resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
+    dev: true
+
+  /which-boxed-primitive@1.0.2:
+    resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
+    dependencies:
+      is-bigint: 1.0.4
+      is-boolean-object: 1.1.2
+      is-number-object: 1.0.7
+      is-string: 1.0.7
+      is-symbol: 1.0.4
+    dev: true
+
+  /which-typed-array@1.1.15:
+    resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      available-typed-arrays: 1.0.7
+      call-bind: 1.0.7
+      for-each: 0.3.3
+      gopd: 1.0.1
+      has-tostringtag: 1.0.2
+    dev: true
+
+  /which@2.0.2:
+    resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+    engines: {node: '>= 8'}
+    hasBin: true
+    dependencies:
+      isexe: 2.0.0
+    dev: true
+
+  /which@3.0.1:
+    resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+    hasBin: true
+    dependencies:
+      isexe: 2.0.0
+    dev: true
+
+  /wide-align@1.1.5:
+    resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
+    dependencies:
+      string-width: 4.2.3
+    dev: true
+
+  /widest-line@4.0.1:
+    resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==}
+    engines: {node: '>=12'}
+    dependencies:
+      string-width: 5.1.2
+    dev: true
+
+  /word-wrap@1.2.5:
+    resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /wrap-ansi@7.0.0:
+    resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+    engines: {node: '>=10'}
+    dependencies:
+      ansi-styles: 4.3.0
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+    dev: true
+
+  /wrap-ansi@8.1.0:
+    resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      ansi-styles: 6.2.1
+      string-width: 5.1.2
+      strip-ansi: 7.1.0
+    dev: true
+
+  /wrap-ansi@9.0.0:
+    resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==}
+    engines: {node: '>=18'}
+    dependencies:
+      ansi-styles: 6.2.1
+      string-width: 7.2.0
+      strip-ansi: 7.1.0
+    dev: true
+
+  /wrappy@1.0.2:
+    resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+    dev: true
+
+  /write-file-atomic@3.0.3:
+    resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==}
+    dependencies:
+      imurmurhash: 0.1.4
+      is-typedarray: 1.0.0
+      signal-exit: 3.0.7
+      typedarray-to-buffer: 3.1.5
+    dev: true
+
+  /xdg-basedir@5.1.0:
+    resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /xml-name-validator@4.0.0:
+    resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /y18n@5.0.8:
+    resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /yallist@3.1.1:
+    resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+    dev: true
+
+  /yallist@4.0.0:
+    resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+    dev: true
+
+  /yaml@2.4.5:
+    resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==}
+    engines: {node: '>= 14'}
+    hasBin: true
+    dev: true
+
+  /yargs-parser@21.1.1:
+    resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /yargs@17.7.2:
+    resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+    engines: {node: '>=12'}
+    dependencies:
+      cliui: 8.0.1
+      escalade: 3.1.2
+      get-caller-file: 2.0.5
+      require-directory: 2.1.1
+      string-width: 4.2.3
+      y18n: 5.0.8
+      yargs-parser: 21.1.1
+    dev: true
+
+  /yocto-queue@0.1.0:
+    resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /yoctocolors@2.1.1:
+    resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==}
+    engines: {node: '>=18'}
+    dev: true
+
+  /zrender@5.5.0:
+    resolution: {integrity: sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==}
+    dependencies:
+      tslib: 2.3.0
+    dev: false

+ 0 - 1
public/favicon.svg

@@ -1 +0,0 @@
-<svg viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg"><path d="M81.28 55.9c-.1-11.67-2.93-22.55-9.37-32.38-1-1.5-2.14-2.86-2.5-4.71a8.1 8.1 0 014-8.61 7.89 7.89 0 019.3 1.23 35.999 35.999 0 015.9 8.83 75.18 75.18 0 018.44 28.58 83.211 83.211 0 01-5.23 36.74 102.983 102.983 0 01-3 7.28 1.2 1.2 0 000 1.41c9.58 13.3 21.76 23 37.85 27.24a54.37 54.37 0 0019.68 1.57 7.72 7.72 0 018.36 6.9 7.903 7.903 0 01-6.7 9 64.744 64.744 0 01-23-1.33 77.68 77.68 0 01-36.93-19.88 93.628 93.628 0 01-11.91-13.71 2.18 2.18 0 00-2.3-1.06 72.744 72.744 0 00-27.38 7.55c-11.6 6-20.67 14.58-26.4 26.45a10.134 10.134 0 01-3.7 4.7 8 8 0 01-9.19-.7 7.86 7.86 0 01-2.36-9.28 60.324 60.324 0 018.72-14.52c12.2-15.43 28.21-24.59 47.32-28.57A85.085 85.085 0 0173.07 87c.524.015 1-.307 1.18-.8a76.06 76.06 0 006.53-22.3c.351-2.652.518-5.325.5-8z" fill="#646cff"/><path d="M136.26 108.34a44.742 44.742 0 01-11.13-2.87 46.108 46.108 0 01-19.66-13.76 8 8 0 015.72-13.22 7.93 7.93 0 016.54 2.93 33.27 33.27 0 0018.87 10.75c1.546.155 3.058.553 4.48 1.18a8.08 8.08 0 013.84 9.21c-.92 3.52-4.13 5.81-8.66 5.78zm-80.6-75.02a7.61 7.61 0 016.64 5 49.139 49.139 0 013.64 17 46.33 46.33 0 01-2.46 17.28c-2 5.77-8.24 7.79-12.89 4.15a8.1 8.1 0 01-2.39-9 31.679 31.679 0 001.68-12.36 35.77 35.77 0 00-2.43-11c-2.1-5.45 1.75-11.07 8.21-11.07zm22.26 93.25a8 8 0 01-6.68 7.86 32.88 32.88 0 00-19.7 12.19 8.13 8.13 0 01-11.21 1.62 8 8 0 01-1.41-11.58A51.043 51.043 0 0154 123.81a45.842 45.842 0 0114-5.1c5.35-1.04 9.91 2.56 9.92 7.86z" fill="#646cff"/></svg>

BIN
public/logo.png


BIN
src/assets/home/app_logo.png


BIN
src/assets/home/home.mp4


+ 2 - 2
src/constants/reg.ts

@@ -7,9 +7,9 @@ export const REG_PHONE =
 /**
  * Password reg
  *
- * 6-18 characters, including letters, numbers, and underscores
+ * 6-18 characters, including letters, numbers, and special characters
  */
-export const REG_PWD = /^[\w@!#&*]{6,18}$/;
+export const REG_PWD = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*()_+])[A-Za-z\d!@#$%^&*()_+]{6,18}$/;
 
 /** Email reg */
 export const REG_EMAIL = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;

+ 31 - 33
src/hooks/common/table.ts

@@ -1,5 +1,3 @@
-import { $t } from '@/locales';
-import { useAppStore } from '@/store/modules/app';
 import { useBoolean, useHookTable } from '@sa/hooks';
 import { useElementSize } from '@vueuse/core';
 import type { TablePaginationConfig } from 'ant-design-vue';
@@ -7,6 +5,8 @@ import type { TableRowSelection } from 'ant-design-vue/es/table/interface';
 import { cloneDeep } from 'lodash-es';
 import type { MaybeRef, Ref } from 'vue';
 import { computed, effectScope, onScopeDispose, reactive, ref, shallowRef, toValue, watch } from 'vue';
+import { useAppStore } from '@/store/modules/app';
+import { $t } from '@/locales';
 
 type TableData = AntDesign.TableData;
 type GetTableData<A extends AntDesign.TableApiFn> = AntDesign.GetTableData<A>;
@@ -34,31 +34,31 @@ export function useTable<A extends AntDesign.TableApiFn>(config: AntDesign.AntDe
     apiParams,
     columns: config.columns,
     transformer: res => {
-      const { list = [], pageSize = 10, total = 0, count = 0, pageIndex =1  } = res.data || {};
-      //此处为处理菜单列表数据格式不统一的问题,详见todoList
-      const data  = res.data
-      let recordsWithIndex = []
-      if(list.length > 0){
-        recordsWithIndex = list.map((item:any, index:any) => {
+      const { list = [], pageSize = 10, total = 0, count = 0, pageIndex = 1 } = res.data || {};
+      // 此处为处理菜单列表数据格式不统一的问题,详见todoList
+      const data = res.data;
+      let recordsWithIndex = [];
+      if (list.length > 0) {
+        recordsWithIndex = list.map((item: any, index: any) => {
           return {
             ...item,
-            index: (pageIndex - 1) * pageSize + index + 1,
-          };
-        });
-      }else{
-        //此处为处理菜单列表数据格式不统一的问题,详见todoList
-        if(Array.isArray(data))
-        recordsWithIndex = data.map((item:any, index:any) => {
-          return {
-            ...item,
-            index: (pageIndex - 1) * pageSize + index + 1,
+            index: (pageIndex - 1) * pageSize + index + 1
           };
         });
+      } else {
+        // 此处为处理菜单列表数据格式不统一的问题,详见todoList
+        if (Array.isArray(data))
+          recordsWithIndex = data.map((item: any, index: any) => {
+            return {
+              ...item,
+              index: (pageIndex - 1) * pageSize + index + 1
+            };
+          });
       }
       return {
         data: recordsWithIndex,
-        pageIndex:  pageIndex,
-        pageSize: pageSize,
+        pageIndex,
+        pageSize,
         total: total || count
       };
     },
@@ -92,9 +92,9 @@ export function useTable<A extends AntDesign.TableApiFn>(config: AntDesign.AntDe
       return filteredColumns;
     },
     onFetched: async transformed => {
-      const {  pageSize, total, pageIndex } = transformed;
+      const { pageSize, total, pageIndex } = transformed;
       updatePagination({
-        pageIndex: pageIndex,
+        pageIndex,
         pageSize,
         total
       });
@@ -104,18 +104,19 @@ export function useTable<A extends AntDesign.TableApiFn>(config: AntDesign.AntDe
 
   const pagination: TablePaginationConfig = reactive({
     pageIndex: 1,
-    current:1,
+    current: 1,
     pageSize: 10,
     showSizeChanger: true,
     pageSizeOptions: ['10', '15', '20', '25', '30'],
     total: 0,
+    showTotal: total => `共 ${total} 条`,
     onChange: async (current: number, size: number) => {
-      pagination.pageIndex = current
-      pagination.pageSize = size
-      pagination.current = current
+      pagination.pageIndex = current;
+      pagination.pageSize = size;
+      pagination.current = current;
       updateSearchParams({
         pageIndex: pagination.pageIndex,
-        pageSize: pagination.pageSize,
+        pageSize: pagination.pageSize
       });
 
       getData();
@@ -142,18 +143,16 @@ export function useTable<A extends AntDesign.TableApiFn>(config: AntDesign.AntDe
    * @param pageNum the page number. default is 1
    */
   async function getDataByPage(pageNum: number = 1, isNeedPageParams: boolean = true) {
-
     updatePagination({
       pageIndex: pageNum || pagination.current
     });
-    if (isNeedPageParams){
+    if (isNeedPageParams) {
       updateSearchParams({
         pageIndex: pagination.current || pageNum,
         pageSize: pagination.pageSize!
       });
     }
 
-
     await getData();
   }
 
@@ -202,9 +201,9 @@ export function useTableOperate<T extends TableData = TableData>(data: Ref<T[]>,
   /** the editing row data */
   const editingData: Ref<T | null> = ref(null);
 
-  function handleEdit(id: T['id'], keyName:string) {
+  function handleEdit(id: T['id'], keyName: string) {
     operateType.value = 'edit';
-    const findItem = data.value.find((item:any) => item[keyName] === id) || null;
+    const findItem = data.value.find((item: any) => item[keyName] === id) || null;
     editingData.value = cloneDeep(findItem);
     openDrawer();
   }
@@ -238,7 +237,6 @@ export function useTableOperate<T extends TableData = TableData>(data: Ref<T[]>,
   async function onDeleted() {
     window.$message?.success($t('common.deleteSuccess'));
 
-
     await getData();
   }
 

+ 1 - 1
src/locales/langs/en-us.ts

@@ -440,7 +440,7 @@ const local: App.I18n.Schema = {
     },
     pwd: {
       required: 'Please enter password',
-      invalid: '6-18 characters, including letters, numbers, and underscores'
+      invalid: '6-18 characters, including letters, numbers, and special characters'
     },
     confirmPwd: {
       required: 'Please enter password again',

+ 2 - 2
src/locales/langs/zh-cn.ts

@@ -1,6 +1,6 @@
 const local: App.I18n.Schema = {
   system: {
-    title: 'Observe 管理系统',
+    title: '可观测平台',
     updateTitle: '系统版本更新通知',
     updateContent: '检测到系统有新版本发布,是否立即刷新页面?',
     updateConfirm: '立即刷新',
@@ -449,7 +449,7 @@ const local: App.I18n.Schema = {
     },
     pwd: {
       required: '请输入密码',
-      invalid: '密码格式不正确,6-18位字符,包含字母、数字、下划线'
+      invalid: '密码格式不正确,6-18位字符,包含字母、数字、特殊字符'
     },
     confirmPwd: {
       required: '请输入确认密码',

+ 6 - 0
src/router/elegant/imports.ts

@@ -21,6 +21,11 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
   "iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"),
   login: () => import("@/views/_builtin/login/index.vue"),
   about: () => import("@/views/about/index.vue"),
+  "admin_sys-dept": () => import("@/views/admin/sys-dept/index.vue"),
+  "admin_sys-menu": () => import("@/views/admin/sys-menu/index.vue"),
+  "admin_sys-role": () => import("@/views/admin/sys-role/index.vue"),
+  "admin_sys-user": () => import("@/views/admin/sys-user/index.vue"),
+  "business-analysis_system-space": () => import("@/views/business-analysis/system-space/index.vue"),
   "function_hide-child_one": () => import("@/views/function/hide-child/one/index.vue"),
   "function_hide-child_three": () => import("@/views/function/hide-child/three/index.vue"),
   "function_hide-child_two": () => import("@/views/function/hide-child/two/index.vue"),
@@ -36,5 +41,6 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
   manage_user: () => import("@/views/manage/user/index.vue"),
   "multi-menu_first_child": () => import("@/views/multi-menu/first_child/index.vue"),
   "multi-menu_second_child_home": () => import("@/views/multi-menu/second_child_home/index.vue"),
+  "new-home": () => import("@/views/new-home/index.vue"),
   "user-center": () => import("@/views/user-center/index.vue"),
 };

+ 77 - 0
src/router/elegant/routes.ts

@@ -50,6 +50,73 @@ export const generatedRoutes: GeneratedRoute[] = [
       order: 10
     }
   },
+  {
+    name: 'admin',
+    path: '/admin',
+    component: 'layout.base',
+    meta: {
+      title: 'admin',
+      i18nKey: 'route.admin'
+    },
+    children: [
+      {
+        name: 'admin_sys-dept',
+        path: '/admin/sys-dept',
+        component: 'view.admin_sys-dept',
+        meta: {
+          title: 'admin_sys-dept',
+          i18nKey: 'route.admin_sys-dept'
+        }
+      },
+      {
+        name: 'admin_sys-menu',
+        path: '/admin/sys-menu',
+        component: 'view.admin_sys-menu',
+        meta: {
+          title: 'admin_sys-menu',
+          i18nKey: 'route.admin_sys-menu'
+        }
+      },
+      {
+        name: 'admin_sys-role',
+        path: '/admin/sys-role',
+        component: 'view.admin_sys-role',
+        meta: {
+          title: 'admin_sys-role',
+          i18nKey: 'route.admin_sys-role'
+        }
+      },
+      {
+        name: 'admin_sys-user',
+        path: '/admin/sys-user',
+        component: 'view.admin_sys-user',
+        meta: {
+          title: 'admin_sys-user',
+          i18nKey: 'route.admin_sys-user'
+        }
+      }
+    ]
+  },
+  {
+    name: 'business-analysis',
+    path: '/business-analysis',
+    component: 'layout.base',
+    meta: {
+      title: 'business-analysis',
+      i18nKey: 'route.business-analysis'
+    },
+    children: [
+      {
+        name: 'business-analysis_system-space',
+        path: '/business-analysis/system-space',
+        component: 'view.business-analysis_system-space',
+        meta: {
+          title: 'business-analysis_system-space',
+          i18nKey: 'route.business-analysis_system-space'
+        }
+      }
+    ]
+  },
   {
     name: 'function',
     path: '/function',
@@ -330,6 +397,16 @@ export const generatedRoutes: GeneratedRoute[] = [
       }
     ]
   },
+  {
+    name: 'new-home',
+    path: '/new-home',
+    component: 'layout.blank$view.new-home',
+    meta: {
+      title: 'new-home',
+      constant: true,
+      i18nKey: 'route.new-home'
+    }
+  },
   {
     name: 'user-center',
     path: '/user-center',

+ 8 - 0
src/router/elegant/transform.ts

@@ -177,6 +177,13 @@ const routeMap: RouteMap = {
   "404": "/404",
   "500": "/500",
   "about": "/about",
+  "admin": "/admin",
+  "admin_sys-dept": "/admin/sys-dept",
+  "admin_sys-menu": "/admin/sys-menu",
+  "admin_sys-role": "/admin/sys-role",
+  "admin_sys-user": "/admin/sys-user",
+  "business-analysis": "/business-analysis",
+  "business-analysis_system-space": "/business-analysis/system-space",
   "function": "/function",
   "function_hide-child": "/function/hide-child",
   "function_hide-child_one": "/function/hide-child/one",
@@ -201,6 +208,7 @@ const routeMap: RouteMap = {
   "multi-menu_second": "/multi-menu/second",
   "multi-menu_second_child": "/multi-menu/second/child",
   "multi-menu_second_child_home": "/multi-menu/second/child/home",
+  "new-home": "/new-home",
   "user-center": "/user-center"
 };
 

+ 7 - 7
src/service/api/auth.ts

@@ -25,16 +25,11 @@ export function fetchLogin(userName: string, password: string) {
  * @param code Code
  * @param uuid uuid
  */
- export function fetchLoginDemo(userName: string, password: string, code: string, uuid: string) {
+export function fetchLoginDemo(data: object) {
   return baseRequest<Api.Auth.LoginToken>({
     url: '/api/v1/login',
     method: 'post',
-    data: {
-      username:userName,
-      password,
-      code,
-      uuid
-    }
+    data
   });
 }
 
@@ -53,6 +48,11 @@ export function fetchGetCode() {
   return baseRequest<Api.Auth.CodeImg>({ url: '/api/v1/captcha' });
 }
 
+/** Get Login Pubkey */
+export function fetchLoginPubkey() {
+  return baseRequest<Api.Auth.Pubkey>({ url: '/api/v1/login/pubkey' });
+}
+
 /**
  * Refresh token
  *

+ 24 - 0
src/service/api/home.ts

@@ -0,0 +1,24 @@
+import { baseRequest, coreRequest } from '../request';
+export function fetchListApps(query?: Api.Home.commonQuery) {
+  return baseRequest({
+    url: '/api/v1/ot-apps',
+    method: 'get',
+    params: query
+  });
+}
+// 首页-业务搜索
+export function searchBizName(query?: Api.Home.bizSearchQuery) {
+  return coreRequest({
+    url: '/v1/biz/search',
+    method: 'get',
+    params: query
+  });
+}
+// 首页- 搜索url
+export function searchServiceUrl(query?: Api.Home.urlSearchQuery) {
+  return baseRequest({
+    url: '/api/v1/url-mapping/match',
+    method: 'get',
+    params: query
+  });
+}

+ 1 - 0
src/service/api/index.ts

@@ -1,3 +1,4 @@
 export * from './auth';
 export * from './route';
 export * from './system-manage';
+export * from './home';

+ 3 - 2
src/service/api/route.ts

@@ -1,4 +1,4 @@
-import { request } from '../request';
+import { baseRequest, request } from '../request';
 
 /** get constant routes */
 export function fetchGetConstantRoutes() {
@@ -7,7 +7,8 @@ export function fetchGetConstantRoutes() {
 
 /** get user routes */
 export function fetchGetUserRoutes() {
-  return request<Api.Route.UserRoute>({ url: '/route/getUserRoutes' });
+  // return request<Api.Route.UserRoute>({ url: '/route/getUserRoutes' });
+  return baseRequest({ url: '/api/v1/menurole' });
 }
 
 /**

+ 46 - 39
src/service/api/system-manage.ts

@@ -17,9 +17,9 @@ export function fetchChangeRoleStatus(data?: Api.SystemManage.ChangeRoleStatusPa
   });
 }
 // 根据角色ID查询菜单权限下拉树结构 /** get menu tree */
-export function fetchGetMenuTree(roleId:number) {
+export function fetchGetMenuTree(roleId: number) {
   return baseRequest({
-    url: '/api/v1/roleMenuTreeselect/' + roleId,
+    url: `/api/v1/roleMenuTreeselect/${roleId}`,
     method: 'get'
   });
 }
@@ -28,7 +28,7 @@ export function fetchGetMenuTree(roleId:number) {
  *
  * these roles are all enabled
  */
-export function fetchGetAllRoles(params:any) {
+export function fetchGetAllRoles(params: any) {
   return baseRequest({
     url: '/api/v1/role',
     method: 'get',
@@ -36,50 +36,50 @@ export function fetchGetAllRoles(params:any) {
   });
 }
 // 根据角色来获取配置的menu 菜单
-export function fetchGetMenuIdsByRole(roleId:number) {
+export function fetchGetMenuIdsByRole(roleId: number) {
   return baseRequest({
-    url: '/api/v1/role/' + roleId,
+    url: `/api/v1/role/${roleId}`,
     method: 'get'
   });
 }
 // 新增角色
-export function fetchAddRole(data:any) {
+export function fetchAddRole(data: any) {
   return baseRequest({
     url: '/api/v1/role',
     method: 'post',
-    data: data
+    data
   });
 }
 // 修改角色
-export function fetchEditRole(data:any, roleId:number) {
+export function fetchEditRole(data: any, roleId: number) {
   return baseRequest({
-    url: '/api/v1/role/' + roleId,
+    url: `/api/v1/role/${roleId}`,
     method: 'put',
-    data: data
+    data
   });
 }
 // 删除角色
-export function fetchDeleteRole(data:any) {
+export function fetchDeleteRole(data: any) {
   return baseRequest({
     url: '/api/v1/role',
     method: 'delete',
-    data: data
+    data
   });
 }
 // 修改角色的权限范围
-export function fetchModifyRolePersion(data:any) {
+export function fetchModifyRolePersion(data: any) {
   return baseRequest({
     url: '/api/v1/roledatascope',
     method: 'put',
-    data: data
+    data
   });
 }
 // 根据角色ID查询部门树结构
-export function fetchDeptTreeByRole(roleId:number) {
+export function fetchDeptTreeByRole(roleId: number) {
   return baseRequest({
-    url: '/api/v1/roleDeptTreeselect/' + roleId,
+    url: `/api/v1/roleDeptTreeselect/${roleId}`,
     method: 'get'
-  })
+  });
 }
 /** get user list */
 export function fetchGetUserList(params?: Api.SystemManage.UserSearchParams) {
@@ -99,41 +99,40 @@ export function fetchGetMenuList(params?: Api.SystemManage.MenuSearchParams) {
   });
 }
 // 添加菜单
-export function fetchAddMenu(data:any) {
+export function fetchAddMenu(data: any) {
   return baseRequest<Api.SystemManage.MenuList>({
     url: '/api/v1/menu',
     method: 'post',
-    data:data
+    data
   });
 }
 // 修改菜单
-export function fetchUpdateMenu(data:any, id:number) {
+export function fetchUpdateMenu(data: any, id: number) {
   return baseRequest({
-    url: '/api/v1/menu/' + id,
+    url: `/api/v1/menu/${id}`,
     method: 'put',
-    data: data
-  })
+    data
+  });
 }
 // 删除菜单
-export function fetchDeleteMenu(data:any) {
+export function fetchDeleteMenu(data: any) {
   return baseRequest({
     url: '/api/v1/menu',
     method: 'delete',
-    data: data
+    data
   });
 }
 
 // 查询菜单详情
-export function fetchGetMenuDetail(menuId:number) {
+export function fetchGetMenuDetail(menuId: number) {
   return baseRequest({
-    url: '/api/v1/menu/' + menuId,
+    url: `/api/v1/menu/${menuId}`,
     method: 'get'
   });
 }
 
-
 // 获取api权限列表
-export function fetchGetSysApiList(data:any) {
+export function fetchGetSysApiList(data: any) {
   return baseRequest({
     url: '/api/v1/sys-api',
     method: 'get',
@@ -149,16 +148,15 @@ export function fetchGetAllPages() {
   });
 }
 
-
 // 根据字典类型查询字典数据信息
-export function getDicts(dictType:string) {
+export function getDicts(dictType: string) {
   return baseRequest({
-    url: '/api/v1/dict-data/option-select?dictType='+ dictType,
-    method: 'get',
+    url: `/api/v1/dict-data/option-select?dictType=${dictType}`,
+    method: 'get'
   });
 }
 // 岗位
-export function fetchGetPostList(params:any) {
+export function fetchGetPostList(params: any) {
   return baseRequest({
     url: '/api/v1/post',
     method: 'get',
@@ -173,15 +171,15 @@ export function fetchGetdeptTreeList() {
   });
 }
 // 新增用户
-export function fetchAddUser(data:any, method: string) {
+export function fetchAddUser(data: any, method: string) {
   return baseRequest({
     url: '/api/v1/sys-user',
-    method: method,
+    method,
     data
   });
 }
 // 删除用户
-export function fetchDelteUser(data:any) {
+export function fetchDelteUser(data: any) {
   return baseRequest({
     url: '/api/v1/sys-user',
     method: 'delete',
@@ -189,7 +187,7 @@ export function fetchDelteUser(data:any) {
   });
 }
 // 重置密码
-export function fetchRestPwsUser(data:any) {
+export function fetchRestPwsUser(data: any) {
   return baseRequest({
     url: '/api/v1/user/pwd/reset',
     method: 'put',
@@ -197,10 +195,19 @@ export function fetchRestPwsUser(data:any) {
   });
 }
 // 用户状态修改
-export function changeUserStatus(data:any) {
+export function changeUserStatus(data: any) {
   return baseRequest({
     url: '/api/v1/user/status',
     method: 'put',
     data
   });
 }
+
+// 获取部门列表
+export function fetchDeptList(params?: Api.SystemManage.UserSearchParams) {
+  return baseRequest<Api.SystemManage.UserList>({
+    url: '/api/v1/dept',
+    method: 'get',
+    params
+  });
+}

+ 178 - 18
src/service/request/index.ts

@@ -1,15 +1,15 @@
+import { BACKEND_ERROR_CODE, createFlatRequest, createRequest } from '@sa/axios';
+import type { AxiosRequestConfig, AxiosResponse } from 'axios';
 import { $t } from '@/locales';
 import { useAuthStore } from '@/store/modules/auth';
 import { getServiceBaseURL } from '@/utils/service';
 import { localStg } from '@/utils/storage';
-import { BACKEND_ERROR_CODE, createFlatRequest, createRequest } from '@sa/axios';
-import type { AxiosRequestConfig, AxiosResponse } from 'axios';
 import { handleRefreshToken, showErrorMsg } from './shared';
 import type { RequestInstanceState } from './type';
 
 const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
-const { baseURL, otherBaseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
 
+const { baseURL, otherBaseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
 export const request = createFlatRequest<App.Service.Response, RequestInstanceState>(
   {
     baseURL,
@@ -18,7 +18,7 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
     }
   },
   {
-    async onRequest(config: { headers: any; }) {
+    async onRequest(config: { headers: any }) {
       const { headers } = config;
 
       // set token
@@ -28,12 +28,12 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
 
       return config;
     },
-    isBackendSuccess(response: { data: { code: any; }; }) {
+    isBackendSuccess(response: { data: { code: any } }) {
       // when the backend response code is "0000"(default), it means the request is success
       // to change this logic by yourself, you can modify the `VITE_SERVICE_SUCCESS_CODE` in `.env` file
       return String(response.data.code) === import.meta.env.VITE_SERVICE_SUCCESS_CODE;
     },
-    async onBackendFail(response: { data: { msg: any; code: string; }; config: AxiosRequestConfig<any>; }, instance) {
+    async onBackendFail(response: { data: { msg: any; code: string }; config: AxiosRequestConfig<any> }, instance) {
       const authStore = useAuthStore();
 
       function handleLogout() {
@@ -95,10 +95,10 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
 
       return null;
     },
-    transformBackendResponse(response: { data: { data: any; }; }) {
+    transformBackendResponse(response: { data: { data: any } }) {
       return response.data.data;
     },
-    onError(error: { message: any; code: any; response: { data: { msg: any; code: string; }; }; }) {
+    onError(error: { message: any; code: any; response: { data: { msg: any; code: string } } }) {
       // when the request is fail, you can show error message
 
       let message = error.message;
@@ -126,13 +126,113 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
     }
   }
 );
-
 export const baseRequest = createRequest<App.Service.DemoResponse>(
   {
     baseURL: otherBaseURL.demo
   },
   {
-    async onRequest(config: { headers: any; }) {
+    async onRequest(config: { headers: any }) {
+      const { headers } = config;
+
+      // set token
+      const token = localStg.get('token');
+      const Authorization = token ? `Bearer ${token}` : null;
+      Object.assign(headers, { Authorization });
+
+      return config;
+    },
+    isBackendSuccess(response: { data: { code: number } }) {
+      // when the backend response code is "200", it means the request is success
+      // you can change this logic by yourself
+      return response.data.code === 200;
+    },
+    async onBackendFail(response: { data: { msg: any; code: string }; config: AxiosRequestConfig<any> }, instance) {
+      const authStore = useAuthStore();
+
+      const responseCode = `${response.data.code}`;
+
+      function handleLogout() {
+        authStore.resetStore();
+      }
+
+      function logoutAndCleanup() {
+        handleLogout();
+        window.removeEventListener('beforeunload', handleLogout);
+
+        request.state.errMsgStack = request.state.errMsgStack.filter((msg: any) => msg !== response.data.msg);
+      }
+
+      // when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
+      const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || [];
+      if (logoutCodes.includes(responseCode)) {
+        handleLogout();
+        return null;
+      }
+
+      // when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
+      const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
+      if (modalLogoutCodes.includes(responseCode) && !request.state.errMsgStack?.includes(response.data.msg)) {
+        request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg];
+
+        // prevent the user from refreshing the page
+        window.addEventListener('beforeunload', handleLogout);
+
+        window.$modal?.error({
+          title: $t('common.error'),
+          content: response.data.msg,
+          okText: $t('common.confirm'),
+          maskClosable: false,
+          onOk() {
+            logoutAndCleanup();
+          },
+          onCancel() {
+            logoutAndCleanup();
+          }
+        });
+
+        return null;
+      }
+
+      // when the backend response code is in `expiredTokenCodes`, it means the token is expired, and refresh token
+      // the api `refreshToken` can not return error code in `expiredTokenCodes`, otherwise it will be a dead loop, should return `logoutCodes` or `modalLogoutCodes`
+      const expiredTokenCodes = import.meta.env.VITE_SERVICE_EXPIRED_TOKEN_CODES?.split(',') || [];
+      if (expiredTokenCodes.includes(responseCode) && !request.state.isRefreshingToken) {
+        request.state.isRefreshingToken = true;
+
+        const refreshConfig = await handleRefreshToken(response.config);
+
+        request.state.isRefreshingToken = false;
+
+        if (refreshConfig) {
+          return instance.request(refreshConfig) as Promise<AxiosResponse>;
+        }
+      }
+
+      return null;
+    },
+    transformBackendResponse(response: { data: any }) {
+      return response.data;
+    },
+    onError(error: { message: any; code: any; response: { data: { message: any } } }) {
+      // when the request is fail, you can show error message
+
+      let message = error.message;
+
+      // show backend error message
+      if (error.code === BACKEND_ERROR_CODE) {
+        message = error.response?.data?.message || message;
+      }
+
+      window.$message?.error(message);
+    }
+  }
+);
+export const coreRequest = createRequest<App.Service.DemoResponse>(
+  {
+    baseURL: otherBaseURL.core
+  },
+  {
+    async onRequest(config: { headers: any }) {
       const { headers } = config;
 
       // set token
@@ -142,20 +242,80 @@ export const baseRequest = createRequest<App.Service.DemoResponse>(
 
       return config;
     },
-    isBackendSuccess(response: { data: { code: number; }}) {
+    isBackendSuccess(response: { data: { code: number } }) {
       // when the backend response code is "200", it means the request is success
       // you can change this logic by yourself
-      return response.data.code === 200
+      return response.data.code === 200;
     },
-    async onBackendFail(_response: any) {
-      // when the backend response code is not "200", it means the request is fail
-      // for example: the token is expired, refresh token and retry request
-      console.log('onBackendFail')
+    async onBackendFail(response: { data: { msg: any; code: string }; config: AxiosRequestConfig<any> }, instance) {
+      const authStore = useAuthStore();
+
+      console.log('onBackendFail', response.data.code);
+      const responseCode = `${response.data.code}`;
+
+      function handleLogout() {
+        authStore.resetStore();
+      }
+
+      function logoutAndCleanup() {
+        handleLogout();
+        window.removeEventListener('beforeunload', handleLogout);
+
+        request.state.errMsgStack = request.state.errMsgStack.filter((msg: any) => msg !== response.data.msg);
+      }
+
+      // when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
+      const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || [];
+      if (logoutCodes.includes(responseCode)) {
+        handleLogout();
+        return null;
+      }
+
+      // when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
+      const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
+      if (modalLogoutCodes.includes(responseCode) && !request.state.errMsgStack?.includes(response.data.msg)) {
+        request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg];
+
+        // prevent the user from refreshing the page
+        window.addEventListener('beforeunload', handleLogout);
+
+        window.$modal?.error({
+          title: $t('common.error'),
+          content: response.data.msg,
+          okText: $t('common.confirm'),
+          maskClosable: false,
+          onOk() {
+            logoutAndCleanup();
+          },
+          onCancel() {
+            logoutAndCleanup();
+          }
+        });
+
+        return null;
+      }
+
+      // when the backend response code is in `expiredTokenCodes`, it means the token is expired, and refresh token
+      // the api `refreshToken` can not return error code in `expiredTokenCodes`, otherwise it will be a dead loop, should return `logoutCodes` or `modalLogoutCodes`
+      const expiredTokenCodes = import.meta.env.VITE_SERVICE_EXPIRED_TOKEN_CODES?.split(',') || [];
+      if (expiredTokenCodes.includes(responseCode) && !request.state.isRefreshingToken) {
+        request.state.isRefreshingToken = true;
+
+        const refreshConfig = await handleRefreshToken(response.config);
+
+        request.state.isRefreshingToken = false;
+
+        if (refreshConfig) {
+          return instance.request(refreshConfig) as Promise<AxiosResponse>;
+        }
+      }
+
+      return null;
     },
-    transformBackendResponse(response: { data: any; }) {
+    transformBackendResponse(response: { data: any }) {
       return response.data;
     },
-    onError(error: { message: any; code: any; response: { data: { message: any; }; }; }) {
+    onError(error: { message: any; code: any; response: { data: { message: any } } }) {
       // when the request is fail, you can show error message
 
       let message = error.message;

+ 15 - 15
src/store/modules/auth/index.ts

@@ -1,12 +1,13 @@
+import { useLoading } from '@sa/hooks';
+import { defineStore } from 'pinia';
+import { computed, reactive, ref } from 'vue';
+import { useRoute } from 'vue-router';
 import { SetupStoreId } from '@/enum';
 import { useRouterPush } from '@/hooks/common/router';
 import { $t } from '@/locales';
 import { fetchGetUserInfoDemo, fetchLoginDemo } from '@/service/api';
+// import { fetchLogin, fetchGetUserInfo } from '@/service/api';
 import { localStg } from '@/utils/storage';
-import { useLoading } from '@sa/hooks';
-import { defineStore } from 'pinia';
-import { computed, reactive, ref } from 'vue';
-import { useRoute } from 'vue-router';
 import { useRouteStore } from '../route';
 import { useTabStore } from '../tab';
 import { clearAuthStorage, getToken } from './shared';
@@ -62,14 +63,14 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
    * @param uuid uuid
    * @param [redirect=true] Whether to redirect after login. Default is `true`
    */
-  async function login(userName: string, password: string,code: string, uuid: string, redirect = true) {
+  async function login(params: object, redirect = true) {
     startLoading();
-    //待完善 此处和目前业务逻辑不同,关于refreshToken需后续处理
-    const { token, currentAuthority: refreshToken, error } = await fetchLoginDemo(userName, password, code, uuid);
-    console.log('error-----', error)
-    const loginToken = { token, refreshToken }
+    // 待完善 此处和目前业务逻辑不同,关于refreshToken需后续处理
+    const { token: currentToken, currentAuthority: refreshToken, error } = await fetchLoginDemo(params);
+    // const { data: loginToken, error } = await fetchLogin('Soybean', '123456');
     if (!error) {
-      const pass = await loginByToken(loginToken);
+      const pass = await loginByToken({ token: currentToken, refreshToken, data: null, code: 200 });
+      // const pass = await loginByToken(loginToken);
 
       if (pass) {
         await routeStore.initAuthRoute();
@@ -93,7 +94,6 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
   }
 
   async function loginByToken(loginToken: Api.Auth.LoginToken) {
-
     // 1. stored in the localStorage, the later requests need it in headers
     localStg.set('token', loginToken.token);
     localStg.set('refreshToken', loginToken.refreshToken);
@@ -112,13 +112,13 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
 
   async function getUserInfo() {
     const { data: info, error } = await fetchGetUserInfoDemo();
+    // const { data: info, error } = await fetchGetUserInfo();
 
     if (!error) {
-
       // update store
-      //此处为权限测试方式
-      const testInfo = {roles:['R_SUPER']}
-      Object.assign(userInfo, info, testInfo);
+      // 此处为权限测试方式
+      // const testInfo = { roles: ['R_SUPER'] };
+      Object.assign(userInfo, info);
 
       return true;
     }

+ 63 - 0
src/store/modules/route/custom.ts

@@ -0,0 +1,63 @@
+import type { ElegantConstRoute, LastLevelRouteKey } from '@elegant-router/types';
+
+interface DataItem {
+  name: string;
+  path: string;
+  component: string;
+  title: string;
+  icon: string;
+  sort: number;
+  children?: DataItem[];
+  visible: string;
+}
+
+function replacePath(val: string) {
+  return val.slice(1).replace('/index', '').replace('/', '_');
+}
+function getTransComponent(item: DataItem, level: number): string {
+  const { component: name, children } = item;
+  let isChildren = true;
+  if (!children || children?.length === 0) {
+    isChildren = false;
+  }
+  if (level === 0 && !isChildren) {
+    return `layout.base$view.${replacePath(name)}`;
+  } else if (name === 'Layout') {
+    return 'layout.base';
+  }
+  const newVal = replacePath(name);
+  return `view.${newVal}`;
+}
+function getTransComponentName(val: string) {
+  const newVal = replacePath(val);
+  return newVal;
+}
+
+function transData(menus: DataItem[], level: number = 0): ElegantConstRoute[] {
+  return menus.map(item => {
+    const obj: ElegantConstRoute = {
+      name: getTransComponentName(item.path),
+      path: item.path,
+      component: getTransComponent(item, level),
+      meta: {
+        title: item.title,
+        order: item.sort,
+        localIcon: item.icon,
+        _level: level,
+        hideInMenu: item.visible === '1'
+      },
+      children: []
+    };
+    if (Array.isArray(item.children)) {
+      obj.children = transData(item.children, level + 1);
+    }
+    return obj;
+  });
+}
+
+export function transformToTargetData(data: DataItem[]): {
+  routes: ElegantConstRoute[];
+  home: LastLevelRouteKey;
+} {
+  return { routes: transData(data), home: 'new-home' };
+}

+ 2 - 3
src/store/modules/route/index.ts

@@ -23,6 +23,7 @@ import {
   transformMenuToSearchMenus,
   updateLocaleOfGlobalMenus
 } from './shared';
+import { transformToTargetData } from './custom';
 
 export const useRouteStore = defineStore(SetupStoreId.Route, () => {
   const appStore = useAppStore();
@@ -249,7 +250,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
     const { data, error } = await fetchGetUserRoutes();
 
     if (!error) {
-      const { routes, home } = data;
+      const { routes, home } = transformToTargetData(data);
 
       addAuthRoutes(routes);
 
@@ -339,9 +340,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
       const { authRoutes: staticAuthRoutes } = createStaticRoutes();
       return isRouteExistByRouteName(routeName, staticAuthRoutes);
     }
-
     const { data } = await fetchIsRouteExist(routeName);
-
     return data;
   }
 

+ 58 - 32
src/typings/api.d.ts

@@ -58,8 +58,8 @@ declare namespace Api {
     interface LoginToken {
       token: string;
       refreshToken: string;
-      data:any;
-      code:number;
+      data: any;
+      code: number;
     }
 
     interface UserInfo {
@@ -71,10 +71,17 @@ declare namespace Api {
 
     // 验证码
     interface CodeImg {
-      code: Number,
-      data: string,
-      id: string,
-      msg: string
+      code: Number;
+      data: string;
+      id: string;
+      msg: string;
+    }
+
+    // 公钥
+    interface Pubkey {
+      code: Number;
+      data: string;
+      msg: string;
     }
   }
 
@@ -113,15 +120,16 @@ declare namespace Api {
       /** role description */
       status: string;
       roleSort: number | string;
-      remark: string
-      menuIds: number[]
-      roleId: number
-      dataScope: string
+      remark: string;
+      menuIds: number[];
+      roleId: number;
+      dataScope: string;
     }>;
 
     /** role search params */
     type RoleSearchParams = Partial<
-      Pick<Api.SystemManage.Role, 'roleName' | 'roleKey' | 'status' | 'roleSort' | 'remark' | 'menuIds' > & CommonSearchParams
+      Pick<Api.SystemManage.Role, 'roleName' | 'roleKey' | 'status' | 'roleSort' | 'remark' | 'menuIds'> &
+        CommonSearchParams
     >;
     type ChangeRoleStatusParams = {
       roleId: number | string;
@@ -131,7 +139,7 @@ declare namespace Api {
     type RoleList = Common.PaginatingQueryRecord<Role>;
 
     /** all role */
-    type AllRole = Pick<Role, 'id' | 'roleName' | 'roleId' | 'roleKey' | 'status' | 'admin' | 'roleSort' >;
+    type AllRole = Pick<Role, 'id' | 'roleName' | 'roleId' | 'roleKey' | 'status' | 'admin' | 'roleSort'>;
 
     /**
      * user gender
@@ -145,9 +153,9 @@ declare namespace Api {
     type User = Common.CommonRecord<{
       /** user name */
       username: string;
-      userId: number,
+      userId: number;
       // 'deptName': string,
-      deptId:number,
+      deptId: number;
       /** user nick name */
       nickName: string;
       /** user phone */
@@ -160,29 +168,39 @@ declare namespace Api {
       email: string;
       sex: string;
       status: string;
-      password: string
+      password: string;
     }>;
 
     /** user search params */
     type UserSearchParams = Partial<
-      Pick<Api.SystemManage.User, 'username' | 'userId' | 'nickName' | 'phone'  | 'status' | 'deptId'| 'postId'| 'remark' | 'email' | 'sex' | 'password'> &
+      Pick<
+        Api.SystemManage.User,
+        | 'username'
+        | 'userId'
+        | 'nickName'
+        | 'phone'
+        | 'status'
+        | 'deptId'
+        | 'postId'
+        | 'remark'
+        | 'email'
+        | 'sex'
+        | 'password'
+      > &
         CommonSearchParams
     >;
 
     /** user list */
     type UserList = Common.PaginatingQueryRecord<User>;
 
-
     /**
      * menu type
      *
      * - "M": 目录
-     * - "C": 菜单
-     * F:按钮
+     * - "C": 菜单 F:按钮
      */
     type MenuType = 'C' | 'M' | 'F';
 
-
     type MenuButton = {
       /**
        * button code
@@ -204,20 +222,14 @@ declare namespace Api {
 
     type MenuPropsOfRoute = Pick<
       import('vue-router').RouteMeta,
-      | 'i18nKey'
-      | 'keepAlive'
-      | 'order'
-      | 'isFrame'
-      | 'multiTab'
-      | 'fixedIndexInTab'
-      | 'query'
+      'i18nKey' | 'keepAlive' | 'order' | 'isFrame' | 'multiTab' | 'fixedIndexInTab' | 'query'
     >;
 
     type Menu = Common.CommonRecord<{
       /** parent menu id */
       parentId: number;
-      title:string;
-      sort:number;
+      title: string;
+      sort: number;
       visible: string;
       permission: string;
       /** menu type */
@@ -235,15 +247,15 @@ declare namespace Api {
       buttons?: MenuButton[] | null;
       /** children menu */
       children?: Menu[];
-      apis:[];
-      menuId?:number;
+      apis: [];
+      menuId?: number;
     }> &
       MenuPropsOfRoute;
 
     /** menu list */
     type MenuList = Common.PaginatingQueryRecord<Menu>;
     /** menu search params */
-    type MenuSearchParams = Partial< Pick<Api.SystemManage.Menu, 'title' | 'visible'> >;
+    type MenuSearchParams = Partial<Pick<Api.SystemManage.Menu, 'title' | 'visible'>>;
     type MenuTree = {
       id: number;
       label: string;
@@ -251,4 +263,18 @@ declare namespace Api {
       children?: MenuTree[];
     };
   }
+  namespace Home {
+    interface commonQuery {
+      pageIndex: number;
+      pageSize: number;
+    }
+    interface bizSearchQuery {
+      name: string;
+      pageIndex: number;
+      pageSize: number;
+    }
+    interface urlSearchQuery extends Omit<bizSearchQuery, 'name'> {
+      url: string;
+    }
+  }
 }

+ 1 - 1
src/typings/app.d.ts

@@ -652,7 +652,7 @@ declare namespace App {
   /** Service namespace */
   namespace Service {
     /** Other baseURL key */
-    type OtherBaseURLKey = 'demo';
+    type OtherBaseURLKey = 'demo' | 'core';
 
     interface ServiceConfigItem {
       /** The backend service base url */

+ 8 - 0
src/typings/components.d.ts

@@ -7,6 +7,7 @@ export {}
 /* prettier-ignore */
 declare module 'vue' {
   export interface GlobalComponents {
+    AAutoComplete: typeof import('ant-design-vue/es')['AutoComplete']
     ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb']
     ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem']
     AButton: typeof import('ant-design-vue/es')['Button']
@@ -50,6 +51,7 @@ declare module 'vue' {
     ATransfer: typeof import('ant-design-vue/es')['Transfer']
     ATree: typeof import('ant-design-vue/es')['Tree']
     ATreeSelect: typeof import('ant-design-vue/es')['TreeSelect']
+    AUpload: typeof import('ant-design-vue/es')['Upload']
     BetterScroll: typeof import('./../components/custom/better-scroll.vue')['default']
     ButtonIcon: typeof import('./../components/custom/button-icon.vue')['default']
     CountTo: typeof import('./../components/custom/count-to.vue')['default']
@@ -67,9 +69,15 @@ declare module 'vue' {
     IconIcRoundRefresh: typeof import('~icons/ic/round-refresh')['default']
     IconIcRoundRemove: typeof import('~icons/ic/round-remove')['default']
     IconIcRoundSearch: typeof import('~icons/ic/round-search')['default']
+    IconLocal404: typeof import('~icons/local/404')['default']
+    IconLocalActivity: typeof import('~icons/local/activity')['default']
+    IconLocalApiTest: typeof import('~icons/local/api-test')['default']
     IconLocalBanner: typeof import('~icons/local/banner')['default']
     IconLocalLogo: typeof import('~icons/local/logo')['default']
+    'IconMaterialSymbolsLight:10k': typeof import('~icons/material-symbols-light/10k')['default']
+    'IconMaterialSymbolsLight:123': typeof import('~icons/material-symbols-light/123')['default']
     IconMdiDrag: typeof import('~icons/mdi/drag')['default']
+    IconMdiEmoticon: typeof import('~icons/mdi/emoticon')['default']
     IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
     LangSwitch: typeof import('./../components/common/lang-switch.vue')['default']
     LookForward: typeof import('./../components/custom/look-forward.vue')['default']

+ 17 - 0
src/typings/elegant-router.d.ts

@@ -33,6 +33,13 @@ declare module "@elegant-router/types" {
     "404": "/404";
     "500": "/500";
     "about": "/about";
+    "admin": "/admin";
+    "admin_sys-dept": "/admin/sys-dept";
+    "admin_sys-menu": "/admin/sys-menu";
+    "admin_sys-role": "/admin/sys-role";
+    "admin_sys-user": "/admin/sys-user";
+    "business-analysis": "/business-analysis";
+    "business-analysis_system-space": "/business-analysis/system-space";
     "function": "/function";
     "function_hide-child": "/function/hide-child";
     "function_hide-child_one": "/function/hide-child/one";
@@ -57,6 +64,7 @@ declare module "@elegant-router/types" {
     "multi-menu_second": "/multi-menu/second";
     "multi-menu_second_child": "/multi-menu/second/child";
     "multi-menu_second_child_home": "/multi-menu/second/child/home";
+    "new-home": "/new-home";
     "user-center": "/user-center";
   };
 
@@ -105,12 +113,15 @@ declare module "@elegant-router/types" {
     | "404"
     | "500"
     | "about"
+    | "admin"
+    | "business-analysis"
     | "function"
     | "home"
     | "iframe-page"
     | "login"
     | "manage"
     | "multi-menu"
+    | "new-home"
     | "user-center"
   >;
 
@@ -136,6 +147,11 @@ declare module "@elegant-router/types" {
     | "iframe-page"
     | "login"
     | "about"
+    | "admin_sys-dept"
+    | "admin_sys-menu"
+    | "admin_sys-role"
+    | "admin_sys-user"
+    | "business-analysis_system-space"
     | "function_hide-child_one"
     | "function_hide-child_three"
     | "function_hide-child_two"
@@ -151,6 +167,7 @@ declare module "@elegant-router/types" {
     | "manage_user"
     | "multi-menu_first_child"
     | "multi-menu_second_child_home"
+    | "new-home"
     | "user-center"
   >;
 

+ 24 - 1
src/typings/storage.d.ts

@@ -8,7 +8,22 @@ declare namespace StorageType {
     //  */
     // themeSettings: App.Theme.ThemeSetting;
   }
-
+  interface appsItem {
+    alias: string;
+    id: number;
+    contractInfo?: string;
+    contractPhone?: string;
+    createBy?: number | string;
+    createdAt?: string;
+    desc?: string;
+    end_time?: number;
+    imgUrl?: string;
+    live?: boolean;
+    name?: string;
+    start_time?: number;
+    updateBy?: number;
+    updatedAt?: string;
+  }
   interface Local {
     /** The i18n language */
     lang: App.I18n.LangType;
@@ -35,5 +50,13 @@ declare namespace StorageType {
       layout: UnionKey.ThemeLayoutMode;
       siderCollapse: boolean;
     };
+    appsItem: appsItem;
+    row: {
+      method?: string;
+      service_name?: string;
+      kind?: string;
+      name?: string;
+      route?: string;
+    };
   }
 }

+ 52 - 28
src/views/_builtin/login/modules/pwd-login.vue

@@ -1,11 +1,12 @@
 <script setup lang="ts">
+import { computed, onMounted, reactive, ref } from 'vue';
+import JSEncrypt from 'jsencrypt';
 import { loginModuleRecord } from '@/constants/app';
 import { useAntdForm, useFormRules } from '@/hooks/common/form';
 import { useRouterPush } from '@/hooks/common/router';
 import { $t } from '@/locales';
-import { fetchGetCode } from '@/service/api';
+import { fetchGetCode, fetchLoginPubkey } from '@/service/api';
 import { useAuthStore } from '@/store/modules/auth';
-import { computed, onMounted, reactive, ref } from 'vue';
 
 defineOptions({
   name: 'PwdLogin'
@@ -18,10 +19,10 @@ const { formRef, validate } = useAntdForm();
 interface FormModel {
   userName: string;
   password: string;
-  code: string
+  code: string;
 }
-let codeUrl = ref<string>('')
-let uuid = ref<string>('')
+const codeUrl = ref<string>('');
+const uuid = ref<string>('');
 
 const model: FormModel = reactive({
   userName: '',
@@ -41,52 +42,75 @@ const rules = computed<Record<keyof FormModel, App.Global.FormRule[]>>(() => {
 });
 
 onMounted(() => {
-  handleGetCode()
+  handleGetCode();
 });
-//获取动态码
-async function handleGetCode(){
-  const { data: codeSrc, id, msg: msg } = await fetchGetCode();
-  if(msg == 'success'){
-    codeUrl.value = codeSrc //code url
-    uuid.value = id // uuid
+// 获取动态码
+async function handleGetCode() {
+  const { data: codeSrc, id, msg } = await fetchGetCode();
+  if (msg === 'success') {
+    codeUrl.value = codeSrc; // code url
+    uuid.value = id; // uuid
   }
 }
+
+// 公钥
+let pubkey: string = '';
+// 获取公钥
+fetchLoginPubkey().then(({ data }) => {
+  pubkey = data;
+});
+// RSA加密
+function encryptRSA(publicKey: string, str: string): string {
+  const encryPt = new JSEncrypt();
+  encryPt.setPublicKey(publicKey);
+  const result = encryPt.encrypt(str);
+  return result || '';
+}
+
 async function handleSubmit() {
   await validate();
-  await authStore.login(model.userName, model.password, model.code, uuid.value);
+  await authStore.login({
+    username: model.userName,
+    password: encryptRSA(pubkey, model.password),
+    code: model.code,
+    uuid: uuid.value
+  });
 }
 </script>
 
 <template>
   <AForm ref="formRef" :model="model" :rules="rules">
     <AFormItem name="userName">
-      <AInput v-model:value="model.userName" size="large" :placeholder="$t('page.login.common.userNamePlaceholder')" />
+      <AInput
+        v-model:value="model.userName"
+        size="large"
+        :placeholder="$t('page.login.common.userNamePlaceholder')"
+        allow-clear
+      />
     </AFormItem>
     <AFormItem name="password">
       <AInputPassword
         v-model:value="model.password"
         size="large"
         :placeholder="$t('page.login.common.passwordPlaceholder')"
+        allow-clear
       />
     </AFormItem>
-    <ARow :gutter="[16,16]" wrap>
+    <ARow :gutter="[16, 16]" wrap>
       <ACol :lg="16" :xs="16">
         <AFormItem name="code">
-        <AInput
-        v-model:value="model.code"
-        size="large"
-        :placeholder="$t('page.login.common.codePlaceholder')"
-      />
-    </AFormItem>
+          <AInput
+            v-model:value="model.code"
+            size="large"
+            :placeholder="$t('page.login.common.codePlaceholder')"
+            allow-clear
+          />
+        </AFormItem>
       </ACol>
 
-    <ACol :lg="8" :xs="8">
-      <img
-      :src="codeUrl"
-      @click="handleGetCode"
-    />
-    </ACol>
-
+      <ACol :lg="8" :xs="8">
+        <img :src="codeUrl" @click="handleGetCode" />
+      </ACol>
     </ARow>
     <ASpace direction="vertical" size="large" class="w-full">
       <div class="flex-y-center justify-between">

+ 162 - 0
src/views/admin/sys-dept/index.vue

@@ -0,0 +1,162 @@
+<script setup lang="tsx">
+import { useTable, useTableOperate, useTableScroll } from '@/hooks/common/table';
+import { $t } from '@/locales';
+import { fetchDelteUser, fetchDeptList } from '@/service/api';
+import { Button, Popconfirm } from 'ant-design-vue';
+import dayjs from 'dayjs';
+import { ref } from 'vue';
+import UserOperateDrawer from './modules/user-operate-drawer.vue';
+import UserResetPwdDialog from './modules/user-resetpwd-dialog.vue';
+import MSearch from './modules/m-search.vue';
+const { tableWrapperRef, scrollConfig } = useTableScroll();
+const apiParams = ref({
+  pageIndex: 1,
+  pageSize: 10
+});
+let transUserId: number | null = null
+let userName = ''
+let resetDialogVisible = ref(false)
+
+const {
+  columns,
+  columnChecks,
+  data,
+  getData,
+  getDataByPage,
+  loading,
+  mobilePagination,
+  searchParams,
+  resetSearchParams
+} = useTable({
+  apiFn: fetchDeptList,
+  apiParams: apiParams.value,
+  showTotal: true,
+  columns: () => [
+    {
+      key: 'deptName',
+      title: '部门名称',
+      dataIndex: 'deptName',
+      align: 'center',
+      minWidth: 100
+    },
+    {
+      key: 'sort',
+      dataIndex: 'sort',
+      title: '排序',
+      align: 'center',
+      minWidth: 120
+    },
+    {
+      key: 'status',
+      dataIndex: 'status',
+      title: '状态',
+      align: 'center',
+      minWidth: 100,
+      customRender: ({ record }) => {
+        let statusMap = {
+          1: '停用',
+          2: '启用',
+        }
+        let typeMap = {
+          1: 'error',
+          2: 'success',
+        }
+        return <a-tag color={typeMap[record.status]}>{statusMap[record.status]}</a-tag>
+      }
+    },
+    {
+      key: 'createdAt',
+      dataIndex: 'createdAt',
+      title: '创建时间',
+      align: 'center',
+      minWidth: 150,
+      customRender: ({ record }) => {
+        return dayjs(record.createdAt).format('YYYY-MM-DD HH:mm:ss')
+      }
+    },
+    {
+      key: 'operate',
+      title: $t('common.operate'),
+      align: 'center',
+      fixed: 'right',
+      width: 180,
+      customRender: ({ record }) => (
+        <div class="flex-center gap-0.1rem">
+          <Button type="primary" ghost size="small" onClick={() => handleRowEdit(record.userId)} style="margin-right:5px">
+            {$t('common.edit')}
+          </Button>
+          <Popconfirm title={$t('common.confirmDelete')} onConfirm={() => handleDelete(record.userId)}>
+            <Button danger size="small" style="margin-right:5px">
+              {$t('common.delete')}
+            </Button>
+          </Popconfirm>
+          <Button size="small" onClick={() => handleResetPwd(record)}>
+            重置
+          </Button>
+        </div>
+      )
+    }
+  ]
+});
+const {
+  drawerVisible,
+  operateType,
+  editingData,
+  handleAdd,
+  handleEdit,
+  checkedRowKeys,
+  onDeleted
+  // closeDrawer
+} = useTableOperate(data, getData);
+
+async function handleBatchDelete() {
+  // request
+  handleDelete(checkedRowKeys.value)
+}
+// 删除
+async function handleDelete(id: any) {
+  // request
+  let ids = []
+  typeof id === 'number' ? ids.push(id) : ids = [].concat(id)
+  const res = await fetchDelteUser({ ids })
+  if (res.code === 200) {
+    onDeleted();
+  } else {
+    window.$message?.error('删除失败!');
+  }
+}
+
+// 重置
+function handleResetPwd(row: any) {
+  resetDialogVisible.value = true
+  userName = row.username
+  transUserId = row.userId
+}
+
+// 编辑
+function handleRowEdit(id: number) {
+  handleEdit(id, 'userId');
+}
+</script>
+
+<template>
+  <div class="min-h-6.25rem flex-col-stretch gap-0.2rem overflow-hidden lt-sm:overflow-auto">
+    <MSearch v-model:model="searchParams" @reset="resetSearchParams" @search="getDataByPage" />
+    <ACard title="部门列表" :bordered="false" :body-style="{ flex: 1, overflow: 'hidden' }"
+      class="flex-col-stretch sm:flex-1-hidden card-wrapper">
+      <template #extra>
+        <TableHeaderOperation v-model:columns="columnChecks" :disabled-delete="checkedRowKeys.length === 0"
+          :loading="loading" @add="handleAdd" @delete="handleBatchDelete" @refresh="getData" />
+      </template>
+      <ATable ref="tableWrapperRef" :columns="columns" :data-source="data" size="small" :scroll="scrollConfig"
+        :loading="loading" row-key="userId" :pagination="mobilePagination" class="h-full"
+        :defaultExpandAllRows="true" />
+
+      <UserOperateDrawer v-model:visible="drawerVisible" :operate-type="operateType" :row-data="editingData"
+        @submitted="getDataByPage" />
+      <UserResetPwdDialog v-model:dialogVisible="resetDialogVisible" :userId="transUserId" :user-name="userName" />
+    </ACard>
+  </div>
+</template>
+
+<style scoped></style>

+ 105 - 0
src/views/admin/sys-dept/modules/m-search.vue

@@ -0,0 +1,105 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { enableStatusOptions } from '@/constants/business';
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { $t } from '@/locales';
+import { fetchGetdeptTreeList } from '@/service/api';
+import { translateOptions } from '@/utils/common';
+import { computed, onMounted, ref } from 'vue';
+defineOptions({
+  name: 'MSearch'
+});
+
+interface Emits {
+  (e: 'reset'): void;
+  (e: 'search'): void;
+}
+
+const emit = defineEmits<Emits>();
+const departOptions = ref<CommonType.Option<string>[]>([]);
+const { formRef, validate, resetFields } = useAntdForm();
+
+const model = defineModel<Api.SystemManage.UserSearchParams>('model', { required: true });
+
+type RuleKey = Extract<keyof Api.SystemManage.UserSearchParams, 'email' | 'phone'>;
+
+const rules = computed<Record<RuleKey, App.Global.FormRule>>(() => {
+  const { patternRules } = useFormRules(); // inside computed to make locale reactive
+
+  return {
+    email: patternRules.email,
+    phone: patternRules.phone
+  };
+});
+onMounted(()=>{
+  getDeptTree()
+})
+async function getDeptTree(){
+  const { data } = await fetchGetdeptTreeList()
+  departOptions.value = data
+}
+async function reset() {
+  await resetFields();
+  emit('reset');
+}
+
+async function search() {
+  await validate();
+  emit('search');
+}
+
+</script>
+
+<template>
+  <ACard :title="$t('common.search')" :bordered="false" class="card-wrapper">
+    <AForm
+      ref="formRef"
+      :model="model"
+      :rules="rules"
+      :label-col="{
+        span: 5,
+        md: 7
+      }"
+    >
+      <ARow :gutter="[16, 16]" wrap>
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem label="部门名称" name="deptName" class="m-0">
+            <AInput v-model:value.trim="model.username" placeholder="请输入部门名称" @keyup.enter.native="search" allowClear/>
+          </AFormItem>
+        </ACol>
+        
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem label="部门状态" name="status" class="m-0">
+            <ASelect
+              v-model:value="model.status"
+              placeholder="请选择部门状态"
+              :options="translateOptions(enableStatusOptions)"
+              @change="search"
+              allowClear
+            />
+          </AFormItem>
+        </ACol>
+        <div class="flex-1">
+          <AFormItem class="m-0">
+            <div class="w-full flex-y-center justify-end gap-12px">
+              <AButton @click="reset">
+                <template #icon>
+                  <icon-ic-round-refresh class="align-sub text-icon" />
+                </template>
+                <span class="ml-8px">{{ $t('common.reset') }}</span>
+              </AButton>
+              <AButton type="primary" ghost @click="search">
+                <template #icon>
+                  <icon-ic-round-search class="align-sub text-icon" />
+                </template>
+                <span class="ml-8px">{{ $t('common.search') }}</span>
+              </AButton>
+            </div>
+          </AFormItem>
+        </div>
+      </ARow>
+    </AForm>
+  </ACard>
+</template>
+
+<style scoped></style>

+ 248 - 0
src/views/admin/sys-dept/modules/user-operate-drawer.vue

@@ -0,0 +1,248 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { $t } from '@/locales';
+import { fetchAddUser, fetchGetAllRoles, fetchGetdeptTreeList, fetchGetPostList, getDicts } from '@/service/api';
+import { computed, nextTick, reactive, ref, watch } from 'vue';
+defineOptions({
+  name: 'UserOperateDrawer'
+});
+
+interface Props {
+  /** the type of operation */
+  operateType: AntDesign.TableOperateType;
+  /** the edit row data */
+  rowData?: Api.SystemManage.User | null;
+}
+
+const props = defineProps<Props>();
+
+interface Emits {
+  (e: 'submitted'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const visible = defineModel<boolean>('visible', {
+  default: false
+});
+
+const { formRef, validate, resetFields } = useAntdForm();
+const { defaultRequiredRule, formRules } = useFormRules();
+
+const title = computed(() => {
+  const titles: Record<AntDesign.TableOperateType, string> = {
+    add: $t('page.manage.user.addUser'),
+    edit: $t('page.manage.user.editUser')
+  };
+  return titles[props.operateType];
+});
+
+type Model = Pick<
+  Api.SystemManage.User,
+  'username' | 'sex' | 'nickName' | 'phone' | 'email' | 'status' | 'deptId' | 'password' | 'postId' | 'roleId' | 'remark'
+>;
+
+const model: Model = reactive(createDefaultModel());
+
+function createDefaultModel(): Model {
+  return {
+    username: '',
+    sex: '',
+    nickName: '',
+    phone: '',
+    email: '',
+    status: '2',
+    deptId: '',
+    password: '',
+    postId: '',
+    roleId: '',
+    remark: ''
+  };
+}
+
+type RuleKey = Extract<keyof Model, 'username' | 'status'| 'nickName'| 'deptId' | 'password'| 'email' | 'phone'>;
+
+const rules: Record<RuleKey, App.Global.FormRule> = {
+  username: defaultRequiredRule,
+  nickName: defaultRequiredRule,
+  deptId: defaultRequiredRule,
+  password: defaultRequiredRule,
+  phone: formRules.phone,
+  email:formRules.email
+};
+
+/** the enabled role options */
+const roleOptions = ref<CommonType.Option<string>[]>([]);
+const userGenderOptions = ref<CommonType.Option<string>[]>([
+  {label: "男", value: "0"},
+  {label: "女", value: "1"},
+  {label: "未知", value: "2"}
+]);
+const enableStatusOptions = ref<CommonType.Option<string>[]>([]);
+const postOptions = ref<CommonType.Option<string>[]>([]);
+const departOptions = ref<CommonType.Option<string>[]>([]);
+
+async function getSixOptions(){
+  const { data } = await getDicts('sys_user_sex')
+  userGenderOptions.value = data || []
+}
+async function getStatusOptions(){
+  const { data } = await getDicts('sys_normal_disable')
+  enableStatusOptions.value = data || []
+}
+async function getPostOptions(){
+  const { data } = await fetchGetPostList({ pageSize: 1000 })
+  const options = data?.list.map((item:any) => ({
+    label: item.postName,
+    value: item.postId,
+    postCode: item.postCode
+  }));
+  postOptions.value = [...options] || []
+}
+async function getDeptTree(){
+  const { data } = await fetchGetdeptTreeList()
+  departOptions.value = data
+}
+
+async function getRoleOptions() {
+  const { data } = await fetchGetAllRoles({ pageSize: 1000 });
+  const options = data?.list.map((item:any) => ({
+    label: item.roleName,
+    value: item.roleId,
+    status: item.status
+  }));
+  roleOptions.value = [...options];
+}
+
+async function handleInitModel() {
+  Object.assign(model, createDefaultModel());
+
+  if (props.operateType === 'edit' && props.rowData) {
+    await nextTick();
+    Object.assign(model, props.rowData);
+  }
+}
+
+function closeDrawer() {
+  visible.value = false;
+}
+
+async function handleSubmit() {
+  await validate();
+  // request 新增method 是post 修改是put
+  let method = ''
+  if (props.operateType === 'add') {
+    method = 'post'
+  } else {
+    method = 'put'
+  }
+  const res = await fetchAddUser(model, method)
+  if (res.code === 200){
+    window.$message?.success(res.msg);
+  }
+  closeDrawer();
+  emit('submitted');
+}
+
+watch(visible, () => {
+  if (visible.value) {
+    handleInitModel();
+    resetFields();
+    getRoleOptions();
+    getSixOptions()
+    getStatusOptions()
+    getPostOptions()
+    getDeptTree()
+  }
+});
+</script>
+
+<template>
+  <AModal v-model:open="visible" :title="title" width="800px">
+    <AForm ref="formRef"  :model="model" :rules="rules" :label-col="{ lg: 8, xs: 4 }" label-wrap class="pr-20px">
+      <ARow  wrap>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.nickName')" name="nickName">
+            <AInput v-model:value="model.nickName" :placeholder="$t('page.manage.user.form.nickName')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.deptId')" name="roleId">
+            <ATreeSelect v-model:value="model.deptId" show-search  :tree-data="departOptions"
+            :fieldNames="{value: 'id', children: 'children', label: 'label'}"
+              :placeholder="$t('page.manage.user.form.deptId')" allowClear/>
+          </AFormItem>
+        </ACol>
+      </ARow>
+      <ARow wrap>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userPhone')" name="phone">
+            <AInput v-model:value="model.phone" :placeholder="$t('page.manage.user.form.userPhone')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userEmail')" name="email">
+            <AInput v-model:value="model.email" :placeholder="$t('page.manage.user.form.userEmail')" allowClear/>
+          </AFormItem>
+        </ACol>
+      </ARow>
+      <ARow wrap>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userName')" name="username">
+            <AInput v-model:value="model.username" :placeholder="$t('page.manage.user.form.userName')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24" v-if="props.operateType === 'add'">
+          <AFormItem :label="$t('page.manage.user.password')" name="password" >
+            <AInput v-model:value="model.password" :placeholder="$t('page.manage.user.form.password')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userGender')" name="sex">
+            <ARadioGroup v-model:value="model.sex">
+              <ARadio v-for="item in userGenderOptions" :key="item.value" :value="item.value">
+                {{item.label }}
+              </ARadio>
+            </ARadioGroup>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userStatus')" name="status">
+            <ARadioGroup v-model:value="model.status">
+              <ARadio v-for="item in enableStatusOptions" :key="item.value" :value="item.value">
+                {{ item.label }}
+              </ARadio>
+            </ARadioGroup>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.postId')" name="postId">
+            <ASelect v-model:value="model.postId" :options="postOptions"
+              :placeholder="$t('page.manage.user.form.postId')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="props.operateType === 'add'? 12: 24" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userRole')" name="roleId">
+            <ASelect v-model:value="model.roleId"  :options="roleOptions"
+              :placeholder="$t('page.manage.user.form.userRole')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="24" :md="24" :xs="24">
+          <AFormItem :label-col="{ lg: 4, xs: 2 }" :label="$t('page.manage.user.remark')" name="remark">
+            <a-textarea v-model:value="model.remark" :placeholder="$t('page.manage.user.form.remark')"
+              :auto-size="{ minRows: 2, maxRows: 5 }" allowClear/>
+          </AFormItem>
+        </ACol>
+      </ARow>
+    </AForm>
+    <template #footer>
+      <ASpace :size="16">
+        <AButton @click="closeDrawer">{{ $t('common.cancel') }}</AButton>
+        <AButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</AButton>
+      </ASpace>
+    </template>
+  </AModal>
+</template>
+
+<style scoped></style>

+ 65 - 0
src/views/admin/sys-dept/modules/user-resetpwd-dialog.vue

@@ -0,0 +1,65 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { fetchRestPwsUser } from '@/service/api';
+import { reactive, watch } from 'vue';
+defineOptions({
+  name: 'UserResetPwdDialog'
+});
+const visible = defineModel<boolean>('dialogVisible', {
+  default: false
+});
+interface Props {
+  userId: number | null,
+  userName: string | null
+}
+const props = defineProps<Props>();
+const model = reactive(createDefaultModel());
+const { formRef, validate, resetFields } = useAntdForm();
+const { formRules } = useFormRules();
+function createDefaultModel(){
+  return {
+    password: '',
+    userId: props.userId
+  };
+}
+const rules: Record<'password', App.Global.FormRule> = {
+  password: formRules.pwd,
+};
+
+function closeDrawer() {
+  visible.value = false;
+}
+async function handleSubmit() {
+  await validate();
+  model.userId = props.userId
+
+  const res = await fetchRestPwsUser(model)
+  if (res.code === 200){
+    window.$message?.success(res.msg);
+  }
+  closeDrawer();
+}
+watch(visible, () => {
+  if (visible.value) {
+    resetFields();
+  }
+});
+</script>
+<template>
+  <AModal v-model:open="visible" title="重置密码" width="420px">
+    <!-- <p style="margin-bottom: 10px;"></p> -->
+    <AForm ref="formRef" layout="vertical" :model="model" :rules="rules">
+      <AFormItem :label="`请输入${userName}的新密码`" name="password">
+        <AInput v-model:value="model.password" placeholder="请输入新密码" allowClear/>
+      </AFormItem>
+    </AForm>
+    <template #footer>
+      <ASpace :size="16">
+        <AButton @click="closeDrawer">{{ $t('common.cancel') }}</AButton>
+        <AButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</AButton>
+      </ASpace>
+    </template>
+  </AModal>
+</template>
+<style scoped></style>

+ 237 - 0
src/views/admin/sys-menu/index.vue

@@ -0,0 +1,237 @@
+<script setup lang="tsx">
+import SvgIcon from '@/components/custom/svg-icon.vue';
+import { useTable, useTableOperate, useTableScroll } from '@/hooks/common/table';
+import { $t } from '@/locales';
+import { fetchDeleteMenu, fetchGetAllPages, fetchGetMenuList, getDicts } from '@/service/api';
+import { useBoolean } from '@sa/hooks';
+import { Button, Popconfirm } from 'ant-design-vue';
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+import MenuOperateModal, { type OperateType } from './modules/menu-operate-modal.vue';
+import MenuSearch from './modules/menu-search.vue';
+const { bool: visible, setTrue: openModal } = useBoolean();
+const { tableWrapperRef, scrollConfig } = useTableScroll();
+const visibleOptions = ref([])
+const { columns, columnChecks, data, loading, getData, getDataByPage, searchParams, resetSearchParams } = useTable({
+  apiFn: fetchGetMenuList,
+  apiParams: {
+    title: '',
+    visible: ''
+  },
+  columns: () => [
+    {
+      key: 'menuId',
+      title: $t('page.manage.menu.id'),
+      align: 'center',
+      dataIndex: 'menuId'
+    },
+    {
+      key: 'title',
+      title: $t('page.manage.menu.menuName'),
+      align: 'center',
+      minWidth: 120,
+      dataIndex: 'title'
+    },
+    {
+      key: 'icon',
+      title: $t('page.manage.menu.icon'),
+      align: 'center',
+      width: 60,
+      customRender: ({ record }) => {
+        return (
+          <div class="flex-center">
+            <SvgIcon localIcon={record.icon}  class="text-icon" />
+          </div>
+        );
+      }
+    },
+    {
+      key: 'path',
+      title: '组件路径',
+      align: 'center',
+      customRender: ({ record }) => {
+        if (record.menuType=='A') {
+          return <a-tooltip placement="top" title={record.path}>{record.path}</a-tooltip>;
+        } else {
+          return <a-tooltip placement="top" title={record.component}>{record.component}</a-tooltip>
+        }
+      }
+    },
+    {
+      key: 'permission',
+      title: '权限标识',
+      dataIndex: 'permission',
+      align: 'center',
+      customRender: ({ record }) => {
+        return  <a-tooltip placement="top" title={record.permission}><span >{record.permission || '--' }</span></a-tooltip>
+      }
+    },
+    {
+      key: 'sort',
+      dataIndex: 'sort',
+      title: $t('page.manage.menu.order'),
+      align: 'center',
+      width: 60
+    },
+    {
+      key: 'visible',
+      dataIndex: 'visible',
+      title: '菜单状态',
+      width: 90,
+      align: 'center',
+      customRender: ({ record }) => {
+        return  <a-tag color={record.visible === '1'? 'error' : 'success'}><span >{visibleFormat(record) }</span></a-tag>
+      }
+    },
+    {
+      key: 'operate',
+      title: $t('common.operate'),
+      align: 'center',
+      width: 230,
+      customRender: ({ record }) => (
+        <div class="flex-center justify-end gap-8px">
+          {record.menuType === 'M' && (
+            <Button type="primary" ghost size="small" onClick={() => handleAddChildMenu(record)}>
+              {$t('page.manage.menu.addChildMenu')}
+            </Button>
+          )}
+          <Button type="primary" ghost size="small" onClick={() => handleEdit(record)}>
+            {$t('common.edit')}
+          </Button>
+          <Popconfirm title={$t('common.confirmDelete')} onConfirm={() => handleDelete(record.menuId)}>
+            <Button danger ghost size="small">
+              {$t('common.delete')}
+            </Button>
+          </Popconfirm>
+        </div>
+      )
+    }
+  ]
+});
+
+const { checkedRowKeys, rowSelection, onDeleted } = useTableOperate(data, getData);
+
+const operateType = ref<OperateType>('add');
+onMounted(() => {
+  getOptions();
+});
+function handleAdd() {
+  operateType.value = 'add';
+  openModal();
+}
+
+async function handleBatchDelete() {
+  // request
+  handleDelete(checkedRowKeys.value)
+}
+
+async function handleDelete(id: any) {
+  // request
+  let ids = []
+  typeof id === 'number' ? ids.push(id) : ids = [].concat(id)
+  const res = await fetchDeleteMenu({ids})
+  if (res.code === 200) {
+    onDeleted();
+  } else {
+    window.$message?.error('删除失败!');
+  }
+}
+/** the edit menu data or the parent menu data when adding a child menu */
+const editingData: Ref<Api.SystemManage.Menu | null> = ref(null);
+
+function handleEdit(item: Api.SystemManage.Menu) {
+  operateType.value = 'edit';
+  editingData.value = { ...item };
+
+  openModal();
+}
+
+function handleAddChildMenu(item: Api.SystemManage.Menu) {
+  operateType.value = 'addChild';
+
+  editingData.value = { ...item };
+
+  openModal();
+}
+
+const allPages = ref<string[]>([]);
+
+async function getAllPages() {
+  const { data: pages } = await fetchGetAllPages();
+  allPages.value = pages || [];
+}
+
+function init() {
+  getAllPages();
+}
+async function getOptions (){
+  const res  = await getDicts('sys_show_hide')
+  if (res.code == 200) {
+    visibleOptions.value = res.data
+  }
+}
+// 菜单显示状态字典翻译
+function visibleFormat(row:any) {
+  if (row.menuType === 'F') {
+    return '--'
+  }
+  return selectDictLabel(visibleOptions.value, row.visible)
+}
+function selectDictLabel(datas:any, value:any) {
+  var actions:any = []
+  Object.keys(datas).map((key) => {
+    if (datas[key].value === ('' + value)) {
+      actions.push(datas[key].label)
+      return false
+    }
+  })
+  return actions.join('')
+}
+// init
+init();
+</script>
+
+<template>
+  <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
+    <MenuSearch v-model:model="searchParams" @reset="resetSearchParams" @search="getDataByPage(1, false)"  :visibleOptions="visibleOptions"/>
+    <ACard
+      :title="$t('page.manage.menu.title')"
+      :bordered="false"
+      :body-style="{ flex: 1, overflow: 'hidden' }"
+      class="flex-col-stretch sm:flex-1-hidden card-wrapper"
+    >
+      <template #extra>
+        <TableHeaderOperation
+          v-model:columns="columnChecks"
+          :disabled-delete="checkedRowKeys.length === 0"
+          :loading="loading"
+          @add="handleAdd"
+          @delete="handleBatchDelete"
+          @refresh="getData"
+        />
+      </template>
+      <ATable
+        ref="tableWrapperRef"
+        :columns="columns"
+        :data-source="data"
+        :row-selection="rowSelection"
+        size="small"
+        :loading="loading"
+        row-key="menuId"
+        :scroll="scrollConfig"
+        :pagination="false"
+        class="h-full"
+      />
+      <MenuOperateModal
+        v-model:visible="visible"
+        :operate-type="operateType"
+        :row-data="editingData"
+        :all-pages="allPages"
+        :visibleOptions="visibleOptions"
+        @submitted="getDataByPage"
+      />
+    </ACard>
+  </div>
+</template>
+
+<style scoped></style>

+ 615 - 0
src/views/admin/sys-menu/modules/menu-operate-modal.vue

@@ -0,0 +1,615 @@
+<script setup lang="tsx">
+import SvgIcon from '@/components/custom/svg-icon.vue';
+import { menuTypeOptions } from '@/constants/business';
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { $t } from '@/locales';
+import { fetchAddMenu, fetchGetMenuDetail, fetchGetMenuList, fetchGetSysApiList, fetchUpdateMenu } from '@/service/api';
+import { getLocalIcons } from '@/utils/icon';
+import { SimpleScrollbar } from '@sa/materials';
+import { computed, nextTick, reactive, ref, watch } from 'vue';
+// import {
+//   getLayoutAndPage,
+//   getPathParamFromRoutePath,
+//   getRoutePathByRouteName,
+//   getRoutePathWithParam,
+//   transformLayoutAndPageToComponent
+// } from './shared';
+
+import {
+QuestionCircleFilled
+} from '@ant-design/icons-vue';
+defineOptions({
+  name: 'MenuOperateModal'
+});
+const menuOptions = ref([])
+const sysapiList = ref([])
+export type OperateType = AntDesign.TableOperateType | 'addChild';
+interface Option {
+  label: string;
+  value: string;
+}
+interface Props {
+  /** the type of operation */
+  operateType: OperateType;
+  /** the edit menu data or the parent menu data when adding a child menu */
+  rowData?: Api.SystemManage.Menu | null;
+  /** all pages */
+  allPages: string[];
+  visibleOptions: Option[];
+}
+
+const props = defineProps<Props>();
+
+interface Emits {
+  (e: 'submitted'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const visible = defineModel<boolean>('visible', {
+  default: false
+});
+
+const { formRef, validate, resetFields } = useAntdForm();
+const { defaultRequiredRule } = useFormRules();
+
+const title = computed(() => {
+  const titles: Record<OperateType, string> = {
+    add: $t('page.manage.menu.addMenu'),
+    addChild: $t('page.manage.menu.addChildMenu'),
+    edit: $t('page.manage.menu.editMenu')
+  };
+  return titles[props.operateType];
+});
+
+type Model = Pick<
+  Api.SystemManage.Menu,
+  | 'menuType'
+  | 'menuName'
+  | 'path'
+  | 'component'
+  | 'sort'
+  | 'i18nKey'
+  | 'icon'
+  | 'visible'
+  | 'parentId'
+  | 'isFrame'
+  | 'permission'
+  | 'title'
+  | 'apis'
+> & {
+  // query: NonNullable<Api.SystemManage.Menu['query']>;
+  // buttons: NonNullable<Api.SystemManage.Menu['buttons']>;
+  layout: string;
+  path: string;
+};
+
+const model: Model = reactive(createDefaultModel());
+
+function createDefaultModel(): Model {
+  return {
+    menuType: 'M',
+    title: '',
+    path: '',
+    component: '',
+    layout: '',
+    // i18nKey: null,
+    icon: '',
+    parentId: 0,
+    visible: '0',
+    isFrame: '1',
+    sort: 0,
+    menuName: '',
+    permission: '',
+    apis: []
+  };
+}
+
+type RuleKey = Extract<keyof Model, 'title' >;
+
+const rules: Record<RuleKey, App.Global.FormRule> = {
+  title: defaultRequiredRule
+};
+
+const isEdit = computed(() => props.operateType === 'edit');
+
+const localIcons = getLocalIcons();
+const localIconOptions = localIcons.map(item => ({
+  label: () => (
+    <div class="flex-y-center gap-16px">
+      <SvgIcon localIcon={item} class="text-icon" />
+      <span>{item}</span>
+    </div>
+  ),
+  value: item
+}));
+
+const showLayout = computed(() => model.parentId === 0);
+
+
+const layoutOptions: CommonType.Option[] = [
+  {
+    label: 'base',
+    value: 'base'
+  },
+  {
+    label: 'blank',
+    value: 'blank'
+  }
+];
+
+
+
+/** - add a query input */
+// function addQuery(index: number) {
+//   model.query.splice(index + 1, 0, {
+//     key: '',
+//     value: ''
+//   });
+// }
+
+// /** - remove a query input */
+// function removeQuery(index: number) {
+//   model.query.splice(index, 1);
+// }
+
+/** - add a button input */
+// function addButton(index: number) {
+//   model.buttons.splice(index + 1, 0, {
+//     code: '',
+//     desc: ''
+//   });
+// }
+
+// /** - remove a button input */
+// function removeButton(index: number) {
+//   model.buttons.splice(index, 1);
+// }
+
+async function handleInitModel() {
+  Object.assign(model, createDefaultModel());
+
+  if (!props.rowData) return;
+
+  await nextTick();
+
+  if (props.operateType === 'addChild') {
+    const { menuId } = props.rowData;
+
+    Object.assign(model, { parentId: menuId });
+  }
+
+  if (props.operateType === 'edit') {
+    const { menuId } = props.rowData;
+    // const { apis, component, ...rest } = props.rowData;
+
+    // const { layout, page } = getLayoutAndPage(component);
+    // const { path, param } = getPathParamFromRoutePath(rest.path);
+    const res:any = await fetchGetMenuDetail(menuId)
+    if (res && res.code === 200) {
+      Object.assign(model, res.data );
+    }
+
+
+  }
+
+
+}
+
+function closeDrawer() {
+  visible.value = false;
+}
+
+// function handleUpdateRoutePathByRouteName() {
+//   if (model.routeName) {
+//     model.path = getRoutePathByRouteName(model.routeName);
+//   } else {
+//     model.path = '';
+//   }
+// }
+
+// function handleUpdateI18nKeyByRouteName() {
+//   if (model.routeName) {
+//     model.i18nKey = `route.${model.routeName}` as App.I18n.I18nKey;
+//   } else {
+//     model.i18nKey = null;
+//   }
+// }
+
+function getSubmitParams() {
+  const { layout, path, ...params } = model;
+
+  // const component = transformLayoutAndPageToComponent(layout, model.page);
+  // const routePath = getRoutePathWithParam(model.path, pathParam);
+
+  // params.component = component;
+  // params.path = routePath;
+  params.path = path
+
+  return params;
+}
+
+async function handleSubmit() {
+  await validate();
+
+  const params = getSubmitParams();
+  let res:any = {}
+  // request
+  if(isEdit.value) {
+    if (params.menuType === 'M'){
+      model.apis = []
+      params.apis = []
+    }
+    res = await fetchUpdateMenu(params, props.rowData.menuId)
+  } else {
+    res = await fetchAddMenu(params)
+  }
+  if (res && res.code == 200) {
+    if(isEdit.value){
+      window.$message?.success($t('common.updateSuccess'));
+    } else {
+      window.$message?.success('添加成功');
+    }
+
+  } else {
+    window.$message?.error(res.msg || '更新失败!');
+  }
+
+  closeDrawer();
+  emit('submitted');
+}
+/** 查询菜单下拉树结构 */
+function getTreeselect() {
+  fetchGetMenuList().then((response:any) => {
+    if (response.code === 200) {
+      menuOptions.value = []
+      const menu = { menuId: 0, title: '主类目', children: [] }
+      menu.children = response.data
+      menuOptions.value.push(menu)
+    }
+  })
+}
+async function getApiList() {
+  const res:any = await fetchGetSysApiList({ 'pageSize': 10000, 'type': 'BUS' })
+  if (res && res.code === 200) {
+    sysapiList.value = res.data.list
+  }
+}
+function handelChangeType() {
+  model.apis = []
+}
+watch(visible, () => {
+  if (visible.value) {
+    handleInitModel();
+    resetFields();
+    getTreeselect();
+    getApiList();
+  }
+});
+
+// watch(
+//   () => model.routeName,
+//   () => {
+//     handleUpdateRoutePathByRouteName();
+//     handleUpdateI18nKeyByRouteName();
+//   }
+// );
+</script>
+
+<template>
+  <AModal v-model:open="visible" :title="title"  width="800px">
+    <div class="h-480px">
+      <SimpleScrollbar>
+        <AForm ref="formRef"  :model="model" :rules="rules" :label-col="{ lg: 8, xs: 4 }" label-wrap class="pr-20px">
+          <ARow wrap>
+            <ACol :lg="12" :xs="24">
+              <AFormItem label="上级菜单" name="parentId">
+                <ATreeSelect v-model:value="model.parentId" show-search  :tree-data="menuOptions"
+                :fieldNames="{value: 'menuId', children: 'children', label: 'title'}"
+                  placeholder="选择上级菜单" allowClear/>
+              </AFormItem>
+            </ACol>
+            <ACol :lg="12" :xs="24">
+              <AFormItem  name="title">
+                <template #label>
+                  <span class="marginRight5">{{$t('page.manage.menu.menuName')}}</span>
+                  <ATooltip>
+                    <template #title>菜单位置显示的说明信息.</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
+
+                <AInput v-model:value="model.title" :placeholder="$t('page.manage.menu.form.menuName')" allowClear/>
+              </AFormItem>
+            </ACol>
+            <ACol :lg="12" :xs="24">
+              <AFormItem name="sort">
+                <template #label>
+                  <span class="marginRight5">显示排序</span>
+                  <ATooltip>
+                    <template #title>根据序号升序排列</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
+                <AInputNumber v-model:value="model.sort as number"  :placeholder="$t('page.manage.menu.form.order')"  class="w-full" />
+
+              </AFormItem>
+            </ACol>
+            <ACol :lg="12" :xs="24">
+              <AFormItem  name="menuType">
+                <template #label>
+                  <span class="marginRight5">{{ $t('page.manage.menu.menuType') }}</span>
+                  <ATooltip>
+                    <template #title>包含目录:以及菜单或者菜单组,菜单:具体对应某一个页面,按钮:功能才做按钮;</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
+                <ARadioGroup v-model:value="model.menuType" >
+                  <ARadio v-for="item in menuTypeOptions" :key="item.value" :value="item.value" @change="handelChangeType">
+                    {{ $t(item.label) }}
+                  </ARadio>
+                </ARadioGroup>
+              </AFormItem>
+            </ACol>
+
+            <ACol :lg="12" :xs="24" v-if="model.menuType == 'M' || model.menuType == 'C'">
+              <AFormItem  name="menuName" >
+                <template #label>
+                  <span class="marginRight5">{{ $t('page.manage.menu.routeName') }}</span>
+                  <ATooltip>
+                    <template #title>需要和页面name保持一致,对应页面即可选择缓存.</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
+                <AInput v-model:value="model.menuName" :placeholder="$t('page.manage.menu.form.routeName')" allowClear/>
+              </AFormItem>
+            </ACol>
+            <ACol :lg="12" :xs="24" v-if="model.menuType == 'M' || model.menuType == 'C'" >
+              <AFormItem name="component">
+                <template #label>
+                  <span class="marginRight5">{{ $t('page.manage.menu.routePath') }}</span>
+                  <ATooltip>
+                    <template #title>菜单对应的具体vue页面文件路径;</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
+                <AInput v-model:value="model.component"  :placeholder="$t('page.manage.menu.form.routePath')" allowClear/>
+              </AFormItem>
+            </ACol>
+
+            <ACol :lg="12" :xs="24"  v-if="model.menuType != 'F'">
+              <AFormItem label="路由地址" name="path">
+                <AInput v-model:value="model.path" placeholder="请输入路由地址" allowClear/>
+              </AFormItem>
+            </ACol>
+            <ACol :lg="12" :xs="24"  v-if="showLayout">
+              <AFormItem :label="$t('page.manage.menu.layout')" name="layout">
+                <ASelect
+                  v-model:value="model.layout"
+                  :options="layoutOptions"
+                  :placeholder="$t('page.manage.menu.form.layout')"
+                  allowClear
+                />
+              </AFormItem>
+            </ACol>
+
+            <!-- <ACol :lg="12" :xs="24">
+              <AFormItem :label="$t('page.manage.menu.i18nKey')" name="i18nKey">
+                <AInput v-model:value="model.i18nKey as string" :placeholder="$t('page.manage.menu.form.i18nKey')" />
+              </AFormItem>
+            </ACol> -->
+            <!-- <ACol :lg="12" :xs="24">
+              <AFormItem :label="$t('page.manage.menu.iconTypeTitle')" name="iconType">
+                <ARadioGroup v-model:value="model.iconType">
+                  <ARadio v-for="item in menuIconTypeOptions" :key="item.value" :value="item.value">
+                    {{ $t(item.label) }}
+                  </ARadio>
+                </ARadioGroup>
+              </AFormItem>
+            </ACol> -->
+
+            <ACol :lg="12" :xs="24">
+              <AFormItem :label="$t('page.manage.menu.icon')" name="icon">
+                <!-- <template v-if="model.iconType === '1'">
+                  <AInput v-model:value="model.icon" :placeholder="$t('page.manage.menu.form.icon')" class="flex-1">
+                    <template #suffix>
+                      <SvgIcon v-if="model.icon" :icon="model.icon" class="text-icon" />
+                    </template>
+                  </AInput>
+                </template> -->
+                  <ASelect
+                    v-model:value="model.icon"
+                    :placeholder="$t('page.manage.menu.form.localIcon')"
+                    :options="localIconOptions"
+                    allowClear
+                  />
+              </AFormItem>
+            </ACol>
+            <ACol :lg="12" :xs="24">
+              <AFormItem name="visible">
+                <template #label>
+                  <span class="marginRight5">{{$t('page.manage.menu.menuStatus') }}</span>
+                  <ATooltip>
+                    <template #title>需要显示在菜单列表的菜单设置为显示,否则设置为隐藏;</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
+                <ARadioGroup v-model:value="model.visible">
+                  <ARadio v-for="item in visibleOptions" :key="item.value" :value="item.value">
+                    {{ item.label }}
+                  </ARadio>
+                </ARadioGroup>
+              </AFormItem>
+            </ACol>
+            <ACol :lg="12" :xs="24"  v-if="model.menuType == 'M' || model.menuType == 'C'">
+              <AFormItem  name="isFrame">
+                <template #label>
+                  <span class="marginRight5">{{ $t('page.manage.menu.href') }}</span>
+                  <ATooltip>
+                    <template #title>可以通过iframe打开指定地址</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
+                <ARadioGroup v-model:value="model.isFrame">
+                  <ARadio value="0">{{ $t('common.yesOrNo.yes') }}</ARadio>
+                  <ARadio value="1">{{ $t('common.yesOrNo.no') }}</ARadio>
+                </ARadioGroup>
+              </AFormItem>
+            </ACol>
+
+            <ACol :lg="12" :xs="24" v-if="model.menuType == 'F' || model.menuType == 'C'" >
+              <AFormItem name="component">
+                <template #label>
+                  <span class="marginRight5">权限标识</span>
+                  <ATooltip>
+                    <template #title>前端权限控制按钮是否显示</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
+                <AInput v-model:value="model.permission"  placeholder="请输入权限标识" />
+              </AFormItem>
+            </ACol>
+            <ACol :lg="24" :xs="24" v-if="model.menuType == 'F' || model.menuType == 'C'">
+              <AFormItem name="component" :label-col="{ style: { width: '120px' } }">
+                <template  #label >
+                  <span class="marginRight5">api权限</span>
+                  <ATooltip>
+                    <template #title>配置在这个才做上需要使用到的接口,否则在设置用户角色时,接口将无权访问。</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
+                <ATransfer
+                  v-model:target-keys="model.apis"
+                  :data-source="sysapiList"
+                  :rowKey="record => record.id"
+                  show-search
+                  :titles="['未授权','已授权']"
+                  :list-style="{
+                    width: '250px',
+                    height: '300px',
+                  }"
+                  :operations="['授权 ','收回' ]"
+                  :render="item => `${item.title}`"
+                >
+
+                  <template #notFoundContent>
+                    <span>没数据</span>
+                  </template>
+                </ATransfer>
+              </AFormItem>
+            </ACol>
+
+            <!-- <ACol :span="24">
+              <AFormItem :label-col="{ span: 4 }" :label="$t('page.manage.menu.query')" name="query">
+                <AButton v-if="model.query.length === 0" type="dashed" block @click="addQuery(-1)">
+                  <template #icon>
+                    <icon-carbon-add class="align-sub text-icon" />
+                  </template>
+                  <span class="ml-8px">{{ $t('common.add') }}</span>
+                </AButton>
+                <template v-else>
+                  <div v-for="(item, index) in model.query" :key="index" class="flex gap-3">
+                    <ACol :span="9">
+                      <AFormItem :name="['query', index, 'key']">
+                        <AInput
+                          v-model:value="item.key"
+                          :placeholder="$t('page.manage.menu.form.queryKey')"
+                          class="flex-1"
+                        />
+                      </AFormItem>
+                    </ACol>
+                    <ACol :span="9">
+                      <AFormItem :name="['query', index, 'value']">
+                        <AInput
+                          v-model:value="item.value"
+                          :placeholder="$t('page.manage.menu.form.queryValue')"
+                          class="flex-1"
+                        />
+                      </AFormItem>
+                    </ACol>
+                    <ACol :span="5">
+                      <ASpace class="ml-12px">
+                        <AButton size="middle" @click="addQuery(index)">
+                          <template #icon>
+                            <icon-ic:round-plus class="align-sub text-icon" />
+                          </template>
+                        </AButton>
+                        <AButton size="middle" @click="removeQuery(index)">
+                          <template #icon>
+                            <icon-ic-round-remove class="align-sub text-icon" />
+                          </template>
+                        </AButton>
+                      </ASpace>
+                    </ACol>
+                  </div>
+                </template>
+              </AFormItem>
+            </ACol> -->
+            <!-- <ACol :span="24">
+              <AFormItem :label-col="{ span: 4 }" :label="$t('page.manage.menu.button')" name="buttons">
+                <AButton v-if="model.buttons.length === 0" type="dashed" block @click="addButton(-1)">
+                  <template #icon>
+                    <icon-carbon-add class="align-sub text-icon" />
+                  </template>
+                  <span class="ml-8px">{{ $t('common.add') }}</span>
+                </AButton>
+                <template v-else>
+                  <div v-for="(item, index) in model.buttons" :key="index" class="flex gap-3">
+                    <ACol :span="9">
+                      <AFormItem :name="['buttons', index, 'code']">
+                        <AInput
+                          v-model:value="item.code"
+                          :placeholder="$t('page.manage.menu.form.buttonCode')"
+                          class="flex-1"
+                        ></AInput>
+                      </AFormItem>
+                    </ACol>
+                    <ACol :span="9">
+                      <AFormItem :name="['buttons', index, 'desc']">
+                        <AInput
+                          v-model:value="item.desc"
+                          :placeholder="$t('page.manage.menu.form.buttonDesc')"
+                          class="flex-1"
+                        ></AInput>
+                      </AFormItem>
+                    </ACol>
+                    <ACol :span="5">
+                      <ASpace class="ml-12px">
+                        <AButton size="middle" @click="addButton(index)">
+                          <template #icon>
+                            <icon-ic:round-plus class="align-sub text-icon" />
+                          </template>
+                        </AButton>
+                        <AButton size="middle" @click="removeButton(index)">
+                          <template #icon>
+                            <icon-ic-round-remove class="align-sub text-icon" />
+                          </template>
+                        </AButton>
+                      </ASpace>
+                    </ACol>
+                  </div>
+                </template>
+              </AFormItem>
+            </ACol> -->
+          </ARow>
+        </AForm>
+      </SimpleScrollbar>
+    </div>
+    <template #footer>
+      <ASpace justify="end" :size="16">
+        <AButton @click="closeDrawer">{{ $t('common.cancel') }}</AButton>
+        <AButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</AButton>
+      </ASpace>
+    </template>
+  </AModal>
+</template>
+
+<style scoped>
+.marginRight5{
+  margin-right: 5px;
+}
+::v-deep .ant-transfer-operation .ant-btn{
+  display: flex;
+  align-items: center;
+}
+</style>

+ 78 - 0
src/views/admin/sys-menu/modules/menu-search.vue

@@ -0,0 +1,78 @@
+/* eslint-disable */
+<script setup lang="ts">defineOptions({
+  name: 'MenuSearch'
+});
+interface Option {
+  label: string;
+  value: string;
+}
+interface Props {
+  visibleOptions: Option[];
+}
+interface Emits {
+  (e: 'reset'): void;
+  (e: 'search'): void;
+}
+defineProps<Props>();
+const emit = defineEmits<Emits>();
+const model = defineModel<Api.SystemManage.MenuSearchParams>('model', { required: true });
+
+
+function reset() {
+  emit('reset');
+}
+
+function search() {
+  emit('search');
+}
+</script>
+
+<template>
+  <ACard :title="$t('common.search')" :bordered="false" class="card-wrapper">
+    <AForm
+      :model="model"
+      :label-col="{
+        span: 5,
+        md: 7
+      }"
+    >
+      <ARow :gutter="[16, 16]" wrap>
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.menu.menuName')" name="title" class="m-0">
+            <AInput v-model:value.trim="model.title" :placeholder="$t('page.manage.menu.form.menuName')" @keyup.enter.native="search" allowClear/>
+          </AFormItem>
+        </ACol>
+
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.menu.menuStatus')" name="visible" class="m-0">
+            <ASelect v-model:value="model.visible"  allowClear @change="search">
+              <ASelectOption v-for="option in visibleOptions" :key="option.value" :value="option.value" >
+                {{ option.label }}
+              </ASelectOption>
+            </ASelect>
+          </AFormItem>
+        </ACol>
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem class="m-0">
+            <div class="w-full flex-y-center justify-end gap-12px">
+              <AButton @click="reset">
+                <template #icon>
+                  <icon-ic-round-refresh class="align-sub text-icon" />
+                </template>
+                <span class="ml-8px">{{ $t('common.reset') }}</span>
+              </AButton>
+              <AButton type="primary" ghost @click="search">
+                <template #icon>
+                  <icon-ic-round-search class="align-sub text-icon" />
+                </template>
+                <span class="ml-8px">{{ $t('common.search') }}</span>
+              </AButton>
+            </div>
+          </AFormItem>
+        </ACol>
+      </ARow>
+    </AForm>
+  </ACard>
+</template>
+
+<style scoped></style>

+ 79 - 0
src/views/admin/sys-menu/modules/shared.ts

@@ -0,0 +1,79 @@
+const LAYOUT_PREFIX = 'layout.';
+const VIEW_PREFIX = 'view.';
+const FIRST_LEVEL_ROUTE_COMPONENT_SPLIT = '$';
+
+export function getLayoutAndPage(component?: string | null) {
+  let layout = '';
+  let page = '';
+
+  const [layoutOrPage = '', pageItem = ''] = component?.split(FIRST_LEVEL_ROUTE_COMPONENT_SPLIT) || [];
+
+  layout = getLayout(layoutOrPage);
+  page = getPage(pageItem || layoutOrPage);
+
+  return { layout, page };
+}
+
+function getLayout(layout: string) {
+  return layout.startsWith(LAYOUT_PREFIX) ? layout.replace(LAYOUT_PREFIX, '') : '';
+}
+
+function getPage(page: string) {
+  return page.startsWith(VIEW_PREFIX) ? page.replace(VIEW_PREFIX, '') : '';
+}
+
+export function transformLayoutAndPageToComponent(layout: string, page: string) {
+  const hasLayout = Boolean(layout);
+  const hasPage = Boolean(page);
+
+  if (hasLayout && hasPage) {
+    return `${LAYOUT_PREFIX}${layout}${FIRST_LEVEL_ROUTE_COMPONENT_SPLIT}${VIEW_PREFIX}${page}`;
+  }
+
+  if (hasLayout) {
+    return `${LAYOUT_PREFIX}${layout}`;
+  }
+
+  if (hasPage) {
+    return `${VIEW_PREFIX}${page}`;
+  }
+
+  return '';
+}
+
+/**
+ * Get route name by route path
+ *
+ * @param routeName
+ */
+export function getRoutePathByRouteName(routeName: string) {
+  return `/${routeName.replace(/_/g, '/')}`;
+}
+
+/**
+ * Get path param from route path
+ *
+ * @param routePath route path
+ */
+export function getPathParamFromRoutePath(routePath: string) {
+  const [path, param = ''] = routePath.split('/:');
+
+  return {
+    path,
+    param
+  };
+}
+
+/**
+ * Get route path with param
+ *
+ * @param routePath route path
+ * @param param path param
+ */
+export function getRoutePathWithParam(routePath: string, param: string) {
+  if (param.trim()) {
+    return `${routePath}/:${param}`;
+  }
+
+  return routePath;
+}

+ 207 - 0
src/views/admin/sys-role/index.vue

@@ -0,0 +1,207 @@
+/* eslint-disable */
+<script setup lang="tsx">
+import { useTable, useTableOperate, useTableScroll } from '@/hooks/common/table';
+import { $t } from '@/locales';
+import { fetchChangeRoleStatus, fetchDeleteRole, fetchGetRoleList } from '@/service/api';
+import { Button, Popconfirm } from 'ant-design-vue';
+import { ref } from 'vue';
+import RuleModifypermisModal from './modules/role-modifypermis-modal.vue';
+import RoleOperateDrawer from './modules/role-operate-drawer.vue';
+import RoleSearch from './modules/role-search.vue';
+const { tableWrapperRef, scrollConfig } = useTableScroll();
+const modalVisible = ref(false)
+const rowRoleKey = ref('')
+const rowRoleName = ref('')
+const rowRoleId = ref()
+const rowData = ref()
+const {
+  columns,
+  columnChecks,
+  data,
+  loading,
+  getData,
+  getDataByPage,
+  mobilePagination,
+  searchParams,
+  resetSearchParams
+} = useTable({
+  apiFn: fetchGetRoleList,
+  apiParams: {
+    pageIndex: 1,
+    pageSize: 10,
+    status: undefined,
+    roleName: undefined,
+    roleKey: undefined
+  },
+  columns: () => [
+    // {
+    //   key: 'index',
+    //   dataIndex: 'index',
+    //   title: $t('common.index'),
+    //   width: 64,
+    //   align: 'center'
+    // },
+    {
+      key: 'roleId',
+      dataIndex: 'roleId',
+      title: '编码',
+      width: 64,
+      align: 'center'
+    },
+    {
+      key: 'roleName',
+      dataIndex: 'roleName',
+      title: $t('page.manage.role.roleName'),
+      align: 'center',
+      minWidth: 120
+    },
+    {
+      key: 'roleKey',
+      dataIndex: 'roleKey',
+      title: $t('page.manage.role.roleKey'),
+      align: 'center',
+      minWidth: 120
+    },
+    {
+      key: 'roleSort',
+      dataIndex: 'roleSort',
+      align: 'center',
+      title: $t('page.manage.role.roleSort'),
+      minWidth: 120
+    },
+    {
+      key: 'status',
+      dataIndex: 'status',
+      title: $t('page.manage.user.userStatus'),
+      align: 'center',
+      minWidth: 100,
+      customRender: ({ record }) => {
+        let showStatus = record.status === '2'? true : false
+        const text = record.status === '2' ? '停用' : '启用'
+        return <Popconfirm title={`确定要${text}${record.roleName}角色吗?`} onConfirm={() => handleChangeStatus(record, text)}>
+          <a-switch v-model:checked={showStatus} />
+        </Popconfirm>
+      }
+    },
+    {
+      key: 'operate',
+      title: $t('common.operate'),
+      align: 'center',
+      width: 200,
+      customRender: ({ record }) => (
+        <div class="flex-center gap-8px">
+          <Button type="primary" ghost size="small" onClick={() => handleRowEdit(record.roleId)}>
+            {$t('common.edit')}
+          </Button>
+          <Button  block size="small" onClick={() => handleModifyPermi(record)}>
+            数据权限
+          </Button>
+          <Popconfirm onConfirm={() => handleDelete(record.roleId)} title={$t('common.confirmDelete')}>
+            <Button danger size="small">
+              {$t('common.delete')}
+            </Button>
+          </Popconfirm>
+        </div>
+      )
+    }
+  ]
+});
+
+const {
+  drawerVisible,
+  operateType,
+  editingData,
+  handleAdd,
+  handleEdit,
+  checkedRowKeys,
+  rowSelection,
+  onDeleted
+  // closeDrawer
+} = useTableOperate(data, getData);
+
+async function handleBatchDelete() {
+  // request
+  handleDelete(checkedRowKeys.value)
+}
+
+async function handleDelete(id: any) {
+  // request
+  let ids = []
+  typeof id === 'number' ? ids.push(id) : ids = [].concat(id)
+  const res = await fetchDeleteRole({ids})
+  if (res.code === 200) {
+    onDeleted();
+  } else {
+    window.$message?.error('删除失败!');
+  }
+}
+
+function handleRowEdit(id: number) {
+  handleEdit(id, 'roleId');
+}
+// 数据权限
+function handleModifyPermi(row:any){
+  modalVisible.value = true
+  rowData.value = row
+  rowRoleId.value = row.roleId
+  rowRoleKey.value = row.roleKey
+  rowRoleName.value = row.roleName
+
+}
+async function handleChangeStatus(row:any, text:string){
+  let paras = {
+    roleId:row.roleId,
+    status: text === '停用'? '1' : '2'
+  }
+  const res:any = await fetchChangeRoleStatus(paras)
+  if (res.code === 200 ){
+    window.$message?.success($t('common.updateSuccess'));
+  } else {
+    window.$message?.error('更新失败!');
+  }
+}
+</script>
+
+<template>
+  <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
+    <RoleSearch v-model:model="searchParams" @reset="resetSearchParams" @search="getDataByPage" />
+    <ACard
+      :title="$t('page.manage.role.title')"
+      :bordered="false"
+      :body-style="{ flex: 1, overflow: 'hidden' }"
+      class="flex-col-stretch sm:flex-1-hidden card-wrapper"
+    >
+      <template #extra>
+        <TableHeaderOperation
+          v-model:columns="columnChecks"
+          :disabled-delete="checkedRowKeys.length === 0"
+          :loading="loading"
+          @add="handleAdd"
+          @delete="handleBatchDelete"
+          @refresh="getData"
+        />
+      </template>
+      <ATable
+        ref="tableWrapperRef"
+        :columns="columns"
+        :data-source="data"
+        :row-selection="rowSelection"
+        :loading="loading"
+        row-key="roleId"
+        size="small"
+        :pagination="mobilePagination"
+        :scroll="scrollConfig"
+        class="h-full"
+      />
+      <RoleOperateDrawer
+        v-model:visible="drawerVisible"
+        :operate-type="operateType"
+        :row-data="editingData"
+        @submitted="getDataByPage"
+      />
+      <RuleModifypermisModal v-model:visible="modalVisible"  :rowData="rowData"  @submitted="getDataByPage"/>
+    </ACard>
+  </div>
+</template>
+
+<style scoped></style>

+ 85 - 0
src/views/admin/sys-role/modules/button-auth-modal.vue

@@ -0,0 +1,85 @@
+<script setup lang="ts">
+import { computed, shallowRef } from 'vue';
+import type { DataNode } from 'ant-design-vue/es/tree';
+import { $t } from '@/locales';
+
+defineOptions({
+  name: 'ButtonAuthModal'
+});
+
+interface Props {
+  /** the roleId */
+  roleId: number;
+}
+
+const props = defineProps<Props>();
+
+const visible = defineModel<boolean>('visible', {
+  default: false
+});
+
+function closeModal() {
+  visible.value = false;
+}
+
+const title = computed(() => $t('common.edit') + $t('page.manage.role.buttonAuth'));
+
+const tree = shallowRef<DataNode[]>([]);
+
+async function getAllButtons() {
+  // request
+  tree.value = [
+    { key: 1, title: 'button1', code: 'code1' },
+    { key: 2, title: 'button2', code: 'code2' },
+    { key: 3, title: 'button3', code: 'code3' },
+    { key: 4, title: 'button4', code: 'code4' },
+    { key: 5, title: 'button5', code: 'code5' },
+    { key: 6, title: 'button6', code: 'code6' },
+    { key: 7, title: 'button7', code: 'code7' },
+    { key: 8, title: 'button8', code: 'code8' },
+    { key: 9, title: 'button9', code: 'code9' },
+    { key: 10, title: 'button10', code: 'code10' }
+  ];
+}
+
+const checks = shallowRef<number[]>([]);
+
+async function getChecks() {
+  console.log(props.roleId);
+  // request
+  checks.value = [1, 2, 3, 4, 5];
+}
+
+function handleSubmit() {
+  console.log(checks.value, props.roleId);
+  // request
+
+  window.$message?.success?.($t('common.modifySuccess'));
+
+  closeModal();
+}
+
+function init() {
+  getAllButtons();
+  getChecks();
+}
+
+// init
+init();
+</script>
+
+<template>
+  <AModal v-model:open="visible" :title="title" class="w-480px">
+    <ATree v-model:checked-keys="checks" :tree-data="tree" checkable :height="280" class="h-280px" />
+    <template #footer>
+      <AButton size="small" class="mt-16px" @click="closeModal">
+        {{ $t('common.cancel') }}
+      </AButton>
+      <AButton type="primary" size="small" class="mt-16px" @click="handleSubmit">
+        {{ $t('common.confirm') }}
+      </AButton>
+    </template>
+  </AModal>
+</template>
+
+<style scoped></style>

+ 149 - 0
src/views/admin/sys-role/modules/menu-auth-modal.vue

@@ -0,0 +1,149 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { computed, shallowRef, watch } from 'vue';
+import type { SelectProps } from 'ant-design-vue';
+import type { DataNode } from 'ant-design-vue/es/tree';
+import { $t } from '@/locales';
+import { fetchGetMenuIdsByRole, fetchGetMenuTree } from '@/service/api';
+
+defineOptions({
+  name: 'MenuAuthModal'
+});
+
+interface Props {
+  /** the roleId */
+  roleId: number;
+  isEdit: boolean;
+}
+
+interface Emits {
+  (e: 'submitted', arg1: number[]): void;
+}
+const emit = defineEmits<Emits>();
+const props = defineProps<Props>();
+
+const visible = defineModel<boolean>('visible', {
+  default: false
+});
+
+function closeModal() {
+  visible.value = false;
+}
+
+const title = computed(() => $t('common.edit') + $t('page.manage.role.menuAuth'));
+
+const home = shallowRef('');
+
+async function getHome() {
+  console.log(props.roleId);
+
+  home.value = 'home';
+}
+
+async function updateHome(val: SelectProps['value']) {
+  // request
+
+  home.value = val as string;
+}
+
+const pages = shallowRef<string[]>([]);
+
+async function getPages() {
+  // const { code, data } = await fetchGetAllPages();
+
+  // if (code == 200) {
+  //   pages.value = data;
+  // }
+}
+
+const pageSelectOptions = computed(() => {
+  const opts: CommonType.Option[] = pages.value.map(page => ({
+    label: page,
+    value: page
+  }));
+
+  return opts;
+});
+
+const tree = shallowRef<DataNode[]>([]);
+
+async function getTree() {
+  const { code, data } = await fetchGetMenuTree(0);
+
+  if (code === 200) {
+    tree.value = recursiveTransform(data.menus);
+  }
+}
+
+function recursiveTransform(data: Api.SystemManage.MenuTree[]): DataNode[] {
+  return data.map(item => {
+    const { id: key, label } = item;
+
+    if (item.children) {
+      return {
+        key,
+        title: label,
+        children: recursiveTransform(item.children)
+      };
+    }
+
+    return {
+      key,
+      title: label
+    };
+  });
+}
+
+const menuIds = shallowRef<number[]>([]);
+
+async function getChecks() {
+  console.log(props.roleId);
+  // request
+  const res = await fetchGetMenuIdsByRole(props.roleId)
+  if (res.code === 200) {
+    menuIds.value = res.data.menuIds
+  }
+}
+
+function handleSubmit() {
+  console.log(menuIds.value, props.roleId);
+  emit('submitted', menuIds.value);
+  closeModal();
+}
+
+async function init() {
+  getHome();
+  getPages();
+  await getTree();
+  if (props.isEdit){
+    await getChecks();
+  }
+
+}
+
+watch(visible, val => {
+  if (val) {
+    init();
+  }
+});
+</script>
+
+<template>
+  <AModal v-model:open="visible" :title="title" class="w-480px">
+    <!-- <div class="flex-y-center gap-16px pb-12px">
+      <div>{{ $t('page.manage.menu.home') }}</div>
+      <ASelect :value="home" :options="pageSelectOptions" class="w-240px" @update:value="updateHome" />
+    </div> -->
+    <ATree v-model:checked-keys="menuIds" :tree-data="tree" checkable :height="280" class="h-280px" />
+    <template #footer>
+      <AButton size="small" class="mt-16px" @click="closeModal">
+        {{ $t('common.cancel') }}
+      </AButton>
+      <AButton type="primary" size="small" class="mt-16px" @click="handleSubmit">
+        {{ $t('common.confirm') }}
+      </AButton>
+    </template>
+  </AModal>
+</template>
+
+<style scoped></style>

+ 132 - 0
src/views/admin/sys-role/modules/role-modifypermis-modal.vue

@@ -0,0 +1,132 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { $t } from '@/locales';
+import { fetchDeptTreeByRole, fetchModifyRolePersion } from '@/service/api';
+import { reactive, ref, watch } from 'vue';
+defineOptions({
+  name: 'RoleModifyPermisModal'
+});
+const visible = defineModel<boolean>('visible', {
+  default: false
+});
+const dataScopeOptions = ref([
+  {
+    value: '1',
+    label: '全部数据权限'
+  },
+  {
+    value: '2',
+    label: '自定数据权限'
+  },
+  {
+    value: '3',
+    label: '本部门数据权限'
+  },
+  {
+    value: '4',
+    label: '本部门及以下数据权限'
+  },
+  {
+    value: '5',
+    label: '仅本人数据权限'
+  }
+])
+interface Emits {
+  (e: 'submitted'): void;
+}
+const emit = defineEmits<Emits>();
+const props = defineProps({
+  rowData: {
+    type: Object,
+    default: () => ({})
+  }
+});
+const { formRef, validate } = useAntdForm();
+const { defaultRequiredRule } = useFormRules();
+const treeData = ref([])
+type Model = Pick<Api.SystemManage.Role,  'roleName'| 'roleKey'| 'dataScope'| 'deptIds'>;
+let model: Model = reactive(createDefaultModel());
+function createDefaultModel(): Model {
+  return {
+    roleName: props.rowData.roleName,
+    roleKey: props.rowData.roleKey,
+    dataScope: props.rowData.dataScope,
+    deptIds: []
+  };
+}
+
+type RuleKey = Exclude<keyof Model, ''>;
+
+const rules: Record<RuleKey, App.Global.FormRule> = {
+  dataScope: defaultRequiredRule
+};
+
+
+
+function closeDrawer() {
+  visible.value = false;
+}
+async function handleSubmit(){
+  await validate()
+  const res = await fetchModifyRolePersion(model)
+  if (res.code === 200){
+    window.$message?.success($t('common.updateSuccess'));
+  } else {
+    window.$message?.error(res.msg);
+  }
+  closeDrawer()
+  emit('submitted');
+}
+function handelChange(){
+  if (treeData.value.length === 0) {
+    getDeptTreeselect()
+  }
+}
+/** 查询部门树结构 */
+async function getDeptTreeselect() {
+  const res = await fetchDeptTreeByRole(props.rowData.roleId)
+  if (res.code === 200) {
+    treeData.value = res.data.depts || []
+    model.deptIds = res.data.checkedKeys || []
+  }
+}
+watch(visible, () => {
+  if (visible.value) {
+    model = props.rowData
+    if(model.dataScope === '2') {
+      getDeptTreeselect()
+    }
+  }
+});
+</script>
+<template>
+  <AModal v-model:open="visible" title="分配数据权限" width="420px">
+    <AForm ref="formRef" layout="vertical" :model="model" :rules="rules">
+      <AFormItem :label="$t('page.manage.role.roleName')" name="roleName">
+        <AInput v-model:value="model.roleName" :placeholder="$t('page.manage.role.form.roleName')" :disabled="true" allowClear/>
+      </AFormItem>
+      <AFormItem :label="$t('page.manage.role.roleKey')" name="roleKey" >
+        <AInput v-model:value.trim="model.roleKey" :placeholder="$t('page.manage.role.form.roleKey')" :disabled="true" allowClear/>
+      </AFormItem>
+      <AFormItem label="权限范围" name="dataScope" >
+        <ASelect v-model:value="model.dataScope"   :placeholder="$t('page.manage.role.form.roleStatus')" allowClear @change="handelChange">
+          <ASelectOption v-for="option in dataScopeOptions" :key="option.value" :value="option.value" >
+            {{ option.label }}
+          </ASelectOption>
+        </ASelect>
+      </AFormItem>
+      <AFormItem label="数据权限" name="dataScope" v-if="model.dataScope === '2'">
+        <ATree v-model:checkedKeys="model.deptIds" :field-names="{children:'children', title:'label', key:'id' }" :tree-data="treeData" allowClear
+        checkable/>
+      </AFormItem>
+    </AForm>
+    <template #footer>
+      <ASpace :size="16">
+        <AButton @click="closeDrawer">{{ $t('common.cancel') }}</AButton>
+        <AButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</AButton>
+      </ASpace>
+    </template>
+  </AModal>
+</template>
+<style scoped></style>

+ 206 - 0
src/views/admin/sys-role/modules/role-operate-drawer.vue

@@ -0,0 +1,206 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { computed, nextTick, reactive, ref, watch } from 'vue';
+// import { useBoolean } from '@sa/hooks';
+import { enableStatusOptions } from '@/constants/business';
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { $t } from '@/locales';
+// import MenuAuthModal from './menu-auth-modal.vue';
+import { fetchAddRole, fetchEditRole, fetchGetMenuTree } from '@/service/api';
+import type { DataNode } from 'ant-design-vue/es/tree';
+defineOptions({
+  name: 'RoleOperateDrawer'
+});
+
+interface Props {
+  /** the type of operation */
+  operateType: AntDesign.TableOperateType;
+  /** the edit row data */
+  rowData?: Api.SystemManage.Role | null;
+}
+
+const props = defineProps<Props>();
+
+interface Emits {
+  (e: 'submitted'): void;
+}
+
+const emit = defineEmits<Emits>();
+const tree = ref<DataNode[]>([]);
+const visible = defineModel<boolean>('visible', {
+  default: false
+});
+
+const { formRef, validate, resetFields } = useAntdForm();
+const { defaultRequiredRule } = useFormRules();
+// const { bool: menuAuthVisible, setTrue: openMenuAuthModal } = useBoolean();
+
+const title = computed(() => {
+  const titles: Record<AntDesign.TableOperateType, string> = {
+    add: $t('page.manage.role.addRole'),
+    edit: $t('page.manage.role.editRole')
+  };
+  return titles[props.operateType];
+});
+
+type Model = Pick<Api.SystemManage.Role, 'roleName' | 'roleKey' | 'roleSort' | 'status' | 'remark' | 'menuIds'>;
+
+const model: Model = reactive(createDefaultModel());
+
+function createDefaultModel(): Model {
+  return {
+    roleName: '',
+    roleKey: '',
+    roleSort: 0,
+    status: '2',
+    remark: '',
+    menuIds: []
+  };
+}
+
+type RuleKey = Exclude<keyof Model, 'status' | 'remark' | 'menuIds'>;
+
+const rules: Record<RuleKey, App.Global.FormRule> = {
+  roleName: defaultRequiredRule,
+  roleKey: defaultRequiredRule,
+  roleSort: defaultRequiredRule
+};
+
+const roleId = computed(() => props.rowData?.roleId || 0);
+
+const isEdit = computed(() => props.operateType === 'edit');
+
+async function handleInitModel() {
+  Object.assign(model, createDefaultModel());
+  if (isEdit && props.rowData) {
+
+    await nextTick();
+    Object.assign(model, props.rowData);
+  }
+}
+
+function closeDrawer() {
+  visible.value = false;
+}
+async function getTree() {
+  const { code, data } = await fetchGetMenuTree(roleId.value);
+
+  if (code === 200) {
+    tree.value = recursiveTransform(data.menus);
+    if(isEdit.value){
+      model.menuIds=  data.checkedKeys || []
+    }
+  }
+}
+function recursiveTransform(data: Api.SystemManage.MenuTree[]): DataNode[] {
+  return data.map(item => {
+    const { id: key, label } = item;
+
+    if (item.children) {
+      return {
+        key,
+        title: label,
+        children: recursiveTransform(item.children)
+      };
+    }
+
+    return {
+      key,
+      title: label
+    };
+  });
+}
+async function handleSubmit() {
+  await validate();
+  let res = null
+  if (isEdit.value) { // 编辑
+    res = await fetchEditRole(model, roleId.value)
+  } else {// 新增
+    res = await fetchAddRole(model)
+  }
+  if (res.code === 200) {
+    if(isEdit.value){
+      window.$message?.success($t('common.updateSuccess'));
+    } else {
+      window.$message?.success($t('common.addSuccess'))
+    }
+  } else {
+    window.$message?.error(res.msg);
+  }
+
+  closeDrawer();
+  emit('submitted');
+}
+
+watch(visible, () => {
+  if (visible.value) {
+    handleInitModel();
+    resetFields();
+    getTree()
+  }
+});
+</script>
+
+<template>
+  <AModal v-model:open="visible" :title="title" width="800px">
+    <AForm ref="formRef"  :model="model" :rules="rules" :label-col="{ lg: 8, xs: 4 }" label-wrap class="pr-20px">
+      <ARow wrap>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.role.roleName')" name="roleName">
+            <AInput v-model:value="model.roleName" :disabled="isEdit" :placeholder="$t('page.manage.role.form.roleName')" allowClear />
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.role.roleKey')" name="roleKey">
+            <AInput v-model:value="model.roleKey" :disabled="isEdit" :placeholder="$t('page.manage.role.form.roleKey')" allowClear/>
+          </AFormItem>
+        </ACol>
+      </ARow>
+      <ARow wrap>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.role.roleSort')" name="roleSort">
+            <AInputNumber v-model:value="model.roleSort" :placeholder="$t('page.manage.role.form.roleSort')"  style="width:100%"/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.role.roleStatus')" name="status">
+            <ARadioGroup v-model:value="model.status">
+              <ARadio v-for="item in enableStatusOptions" :key="item.value" :value="item.value">
+                {{ $t(item.label) }}
+              </ARadio>
+            </ARadioGroup>
+          </AFormItem>
+        </ACol>
+      </ARow>
+      <ARow wrap >
+        <ACol :span="24" :md="24" :xs="24">
+          <AFormItem :label-col="{ lg: 4, xs: 2 }" :label="$t('page.manage.user.remark')" name="remark">
+          <a-textarea v-model:value="model.remark" :placeholder="$t('page.manage.user.form.remark')" allowClear
+            :auto-size="{ minRows: 2, maxRows: 5 }" />
+        </AFormItem>
+        </ACol>
+      </ARow>
+      <ARow wrap >
+        <ACol :span="24" :md="24" :xs="24">
+          <AFormItem :label-col="{ lg: 4, xs: 2 }" :label="$t('page.manage.role.menuAuth')" name="remark">
+          <ATree :label-col="{ lg: 4, xs: 2 }" v-model:checked-keys="model.menuIds" :tree-data="tree" checkable :height="280" class="h-280px" allowClear/>
+        </AFormItem>
+        </ACol>
+      </ARow>
+    </AForm>
+    <ASpace >
+      <!-- <AButton @click="openMenuAuthModal">{{ $t('page.manage.role.menuAuth') }}</AButton>
+      <MenuAuthModal v-model:visible="menuAuthVisible" :role-id="roleId" :isEdit="isEdit" @submitted="getMenuIds"/> -->
+      <!-- <AButton @click="openButtonAuthModal">{{ $t('page.manage.role.buttonAuth') }}</AButton>
+      <ButtonAuthModal v-model:visible="buttonAuthVisible" :role-id="roleId" /> -->
+    </ASpace>
+    <template #footer>
+      <div class="flex-y-center justify-end gap-12px">
+        <AButton @click="closeDrawer">{{ $t('common.cancel') }}</AButton>
+        <AButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</AButton>
+      </div>
+    </template>
+  </AModal>
+</template>
+
+<style scoped></style>

+ 80 - 0
src/views/admin/sys-role/modules/role-search.vue

@@ -0,0 +1,80 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { enableStatusOptions } from '@/constants/business';
+import { $t } from '@/locales';
+
+defineOptions({
+  name: 'RoleSearch'
+});
+
+interface Emits {
+  (e: 'reset'): void;
+  (e: 'search'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const model = defineModel<Api.SystemManage.RoleSearchParams>('model', { required: true });
+
+function reset() {
+  emit('reset');
+}
+
+function search() {
+  emit('search');
+}
+</script>
+
+<template>
+  <ACard :title="$t('common.search')" :bordered="false" class="card-wrapper">
+    <AForm
+      :model="model"
+      :label-col="{
+        span: 5,
+        md: 7
+      }"
+    >
+      <ARow :gutter="[16, 16]" wrap>
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.role.roleName')" name="roleName" class="m-0">
+            <AInput v-model:value.trim="model.roleName" :placeholder="$t('page.manage.role.form.roleName')" @keyup.enter.native="search" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.role.roleKey')" name="roleKey" class="m-0">
+            <AInput v-model:value.trim="model.roleKey" :placeholder="$t('page.manage.role.form.roleKey')" @keyup.enter.native="search" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.role.roleStatus')" name="status" class="m-0">
+            <ASelect v-model:value="model.status" :placeholder="$t('page.manage.role.form.roleStatus')" allowClear @change="search">
+              <ASelectOption v-for="option in enableStatusOptions" :key="option.value" :value="option.value" >
+                {{ $t(option.label) }}
+              </ASelectOption>
+            </ASelect>
+          </AFormItem>
+        </ACol>
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem class="m-0">
+            <div class="w-full flex-y-center justify-end gap-12px">
+              <AButton @click="reset">
+                <template #icon>
+                  <icon-ic-round-refresh class="align-sub text-icon" />
+                </template>
+                <span class="ml-8px">{{ $t('common.reset') }}</span>
+              </AButton>
+              <AButton type="primary" ghost @click="search">
+                <template #icon>
+                  <icon-ic-round-search class="align-sub text-icon" />
+                </template>
+                <span class="ml-8px">{{ $t('common.search') }}</span>
+              </AButton>
+            </div>
+          </AFormItem>
+        </ACol>
+      </ARow>
+    </AForm>
+  </ACard>
+</template>
+
+<style scoped></style>

+ 220 - 0
src/views/admin/sys-user/index.vue

@@ -0,0 +1,220 @@
+<script setup lang="tsx">
+import { useTable, useTableOperate, useTableScroll } from '@/hooks/common/table';
+import { $t } from '@/locales';
+import { changeUserStatus, fetchDelteUser, fetchGetUserList } from '@/service/api';
+import { Button, Popconfirm } from 'ant-design-vue';
+import dayjs from 'dayjs';
+import { ref } from 'vue';
+import UserOperateDrawer from './modules/user-operate-drawer.vue';
+import UserResetPwdDialog from './modules/user-resetpwd-dialog.vue';
+import UserSearch from './modules/user-search.vue';
+const { tableWrapperRef, scrollConfig } = useTableScroll();
+const apiParams = ref({
+  pageIndex: 1,
+  pageSize: 10
+});
+let transUserId:number | null = null
+let userName = ''
+let resetDialogVisible = ref(false)
+
+const {
+  columns,
+  columnChecks,
+  data,
+  getData,
+  getDataByPage,
+  loading,
+  mobilePagination,
+  searchParams,
+  resetSearchParams
+} = useTable({
+  apiFn: fetchGetUserList,
+  apiParams:apiParams.value,
+  showTotal: true,
+  columns: () => [
+    {
+      key: 'userId',
+      title: '用户ID',
+      dataIndex: 'userId',
+      align: 'center',
+      width: 64
+    },
+    {
+      key: 'username',
+      dataIndex: 'username',
+      title: '登录名',
+      align: 'center',
+      minWidth: 120
+    },
+    {
+      key: 'nickName',
+      title: '昵称',
+      align: 'center',
+      dataIndex: 'nickName',
+      minWidth: 100
+    },
+    {
+      key: 'deptName',
+      dataIndex: 'deptName',
+      title: '部门',
+      align: 'center',
+      minWidth: 120,
+      customRender: ({ record }) => {
+        return record.dept.deptName;
+      }
+    },
+    {
+      key: 'phone',
+      dataIndex: 'phone',
+      title: $t('page.manage.user.userPhone'),
+      align: 'center',
+      minWidth: 120
+    },
+    {
+      key: 'status',
+      dataIndex: 'status',
+      title: $t('page.manage.user.userStatus'),
+      align: 'center',
+      minWidth: 100,
+      customRender: ({ record}) => {
+        let showStatus:boolean = record.status == '2' ? true : false;
+        const text:string = record.status == '2' ? '停用' : '启用';
+        return <Popconfirm title={`确定要${text}${record.username}的用户吗?`} onConfirm={() => handleChangeStatus(record, text)} >
+          <a-switch v-model:checked={showStatus} ></a-switch>
+        </Popconfirm>;
+      }
+    },
+    {
+      key: 'createdAt',
+      dataIndex: 'createdAt',
+      title: '创建时间',
+      align: 'center',
+      minWidth: 150,
+      customRender:({record})=>{
+        return dayjs(record.createdAt).format('YYYY-MM-DD HH:mm:ss')
+      }
+    },
+    {
+      key: 'operate',
+      title: $t('common.operate'),
+      align: 'center',
+      fixed: 'right',
+      width: 180,
+      customRender: ({ record }) => (
+        <div class="flex-center gap-0.1rem">
+          <Button type="primary" ghost size="small" onClick={() => handleRowEdit(record.userId)} style="margin-right:5px">
+            {$t('common.edit')}
+          </Button>
+          <Popconfirm title={$t('common.confirmDelete')} onConfirm={() => handleDelete(record.userId)}>
+            <Button danger size="small" style="margin-right:5px">
+              {$t('common.delete')}
+            </Button>
+          </Popconfirm>
+          <Button size="small" onClick={() => handleResetPwd(record)}>
+            重置
+          </Button>
+        </div>
+      )
+    }
+  ]
+});
+const {
+  drawerVisible,
+  operateType,
+  editingData,
+  handleAdd,
+  handleEdit,
+  checkedRowKeys,
+  rowSelection,
+  onDeleted
+  // closeDrawer
+} = useTableOperate(data, getData);
+
+async function handleBatchDelete() {
+  // request
+  handleDelete(checkedRowKeys.value)
+}
+async function handleChangeStatus(row:any, text:string){
+  const data = {
+    userId: row.userId,
+    status: text === '停用'? '1' : '2'
+  }
+  const res = await changeUserStatus(data)
+  if (res.code === 200) {
+    window.$message?.success('更新成功!');
+  } else {
+    window.$message?.error('更新失败!');
+  }
+  await getData()
+
+}
+// 删除
+async function handleDelete(id: any) {
+  // request
+  let ids = []
+  typeof id === 'number' ? ids.push(id) : ids = [].concat(id)
+  const res = await fetchDelteUser({ids})
+  if (res.code === 200) {
+    onDeleted();
+  } else {
+    window.$message?.error('删除失败!');
+  }
+}
+
+// 重置
+function handleResetPwd(row:any) {
+  resetDialogVisible.value = true
+  userName = row.username
+  transUserId = row.userId
+}
+
+// 编辑
+function handleRowEdit(id: number) {
+  handleEdit(id, 'userId');
+}
+</script>
+
+<template>
+  <div class="min-h-6.25rem flex-col-stretch gap-0.2rem overflow-hidden lt-sm:overflow-auto">
+    <UserSearch v-model:model="searchParams" @reset="resetSearchParams" @search="getDataByPage" />
+    <ACard
+      :title="$t('page.manage.user.title')"
+      :bordered="false"
+      :body-style="{ flex: 1, overflow: 'hidden' }"
+      class="flex-col-stretch sm:flex-1-hidden card-wrapper"
+    >
+      <template #extra>
+        <TableHeaderOperation
+          v-model:columns="columnChecks"
+          :disabled-delete="checkedRowKeys.length === 0"
+          :loading="loading"
+          @add="handleAdd"
+          @delete="handleBatchDelete"
+          @refresh="getData"
+        />
+      </template>
+      <ATable
+        ref="tableWrapperRef"
+        :columns="columns"
+        :data-source="data"
+        size="small"
+        :row-selection="rowSelection"
+        :scroll="scrollConfig"
+        :loading="loading"
+        row-key="userId"
+        :pagination="mobilePagination"
+        class="h-full"
+      />
+
+      <UserOperateDrawer
+        v-model:visible="drawerVisible"
+        :operate-type="operateType"
+        :row-data="editingData"
+        @submitted="getDataByPage"
+      />
+      <UserResetPwdDialog v-model:dialogVisible="resetDialogVisible" :userId="transUserId" :user-name="userName"/>
+    </ACard>
+  </div>
+</template>
+
+<style scoped></style>

+ 248 - 0
src/views/admin/sys-user/modules/user-operate-drawer.vue

@@ -0,0 +1,248 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { $t } from '@/locales';
+import { fetchAddUser, fetchGetAllRoles, fetchGetdeptTreeList, fetchGetPostList, getDicts } from '@/service/api';
+import { computed, nextTick, reactive, ref, watch } from 'vue';
+defineOptions({
+  name: 'UserOperateDrawer'
+});
+
+interface Props {
+  /** the type of operation */
+  operateType: AntDesign.TableOperateType;
+  /** the edit row data */
+  rowData?: Api.SystemManage.User | null;
+}
+
+const props = defineProps<Props>();
+
+interface Emits {
+  (e: 'submitted'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const visible = defineModel<boolean>('visible', {
+  default: false
+});
+
+const { formRef, validate, resetFields } = useAntdForm();
+const { defaultRequiredRule, formRules } = useFormRules();
+
+const title = computed(() => {
+  const titles: Record<AntDesign.TableOperateType, string> = {
+    add: $t('page.manage.user.addUser'),
+    edit: $t('page.manage.user.editUser')
+  };
+  return titles[props.operateType];
+});
+
+type Model = Pick<
+  Api.SystemManage.User,
+  'username' | 'sex' | 'nickName' | 'phone' | 'email' | 'status' | 'deptId' | 'password' | 'postId' | 'roleId' | 'remark'
+>;
+
+const model: Model = reactive(createDefaultModel());
+
+function createDefaultModel(): Model {
+  return {
+    username: '',
+    sex: '',
+    nickName: '',
+    phone: '',
+    email: '',
+    status: '2',
+    deptId: '',
+    password: '',
+    postId: '',
+    roleId: '',
+    remark: ''
+  };
+}
+
+type RuleKey = Extract<keyof Model, 'username' | 'status'| 'nickName'| 'deptId' | 'password'| 'email' | 'phone'>;
+
+const rules: Record<RuleKey, App.Global.FormRule> = {
+  username: defaultRequiredRule,
+  nickName: defaultRequiredRule,
+  deptId: defaultRequiredRule,
+  password: defaultRequiredRule,
+  phone: formRules.phone,
+  email:formRules.email
+};
+
+/** the enabled role options */
+const roleOptions = ref<CommonType.Option<string>[]>([]);
+const userGenderOptions = ref<CommonType.Option<string>[]>([
+  {label: "男", value: "0"},
+  {label: "女", value: "1"},
+  {label: "未知", value: "2"}
+]);
+const enableStatusOptions = ref<CommonType.Option<string>[]>([]);
+const postOptions = ref<CommonType.Option<string>[]>([]);
+const departOptions = ref<CommonType.Option<string>[]>([]);
+
+async function getSixOptions(){
+  const { data } = await getDicts('sys_user_sex')
+  userGenderOptions.value = data || []
+}
+async function getStatusOptions(){
+  const { data } = await getDicts('sys_normal_disable')
+  enableStatusOptions.value = data || []
+}
+async function getPostOptions(){
+  const { data } = await fetchGetPostList({ pageSize: 1000 })
+  const options = data?.list.map((item:any) => ({
+    label: item.postName,
+    value: item.postId,
+    postCode: item.postCode
+  }));
+  postOptions.value = [...options] || []
+}
+async function getDeptTree(){
+  const { data } = await fetchGetdeptTreeList()
+  departOptions.value = data
+}
+
+async function getRoleOptions() {
+  const { data } = await fetchGetAllRoles({ pageSize: 1000 });
+  const options = data?.list.map((item:any) => ({
+    label: item.roleName,
+    value: item.roleId,
+    status: item.status
+  }));
+  roleOptions.value = [...options];
+}
+
+async function handleInitModel() {
+  Object.assign(model, createDefaultModel());
+
+  if (props.operateType === 'edit' && props.rowData) {
+    await nextTick();
+    Object.assign(model, props.rowData);
+  }
+}
+
+function closeDrawer() {
+  visible.value = false;
+}
+
+async function handleSubmit() {
+  await validate();
+  // request 新增method 是post 修改是put
+  let method = ''
+  if (props.operateType === 'add') {
+    method = 'post'
+  } else {
+    method = 'put'
+  }
+  const res = await fetchAddUser(model, method)
+  if (res.code === 200){
+    window.$message?.success(res.msg);
+  }
+  closeDrawer();
+  emit('submitted');
+}
+
+watch(visible, () => {
+  if (visible.value) {
+    handleInitModel();
+    resetFields();
+    getRoleOptions();
+    getSixOptions()
+    getStatusOptions()
+    getPostOptions()
+    getDeptTree()
+  }
+});
+</script>
+
+<template>
+  <AModal v-model:open="visible" :title="title" width="800px">
+    <AForm ref="formRef"  :model="model" :rules="rules" :label-col="{ lg: 8, xs: 4 }" label-wrap class="pr-20px">
+      <ARow  wrap>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.nickName')" name="nickName">
+            <AInput v-model:value="model.nickName" :placeholder="$t('page.manage.user.form.nickName')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.deptId')" name="roleId">
+            <ATreeSelect v-model:value="model.deptId" show-search  :tree-data="departOptions"
+            :fieldNames="{value: 'id', children: 'children', label: 'label'}"
+              :placeholder="$t('page.manage.user.form.deptId')" allowClear/>
+          </AFormItem>
+        </ACol>
+      </ARow>
+      <ARow wrap>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userPhone')" name="phone">
+            <AInput v-model:value="model.phone" :placeholder="$t('page.manage.user.form.userPhone')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userEmail')" name="email">
+            <AInput v-model:value="model.email" :placeholder="$t('page.manage.user.form.userEmail')" allowClear/>
+          </AFormItem>
+        </ACol>
+      </ARow>
+      <ARow wrap>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userName')" name="username">
+            <AInput v-model:value="model.username" :placeholder="$t('page.manage.user.form.userName')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24" v-if="props.operateType === 'add'">
+          <AFormItem :label="$t('page.manage.user.password')" name="password" >
+            <AInput v-model:value="model.password" :placeholder="$t('page.manage.user.form.password')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userGender')" name="sex">
+            <ARadioGroup v-model:value="model.sex">
+              <ARadio v-for="item in userGenderOptions" :key="item.value" :value="item.value">
+                {{item.label }}
+              </ARadio>
+            </ARadioGroup>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userStatus')" name="status">
+            <ARadioGroup v-model:value="model.status">
+              <ARadio v-for="item in enableStatusOptions" :key="item.value" :value="item.value">
+                {{ item.label }}
+              </ARadio>
+            </ARadioGroup>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="12" :xs="24">
+          <AFormItem :label="$t('page.manage.user.postId')" name="postId">
+            <ASelect v-model:value="model.postId" :options="postOptions"
+              :placeholder="$t('page.manage.user.form.postId')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="12" :md="props.operateType === 'add'? 12: 24" :xs="24">
+          <AFormItem :label="$t('page.manage.user.userRole')" name="roleId">
+            <ASelect v-model:value="model.roleId"  :options="roleOptions"
+              :placeholder="$t('page.manage.user.form.userRole')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="24" :md="24" :xs="24">
+          <AFormItem :label-col="{ lg: 4, xs: 2 }" :label="$t('page.manage.user.remark')" name="remark">
+            <a-textarea v-model:value="model.remark" :placeholder="$t('page.manage.user.form.remark')"
+              :auto-size="{ minRows: 2, maxRows: 5 }" allowClear/>
+          </AFormItem>
+        </ACol>
+      </ARow>
+    </AForm>
+    <template #footer>
+      <ASpace :size="16">
+        <AButton @click="closeDrawer">{{ $t('common.cancel') }}</AButton>
+        <AButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</AButton>
+      </ASpace>
+    </template>
+  </AModal>
+</template>
+
+<style scoped></style>

+ 65 - 0
src/views/admin/sys-user/modules/user-resetpwd-dialog.vue

@@ -0,0 +1,65 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { fetchRestPwsUser } from '@/service/api';
+import { reactive, watch } from 'vue';
+defineOptions({
+  name: 'UserResetPwdDialog'
+});
+const visible = defineModel<boolean>('dialogVisible', {
+  default: false
+});
+interface Props {
+  userId: number | null,
+  userName: string | null
+}
+const props = defineProps<Props>();
+const model = reactive(createDefaultModel());
+const { formRef, validate, resetFields } = useAntdForm();
+const { formRules } = useFormRules();
+function createDefaultModel(){
+  return {
+    password: '',
+    userId: props.userId
+  };
+}
+const rules: Record<'password', App.Global.FormRule> = {
+  password: formRules.pwd,
+};
+
+function closeDrawer() {
+  visible.value = false;
+}
+async function handleSubmit() {
+  await validate();
+  model.userId = props.userId
+
+  const res = await fetchRestPwsUser(model)
+  if (res.code === 200){
+    window.$message?.success(res.msg);
+  }
+  closeDrawer();
+}
+watch(visible, () => {
+  if (visible.value) {
+    resetFields();
+  }
+});
+</script>
+<template>
+  <AModal v-model:open="visible" title="重置密码" width="420px">
+    <!-- <p style="margin-bottom: 10px;"></p> -->
+    <AForm ref="formRef" layout="vertical" :model="model" :rules="rules">
+      <AFormItem :label="`请输入${userName}的新密码`" name="password">
+        <AInput v-model:value="model.password" placeholder="请输入新密码" allowClear/>
+      </AFormItem>
+    </AForm>
+    <template #footer>
+      <ASpace :size="16">
+        <AButton @click="closeDrawer">{{ $t('common.cancel') }}</AButton>
+        <AButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</AButton>
+      </ASpace>
+    </template>
+  </AModal>
+</template>
+<style scoped></style>

+ 137 - 0
src/views/admin/sys-user/modules/user-search.vue

@@ -0,0 +1,137 @@
+/* eslint-disable */
+<script setup lang="ts">
+import { enableStatusOptions } from '@/constants/business';
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { $t } from '@/locales';
+import { fetchGetdeptTreeList } from '@/service/api';
+import { translateOptions } from '@/utils/common';
+import { computed, onMounted, ref } from 'vue';
+defineOptions({
+  name: 'UserSearch'
+});
+
+interface Emits {
+  (e: 'reset'): void;
+  (e: 'search'): void;
+}
+
+const emit = defineEmits<Emits>();
+const departOptions = ref<CommonType.Option<string>[]>([]);
+const { formRef, validate, resetFields } = useAntdForm();
+
+const model = defineModel<Api.SystemManage.UserSearchParams>('model', { required: true });
+
+type RuleKey = Extract<keyof Api.SystemManage.UserSearchParams, 'email' | 'phone'>;
+
+const rules = computed<Record<RuleKey, App.Global.FormRule>>(() => {
+  const { patternRules } = useFormRules(); // inside computed to make locale reactive
+
+  return {
+    email: patternRules.email,
+    phone: patternRules.phone
+  };
+});
+onMounted(()=>{
+  getDeptTree()
+})
+async function getDeptTree(){
+  const { data } = await fetchGetdeptTreeList()
+  departOptions.value = data
+}
+async function reset() {
+  await resetFields();
+  emit('reset');
+}
+
+async function search() {
+  await validate();
+  emit('search');
+}
+
+</script>
+
+<template>
+  <ACard :title="$t('common.search')" :bordered="false" class="card-wrapper">
+    <AForm
+      ref="formRef"
+      :model="model"
+      :rules="rules"
+      :label-col="{
+        span: 5,
+        md: 7
+      }"
+    >
+      <ARow :gutter="[16, 16]" wrap>
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.user.userName')" name="username" class="m-0">
+            <AInput v-model:value.trim="model.username" :placeholder="$t('page.manage.user.form.userName')" @keyup.enter.native="search" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.user.deptId')" name="roleId">
+            <ATreeSelect v-model:value="model.deptId" show-search  :tree-data="departOptions"
+            :fieldNames="{value: 'id', children: 'children', label: 'label'}" @change="search"
+              :placeholder="$t('page.manage.user.form.deptId')" allowClear/>
+          </AFormItem>
+        </ACol>
+
+        <!-- <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.user.userGender')" name="sex" class="m-0">
+            <ASelect
+              v-model:value="model.sex"
+              :placeholder="$t('page.manage.user.form.userGender')"
+              :options="translateOptions(userGenderOptions)"
+              clearable
+            />
+          </AFormItem>
+        </ACol> -->
+        <!-- <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.user.nickName')" name="nickName" class="m-0">
+            <AInput v-model:value="model.nickName" :placeholder="$t('page.manage.user.form.nickName')" />
+          </AFormItem>
+        </ACol> -->
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.user.userPhone')" name="phone" class="m-0">
+            <AInput v-model:value.trim="model.phone" :placeholder="$t('page.manage.user.form.userPhone')" @keyup.enter.native="search" allowClear/>
+          </AFormItem>
+        </ACol>
+        <!-- <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.user.userEmail')" name="email" class="m-0">
+            <AInput v-model:value="model.email" :placeholder="$t('page.manage.user.form.userEmail')" />
+          </AFormItem>
+        </ACol> -->
+        <ACol :span="24" :md="12" :lg="6">
+          <AFormItem :label="$t('page.manage.user.userStatus')" name="status" class="m-0">
+            <ASelect
+              v-model:value="model.status"
+              :placeholder="$t('page.manage.user.form.userStatus')"
+              :options="translateOptions(enableStatusOptions)"
+              @change="search"
+              allowClear
+            />
+          </AFormItem>
+        </ACol>
+        <div class="flex-1">
+          <AFormItem class="m-0">
+            <div class="w-full flex-y-center justify-end gap-12px">
+              <AButton @click="reset">
+                <template #icon>
+                  <icon-ic-round-refresh class="align-sub text-icon" />
+                </template>
+                <span class="ml-8px">{{ $t('common.reset') }}</span>
+              </AButton>
+              <AButton type="primary" ghost @click="search">
+                <template #icon>
+                  <icon-ic-round-search class="align-sub text-icon" />
+                </template>
+                <span class="ml-8px">{{ $t('common.search') }}</span>
+              </AButton>
+            </div>
+          </AFormItem>
+        </div>
+      </ARow>
+    </AForm>
+  </ACard>
+</template>
+
+<style scoped></style>

+ 494 - 0
src/views/business-analysis/system-space/index.vue

@@ -0,0 +1,494 @@
+<script setup lang="ts">
+import { reactive, ref } from 'vue';
+</script>
+
+<template>
+  <div class="ob-basic-layout">
+    <div class="system-content">
+      <div class="system-left-content">
+        <!-- 基本信息 -->
+        <div class="system-basic-info">
+          <span class="fontSize16">基本信息</span>
+          <div>
+            <p class="service-header-p">
+              <span class="service-span-right">应用:</span>
+              <ElTooltip class="item" effect="dark" :content="appItem.name + '(' + appItem.alias + ')'" placement="top">
+                <span class="service-span-left">{{ appItem.name }} ({{ appItem.alias }})</span>
+              </ElTooltip>
+            </p>
+          </div>
+        </div>
+        <!-- 性能指标概述 -->
+        <div class="performance-box">
+          <div class="performance-title">
+            <div class="title-info">整体性能</div>
+            <div class="title-info-icon-box">
+              <ElTooltip placement="top">
+                <template #content>
+                  <div>
+                    <div style="text-align: center; padding: 1px 0 6px">性能说明</div>
+                    <div>
+                      <div>
+                        <span>性能极佳:</span>
+                        <span>应用分数 >= 0.94</span>
+                      </div>
+                      <div>
+                        <span>性能较好:</span>
+                        <span>0.85 <= 应用分数 < 0.94</span>
+                      </div>
+                      <div>
+                        <span>性能一般:</span>
+                        <span>0.50 <= 应用分数 < 0.85</span>
+                      </div>
+                      <div>
+                        <span>性能未知:</span>
+                        <span>应用分数 < 0.50</span>
+                      </div>
+                    </div>
+                  </div>
+                </template>
+                <!-- <i class="el-icon-question" /> -->
+                <img class="icon-help" src="../../../assets/icons/help.svg" />
+              </ElTooltip>
+            </div>
+          </div>
+          <div class="performance-content">
+            <div class="performance-content-left">
+              <div class="apdex-box">
+                <div
+                  class="apdex-con"
+                  :class="
+                    ApdexNum >= 0.94
+                      ? 'gc'
+                      : ApdexNum >= 0.85 && ApdexNum < 0.94
+                        ? 'bc'
+                        : ApdexNum >= 0.7 && ApdexNum < 0.85
+                          ? 'grc'
+                          : ApdexNum >= 0.5 && ApdexNum < 0.7
+                            ? 'oc'
+                            : 'rc'
+                  "
+                >
+                  {{
+                    ApdexNum >= 0.94
+                      ? '性能极佳'
+                      : ApdexNum >= 0.85 && ApdexNum < 0.94
+                        ? '性能较好'
+                        : ApdexNum >= 0.7 && ApdexNum < 0.85
+                          ? '性能一般'
+                          : ApdexNum >= 0.5 && ApdexNum < 0.7
+                            ? '性能一般'
+                            : '性能未知'
+                  }}
+                </div>
+              </div>
+            </div>
+            <div class="performance-content-right">
+              <div class="formula-title">
+                <div style="padding-bottom: 2px">计算公式:</div>
+                {{
+                  truncateNumber(
+                    (performanceObj.satisfied + performanceObj.tolerable / 2) /
+                      (performanceObj.satisfied + performanceObj.tolerable + performanceObj.highLatencyNum),
+                    2
+                  )
+                }}=({{ performanceObj.satisfied }}+{{ performanceObj.tolerable }}/2)/{{
+                  performanceObj.satisfied + performanceObj.tolerable + performanceObj.highLatencyNum
+                }}
+              </div>
+              <div class="formula-content">
+                <div class="item">
+                  <span class="item-name">较满意请求:</span>
+                  <span class="item-info">{{ performanceObj.satisfied }}</span>
+                </div>
+                <div class="item">
+                  <span class="item-name">可容忍请求:</span>
+                  <span class="item-info">{{ performanceObj.tolerable }}</span>
+                </div>
+                <div class="item">
+                  <span class="item-name">高延迟请求:</span>
+                  <span class="item-info">{{ performanceObj.highLatencyNum }}</span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <!-- 面板数据-->
+        <div class="panel-box">
+          <div class="panel-item">
+            <ElTooltip placement="bottom" effect="dark" :visible-arrow="false">
+              <template #content>
+                <div>
+                  <i class="dot" />
+                  <span>自己关注业务总数</span>
+                </div>
+              </template>
+              <div class="icon-box">
+                <img class="icon-help" src="../../../assets/icons/help.svg" />
+              </div>
+            </ElTooltip>
+            <div>
+              <div class="panel-item-tit">重点业务总数</div>
+              <div class="panel-item-con">{{ digitsObj.vip_biz != undefined ? digitsObj.vip_biz : 0 }}</div>
+            </div>
+          </div>
+          <div class="panel-item">
+            <ElTooltip effect="dark" :visible-arrow="false">
+              <template #content>
+                <div>
+                  <i class="dot" />
+                  <span>当前应用所包含的服务包总数</span>
+                </div>
+              </template>
+              <div class="icon-box">
+                <img class="icon-help" src="../../../assets/icons/help.svg" />
+              </div>
+            </ElTooltip>
+            <div>
+              <div class="panel-item-tit">部署包总数</div>
+              <div class="panel-item-con">{{ digitsObj.service || 0 }}</div>
+            </div>
+          </div>
+          <div class="panel-item">
+            <ElTooltip placement="bottom" effect="dark" :visible-arrow="false">
+              <template #content>
+                <div>
+                  <i class="dot" />
+                  <span>当前应用所涉及的消息系统总数</span>
+                </div>
+              </template>
+              <div class="icon-box">
+                <img class="icon-help" src="../../../assets/icons/help.svg" />
+              </div>
+            </ElTooltip>
+            <div>
+              <div class="panel-item-tit">中间件总数</div>
+              <div class="panel-item-con">{{ digitsObj.messaging != undefined ? Number(digitsObj.messaging) : 0 }}</div>
+            </div>
+          </div>
+          <div class="panel-item">
+            <ElTooltip placement="bottom" effect="dark" :visible-arrow="false">
+              <template #content>
+                <div>
+                  <i class="dot" />
+                  <span>当前应用所包含的数据库类型总数</span>
+                </div>
+              </template>
+              <div class="icon-box">
+                <img class="icon-help" src="../../../assets/icons/help.svg" />
+              </div>
+            </ElTooltip>
+            <div>
+              <div class="panel-item-tit">数据库总数</div>
+              <div class="panel-item-con">{{ digitsObj.database != undefined ? Number(digitsObj.database) : 0 }}</div>
+            </div>
+          </div>
+        </div>
+        <!-- 性能指标面板 -->
+        <div class="performance-panel-box">
+          <div class="performance-panel-item">
+            <ElTooltip placement="bottom" effect="dark" :visible-arrow="false">
+              <template #content>
+                <div>
+                  <i class="dot" />
+                  <span>当日应用所涉及的业务请求总数</span>
+                </div>
+              </template>
+              <div class="icon-box">
+                <img class="icon-help" src="../../../assets/icons/help.svg" />
+              </div>
+            </ElTooltip>
+            <div>
+              <div class="performance-panel-item-tit">业务请求总数</div>
+              <div class="performance-panel-item-con">{{ digitsObj.request_total || 0 }}</div>
+              <div class="performance-panel-item-day-rate">
+                日同比
+                <i
+                  v-show="processNumber(digitsObj.request_total_dod).sign"
+                  :class="
+                    processNumber(digitsObj.request_total_dod).sign == 'up'
+                      ? 'el-icon-top goUpColor'
+                      : processNumber(digitsObj.request_total_dod).sign == 'down'
+                        ? 'el-icon-bottom goDownColor'
+                        : 'el-icon-minus equalColor'
+                  "
+                />
+                <span>
+                  {{
+                    digitsObj.request_total_dod == undefined || digitsObj.request_total_dod == '0'
+                      ? ''
+                      : getErrRate(processNumber(digitsObj.request_total_dod).value)
+                  }}
+                </span>
+              </div>
+              <div class="inchart-box">
+                <RequestInChart />
+              </div>
+            </div>
+          </div>
+          <div class="performance-panel-item">
+            <ElTooltip placement="bottom" effect="dark" :visible-arrow="false">
+              <template #content>
+                <div>
+                  <i class="dot" />
+                  <span>当日应用所涉及的业务请求错误总数</span>
+                </div>
+              </template>
+              <div class="icon-box">
+                <img class="icon-help" src="../../../assets/icons/help.svg" />
+              </div>
+            </ElTooltip>
+            <div @click="goPage">
+              <div class="performance-panel-item-tit">业务错误数</div>
+              <div class="performance-panel-item-con">{{ digitsObj.error_num || 0 }}</div>
+              <div class="performance-panel-item-day-rate">
+                日同比
+                <i
+                  v-show="processNumber(digitsObj.error_num_dod).sign"
+                  :class="
+                    processNumber(digitsObj.error_num_dod).sign == 'up'
+                      ? 'el-icon-top goUpColor'
+                      : processNumber(digitsObj.error_num_dod).sign == 'down'
+                        ? 'el-icon-bottom goDownColor'
+                        : 'el-icon-minus equalColor'
+                  "
+                />
+                <span>
+                  {{
+                    digitsObj.error_num_dod == undefined || digitsObj.error_num_dod == '0'
+                      ? ''
+                      : getErrRate(processNumber(digitsObj.error_num_dod).value)
+                  }}
+                </span>
+              </div>
+              <div class="inchart-box">
+                <RequestInChart />
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div></div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.ob-basic-layout {
+  padding: 10px;
+  box-sizing: border-box;
+  .system-content {
+    display: flex;
+    background: #f0f1f5;
+    font-family: Roboto, sans-serif;
+    .system-left-content {
+      position: relative;
+      height: calc(100vh - 78px);
+      padding: 20px 10px;
+      box-sizing: border-box;
+      width: 30%; /* 设置左边盒子的初始宽度 */
+      min-width: 350px;
+      background-color: #fff;
+      margin-right: 16px;
+      border: 1px solid #f5f5f5;
+      overflow-y: auto;
+      .system-basic-info {
+        height: 100px;
+        border-radius: 8px;
+        color: #4e5969;
+        padding: 16px;
+        box-sizing: border-box;
+        background: url('../../../assets/pic-bg.png');
+        background-position: right;
+        background-size: cover;
+        background-repeat: no-repeat;
+        .service-header-p {
+          font-weight: bold;
+          font-size: 16px;
+          margin-bottom: 0;
+          margin-top: 20px;
+          display: flex;
+          align-items: center;
+          span {
+            display: inline-block;
+          }
+          .service-span-right {
+            text-align: left;
+            width: 58px;
+          }
+          .service-span-left {
+            text-align: left;
+            cursor: pointer;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+          }
+        }
+      }
+      .panel-box {
+        width: 100%;
+        // font-size: 0;
+        padding-top: 10px;
+        .panel-item {
+          position: relative;
+          display: inline-flex;
+          width: calc(50% - 5px);
+          box-sizing: border-box;
+          height: 100px;
+          background: linear-gradient(155deg, #ffffff 0%, #ffffff 50%, #eff4ff 100%);
+          border: 1px solid rgba(96, 97, 112, 0.07);
+          margin: 0 10px 10px 0;
+          justify-content: center;
+          align-items: center;
+          padding: 0 10px;
+          border-radius: 8px;
+          .icon-box {
+            position: absolute;
+            right: 10px;
+            top: 10px;
+            i {
+              font-size: 16px;
+            }
+          }
+          &:nth-child(even) {
+            margin-right: 0;
+          }
+          .panel-item-tit {
+            font-weight: bold;
+            font-size: 16px;
+            color: #4e5969;
+            text-align: center;
+          }
+          .panel-item-con {
+            font-weight: bold;
+            font-size: 36px;
+            color: #1a2233;
+            margin-top: 10px;
+            text-align: center;
+          }
+          .panel-item-day-rate {
+            font-size: 10px;
+            opacity: 0.9;
+          }
+        }
+      }
+      .performance-box {
+        width: 100%;
+        padding-top: 10px;
+        border: 1px solid rgba(96, 97, 112, 0.07);
+        border-radius: 8px;
+        margin-top: 10px;
+        .performance-title {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          height: 30px;
+          padding: 0 10px;
+          .title-info {
+            font-size: 16px;
+            font-weight: bold;
+            // color: '#1a2233';
+          }
+          .title-info-icon-box {
+            font-size: 16px;
+          }
+        }
+        .performance-content {
+          display: flex;
+          justify-content: space-between;
+          .performance-content-left {
+            align-self: center;
+            min-width: 110px;
+            padding-left: 10px;
+            flex: 1;
+            .apdex-box {
+              box-sizing: border-box;
+              color: #fff;
+              .apdex-con {
+                height: 72px;
+                line-height: 72px;
+                text-align: center;
+                font-size: 16px;
+                font-weight: bold;
+                border-radius: 3px;
+              }
+            }
+          }
+          .performance-content-right {
+            font-size: 10px;
+            padding: 10px;
+            // min-width: 200px;
+            .formula-title {
+              line-height: 14px;
+              font-weight: bold;
+              margin-bottom: 2px;
+              text-align: center;
+            }
+            .formula-content {
+              line-height: 14px;
+              .item {
+                display: flex;
+                justify-content: space-between;
+                .item-info {
+                  align-self: flex-start;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    .performance-panel-box {
+      margin: 10px 0;
+      .performance-panel-item {
+        position: relative;
+        display: inline-flex;
+        width: calc(50% - 5px);
+        box-sizing: border-box;
+        // height: 160px;
+        background: linear-gradient(155deg, #ffffff 0%, #ffffff 50%, #eff4ff 100%);
+        border: 1px solid rgba(96, 97, 112, 0.07);
+        margin: 0 10px 10px 0;
+        justify-content: space-between;
+        align-items: center;
+        padding: 0 10px;
+        border-radius: 8px;
+        cursor: pointer;
+        .icon-box {
+          position: absolute;
+          right: 10px;
+          top: 10px;
+          i {
+            font-size: 16px;
+          }
+        }
+        &:nth-child(even) {
+          margin-right: 0;
+        }
+        .performance-panel-item-tit {
+          font-weight: bold;
+          font-size: 16px;
+          color: #4e5969;
+          padding: 10px 0px 10px;
+          // text-align: center;
+        }
+        .performance-panel-item-con {
+          font-weight: bold;
+          font-size: 36px;
+          color: #1a2233;
+          // margin-top:10px;
+          // text-align: center;
+        }
+        .performance-panel-item-day-rate {
+          font-size: 12px;
+          opacity: 0.9;
+        }
+        .inchart-box {
+          width: 100%;
+          margin: 20px 0;
+        }
+      }
+    }
+  }
+}
+</style>

+ 54 - 34
src/views/manage/menu/index.vue

@@ -1,17 +1,17 @@
 <script setup lang="tsx">
-import { useTable, useTableOperate, useTableScroll } from '@/hooks/common/table';
-import { $t } from '@/locales';
-import { fetchDeleteMenu, fetchGetAllPages, fetchGetMenuList, getDicts } from '@/service/api';
 import { useBoolean } from '@sa/hooks';
 import { Button, Popconfirm } from 'ant-design-vue';
 import type { Ref } from 'vue';
-import { ref, onMounted } from 'vue';
-import MenuOperateModal, { type OperateType } from './modules/menu-operate-modal.vue';
+import { onMounted, ref } from 'vue';
 import SvgIcon from '@/components/custom/svg-icon.vue';
-import MenuSearch from './modules/menu-search.vue'
+import { useTable, useTableOperate, useTableScroll } from '@/hooks/common/table';
+import { $t } from '@/locales';
+import { fetchDeleteMenu, fetchGetAllPages, fetchGetMenuList, getDicts } from '@/service/api';
+import MenuOperateModal, { type OperateType } from './modules/menu-operate-modal.vue';
+import MenuSearch from './modules/menu-search.vue';
 const { bool: visible, setTrue: openModal } = useBoolean();
 const { tableWrapperRef, scrollConfig } = useTableScroll();
-const visibleOptions = ref([])
+const visibleOptions = ref([]);
 const { columns, columnChecks, data, loading, getData, getDataByPage, searchParams, resetSearchParams } = useTable({
   apiFn: fetchGetMenuList,
   apiParams: {
@@ -40,7 +40,7 @@ const { columns, columnChecks, data, loading, getData, getDataByPage, searchPara
       customRender: ({ record }) => {
         return (
           <div class="flex-center">
-            <SvgIcon localIcon={record.icon}  class="text-icon" />
+            <SvgIcon localIcon={record.icon} class="text-icon" />
           </div>
         );
       }
@@ -50,11 +50,18 @@ const { columns, columnChecks, data, loading, getData, getDataByPage, searchPara
       title: '组件路径',
       align: 'center',
       customRender: ({ record }) => {
-        if (record.menuType=='A') {
-          return <a-tooltip placement="top" title={record.path}>{record.path}</a-tooltip>;
-        } else {
-          return <a-tooltip placement="top" title={record.component}>{record.component}</a-tooltip>
+        if (record.menuType == 'A') {
+          return (
+            <a-tooltip placement="top" title={record.path}>
+              {record.path}
+            </a-tooltip>
+          );
         }
+        return (
+          <a-tooltip placement="top" title={record.component}>
+            {record.component}
+          </a-tooltip>
+        );
       }
     },
     {
@@ -63,7 +70,11 @@ const { columns, columnChecks, data, loading, getData, getDataByPage, searchPara
       dataIndex: 'permission',
       align: 'center',
       customRender: ({ record }) => {
-        return  <a-tooltip placement="top" title={record.permission}><span >{record.permission || '--' }</span></a-tooltip>
+        return (
+          <a-tooltip placement="top" title={record.permission}>
+            <span>{record.permission || '--'}</span>
+          </a-tooltip>
+        );
       }
     },
     {
@@ -80,7 +91,11 @@ const { columns, columnChecks, data, loading, getData, getDataByPage, searchPara
       width: 90,
       align: 'center',
       customRender: ({ record }) => {
-        return  <a-tag color={record.visible === '1'? 'error' : 'success'}><span >{visibleFormat(record) }</span></a-tag>
+        return (
+          <a-tag color={record.visible === '1' ? 'error' : 'success'}>
+            <span>{visibleFormat(record)}</span>
+          </a-tag>
+        );
       }
     },
     {
@@ -122,14 +137,14 @@ function handleAdd() {
 
 async function handleBatchDelete() {
   // request
-  handleDelete(checkedRowKeys.value)
+  handleDelete(checkedRowKeys.value);
 }
 
 async function handleDelete(id: any) {
   // request
-  let ids = []
-  typeof id === 'number' ? ids.push(id) : ids = [].concat(id)
-  const res = await fetchDeleteMenu({ids})
+  let ids = [];
+  typeof id === 'number' ? ids.push(id) : (ids = [].concat(id));
+  const res = await fetchDeleteMenu({ ids });
   if (res.code === 200) {
     onDeleted();
   } else {
@@ -164,28 +179,28 @@ async function getAllPages() {
 function init() {
   getAllPages();
 }
-async function getOptions (){
-  const res  = await getDicts('sys_show_hide')
+async function getOptions() {
+  const res = await getDicts('sys_show_hide');
   if (res.code == 200) {
-    visibleOptions.value = res.data
+    visibleOptions.value = res.data;
   }
 }
 // 菜单显示状态字典翻译
-function visibleFormat(row:any) {
+function visibleFormat(row: any) {
   if (row.menuType === 'F') {
-    return '--'
+    return '--';
   }
-  return selectDictLabel(visibleOptions.value, row.visible)
+  return selectDictLabel(visibleOptions.value, row.visible);
 }
-function selectDictLabel(datas:any, value:any) {
-  var actions:any = []
-  Object.keys(datas).map((key) => {
-    if (datas[key].value === ('' + value)) {
-      actions.push(datas[key].label)
-      return false
+function selectDictLabel(datas: any, value: any) {
+  const actions: any = [];
+  Object.keys(datas).map(key => {
+    if (datas[key].value === `${value}`) {
+      actions.push(datas[key].label);
+      return false;
     }
-  })
-  return actions.join('')
+  });
+  return actions.join('');
 }
 // init
 init();
@@ -193,7 +208,12 @@ init();
 
 <template>
   <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
-    <MenuSearch v-model:model="searchParams" @reset="resetSearchParams" @search="getDataByPage(1, false)"  :visibleOptions="visibleOptions"/>
+    <MenuSearch
+      v-model:model="searchParams"
+      :visible-options="visibleOptions"
+      @reset="resetSearchParams"
+      @search="getDataByPage(1, false)"
+    />
     <ACard
       :title="$t('page.manage.menu.title')"
       :bordered="false"
@@ -227,7 +247,7 @@ init();
         :operate-type="operateType"
         :row-data="editingData"
         :all-pages="allPages"
-        :visibleOptions="visibleOptions"
+        :visible-options="visibleOptions"
         @submitted="getDataByPage"
       />
     </ACard>

+ 27 - 18
src/views/manage/menu/modules/menu-operate-modal.vue

@@ -1,12 +1,12 @@
 <script setup lang="tsx">
-import { computed, nextTick, reactive, ref, watch } from 'vue';
-import { SimpleScrollbar } from '@sa/materials';
+import SvgIcon from '@/components/custom/svg-icon.vue';
+import { menuTypeOptions } from '@/constants/business';
 import { useAntdForm, useFormRules } from '@/hooks/common/form';
 import { $t } from '@/locales';
-import { menuTypeOptions } from '@/constants/business';
-import SvgIcon from '@/components/custom/svg-icon.vue';
+import { fetchAddMenu, fetchGetMenuDetail, fetchGetMenuList, fetchGetSysApiList, fetchUpdateMenu } from '@/service/api';
 import { getLocalIcons } from '@/utils/icon';
-import { fetchGetMenuList, fetchAddMenu, fetchGetSysApiList, fetchGetMenuDetail, fetchUpdateMenu} from '@/service/api';
+import { SimpleScrollbar } from '@sa/materials';
+import { computed, nextTick, reactive, ref, watch } from 'vue';
 // import {
 //   getLayoutAndPage,
 //   getPathParamFromRoutePath,
@@ -16,7 +16,7 @@ import { fetchGetMenuList, fetchAddMenu, fetchGetSysApiList, fetchGetMenuDetail,
 // } from './shared';
 
 import {
-  QuestionCircleFilled,
+QuestionCircleFilled
 } from '@ant-design/icons-vue';
 defineOptions({
   name: 'MenuOperateModal'
@@ -300,8 +300,8 @@ watch(visible, () => {
   <AModal v-model:open="visible" :title="title"  width="800px">
     <div class="h-480px">
       <SimpleScrollbar>
-        <AForm ref="formRef" layout="vertical" :model="model" :rules="rules" :label-col="{ lg: 8, xs: 4 }" label-wrap class="pr-20px" :labelAlign="'left'">
-          <ARow :gutter="[16,16]" wrap>
+        <AForm ref="formRef"  :model="model" :rules="rules" :label-col="{ lg: 8, xs: 4 }" label-wrap class="pr-20px">
+          <ARow wrap>
             <ACol :lg="12" :xs="24">
               <AFormItem label="上级菜单" name="parentId">
                 <ATreeSelect v-model:value="model.parentId" show-search  :tree-data="menuOptions"
@@ -314,12 +314,12 @@ watch(visible, () => {
                 <template #label>
                   <span class="marginRight5">{{$t('page.manage.menu.menuName')}}</span>
                   <ATooltip>
-                    <template #title>包含目录:以及菜单或者菜单组,菜单:具体对应某一个页面,按钮:功能才做按钮.</template>
+                    <template #title>菜单位置显示的说明信息.</template>
                     <QuestionCircleFilled />
                   </ATooltip>
                 </template>
 
-                <AInput v-model:value="model.title" :placeholder="$t('page.manage.menu.form.menuName')" />
+                <AInput v-model:value="model.title" :placeholder="$t('page.manage.menu.form.menuName')" allowClear/>
               </AFormItem>
             </ACol>
             <ACol :lg="12" :xs="24">
@@ -331,7 +331,7 @@ watch(visible, () => {
                     <QuestionCircleFilled />
                   </ATooltip>
                 </template>
-                <AInputNumber v-model:value="model.sort as number"  :placeholder="$t('page.manage.menu.form.order')"  class="w-full"/>
+                <AInputNumber v-model:value="model.sort as number"  :placeholder="$t('page.manage.menu.form.order')"  class="w-full" />
 
               </AFormItem>
             </ACol>
@@ -361,7 +361,7 @@ watch(visible, () => {
                     <QuestionCircleFilled />
                   </ATooltip>
                 </template>
-                <AInput v-model:value="model.menuName" :placeholder="$t('page.manage.menu.form.routeName')" />
+                <AInput v-model:value="model.menuName" :placeholder="$t('page.manage.menu.form.routeName')" allowClear/>
               </AFormItem>
             </ACol>
             <ACol :lg="12" :xs="24" v-if="model.menuType == 'M' || model.menuType == 'C'" >
@@ -369,25 +369,26 @@ watch(visible, () => {
                 <template #label>
                   <span class="marginRight5">{{ $t('page.manage.menu.routePath') }}</span>
                   <ATooltip>
-                    <template #title>菜单对应的具体vue页面文件路径views的下级路径/admin/sys-api/index;目录类型:填写Layout,如何有二级目录请参照日志目录填写;</template>
+                    <template #title>菜单对应的具体vue页面文件路径;</template>
                     <QuestionCircleFilled />
                   </ATooltip>
                 </template>
-                <AInput v-model:value="model.component"  :placeholder="$t('page.manage.menu.form.routePath')" />
+                <AInput v-model:value="model.component"  :placeholder="$t('page.manage.menu.form.routePath')" allowClear/>
               </AFormItem>
             </ACol>
 
             <ACol :lg="12" :xs="24"  v-if="model.menuType != 'F'">
               <AFormItem label="路由地址" name="path">
-                <AInput v-model:value="model.path" placeholder="请输入路由地址" />
+                <AInput v-model:value="model.path" placeholder="请输入路由地址" allowClear/>
               </AFormItem>
             </ACol>
-            <ACol :lg="12" :xs="24">
-              <AFormItem v-if="showLayout" :label="$t('page.manage.menu.layout')" name="layout">
+            <ACol :lg="12" :xs="24"  v-if="showLayout">
+              <AFormItem :label="$t('page.manage.menu.layout')" name="layout">
                 <ASelect
                   v-model:value="model.layout"
                   :options="layoutOptions"
                   :placeholder="$t('page.manage.menu.form.layout')"
+                  allowClear
                 />
               </AFormItem>
             </ACol>
@@ -420,11 +421,19 @@ watch(visible, () => {
                     v-model:value="model.icon"
                     :placeholder="$t('page.manage.menu.form.localIcon')"
                     :options="localIconOptions"
+                    allowClear
                   />
               </AFormItem>
             </ACol>
             <ACol :lg="12" :xs="24">
-              <AFormItem :label="$t('page.manage.menu.menuStatus')" name="visible">
+              <AFormItem name="visible">
+                <template #label>
+                  <span class="marginRight5">{{$t('page.manage.menu.menuStatus') }}</span>
+                  <ATooltip>
+                    <template #title>需要显示在菜单列表的菜单设置为显示,否则设置为隐藏;</template>
+                    <QuestionCircleFilled />
+                  </ATooltip>
+                </template>
                 <ARadioGroup v-model:value="model.visible">
                   <ARadio v-for="item in visibleOptions" :key="item.value" :value="item.value">
                     {{ item.label }}

+ 13 - 9
src/views/manage/menu/modules/menu-search.vue

@@ -1,7 +1,5 @@
 /* eslint-disable */
-<script setup lang="ts">
-import { reactive, ref, watch } from 'vue';
-defineOptions({
+<script setup lang="ts">defineOptions({
   name: 'MenuSearch'
 });
 interface Option {
@@ -31,24 +29,30 @@ function search() {
 
 <template>
   <ACard :title="$t('common.search')" :bordered="false" class="card-wrapper">
-    <AForm :model="model" :label-width="80">
+    <AForm
+      :model="model"
+      :label-col="{
+        span: 5,
+        md: 7
+      }"
+    >
       <ARow :gutter="[16, 16]" wrap>
-        <ACol :span="24" :md="12" :lg="8">
+        <ACol :span="24" :md="12" :lg="6">
           <AFormItem :label="$t('page.manage.menu.menuName')" name="title" class="m-0">
-            <AInput v-model:value.trim="model.title" :placeholder="$t('page.manage.menu.form.menuName')" @keyup.enter.native="search"/>
+            <AInput v-model:value.trim="model.title" :placeholder="$t('page.manage.menu.form.menuName')" @keyup.enter.native="search" allowClear/>
           </AFormItem>
         </ACol>
 
-        <ACol :span="24" :md="12" :lg="8">
+        <ACol :span="24" :md="12" :lg="6">
           <AFormItem :label="$t('page.manage.menu.menuStatus')" name="visible" class="m-0">
-            <ASelect v-model:value="model.visible"  allow-clear @change="search">
+            <ASelect v-model:value="model.visible"  allowClear @change="search">
               <ASelectOption v-for="option in visibleOptions" :key="option.value" :value="option.value" >
                 {{ option.label }}
               </ASelectOption>
             </ASelect>
           </AFormItem>
         </ACol>
-        <ACol :span="24" :md="12" :lg="8">
+        <ACol :span="24" :md="12" :lg="6">
           <AFormItem class="m-0">
             <div class="w-full flex-y-center justify-end gap-12px">
               <AButton @click="reset">

+ 37 - 33
src/views/manage/role/index.vue

@@ -1,19 +1,19 @@
 /* eslint-disable */
 <script setup lang="tsx">
+import { Button, Popconfirm } from 'ant-design-vue';
+import { ref } from 'vue';
 import { useTable, useTableOperate, useTableScroll } from '@/hooks/common/table';
 import { $t } from '@/locales';
 import { fetchChangeRoleStatus, fetchDeleteRole, fetchGetRoleList } from '@/service/api';
-import { Button, Popconfirm } from 'ant-design-vue';
-import { ref } from 'vue';
 import RuleModifypermisModal from './modules/role-modifypermis-modal.vue';
 import RoleOperateDrawer from './modules/role-operate-drawer.vue';
 import RoleSearch from './modules/role-search.vue';
 const { tableWrapperRef, scrollConfig } = useTableScroll();
-const modalVisible = ref(false)
-const rowRoleKey = ref('')
-const rowRoleName = ref('')
-const rowRoleId = ref()
-const rowData = ref()
+const modalVisible = ref(false);
+const rowRoleKey = ref('');
+const rowRoleName = ref('');
+const rowRoleId = ref();
+const rowData = ref();
 const {
   columns,
   columnChecks,
@@ -76,24 +76,29 @@ const {
       align: 'center',
       minWidth: 100,
       customRender: ({ record }) => {
-        let showStatus = record.status === '2'? true : false
-        const text = record.status === '2' ? '停用' : '启用'
-        return <Popconfirm title={`确定要${text}${record.roleName}角色吗?`} onConfirm={() => handleChangeStatus(record, text)}>
-          <a-switch v-model:checked={showStatus} />
-        </Popconfirm>
+        const showStatus = record.status === '2';
+        const text = record.status === '2' ? '停用' : '启用';
+        return (
+          <Popconfirm
+            title={`确定要${text}${record.roleName}角色吗?`}
+            onConfirm={() => handleChangeStatus(record, text)}
+          >
+            <a-switch v-model:checked={showStatus} />
+          </Popconfirm>
+        );
       }
     },
     {
       key: 'operate',
       title: $t('common.operate'),
       align: 'center',
-      width: 130,
+      width: 200,
       customRender: ({ record }) => (
         <div class="flex-center gap-8px">
           <Button type="primary" ghost size="small" onClick={() => handleRowEdit(record.roleId)}>
             {$t('common.edit')}
           </Button>
-          <Button  block size="small" onClick={() => handleModifyPermi(record)}>
+          <Button block size="small" onClick={() => handleModifyPermi(record)}>
             数据权限
           </Button>
           <Popconfirm onConfirm={() => handleDelete(record.roleId)} title={$t('common.confirmDelete')}>
@@ -121,14 +126,14 @@ const {
 
 async function handleBatchDelete() {
   // request
-  handleDelete(checkedRowKeys.value)
+  handleDelete(checkedRowKeys.value);
 }
 
 async function handleDelete(id: any) {
   // request
-  let ids = []
-  typeof id === 'number' ? ids.push(id) : ids = [].concat(id)
-  const res = await fetchDeleteRole({ids})
+  let ids = [];
+  typeof id === 'number' ? ids.push(id) : (ids = [].concat(id));
+  const res = await fetchDeleteRole({ ids });
   if (res.code === 200) {
     onDeleted();
   } else {
@@ -140,21 +145,20 @@ function handleRowEdit(id: number) {
   handleEdit(id, 'roleId');
 }
 // 数据权限
-function handleModifyPermi(row:any){
-  modalVisible.value = true
-  rowData.value = row
-  rowRoleId.value = row.roleId
-  rowRoleKey.value = row.roleKey
-  rowRoleName.value = row.roleName
-
+function handleModifyPermi(row: any) {
+  modalVisible.value = true;
+  rowData.value = row;
+  rowRoleId.value = row.roleId;
+  rowRoleKey.value = row.roleKey;
+  rowRoleName.value = row.roleName;
 }
-async function handleChangeStatus(row:any, text:string){
-  let paras = {
-    roleId:row.roleId,
-    status: text === '停用'? '1' : '2'
-  }
-  const res:any = await fetchChangeRoleStatus(paras)
-  if (res.code === 200 ){
+async function handleChangeStatus(row: any, text: string) {
+  const paras = {
+    roleId: row.roleId,
+    status: text === '停用' ? '1' : '2'
+  };
+  const res: any = await fetchChangeRoleStatus(paras);
+  if (res.code === 200) {
     window.$message?.success($t('common.updateSuccess'));
   } else {
     window.$message?.error('更新失败!');
@@ -199,7 +203,7 @@ async function handleChangeStatus(row:any, text:string){
         :row-data="editingData"
         @submitted="getDataByPage"
       />
-      <RuleModifypermisModal v-model:visible="modalVisible"  :rowData="rowData"  @submitted="getDataByPage"/>
+      <RuleModifypermisModal v-model:visible="modalVisible" :row-data="rowData" @submitted="getDataByPage" />
     </ACard>
   </div>
 </template>

+ 7 - 7
src/views/manage/role/modules/role-modifypermis-modal.vue

@@ -1,9 +1,9 @@
 /* eslint-disable */
 <script setup lang="ts">
-import { ref, reactive, watch } from 'vue';
-import { $t } from '@/locales';
 import { useAntdForm, useFormRules } from '@/hooks/common/form';
-import { fetchModifyRolePersion, fetchDeptTreeByRole}  from '@/service/api';
+import { $t } from '@/locales';
+import { fetchDeptTreeByRole, fetchModifyRolePersion } from '@/service/api';
+import { reactive, ref, watch } from 'vue';
 defineOptions({
   name: 'RoleModifyPermisModal'
 });
@@ -104,20 +104,20 @@ watch(visible, () => {
   <AModal v-model:open="visible" title="分配数据权限" width="420px">
     <AForm ref="formRef" layout="vertical" :model="model" :rules="rules">
       <AFormItem :label="$t('page.manage.role.roleName')" name="roleName">
-        <AInput v-model:value="model.roleName" :placeholder="$t('page.manage.role.form.roleName')" :disabled="true" />
+        <AInput v-model:value="model.roleName" :placeholder="$t('page.manage.role.form.roleName')" :disabled="true" allowClear/>
       </AFormItem>
       <AFormItem :label="$t('page.manage.role.roleKey')" name="roleKey" >
-        <AInput v-model:value.trim="model.roleKey" :placeholder="$t('page.manage.role.form.roleKey')" :disabled="true" />
+        <AInput v-model:value.trim="model.roleKey" :placeholder="$t('page.manage.role.form.roleKey')" :disabled="true" allowClear/>
       </AFormItem>
       <AFormItem label="权限范围" name="dataScope" >
-        <ASelect v-model:value="model.dataScope"   :placeholder="$t('page.manage.role.form.roleStatus')" allow-clear @change="handelChange">
+        <ASelect v-model:value="model.dataScope"   :placeholder="$t('page.manage.role.form.roleStatus')" allowClear @change="handelChange">
           <ASelectOption v-for="option in dataScopeOptions" :key="option.value" :value="option.value" >
             {{ option.label }}
           </ASelectOption>
         </ASelect>
       </AFormItem>
       <AFormItem label="数据权限" name="dataScope" v-if="model.dataScope === '2'">
-        <ATree v-model:checkedKeys="model.deptIds" :field-names="{children:'children', title:'label', key:'id' }" :tree-data="treeData"
+        <ATree v-model:checkedKeys="model.deptIds" :field-names="{children:'children', title:'label', key:'id' }" :tree-data="treeData" allowClear
         checkable/>
       </AFormItem>
     </AForm>

+ 15 - 15
src/views/manage/role/modules/role-operate-drawer.vue

@@ -1,13 +1,13 @@
 /* eslint-disable */
 <script setup lang="ts">
-import { computed, nextTick, reactive, watch, ref } from 'vue';
+import { computed, nextTick, reactive, ref, watch } from 'vue';
 // import { useBoolean } from '@sa/hooks';
+import { enableStatusOptions } from '@/constants/business';
 import { useAntdForm, useFormRules } from '@/hooks/common/form';
 import { $t } from '@/locales';
-import { enableStatusOptions } from '@/constants/business';
 // import MenuAuthModal from './menu-auth-modal.vue';
+import { fetchAddRole, fetchEditRole, fetchGetMenuTree } from '@/service/api';
 import type { DataNode } from 'ant-design-vue/es/tree';
-import { fetchGetMenuTree, fetchAddRole, fetchEditRole } from '@/service/api';
 defineOptions({
   name: 'RoleOperateDrawer'
 });
@@ -142,21 +142,21 @@ watch(visible, () => {
 </script>
 
 <template>
-  <AModal v-model:open="visible" :title="title" width="600px">
-    <AForm ref="formRef" layout="vertical" :model="model" :rules="rules">
-      <ARow :gutter="[16, 16]" wrap>
+  <AModal v-model:open="visible" :title="title" width="800px">
+    <AForm ref="formRef"  :model="model" :rules="rules" :label-col="{ lg: 8, xs: 4 }" label-wrap class="pr-20px">
+      <ARow wrap>
         <ACol :span="12" :md="12" :xs="24">
           <AFormItem :label="$t('page.manage.role.roleName')" name="roleName">
-            <AInput v-model:value="model.roleName" :disabled="isEdit" :placeholder="$t('page.manage.role.form.roleName')" />
+            <AInput v-model:value="model.roleName" :disabled="isEdit" :placeholder="$t('page.manage.role.form.roleName')" allowClear />
           </AFormItem>
         </ACol>
         <ACol :span="12" :md="12" :xs="24">
           <AFormItem :label="$t('page.manage.role.roleKey')" name="roleKey">
-            <AInput v-model:value="model.roleKey" :disabled="isEdit" :placeholder="$t('page.manage.role.form.roleKey')" />
+            <AInput v-model:value="model.roleKey" :disabled="isEdit" :placeholder="$t('page.manage.role.form.roleKey')" allowClear/>
           </AFormItem>
         </ACol>
       </ARow>
-      <ARow :gutter="[16, 16]" wrap>
+      <ARow wrap>
         <ACol :span="12" :md="12" :xs="24">
           <AFormItem :label="$t('page.manage.role.roleSort')" name="roleSort">
             <AInputNumber v-model:value="model.roleSort" :placeholder="$t('page.manage.role.form.roleSort')"  style="width:100%"/>
@@ -172,18 +172,18 @@ watch(visible, () => {
           </AFormItem>
         </ACol>
       </ARow>
-      <ARow :gutter="[16, 16]" wrap >
+      <ARow wrap >
         <ACol :span="24" :md="24" :xs="24">
-          <AFormItem :label="$t('page.manage.user.remark')" name="remark">
-          <a-textarea v-model:value="model.remark" :placeholder="$t('page.manage.user.form.remark')"
+          <AFormItem :label-col="{ lg: 4, xs: 2 }" :label="$t('page.manage.user.remark')" name="remark">
+          <a-textarea v-model:value="model.remark" :placeholder="$t('page.manage.user.form.remark')" allowClear
             :auto-size="{ minRows: 2, maxRows: 5 }" />
         </AFormItem>
         </ACol>
       </ARow>
-      <ARow :gutter="[16, 16]" wrap >
+      <ARow wrap >
         <ACol :span="24" :md="24" :xs="24">
-          <AFormItem :label="$t('page.manage.role.menuAuth')" name="remark">
-          <ATree v-model:checked-keys="model.menuIds" :tree-data="tree" checkable :height="280" class="h-280px" />
+          <AFormItem :label-col="{ lg: 4, xs: 2 }" :label="$t('page.manage.role.menuAuth')" name="remark">
+          <ATree :label-col="{ lg: 4, xs: 2 }" v-model:checked-keys="model.menuIds" :tree-data="tree" checkable :height="280" class="h-280px" allowClear/>
         </AFormItem>
         </ACol>
       </ARow>

+ 11 - 5
src/views/manage/role/modules/role-search.vue

@@ -1,7 +1,7 @@
 /* eslint-disable */
 <script setup lang="ts">
-import { $t } from '@/locales';
 import { enableStatusOptions } from '@/constants/business';
+import { $t } from '@/locales';
 
 defineOptions({
   name: 'RoleSearch'
@@ -27,21 +27,27 @@ function search() {
 
 <template>
   <ACard :title="$t('common.search')" :bordered="false" class="card-wrapper">
-    <AForm :model="model" :label-width="80">
+    <AForm
+      :model="model"
+      :label-col="{
+        span: 5,
+        md: 7
+      }"
+    >
       <ARow :gutter="[16, 16]" wrap>
         <ACol :span="24" :md="12" :lg="6">
           <AFormItem :label="$t('page.manage.role.roleName')" name="roleName" class="m-0">
-            <AInput v-model:value.trim="model.roleName" :placeholder="$t('page.manage.role.form.roleName')" @keyup.enter.native="search"/>
+            <AInput v-model:value.trim="model.roleName" :placeholder="$t('page.manage.role.form.roleName')" @keyup.enter.native="search" allowClear/>
           </AFormItem>
         </ACol>
         <ACol :span="24" :md="12" :lg="6">
           <AFormItem :label="$t('page.manage.role.roleKey')" name="roleKey" class="m-0">
-            <AInput v-model:value.trim="model.roleKey" :placeholder="$t('page.manage.role.form.roleKey')" @keyup.enter.native="search"/>
+            <AInput v-model:value.trim="model.roleKey" :placeholder="$t('page.manage.role.form.roleKey')" @keyup.enter.native="search" allowClear/>
           </AFormItem>
         </ACol>
         <ACol :span="24" :md="12" :lg="6">
           <AFormItem :label="$t('page.manage.role.roleStatus')" name="status" class="m-0">
-            <ASelect v-model:value="model.status" :placeholder="$t('page.manage.role.form.roleStatus')" allow-clear @change="search">
+            <ASelect v-model:value="model.status" :placeholder="$t('page.manage.role.form.roleStatus')" allowClear @change="search">
               <ASelectOption v-for="option in enableStatusOptions" :key="option.value" :value="option.value" >
                 {{ $t(option.label) }}
               </ASelectOption>

+ 41 - 31
src/views/manage/user/index.vue

@@ -1,21 +1,21 @@
 <script setup lang="tsx">
 import { Button, Popconfirm } from 'ant-design-vue';
-import { fetchGetUserList, fetchDelteUser, changeUserStatus } from '@/service/api';
+import dayjs from 'dayjs';
+import { ref } from 'vue';
 import { useTable, useTableOperate, useTableScroll } from '@/hooks/common/table';
 import { $t } from '@/locales';
+import { changeUserStatus, fetchDelteUser, fetchGetUserList } from '@/service/api';
 import UserOperateDrawer from './modules/user-operate-drawer.vue';
 import UserResetPwdDialog from './modules/user-resetpwd-dialog.vue';
 import UserSearch from './modules/user-search.vue';
-import dayjs from 'dayjs';
-import { ref } from 'vue';
 const { tableWrapperRef, scrollConfig } = useTableScroll();
 const apiParams = ref({
   pageIndex: 1,
   pageSize: 10
 });
-let transUserId:number | null = null
-let userName = ''
-let resetDialogVisible = ref(false)
+let transUserId: number | null = null;
+let userName = '';
+const resetDialogVisible = ref(false);
 
 const {
   columns,
@@ -29,7 +29,7 @@ const {
   resetSearchParams
 } = useTable({
   apiFn: fetchGetUserList,
-  apiParams:apiParams.value,
+  apiParams: apiParams.value,
   showTotal: true,
   columns: () => [
     {
@@ -76,12 +76,17 @@ const {
       title: $t('page.manage.user.userStatus'),
       align: 'center',
       minWidth: 100,
-      customRender: ({ record}) => {
-        let showStatus:boolean = record.status == '2' ? true : false;
-        const text:string = record.status == '2' ? '停用' : '启用';
-        return <Popconfirm title={`确定要${text}${record.username}的用户吗?`} onConfirm={() => handleChangeStatus(record, text)} >
-          <a-switch v-model:checked={showStatus} ></a-switch>
-        </Popconfirm>;
+      customRender: ({ record }) => {
+        const showStatus: boolean = record.status == '2';
+        const text: string = record.status == '2' ? '停用' : '启用';
+        return (
+          <Popconfirm
+            title={`确定要${text}${record.username}的用户吗?`}
+            onConfirm={() => handleChangeStatus(record, text)}
+          >
+            <a-switch v-model:checked={showStatus}></a-switch>
+          </Popconfirm>
+        );
       }
     },
     {
@@ -90,8 +95,8 @@ const {
       title: '创建时间',
       align: 'center',
       minWidth: 150,
-      customRender:({record})=>{
-        return dayjs(record.createdAt).format('YYYY-MM-DD HH:mm:ss')
+      customRender: ({ record }) => {
+        return dayjs(record.createdAt).format('YYYY-MM-DD HH:mm:ss');
       }
     },
     {
@@ -102,7 +107,13 @@ const {
       width: 180,
       customRender: ({ record }) => (
         <div class="flex-center gap-0.1rem">
-          <Button type="primary" ghost size="small" onClick={() => handleRowEdit(record.userId)} style="margin-right:5px">
+          <Button
+            type="primary"
+            ghost
+            size="small"
+            onClick={() => handleRowEdit(record.userId)}
+            style="margin-right:5px"
+          >
             {$t('common.edit')}
           </Button>
           <Popconfirm title={$t('common.confirmDelete')} onConfirm={() => handleDelete(record.userId)}>
@@ -132,28 +143,27 @@ const {
 
 async function handleBatchDelete() {
   // request
-  handleDelete(checkedRowKeys.value)
+  handleDelete(checkedRowKeys.value);
 }
-async function handleChangeStatus(row:any, text:string){
+async function handleChangeStatus(row: any, text: string) {
   const data = {
     userId: row.userId,
-    status: text === '停用'? '1' : '2'
-  }
-  const res = await changeUserStatus(data)
+    status: text === '停用' ? '1' : '2'
+  };
+  const res = await changeUserStatus(data);
   if (res.code === 200) {
     window.$message?.success('更新成功!');
   } else {
     window.$message?.error('更新失败!');
   }
-  await getData()
-
+  await getData();
 }
 // 删除
 async function handleDelete(id: any) {
   // request
-  let ids = []
-  typeof id === 'number' ? ids.push(id) : ids = [].concat(id)
-  const res = await fetchDelteUser({ids})
+  let ids = [];
+  typeof id === 'number' ? ids.push(id) : (ids = [].concat(id));
+  const res = await fetchDelteUser({ ids });
   if (res.code === 200) {
     onDeleted();
   } else {
@@ -162,10 +172,10 @@ async function handleDelete(id: any) {
 }
 
 // 重置
-function handleResetPwd(row:any) {
-  resetDialogVisible.value = true
-  userName = row.username
-  transUserId = row.userId
+function handleResetPwd(row: any) {
+  resetDialogVisible.value = true;
+  userName = row.username;
+  transUserId = row.userId;
 }
 
 // 编辑
@@ -212,7 +222,7 @@ function handleRowEdit(id: number) {
         :row-data="editingData"
         @submitted="getDataByPage"
       />
-      <UserResetPwdDialog v-model:dialogVisible="resetDialogVisible" :userId="transUserId" :user-name="userName"/>
+      <UserResetPwdDialog v-model:dialogVisible="resetDialogVisible" :user-id="transUserId" :user-name="userName" />
     </ACard>
   </div>
 </template>

+ 20 - 18
src/views/manage/user/modules/user-operate-drawer.vue

@@ -1,9 +1,9 @@
 /* eslint-disable */
 <script setup lang="ts">
-import { computed, nextTick, reactive, ref, watch } from 'vue';
 import { useAntdForm, useFormRules } from '@/hooks/common/form';
-import { fetchGetAllRoles, getDicts, fetchGetPostList, fetchGetdeptTreeList, fetchAddUser } from '@/service/api';
 import { $t } from '@/locales';
+import { fetchAddUser, fetchGetAllRoles, fetchGetdeptTreeList, fetchGetPostList, getDicts } from '@/service/api';
+import { computed, nextTick, reactive, ref, watch } from 'vue';
 defineOptions({
   name: 'UserOperateDrawer'
 });
@@ -159,12 +159,12 @@ watch(visible, () => {
 </script>
 
 <template>
-  <AModal v-model:open="visible" :title="title" width="600px">
-    <AForm ref="formRef" layout="vertical" :model="model" :rules="rules">
-      <ARow :gutter="[16,16]" wrap>
+  <AModal v-model:open="visible" :title="title" width="800px">
+    <AForm ref="formRef"  :model="model" :rules="rules" :label-col="{ lg: 8, xs: 4 }" label-wrap class="pr-20px">
+      <ARow  wrap>
         <ACol :span="12" :md="12" :xs="24">
           <AFormItem :label="$t('page.manage.user.nickName')" name="nickName">
-            <AInput v-model:value="model.nickName" :placeholder="$t('page.manage.user.form.nickName')" />
+            <AInput v-model:value="model.nickName" :placeholder="$t('page.manage.user.form.nickName')" allowClear/>
           </AFormItem>
         </ACol>
         <ACol :span="12" :md="12" :xs="24">
@@ -175,27 +175,27 @@ watch(visible, () => {
           </AFormItem>
         </ACol>
       </ARow>
-      <ARow  :gutter="[16,16]" wrap>
+      <ARow wrap>
         <ACol :span="12" :md="12" :xs="24">
           <AFormItem :label="$t('page.manage.user.userPhone')" name="phone">
-            <AInput v-model:value="model.phone" :placeholder="$t('page.manage.user.form.userPhone')" />
+            <AInput v-model:value="model.phone" :placeholder="$t('page.manage.user.form.userPhone')" allowClear/>
           </AFormItem>
         </ACol>
         <ACol :span="12" :md="12" :xs="24">
           <AFormItem :label="$t('page.manage.user.userEmail')" name="email">
-            <AInput v-model:value="model.email" :placeholder="$t('page.manage.user.form.userEmail')" />
+            <AInput v-model:value="model.email" :placeholder="$t('page.manage.user.form.userEmail')" allowClear/>
           </AFormItem>
         </ACol>
       </ARow>
-      <ARow  :gutter="[16,16]" wrap>
+      <ARow wrap>
         <ACol :span="12" :md="12" :xs="24">
           <AFormItem :label="$t('page.manage.user.userName')" name="username">
-            <AInput v-model:value="model.username" :placeholder="$t('page.manage.user.form.userName')" />
+            <AInput v-model:value="model.username" :placeholder="$t('page.manage.user.form.userName')" allowClear/>
           </AFormItem>
         </ACol>
         <ACol :span="12" :md="12" :xs="24" v-if="props.operateType === 'add'">
           <AFormItem :label="$t('page.manage.user.password')" name="password" >
-            <AInput v-model:value="model.password" :placeholder="$t('page.manage.user.form.password')" />
+            <AInput v-model:value="model.password" :placeholder="$t('page.manage.user.form.password')" allowClear/>
           </AFormItem>
         </ACol>
         <ACol :span="12" :md="12" :xs="24">
@@ -219,20 +219,22 @@ watch(visible, () => {
         <ACol :span="12" :md="12" :xs="24">
           <AFormItem :label="$t('page.manage.user.postId')" name="postId">
             <ASelect v-model:value="model.postId" :options="postOptions"
-              :placeholder="$t('page.manage.user.form.postId')" />
+              :placeholder="$t('page.manage.user.form.postId')" allowClear/>
           </AFormItem>
         </ACol>
         <ACol :span="12" :md="props.operateType === 'add'? 12: 24" :xs="24">
           <AFormItem :label="$t('page.manage.user.userRole')" name="roleId">
             <ASelect v-model:value="model.roleId"  :options="roleOptions"
-              :placeholder="$t('page.manage.user.form.userRole')" />
+              :placeholder="$t('page.manage.user.form.userRole')" allowClear/>
+          </AFormItem>
+        </ACol>
+        <ACol :span="24" :md="24" :xs="24">
+          <AFormItem :label-col="{ lg: 4, xs: 2 }" :label="$t('page.manage.user.remark')" name="remark">
+            <a-textarea v-model:value="model.remark" :placeholder="$t('page.manage.user.form.remark')"
+              :auto-size="{ minRows: 2, maxRows: 5 }" allowClear/>
           </AFormItem>
         </ACol>
       </ARow>
-      <AFormItem :label="$t('page.manage.user.remark')" name="remark">
-        <a-textarea v-model:value="model.remark" :placeholder="$t('page.manage.user.form.remark')"
-          :auto-size="{ minRows: 2, maxRows: 5 }" />
-      </AFormItem>
     </AForm>
     <template #footer>
       <ASpace :size="16">

+ 4 - 4
src/views/manage/user/modules/user-resetpwd-dialog.vue

@@ -1,8 +1,8 @@
 /* eslint-disable */
 <script setup lang="ts">
-import { reactive, watch } from 'vue';
 import { useAntdForm, useFormRules } from '@/hooks/common/form';
 import { fetchRestPwsUser } from '@/service/api';
+import { reactive, watch } from 'vue';
 defineOptions({
   name: 'UserResetPwdDialog'
 });
@@ -16,7 +16,7 @@ interface Props {
 const props = defineProps<Props>();
 const model = reactive(createDefaultModel());
 const { formRef, validate, resetFields } = useAntdForm();
-const { defaultRequiredRule } = useFormRules();
+const { formRules } = useFormRules();
 function createDefaultModel(){
   return {
     password: '',
@@ -24,7 +24,7 @@ function createDefaultModel(){
   };
 }
 const rules: Record<'password', App.Global.FormRule> = {
-  password: defaultRequiredRule,
+  password: formRules.pwd,
 };
 
 function closeDrawer() {
@@ -51,7 +51,7 @@ watch(visible, () => {
     <!-- <p style="margin-bottom: 10px;"></p> -->
     <AForm ref="formRef" layout="vertical" :model="model" :rules="rules">
       <AFormItem :label="`请输入${userName}的新密码`" name="password">
-        <AInput v-model:value="model.password" placeholder="请输入新密码" />
+        <AInput v-model:value="model.password" placeholder="请输入新密码" allowClear/>
       </AFormItem>
     </AForm>
     <template #footer>

+ 6 - 6
src/views/manage/user/modules/user-search.vue

@@ -1,11 +1,11 @@
 /* eslint-disable */
 <script setup lang="ts">
-import { computed, ref,onMounted } from 'vue';
-import { $t } from '@/locales';
-import { useAntdForm, useFormRules } from '@/hooks/common/form';
 import { enableStatusOptions } from '@/constants/business';
-import { translateOptions } from '@/utils/common';
+import { useAntdForm, useFormRules } from '@/hooks/common/form';
+import { $t } from '@/locales';
 import { fetchGetdeptTreeList } from '@/service/api';
+import { translateOptions } from '@/utils/common';
+import { computed, onMounted, ref } from 'vue';
 defineOptions({
   name: 'UserSearch'
 });
@@ -64,7 +64,7 @@ async function search() {
       <ARow :gutter="[16, 16]" wrap>
         <ACol :span="24" :md="12" :lg="6">
           <AFormItem :label="$t('page.manage.user.userName')" name="username" class="m-0">
-            <AInput v-model:value.trim="model.username" :placeholder="$t('page.manage.user.form.userName')" @keyup.enter.native="search"/>
+            <AInput v-model:value.trim="model.username" :placeholder="$t('page.manage.user.form.userName')" @keyup.enter.native="search" allowClear/>
           </AFormItem>
         </ACol>
         <ACol :span="24" :md="12" :lg="6">
@@ -92,7 +92,7 @@ async function search() {
         </ACol> -->
         <ACol :span="24" :md="12" :lg="6">
           <AFormItem :label="$t('page.manage.user.userPhone')" name="phone" class="m-0">
-            <AInput v-model:value.trim="model.phone" :placeholder="$t('page.manage.user.form.userPhone')" @keyup.enter.native="search"/>
+            <AInput v-model:value.trim="model.phone" :placeholder="$t('page.manage.user.form.userPhone')" @keyup.enter.native="search" allowClear/>
           </AFormItem>
         </ACol>
         <!-- <ACol :span="24" :md="12" :lg="6">

+ 529 - 0
src/views/new-home/index.vue

@@ -0,0 +1,529 @@
+<script setup lang="ts">
+import { nextTick, onMounted, reactive, ref, watch } from 'vue';
+import { useRouter } from 'vue-router';
+import { debounce } from 'lodash-es';
+import { localStg } from '@/utils/storage';
+import { fetchListApps, searchBizName, searchServiceUrl } from '@/service/api';
+import { useRouterPush } from '@/hooks/common/router';
+const { routerPush } = useRouterPush();
+interface urlOption {
+  AppAlias: string;
+  Method: string;
+  Route: string;
+  ServiceName: string;
+}
+interface bizOption {
+  active: boolean;
+  app_alias: string;
+  app_name: string;
+  favor: boolean;
+  hash: string;
+  id: string;
+  name: string;
+  node_num: string;
+  service_name: string;
+}
+
+const openMonitor = ref(false);
+
+const router = useRouter();
+const queryParams = reactive({
+  name: ''
+});
+const selectOption = ref('1');
+let appList = reactive<StorageType.appsItem[]>([]);
+const stateurl = ref('');
+const urlLoading = ref(false);
+const suppilerListQuery = reactive({
+  url: '',
+  pageIndex: 1,
+  pageSize: 100
+});
+let urlSuggestions = reactive<urlOption[]>([]);
+const autocompleteRef = ref();
+const bizCompleteRef = ref();
+const stateBiz = ref('');
+const bizLoading = ref(false);
+const bizSearchQuery = reactive({
+  name: stateBiz.value,
+  pageIndex: 1,
+  pageSize: 100
+});
+let bizSuggestions = reactive<bizOption[]>([]);
+let bizPageTotal = 0;
+let pageTotal = 0;
+
+function handChange(val: any) {
+  if (val) {
+    const obj = val;
+    localStg.set('appsItem', obj);
+    // this.$store.commit('alias/setCurrentAlias', val.alias); // todo
+    router
+      .push({
+        path: '/business-analysis/system-space/index',
+        query: {
+          id: val.id,
+          app_alias: val.alias,
+          name: val.name,
+          item: val,
+          live: val.live
+        }
+      })
+      .catch(err => err);
+  }
+}
+function getList() {
+  fetchListApps({ pageIndex: 0, pageSize: 200 }).then((res: any) => {
+    if (res.code === 200) {
+      appList = res.data.list || [];
+    } else {
+      appList = [];
+    }
+  });
+}
+// url-滚到底部执行的方法
+async function handelScroll(e: any) {
+  if (Number(pageTotal) <= urlSuggestions.length) {
+    // 全部已经展示完了
+    suppilerListQuery.pageIndex = 1;
+    return;
+  }
+  const { scrollHeight, scrollTop, clientHeight } = e.target;
+  if (clientHeight + scrollTop + 2 >= scrollHeight) {
+    // 到底部
+    console.log('到底了~~~~~~');
+    suppilerListQuery.pageIndex += 1;
+    urlLoading.value = true;
+    const result = await searchServiceUrl(suppilerListQuery);
+    // 根据实际接口返回数据格式将数据插入到选项中
+    urlSuggestions = urlSuggestions.concat(result.data.list || []);
+    pageTotal = result.data.count || 0;
+    urlLoading.value = false;
+  }
+}
+// url-查询
+const querySearchAsync = debounce(async value => {
+  // 300ms 防抖延迟
+  console.log('stateurl---', value);
+  suppilerListQuery.url = value && value.trim();
+  stateurl.value = value && value.trim();
+  if (stateurl.value === '') {
+    suppilerListQuery.pageIndex = 1;
+  }
+  urlLoading.value = true;
+  try {
+    const res = await searchServiceUrl(suppilerListQuery);
+    if (res && res.code === 200) {
+      urlSuggestions = res.data.list || [];
+      pageTotal = res.data.count || 0;
+    } else {
+      urlSuggestions = [];
+      pageTotal = 0;
+    }
+  } catch (error) {
+    console.error('搜索失败:', error);
+  } finally {
+    urlLoading.value = false;
+  }
+}, 100);
+function urlHandleFocus() {
+  querySearchAsync('');
+}
+// url-选中
+function handleSelect(item: urlOption) {
+  console.log('handleSelect----', item);
+  // 处理选中项)
+  const obj = appList.filter((m: any) => m.alias === item.AppAlias)[0];
+  localStg.set('appsItem', obj);
+  const rowItem = {
+    method: item.Method,
+    service_name: item.ServiceName,
+    kind: item.Route,
+    name: item.Route,
+    route: item.Route
+  };
+  localStg.set('row', rowItem);
+  router.push({
+    path: '/service/InterfaceDetail/index',
+    query: {
+      kind: item.Route,
+      method: item.Method,
+      name: item.Route,
+      service_name: item.ServiceName,
+      route: item.Route
+    }
+  });
+}
+
+// 业务查询
+const bizSearchAsync = debounce(async value => {
+  // if (!value) {
+  //   bizSuggestions = [];
+  //   return;
+  // }
+  console.log('bizSearchAsync---', value);
+  bizSearchQuery.name = value && value.trim();
+  stateBiz.value = value && value.trim();
+  if (stateBiz.value === '') {
+    bizSearchQuery.pageIndex = 1;
+  }
+  bizLoading.value = true;
+
+  try {
+    const res = await searchBizName(bizSearchQuery);
+    if (res && res.code === 200) {
+      bizSuggestions = res.data.list || [];
+      bizPageTotal = res.data.total || 0;
+    } else {
+      bizSuggestions = [];
+      bizPageTotal = 0;
+    }
+  } catch (error) {
+    console.error('搜索请求失败', error);
+  } finally {
+    bizLoading.value = false;
+  }
+}, 10); // 300ms 防抖延迟
+function bizHandleFocus() {
+  bizSearchAsync('');
+}
+// 业务-滚到底部执行的方法
+async function bizHandelScroll(e: any) {
+  const { scrollHeight, scrollTop, clientHeight } = e.target;
+  if (Number(bizPageTotal) <= bizSuggestions.length) {
+    // 全部已经展示完了
+    bizSearchQuery.pageIndex = 1;
+    return;
+  }
+  if (clientHeight + scrollTop + 2 >= scrollHeight) {
+    // 到底部
+    console.log('到底了~~~~~~');
+    bizSearchQuery.pageIndex += 1;
+    bizLoading.value = true;
+    const result = await searchBizName(bizSearchQuery);
+    // 根据实际接口返回数据格式将数据插入到选项中
+    bizSuggestions = bizSuggestions.concat(result.data.list || []);
+    bizPageTotal = result.data.total || 0;
+    bizLoading.value = false;
+  }
+}
+// 业务-下拉选中
+function bizHandleSelect(item: any) {
+  // 处理选中项
+  const obj = appList.filter((m: any) => m.alias === item.app_alias)[0];
+  localStg.set('appsItem', obj);
+  router.push({
+    path: '/business-analysis/business-topics/index',
+    query: {
+      rowHash: item.hash,
+      rowId: item.id,
+      service_name: item.service_name,
+      name: item.name,
+      subconditionValue: item.name
+    }
+  });
+}
+onMounted(() => {
+  getList();
+});
+</script>
+
+<template>
+  <div class="index-wrap">
+    <video
+      v-if="!openMonitor"
+      class="bg_video"
+      data-v-93f40d6c=""
+      data-v-45e53fd3=""
+      autoplay="true"
+      loop="true"
+      muted="true"
+    >
+      <source src="@/assets/home/home.mp4" data-v-93f40d6c="" data-v-45e53fd3="" type="video/mp4" />
+    </video>
+    <div class="index">
+      <div v-if="!openMonitor" class="content">
+        <div class="content-form">
+          <div class="lg-logo">
+            <img src="@/assets/home/app_logo.png" class="lg-img" width="32" height="32" />
+          </div>
+          <AForm ref="queryForm" :model="queryParams" class="content-form-content">
+            <div class="content-form-flex">
+              <ASelect
+                v-model:value="selectOption"
+                placeholder="请选择"
+                class="content-select-left"
+                size="large"
+                :bordered="false"
+              >
+                <ASelectOption value="1">应用系统</ASelectOption>
+                <ASelectOption value="2">接口URL</ASelectOption>
+                <ASelectOption value="3">业务功能</ASelectOption>
+              </ASelect>
+              <AFormItem v-if="selectOption == '1'" label="" name="name">
+                <ASelect
+                  v-model="queryParams.name"
+                  class="content-select-right"
+                  placeholder="请选择要访问的业务系统"
+                  clearable
+                  filterable
+                  value-key="id"
+                  size="large"
+                  :bordered="false"
+                  @change="handChange"
+                >
+                  <ASelectOption v-for="app in appList" :key="app.id" :title="app.name" :value="app.name" />
+                </ASelect>
+              </AFormItem>
+              <!-- 接口URL -->
+              <AFormItem v-if="selectOption == '2'" label="" name="url">
+                <ASelect
+                  v-model:value="stateurl"
+                  :filter-option="false"
+                  class="content-select-right"
+                  placeholder="请输入url"
+                  :bordered="false"
+                  :show-search="true"
+                  :loading="urlLoading"
+                  @search="querySearchAsync"
+                  @focus="urlHandleFocus"
+                  @popup-scroll="handelScroll"
+                  @select="handleSelect"
+                >
+                  <ASelectOption v-for="item in urlSuggestions" :key="item.Route + item.Method" :value="item.Method">
+                    <div
+                      v-show="item.Route"
+                      class="ob-select-box"
+                      style="display: flex; align-items: center; justify-content: space-between"
+                    >
+                      <ATooltip placement="bottom" effect="dark" :content="item.Route">
+                        <span class="ob-select-title">{{ item.Route }}</span>
+                      </ATooltip>
+                      <div>
+                        <ATag size="mini" color="success" class="ob-tag-right">{{ item.Method }}</ATag>
+                        <ATag size="mini" color="blue">{{ item.ServiceName }}</ATag>
+                      </div>
+                    </div>
+                  </ASelectOption>
+                </ASelect>
+              </AFormItem>
+
+              <!-- 业务 -->
+              <AFormItem v-if="selectOption == '3'" label="">
+                <ASelect
+                  ref="bizCompleteRef"
+                  v-model:value="stateBiz"
+                  :filter-option="false"
+                  class="content-select-right"
+                  placeholder="请输入业务"
+                  :bordered="false"
+                  :show-search="true"
+                  autofocus
+                  :loading="bizLoading"
+                  @search="bizSearchAsync"
+                  @focus="bizHandleFocus"
+                  @popup-scroll="bizHandelScroll"
+                  @select="bizHandleSelect"
+                >
+                  <ASelectOption v-for="item in bizSuggestions" :key="item.app_name + item.name" :value="item.name">
+                    <div
+                      v-show="item.name"
+                      class="ob-select-box"
+                      style="display: flex; align-items: center; justify-content: space-between"
+                    >
+                      <ATooltip placement="bottom" effect="dark" :content="item.name">
+                        <span ref="bussinessContent" class="ob-select-title">{{ item.name }}</span>
+                      </ATooltip>
+                      <div>
+                        <ATag size="mini" color="blue">{{ item.app_name }}</ATag>
+                      </div>
+                    </div>
+                  </ASelectOption>
+                </ASelect>
+              </AFormItem>
+            </div>
+          </AForm>
+        </div>
+      </div>
+      <!-- <Monitoring v-if="openMonitor" :services-number="servicesNumber" /> -->
+    </div>
+    <!-- 添加或修改应用配置对话框 -->
+    <!--
+ <AModal
+      v-if="open"
+      v-model:visible="open"
+      :title="title"
+      width="700px"
+      :center="true"
+      :close-on-click-modal="false"
+    >
+      <ElForm ref="form" :model="form" :rules="rules" label-width="80px">
+        <AFormItem label="应用名称" prop="name">
+          <AInput v-model="form.name" placeholder="请输入应用名称" />
+        </AFormItem>
+        <AFormItem label="应用别名" prop="alias">
+          <AInput v-model="form.alias" placeholder="请输入应用别名" :disabled="isEdit" />
+        </AFormItem>
+        <AFormItem label="应用备注">
+          <AInput v-model="form.desc" type="textarea" placeholder="请输入应用详情" />
+        </AFormItem>
+        <AFormItem label="应用图片" prop="imgUrl">
+          <img v-if="form.imgUrl" :src="form.imgUrl" class="el-upload el-upload--picture-card" style="float: left" />
+          <AUpload
+            ref="sys_app_logo"
+            accept=".png,.jpg,.jpeg"
+            :headers="headers"
+            :file-list="appsfileList"
+            :action="appsAction"
+            style="float: left"
+            :before-upload="beforeUpload"
+            list-type="picture-card"
+            :show-file-list="false"
+            :on-success="uploadSuccess"
+          >
+            <i class="el-icon-plus" />
+          </AUpload>
+        </AFormItem>
+        <AFormItem label="负责人" prop="contractInfo">
+          <AInput v-model="form.contractInfo" placeholder="请输入负责人" />
+        </AFormItem>
+        <AFormItem label="手机号码" prop="contractPhone">
+          <AInput v-model="form.contractPhone" placeholder="请输入合作手机号" />
+        </AFormItem>
+      </ElForm>
+      <template #footer>
+        <div class="dialog-footer">
+          <AButton type="primary" @click="submitForm">确 定</AButton>
+          <AButton @click="cancel">取 消</AButton>
+        </div>
+      </template>
+    </AModal>
+-->
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.index-wrap {
+  // min-width: 1250px;
+  width: 100%;
+  height: 100%;
+  // min-height: 600px;
+  min-height: 100vh;
+  font-family: Arial, sans-serif;
+  // background: #fff;
+  position: relative;
+  .index {
+    position: relative;
+    padding-bottom: 0;
+    height: 100%;
+    min-height: 600px;
+    text-align: center;
+  }
+  .header {
+    position: absolute;
+    z-index: 99;
+    min-width: 1000px;
+    width: 100%;
+    border-bottom: 0;
+    height: 60px;
+    line-height: 60px;
+    // background: #fff;
+    left: 0px;
+    .header-right {
+      position: absolute;
+      right: 0;
+      top: 0;
+      z-index: 100;
+      height: 60px;
+      padding-right: 24px;
+      padding-left: 200px;
+      cursor: pointer;
+      -webkit-tap-highlight-color: transparent;
+    }
+  }
+  .content {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    width: 1000px;
+    margin: 0 auto;
+    .content-form {
+      margin-top: 20px;
+      width: 850px;
+      height: 100%;
+      margin: 0 auto;
+      text-align: left;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      margin-bottom: 20px;
+    }
+    .content-form-content {
+      flex: 1;
+    }
+    .content-form-flex {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+      height: 60px;
+    }
+    .content-form-flex ::v-deep .ant-select-selector {
+      background: white !important;
+      width: 100%;
+    }
+    .content-select-left ::v-deep .ant-select-selector {
+      width: 120px !important;
+      height: 44px;
+      border-radius: 8px 0 0 8px;
+    }
+    .content-select-right ::v-deep .ant-select-selector {
+      width: 100% !important;
+      height: 44px;
+      border-radius: 0 8px 8px 0;
+      margin-top: 24px;
+    }
+    /* 在这里添加上面的CSS规则 */
+    .content-select-right ::v-deep .ant-select-dropdown {
+      display: block !important;
+    }
+    .content-select-right ::v-deep.ant-select .ant-select-arrow {
+      top: 70%;
+    }
+    .content-form-flex ::v-deep .ant-form-item {
+      width: 100%;
+    }
+
+    .lg-logo {
+      width: 32px;
+      height: 32px;
+      margin-right: 16px;
+    }
+  }
+}
+.bg_video {
+  height: 100vh;
+  width: 100vw;
+  position: absolute;
+  top: 0;
+  left: 0;
+  -o-object-fit: cover;
+  object-fit: cover;
+}
+::v-deep .ob-select-box {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+::v-deep .ob-tag-right {
+  margin-right: 10px;
+}
+::v-deep .ob-select-title {
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  display: inline-block;
+  max-width: 70%;
+}
+</style>

+ 0 - 1
vite.config.ts

@@ -8,7 +8,6 @@ export default defineConfig(configEnv => {
   const viteEnv = loadEnv(configEnv.mode, process.cwd()) as unknown as Env.ImportMeta;
 
   const buildTime = getBuildTime();
-
   return {
     base: viteEnv.VITE_BASE_URL,
     resolve: {