Browse Source

项目初始化

lm 1 week ago
commit
a65e25fe91
100 changed files with 14493 additions and 0 deletions
  1. 14 0
      .env.dev
  2. 8 0
      .env.self
  3. 9 0
      .env.test
  4. 24 0
      .gitignore
  5. 24 0
      README.md
  6. 17 0
      index.html
  7. 7277 0
      package-lock.json
  8. 47 0
      package.json
  9. BIN
      public/favicon.ico
  10. BIN
      public/font/SIMHEI.TTF
  11. BIN
      public/font/STXIHEI.TTF
  12. 24 0
      src/App.vue
  13. 13 0
      src/api/demo.ts
  14. 30 0
      src/api/login.ts
  15. BIN
      src/assets/bg/table_no_data.png
  16. BIN
      src/assets/bg/zanwushuju.png
  17. 27 0
      src/assets/icon/AddIcon.vue
  18. 22 0
      src/assets/icon/DeleteIcon.vue
  19. BIN
      src/assets/icon/add.png
  20. 4 0
      src/assets/icon/add.svg
  21. 11 0
      src/assets/icon/cancel.svg
  22. 3 0
      src/assets/icon/close.svg
  23. 6 0
      src/assets/icon/close_fill.svg
  24. 3 0
      src/assets/icon/confirm.svg
  25. 13 0
      src/assets/icon/delete.svg
  26. BIN
      src/assets/icon/edit.png
  27. BIN
      src/assets/icon/exitFullScreen.png
  28. BIN
      src/assets/icon/file.png
  29. BIN
      src/assets/icon/fullScreen.png
  30. 4 0
      src/assets/icon/home_hover.svg
  31. 4 0
      src/assets/icon/home_light.svg
  32. 4 0
      src/assets/icon/home_normal.svg
  33. 8 0
      src/assets/icon/join_exam_hover.svg
  34. 8 0
      src/assets/icon/join_exam_light.svg
  35. 8 0
      src/assets/icon/join_exam_normal.svg
  36. BIN
      src/assets/icon/left_back_arrow_.png
  37. BIN
      src/assets/icon/line_close_icon.webp
  38. BIN
      src/assets/icon/list.png
  39. BIN
      src/assets/icon/list_light.png
  40. BIN
      src/assets/icon/list_white.png
  41. 2 0
      src/assets/icon/manage_hover.svg
  42. 2 0
      src/assets/icon/manage_light.svg
  43. 2 0
      src/assets/icon/manage_normal.svg
  44. BIN
      src/assets/icon/move_up_down.png
  45. BIN
      src/assets/icon/novolume.png
  46. 3 0
      src/assets/icon/open.svg
  47. 1 0
      src/assets/icon/password.svg
  48. BIN
      src/assets/icon/pause.png
  49. BIN
      src/assets/icon/play.png
  50. BIN
      src/assets/icon/publish.png
  51. BIN
      src/assets/icon/publish_light.png
  52. 19 0
      src/assets/icon/red_time_icon.svg
  53. 2 0
      src/assets/icon/refresh.svg
  54. BIN
      src/assets/icon/save_icon.png
  55. 2 0
      src/assets/icon/school_hover.svg
  56. 2 0
      src/assets/icon/school_light.svg
  57. 2 0
      src/assets/icon/school_normal.svg
  58. 4 0
      src/assets/icon/search_line.svg
  59. 11 0
      src/assets/icon/user_all.svg
  60. 11 0
      src/assets/icon/user_blue.svg
  61. 11 0
      src/assets/icon/user_green.svg
  62. 11 0
      src/assets/icon/user_orange.svg
  63. BIN
      src/assets/icon/view.png
  64. BIN
      src/assets/icon/view_light.png
  65. BIN
      src/assets/icon/view_white.png
  66. BIN
      src/assets/icon/volume.png
  67. 1 0
      src/assets/icon/warn.svg
  68. BIN
      src/assets/login/input_clear.webp
  69. BIN
      src/assets/login/input_eye.webp
  70. BIN
      src/assets/login/input_pass.webp
  71. BIN
      src/assets/login/input_show_pass.webp
  72. BIN
      src/assets/login/input_user.webp
  73. BIN
      src/assets/login/login_bg.webp
  74. BIN
      src/assets/login/login_bg_center.webp
  75. BIN
      src/assets/login/login_email.webp
  76. BIN
      src/assets/login/login_feishu.webp
  77. BIN
      src/assets/login/login_logo.webp
  78. BIN
      src/assets/login/login_wechat.webp
  79. BIN
      src/assets/login/logo.png
  80. 9 0
      src/assets/school/default_logo.svg
  81. 435 0
      src/baseComponents/BarCharts.vue
  82. 187 0
      src/baseComponents/CustomCheckboxForm.vue
  83. 223 0
      src/baseComponents/CustomCheckboxForm2.vue
  84. 100 0
      src/baseComponents/Dialog.vue
  85. 414 0
      src/baseComponents/DoughnutCharts.vue
  86. 413 0
      src/baseComponents/FilePreview.vue
  87. 508 0
      src/baseComponents/FileWatch.vue
  88. 635 0
      src/baseComponents/Form.vue
  89. 1216 0
      src/baseComponents/FormDialog.vue
  90. 171 0
      src/baseComponents/FormSearchGroup.vue
  91. 272 0
      src/baseComponents/HeaderSmallBgComponent.vue
  92. 72 0
      src/baseComponents/HeaderSmallTips.vue
  93. 901 0
      src/baseComponents/MultipleBarCharts.vue
  94. 455 0
      src/baseComponents/PdfViewer/PdfViewer.vue
  95. 9 0
      src/baseComponents/PdfViewer/pdf.js
  96. 200 0
      src/baseComponents/PptViewer/PptViewer.vue
  97. 189 0
      src/baseComponents/SearchBlock.vue
  98. 155 0
      src/baseComponents/TabSearch.vue
  99. 186 0
      src/baseComponents/Table.vue
  100. 45 0
      src/baseComponents/TableRowStatus.vue

+ 14 - 0
.env.dev

@@ -0,0 +1,14 @@
+# 线上环境配置文件
+NODE_ENV = 'production'
+
+VITE_API_BASE_URL = "/"
+
+
+#生产访问地址
+# VITE_API_BASE_URL = "index.k12100.com"
+
+
+
+VITE_API_TEACHER_PRE = "/teaching"
+
+VITE_API_STUDENT_PRE = "/student"

+ 8 - 0
.env.self

@@ -0,0 +1,8 @@
+# 测试环境配置文件
+NODE_ENV = 'self'
+
+VITE_API_BASE_URL = ""
+
+VITE_API_TEACHER_PRE = "/teaching"
+
+VITE_API_STUDENT_PRE = "/student"

+ 9 - 0
.env.test

@@ -0,0 +1,9 @@
+# 测试环境配置文件
+NODE_ENV = 'test'
+
+VITE_API_BASE_URL = "https://index.k12100.net"
+
+
+VITE_API_TEACHER_PRE = "/teaching"
+
+VITE_API_STUDENT_PRE = "/student"

+ 24 - 0
.gitignore

@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 24 - 0
README.md

@@ -0,0 +1,24 @@
+# admin_system
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run dev
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 17 - 0
index.html

@@ -0,0 +1,17 @@
+<!doctype html>
+<html >
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/favicon.ico" />
+    <!-- 登录有关图标 -->
+    <link rel="stylesheet" href="//at.alicdn.com/t/c/font_4939100_i0i4t6ghfug.css">
+    <!-- 本项目图标 -->
+    <link rel="stylesheet" href="//at.alicdn.com/t/c/font_5103535_leaz9fzqvpm.css">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>客户管理系统</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.ts"></script>
+  </body>
+</html>

+ 7277 - 0
package-lock.json

@@ -0,0 +1,7277 @@
+{
+  "name": "clientManageSystem",
+  "version": "0.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "clientManageSystem",
+      "version": "0.0.0",
+      "dependencies": {
+        "@element-plus/icons-vue": "^2.3.1",
+        "@vue-office/docx": "^1.6.3",
+        "@vue-office/excel": "^1.7.14",
+        "axios": "^1.9.0",
+        "echarts": "^6.0.0",
+        "element-plus": "^2.9.11",
+        "exceljs": "^4.4.0",
+        "jsencrypt": "^3.5.4",
+        "jspdf": "^4.2.1",
+        "jspdf-autotable": "^5.0.8",
+        "lodash": "^4.17.21",
+        "particles.js": "^2.0.0",
+        "pdfjs-dist": "^5.4.624",
+        "pdfmake": "^0.3.11",
+        "pptx-preview": "^1.0.7",
+        "qrcode": "^1.5.4",
+        "vue": "^3.5.13",
+        "vue-demi": "^0.14.6",
+        "vue-pdf-embed": "^2.1.3",
+        "vue-router": "^4.5.1",
+        "vuex": "^4.1.0"
+      },
+      "devDependencies": {
+        "@types/node": "^22.15.26",
+        "@vitejs/plugin-vue": "^5.2.3",
+        "@vue/tsconfig": "^0.7.0",
+        "sass": "^1.89.0",
+        "sass-loader": "^16.0.5",
+        "typescript": "~5.8.3",
+        "vite": "^6.3.5",
+        "vue-tsc": "^2.2.8"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+      "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.27.3",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.3.tgz",
+      "integrity": "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==",
+      "dependencies": {
+        "@babel/types": "^7.27.3"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/runtime": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.29.7.tgz",
+      "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.27.3",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.3.tgz",
+      "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@ctrl/tinycolor": {
+      "version": "3.6.1",
+      "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
+      "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@element-plus/icons-vue": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
+      "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==",
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
+      "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
+      "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
+      "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
+      "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
+      "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
+      "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
+      "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
+      "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
+      "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
+      "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
+      "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
+      "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
+      "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
+      "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
+      "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
+      "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
+      "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
+      "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
+      "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
+      "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
+      "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
+      "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
+      "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
+      "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
+      "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@fast-csv/format": {
+      "version": "4.3.5",
+      "resolved": "https://registry.npmmirror.com/@fast-csv/format/-/format-4.3.5.tgz",
+      "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/node": "^14.0.1",
+        "lodash.escaperegexp": "^4.1.2",
+        "lodash.isboolean": "^3.0.3",
+        "lodash.isequal": "^4.5.0",
+        "lodash.isfunction": "^3.0.9",
+        "lodash.isnil": "^4.0.0"
+      }
+    },
+    "node_modules/@fast-csv/format/node_modules/@types/node": {
+      "version": "14.18.63",
+      "resolved": "https://registry.npmmirror.com/@types/node/-/node-14.18.63.tgz",
+      "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==",
+      "license": "MIT"
+    },
+    "node_modules/@fast-csv/parse": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmmirror.com/@fast-csv/parse/-/parse-4.3.6.tgz",
+      "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/node": "^14.0.1",
+        "lodash.escaperegexp": "^4.1.2",
+        "lodash.groupby": "^4.6.0",
+        "lodash.isfunction": "^3.0.9",
+        "lodash.isnil": "^4.0.0",
+        "lodash.isundefined": "^3.0.1",
+        "lodash.uniq": "^4.5.0"
+      }
+    },
+    "node_modules/@fast-csv/parse/node_modules/@types/node": {
+      "version": "14.18.63",
+      "resolved": "https://registry.npmmirror.com/@types/node/-/node-14.18.63.tgz",
+      "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==",
+      "license": "MIT"
+    },
+    "node_modules/@floating-ui/core": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.0.tgz",
+      "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==",
+      "dependencies": {
+        "@floating-ui/utils": "^0.2.9"
+      }
+    },
+    "node_modules/@floating-ui/dom": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.0.tgz",
+      "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==",
+      "dependencies": {
+        "@floating-ui/core": "^1.7.0",
+        "@floating-ui/utils": "^0.2.9"
+      }
+    },
+    "node_modules/@floating-ui/utils": {
+      "version": "0.2.9",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.9.tgz",
+      "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
+    },
+    "node_modules/@napi-rs/canvas": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas/-/canvas-0.1.88.tgz",
+      "integrity": "sha512-/p08f93LEbsL5mDZFQ3DBxcPv/I4QG9EDYRRq1WNlCOXVfAHBTHMSVMwxlqG/AtnSfUr9+vgfN7MKiyDo0+Weg==",
+      "license": "MIT",
+      "optional": true,
+      "workspaces": [
+        "e2e/*"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      },
+      "optionalDependencies": {
+        "@napi-rs/canvas-android-arm64": "0.1.88",
+        "@napi-rs/canvas-darwin-arm64": "0.1.88",
+        "@napi-rs/canvas-darwin-x64": "0.1.88",
+        "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.88",
+        "@napi-rs/canvas-linux-arm64-gnu": "0.1.88",
+        "@napi-rs/canvas-linux-arm64-musl": "0.1.88",
+        "@napi-rs/canvas-linux-riscv64-gnu": "0.1.88",
+        "@napi-rs/canvas-linux-x64-gnu": "0.1.88",
+        "@napi-rs/canvas-linux-x64-musl": "0.1.88",
+        "@napi-rs/canvas-win32-arm64-msvc": "0.1.88",
+        "@napi-rs/canvas-win32-x64-msvc": "0.1.88"
+      }
+    },
+    "node_modules/@napi-rs/canvas-android-arm64": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.88.tgz",
+      "integrity": "sha512-KEaClPnZuVxJ8smUWjV1wWFkByBO/D+vy4lN+Dm5DFH514oqwukxKGeck9xcKJhaWJGjfruGmYGiwRe//+/zQQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-darwin-arm64": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.88.tgz",
+      "integrity": "sha512-Xgywz0dDxOKSgx3eZnK85WgGMmGrQEW7ZLA/E7raZdlEE+xXCozobgqz2ZvYigpB6DJFYkqnwHjqCOTSDGlFdg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-darwin-x64": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.88.tgz",
+      "integrity": "sha512-Yz4wSCIQOUgNucgk+8NFtQxQxZV5NO8VKRl9ePKE6XoNyNVC8JDqtvhh3b3TPqKK8W5p2EQpAr1rjjm0mfBxdg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.88.tgz",
+      "integrity": "sha512-9gQM2SlTo76hYhxHi2XxWTAqpTOb+JtxMPEIr+H5nAhHhyEtNmTSDRtz93SP7mGd2G3Ojf2oF5tP9OdgtgXyKg==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-linux-arm64-gnu": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.88.tgz",
+      "integrity": "sha512-7qgaOBMXuVRk9Fzztzr3BchQKXDxGbY+nwsovD3I/Sx81e+sX0ReEDYHTItNb0Je4NHbAl7D0MKyd4SvUc04sg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-linux-arm64-musl": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.88.tgz",
+      "integrity": "sha512-kYyNrUsHLkoGHBc77u4Unh067GrfiCUMbGHC2+OTxbeWfZkPt2o32UOQkhnSswKd9Fko/wSqqGkY956bIUzruA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-linux-riscv64-gnu": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.88.tgz",
+      "integrity": "sha512-HVuH7QgzB0yavYdNZDRyAsn/ejoXB0hn8twwFnOqUbCCdkV+REna7RXjSR7+PdfW0qMQ2YYWsLvVBT5iL/mGpw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-linux-x64-gnu": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.88.tgz",
+      "integrity": "sha512-hvcvKIcPEQrvvJtJnwD35B3qk6umFJ8dFIr8bSymfrSMem0EQsfn1ztys8ETIFndTwdNWJKWluvxztA41ivsEw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-linux-x64-musl": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.88.tgz",
+      "integrity": "sha512-eSMpGYY2xnZSQ6UxYJ6plDboxq4KeJ4zT5HaVkUnbObNN6DlbJe0Mclh3wifAmquXfrlgTZt6zhHsUgz++AK6g==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-win32-arm64-msvc": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.88.tgz",
+      "integrity": "sha512-qcIFfEgHrchyYqRrxsCeTQgpJZ/GqHiqPcU/Fvw/ARVlQeDX1VyFH+X+0gCR2tca6UJrq96vnW+5o7buCq+erA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@napi-rs/canvas-win32-x64-msvc": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.88.tgz",
+      "integrity": "sha512-ROVqbfS4QyZxYkqmaIBBpbz/BQvAR+05FXM5PAtTYVc0uyY8Y4BHJSMdGAaMf6TdIVRsQsiq+FG/dH9XhvWCFQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/Brooooooklyn"
+      }
+    },
+    "node_modules/@noble/ciphers": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/@noble/ciphers/-/ciphers-1.3.0.tgz",
+      "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==",
+      "license": "MIT",
+      "engines": {
+        "node": "^14.21.3 || >=16"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/@noble/hashes": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmmirror.com/@noble/hashes/-/hashes-1.8.0.tgz",
+      "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+      "license": "MIT",
+      "engines": {
+        "node": "^14.21.3 || >=16"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/@parcel/watcher": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz",
+      "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "dependencies": {
+        "detect-libc": "^1.0.3",
+        "is-glob": "^4.0.3",
+        "micromatch": "^4.0.5",
+        "node-addon-api": "^7.0.0"
+      },
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      },
+      "optionalDependencies": {
+        "@parcel/watcher-android-arm64": "2.5.1",
+        "@parcel/watcher-darwin-arm64": "2.5.1",
+        "@parcel/watcher-darwin-x64": "2.5.1",
+        "@parcel/watcher-freebsd-x64": "2.5.1",
+        "@parcel/watcher-linux-arm-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm-musl": "2.5.1",
+        "@parcel/watcher-linux-arm64-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm64-musl": "2.5.1",
+        "@parcel/watcher-linux-x64-glibc": "2.5.1",
+        "@parcel/watcher-linux-x64-musl": "2.5.1",
+        "@parcel/watcher-win32-arm64": "2.5.1",
+        "@parcel/watcher-win32-ia32": "2.5.1",
+        "@parcel/watcher-win32-x64": "2.5.1"
+      }
+    },
+    "node_modules/@parcel/watcher-android-arm64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
+      "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-darwin-arm64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
+      "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-darwin-x64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
+      "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-freebsd-x64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
+      "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-arm-glibc": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
+      "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-arm-musl": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
+      "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-arm64-glibc": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
+      "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-arm64-musl": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
+      "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-x64-glibc": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
+      "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-x64-musl": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
+      "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-win32-arm64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
+      "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-win32-ia32": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
+      "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-win32-x64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
+      "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@popperjs/core": {
+      "name": "@sxzz/popperjs-es",
+      "version": "2.11.7",
+      "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
+      "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/popperjs"
+      }
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz",
+      "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz",
+      "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz",
+      "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz",
+      "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-arm64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz",
+      "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-x64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz",
+      "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz",
+      "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz",
+      "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz",
+      "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz",
+      "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz",
+      "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz",
+      "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz",
+      "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz",
+      "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz",
+      "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz",
+      "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz",
+      "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz",
+      "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz",
+      "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz",
+      "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@swc/helpers": {
+      "version": "0.5.23",
+      "resolved": "https://registry.npmmirror.com/@swc/helpers/-/helpers-0.5.23.tgz",
+      "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "tslib": "^2.8.0"
+      }
+    },
+    "node_modules/@swc/helpers/node_modules/tslib": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+      "license": "0BSD"
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.7.tgz",
+      "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
+      "dev": true
+    },
+    "node_modules/@types/lodash": {
+      "version": "4.17.17",
+      "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.17.tgz",
+      "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ=="
+    },
+    "node_modules/@types/lodash-es": {
+      "version": "4.17.12",
+      "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
+      "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
+      "dependencies": {
+        "@types/lodash": "*"
+      }
+    },
+    "node_modules/@types/node": {
+      "version": "22.15.26",
+      "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.15.26.tgz",
+      "integrity": "sha512-lgISkNrqdQ5DAzjBhnDNGKDuXDNo7/1V4FhNzsKREhWLZTOELQAptuAnJMzHtUl1qyEBBy9lNBKQ9WjyiSloTw==",
+      "dev": true,
+      "dependencies": {
+        "undici-types": "~6.21.0"
+      }
+    },
+    "node_modules/@types/pako": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/@types/pako/-/pako-2.0.4.tgz",
+      "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==",
+      "license": "MIT"
+    },
+    "node_modules/@types/raf": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmmirror.com/@types/raf/-/raf-3.4.3.tgz",
+      "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/@types/trusted-types": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+      "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/@types/web-bluetooth": {
+      "version": "0.0.16",
+      "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
+      "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
+    },
+    "node_modules/@vitejs/plugin-vue": {
+      "version": "5.2.4",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+      "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+      "dev": true,
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "peerDependencies": {
+        "vite": "^5.0.0 || ^6.0.0",
+        "vue": "^3.2.25"
+      }
+    },
+    "node_modules/@volar/language-core": {
+      "version": "2.4.14",
+      "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.14.tgz",
+      "integrity": "sha512-X6beusV0DvuVseaOEy7GoagS4rYHgDHnTrdOj5jeUb49fW5ceQyP9Ej5rBhqgz2wJggl+2fDbbojq1XKaxDi6w==",
+      "dev": true,
+      "dependencies": {
+        "@volar/source-map": "2.4.14"
+      }
+    },
+    "node_modules/@volar/source-map": {
+      "version": "2.4.14",
+      "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.14.tgz",
+      "integrity": "sha512-5TeKKMh7Sfxo8021cJfmBzcjfY1SsXsPMMjMvjY7ivesdnybqqS+GxGAoXHAOUawQTwtdUxgP65Im+dEmvWtYQ==",
+      "dev": true
+    },
+    "node_modules/@volar/typescript": {
+      "version": "2.4.14",
+      "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.14.tgz",
+      "integrity": "sha512-p8Z6f/bZM3/HyCdRNFZOEEzts51uV8WHeN8Tnfnm2EBv6FDB2TQLzfVx7aJvnl8ofKAOnS64B2O8bImBFaauRw==",
+      "dev": true,
+      "dependencies": {
+        "@volar/language-core": "2.4.14",
+        "path-browserify": "^1.0.1",
+        "vscode-uri": "^3.0.8"
+      }
+    },
+    "node_modules/@vue-office/docx": {
+      "version": "1.6.3",
+      "resolved": "https://registry.npmmirror.com/@vue-office/docx/-/docx-1.6.3.tgz",
+      "integrity": "sha512-Cs+3CAaRBOWOiW4XAhTwwxJ0dy8cPIf6DqfNvYcD3YACiLwO4kuawLF2IAXxyijhbuOeoFsfvoVbOc16A/4bZA==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "@vue/composition-api": "^1.7.1",
+        "vue": "^2.0.0 || >=3.0.0",
+        "vue-demi": "^0.14.6"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue-office/excel": {
+      "version": "1.7.14",
+      "resolved": "https://registry.npmmirror.com/@vue-office/excel/-/excel-1.7.14.tgz",
+      "integrity": "sha512-pVUgt+emDQUnW7q22CfnQ+jl43mM/7IFwYzOg7lwOwPEbiVB4K4qEQf+y/bc4xGXz75w1/e3Kz3G6wAafmFBFg==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "@vue/composition-api": "^1.7.1",
+        "vue": "^2.0.0 || >=3.0.0",
+        "vue-demi": "^0.14.6"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.16.tgz",
+      "integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==",
+      "dependencies": {
+        "@babel/parser": "^7.27.2",
+        "@vue/shared": "3.5.16",
+        "entities": "^4.5.0",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz",
+      "integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==",
+      "dependencies": {
+        "@vue/compiler-core": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz",
+      "integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==",
+      "dependencies": {
+        "@babel/parser": "^7.27.2",
+        "@vue/compiler-core": "3.5.16",
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/compiler-ssr": "3.5.16",
+        "@vue/shared": "3.5.16",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.17",
+        "postcss": "^8.5.3",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz",
+      "integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "node_modules/@vue/compiler-vue2": {
+      "version": "2.7.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz",
+      "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==",
+      "dev": true,
+      "dependencies": {
+        "de-indent": "^1.0.2",
+        "he": "^1.2.0"
+      }
+    },
+    "node_modules/@vue/devtools-api": {
+      "version": "6.6.4",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+      "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
+    },
+    "node_modules/@vue/language-core": {
+      "version": "2.2.10",
+      "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.10.tgz",
+      "integrity": "sha512-+yNoYx6XIKuAO8Mqh1vGytu8jkFEOH5C8iOv3i8Z/65A7x9iAOXA97Q+PqZ3nlm2lxf5rOJuIGI/wDtx/riNYw==",
+      "dev": true,
+      "dependencies": {
+        "@volar/language-core": "~2.4.11",
+        "@vue/compiler-dom": "^3.5.0",
+        "@vue/compiler-vue2": "^2.7.16",
+        "@vue/shared": "^3.5.0",
+        "alien-signals": "^1.0.3",
+        "minimatch": "^9.0.3",
+        "muggle-string": "^0.4.1",
+        "path-browserify": "^1.0.1"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.16.tgz",
+      "integrity": "sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==",
+      "dependencies": {
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.16.tgz",
+      "integrity": "sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==",
+      "dependencies": {
+        "@vue/reactivity": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.16.tgz",
+      "integrity": "sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==",
+      "dependencies": {
+        "@vue/reactivity": "3.5.16",
+        "@vue/runtime-core": "3.5.16",
+        "@vue/shared": "3.5.16",
+        "csstype": "^3.1.3"
+      }
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.16.tgz",
+      "integrity": "sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.5.16",
+        "@vue/shared": "3.5.16"
+      },
+      "peerDependencies": {
+        "vue": "3.5.16"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.16.tgz",
+      "integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg=="
+    },
+    "node_modules/@vue/tsconfig": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.7.0.tgz",
+      "integrity": "sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==",
+      "dev": true,
+      "peerDependencies": {
+        "typescript": "5.x",
+        "vue": "^3.4.0"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        },
+        "vue": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vueuse/core": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
+      "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
+      "dependencies": {
+        "@types/web-bluetooth": "^0.0.16",
+        "@vueuse/metadata": "9.13.0",
+        "@vueuse/shared": "9.13.0",
+        "vue-demi": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vueuse/metadata": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
+      "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vueuse/shared": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
+      "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
+      "dependencies": {
+        "vue-demi": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/alien-signals": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz",
+      "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==",
+      "dev": true
+    },
+    "node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/archiver": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmmirror.com/archiver/-/archiver-5.3.2.tgz",
+      "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
+      "license": "MIT",
+      "dependencies": {
+        "archiver-utils": "^2.1.0",
+        "async": "^3.2.4",
+        "buffer-crc32": "^0.2.1",
+        "readable-stream": "^3.6.0",
+        "readdir-glob": "^1.1.2",
+        "tar-stream": "^2.2.0",
+        "zip-stream": "^4.1.0"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/archiver-utils": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/archiver-utils/-/archiver-utils-2.1.0.tgz",
+      "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
+      "license": "MIT",
+      "dependencies": {
+        "glob": "^7.1.4",
+        "graceful-fs": "^4.2.0",
+        "lazystream": "^1.0.0",
+        "lodash.defaults": "^4.2.0",
+        "lodash.difference": "^4.5.0",
+        "lodash.flatten": "^4.4.0",
+        "lodash.isplainobject": "^4.0.6",
+        "lodash.union": "^4.6.0",
+        "normalize-path": "^3.0.0",
+        "readable-stream": "^2.0.0"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/archiver/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/async": {
+      "version": "3.2.6",
+      "resolved": "https://registry.npmmirror.com/async/-/async-3.2.6.tgz",
+      "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+      "license": "MIT"
+    },
+    "node_modules/async-validator": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
+      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+    },
+    "node_modules/axios": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.9.0.tgz",
+      "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
+      "dependencies": {
+        "follow-redirects": "^1.15.6",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+    },
+    "node_modules/base64-arraybuffer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+      "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.6.0"
+      }
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/big-integer": {
+      "version": "1.6.52",
+      "resolved": "https://registry.npmmirror.com/big-integer/-/big-integer-1.6.52.tgz",
+      "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
+      "license": "Unlicense",
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/binary": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/binary/-/binary-0.3.0.tgz",
+      "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==",
+      "license": "MIT",
+      "dependencies": {
+        "buffers": "~0.1.1",
+        "chainsaw": "~0.1.0"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/bl": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz",
+      "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+      "license": "MIT",
+      "dependencies": {
+        "buffer": "^5.5.0",
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.4.0"
+      }
+    },
+    "node_modules/bl/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/bluebird": {
+      "version": "3.4.7",
+      "resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.4.7.tgz",
+      "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==",
+      "license": "MIT"
+    },
+    "node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "fill-range": "^7.1.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/brotli": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmmirror.com/brotli/-/brotli-1.3.3.tgz",
+      "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
+      "license": "MIT",
+      "dependencies": {
+        "base64-js": "^1.1.2"
+      }
+    },
+    "node_modules/browserify-zlib": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmmirror.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+      "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+      "license": "MIT",
+      "dependencies": {
+        "pako": "~1.0.5"
+      }
+    },
+    "node_modules/buffer": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz",
+      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.1.13"
+      }
+    },
+    "node_modules/buffer-crc32": {
+      "version": "0.2.13",
+      "resolved": "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+      "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+      "license": "MIT",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/buffer-indexof-polyfill": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
+      "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/buffers": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmmirror.com/buffers/-/buffers-0.1.1.tgz",
+      "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==",
+      "engines": {
+        "node": ">=0.2.0"
+      }
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/canvg": {
+      "version": "3.0.11",
+      "resolved": "https://registry.npmmirror.com/canvg/-/canvg-3.0.11.tgz",
+      "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "@babel/runtime": "^7.12.5",
+        "@types/raf": "^3.4.0",
+        "core-js": "^3.8.3",
+        "raf": "^3.4.1",
+        "regenerator-runtime": "^0.13.7",
+        "rgbcolor": "^1.0.1",
+        "stackblur-canvas": "^2.0.0",
+        "svg-pathdata": "^6.0.3"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/chainsaw": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmmirror.com/chainsaw/-/chainsaw-0.1.0.tgz",
+      "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==",
+      "license": "MIT/X11",
+      "dependencies": {
+        "traverse": ">=0.3.0 <0.4"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz",
+      "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+      "dev": true,
+      "dependencies": {
+        "readdirp": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 14.16.0"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/cliui": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "license": "ISC",
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
+      }
+    },
+    "node_modules/clone": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmmirror.com/clone/-/clone-2.1.2.tgz",
+      "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "license": "MIT"
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/compress-commons": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/compress-commons/-/compress-commons-4.1.2.tgz",
+      "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
+      "license": "MIT",
+      "dependencies": {
+        "buffer-crc32": "^0.2.13",
+        "crc32-stream": "^4.0.2",
+        "normalize-path": "^3.0.0",
+        "readable-stream": "^3.6.0"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/compress-commons/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "license": "MIT"
+    },
+    "node_modules/core-js": {
+      "version": "3.49.0",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.49.0.tgz",
+      "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
+      }
+    },
+    "node_modules/core-util-is": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz",
+      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+      "license": "MIT"
+    },
+    "node_modules/crc-32": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz",
+      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+      "license": "Apache-2.0",
+      "bin": {
+        "crc32": "bin/crc32.njs"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/crc32-stream": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/crc32-stream/-/crc32-stream-4.0.3.tgz",
+      "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
+      "license": "MIT",
+      "dependencies": {
+        "crc-32": "^1.2.0",
+        "readable-stream": "^3.4.0"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/crc32-stream/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/css-line-break": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz",
+      "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "utrie": "^1.0.2"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
+      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.13",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
+      "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
+    },
+    "node_modules/de-indent": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz",
+      "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
+      "dev": true
+    },
+    "node_modules/decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/detect-libc": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+      "dev": true,
+      "optional": true,
+      "bin": {
+        "detect-libc": "bin/detect-libc.js"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/dfa": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/dfa/-/dfa-1.2.0.tgz",
+      "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==",
+      "license": "MIT"
+    },
+    "node_modules/dijkstrajs": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+      "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
+      "license": "MIT"
+    },
+    "node_modules/dompurify": {
+      "version": "3.4.12",
+      "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.4.12.tgz",
+      "integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==",
+      "license": "(MPL-2.0 OR Apache-2.0)",
+      "optional": true,
+      "optionalDependencies": {
+        "@types/trusted-types": "^2.0.7"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/duplexer2": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmmirror.com/duplexer2/-/duplexer2-0.1.4.tgz",
+      "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "readable-stream": "^2.0.2"
+      }
+    },
+    "node_modules/echarts": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-6.0.0.tgz",
+      "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "tslib": "2.3.0",
+        "zrender": "6.0.0"
+      }
+    },
+    "node_modules/element-plus": {
+      "version": "2.9.11",
+      "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.11.tgz",
+      "integrity": "sha512-x4L/6YC8de4JtuE3vpaEugJdQIeHQaHtIYKyk67IeF6dTIiVax45aX4nWOygnh+xX+0gTvL6xO+9BZhPA3G82w==",
+      "dependencies": {
+        "@ctrl/tinycolor": "^3.4.1",
+        "@element-plus/icons-vue": "^2.3.1",
+        "@floating-ui/dom": "^1.0.1",
+        "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
+        "@types/lodash": "^4.14.182",
+        "@types/lodash-es": "^4.17.6",
+        "@vueuse/core": "^9.1.0",
+        "async-validator": "^4.2.5",
+        "dayjs": "^1.11.13",
+        "escape-html": "^1.0.3",
+        "lodash": "^4.17.21",
+        "lodash-es": "^4.17.21",
+        "lodash-unified": "^1.0.2",
+        "memoize-one": "^6.0.0",
+        "normalize-wheel-es": "^1.2.0"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "license": "MIT"
+    },
+    "node_modules/end-of-stream": {
+      "version": "1.4.5",
+      "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz",
+      "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+      "license": "MIT",
+      "dependencies": {
+        "once": "^1.4.0"
+      }
+    },
+    "node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.5.tgz",
+      "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==",
+      "dev": true,
+      "hasInstallScript": true,
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.25.5",
+        "@esbuild/android-arm": "0.25.5",
+        "@esbuild/android-arm64": "0.25.5",
+        "@esbuild/android-x64": "0.25.5",
+        "@esbuild/darwin-arm64": "0.25.5",
+        "@esbuild/darwin-x64": "0.25.5",
+        "@esbuild/freebsd-arm64": "0.25.5",
+        "@esbuild/freebsd-x64": "0.25.5",
+        "@esbuild/linux-arm": "0.25.5",
+        "@esbuild/linux-arm64": "0.25.5",
+        "@esbuild/linux-ia32": "0.25.5",
+        "@esbuild/linux-loong64": "0.25.5",
+        "@esbuild/linux-mips64el": "0.25.5",
+        "@esbuild/linux-ppc64": "0.25.5",
+        "@esbuild/linux-riscv64": "0.25.5",
+        "@esbuild/linux-s390x": "0.25.5",
+        "@esbuild/linux-x64": "0.25.5",
+        "@esbuild/netbsd-arm64": "0.25.5",
+        "@esbuild/netbsd-x64": "0.25.5",
+        "@esbuild/openbsd-arm64": "0.25.5",
+        "@esbuild/openbsd-x64": "0.25.5",
+        "@esbuild/sunos-x64": "0.25.5",
+        "@esbuild/win32-arm64": "0.25.5",
+        "@esbuild/win32-ia32": "0.25.5",
+        "@esbuild/win32-x64": "0.25.5"
+      }
+    },
+    "node_modules/escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+    },
+    "node_modules/exceljs": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmmirror.com/exceljs/-/exceljs-4.4.0.tgz",
+      "integrity": "sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==",
+      "license": "MIT",
+      "dependencies": {
+        "archiver": "^5.0.0",
+        "dayjs": "^1.8.34",
+        "fast-csv": "^4.3.1",
+        "jszip": "^3.10.1",
+        "readable-stream": "^3.6.0",
+        "saxes": "^5.0.1",
+        "tmp": "^0.2.0",
+        "unzipper": "^0.10.11",
+        "uuid": "^8.3.0"
+      },
+      "engines": {
+        "node": ">=8.3.0"
+      }
+    },
+    "node_modules/exceljs/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/exceljs/node_modules/uuid": {
+      "version": "8.3.2",
+      "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
+      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+      "license": "MIT",
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
+    "node_modules/fast-csv": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmmirror.com/fast-csv/-/fast-csv-4.3.6.tgz",
+      "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==",
+      "license": "MIT",
+      "dependencies": {
+        "@fast-csv/format": "4.3.5",
+        "@fast-csv/parse": "4.3.6"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "license": "MIT"
+    },
+    "node_modules/fast-png": {
+      "version": "6.4.0",
+      "resolved": "https://registry.npmmirror.com/fast-png/-/fast-png-6.4.0.tgz",
+      "integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/pako": "^2.0.3",
+        "iobuffer": "^5.3.2",
+        "pako": "^2.1.0"
+      }
+    },
+    "node_modules/fast-png/node_modules/pako": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/pako/-/pako-2.2.0.tgz",
+      "integrity": "sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/puzrin"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/nodeca"
+        }
+      ],
+      "license": "(MIT AND Zlib)"
+    },
+    "node_modules/fdir": {
+      "version": "6.4.5",
+      "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.4.5.tgz",
+      "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==",
+      "dev": true,
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/fflate": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.8.3.tgz",
+      "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
+      "license": "MIT"
+    },
+    "node_modules/fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "license": "MIT",
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/follow-redirects": {
+      "version": "1.15.9",
+      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
+      "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/fontkit": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/fontkit/-/fontkit-2.0.4.tgz",
+      "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==",
+      "license": "MIT",
+      "dependencies": {
+        "@swc/helpers": "^0.5.12",
+        "brotli": "^1.3.2",
+        "clone": "^2.1.2",
+        "dfa": "^1.2.0",
+        "fast-deep-equal": "^3.1.3",
+        "restructure": "^3.0.0",
+        "tiny-inflate": "^1.0.3",
+        "unicode-properties": "^1.4.0",
+        "unicode-trie": "^2.0.0"
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.2.tgz",
+      "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fs-constants": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz",
+      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+      "license": "MIT"
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "license": "ISC"
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/fstream": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmmirror.com/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "deprecated": "This package is no longer supported.",
+      "license": "ISC",
+      "dependencies": {
+        "graceful-fs": "^4.1.2",
+        "inherits": "~2.0.0",
+        "mkdirp": ">=0.5 0",
+        "rimraf": "2"
+      },
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "license": "ISC",
+      "engines": {
+        "node": "6.* || 8.* || >= 10.*"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/glob": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "deprecated": "Glob versions prior to v9 are no longer supported",
+      "license": "ISC",
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob/node_modules/brace-expansion": {
+      "version": "1.1.16",
+      "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.16.tgz",
+      "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==",
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/glob/node_modules/minimatch": {
+      "version": "3.1.5",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz",
+      "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "license": "ISC"
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true,
+      "bin": {
+        "he": "bin/he"
+      }
+    },
+    "node_modules/html2canvas": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz",
+      "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "css-line-break": "^2.1.0",
+        "text-segmentation": "^1.0.3"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "BSD-3-Clause"
+    },
+    "node_modules/immediate": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz",
+      "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
+      "license": "MIT"
+    },
+    "node_modules/immutable": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.2.tgz",
+      "integrity": "sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==",
+      "dev": true
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
+      "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.",
+      "license": "ISC",
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "license": "ISC"
+    },
+    "node_modules/iobuffer": {
+      "version": "5.4.0",
+      "resolved": "https://registry.npmmirror.com/iobuffer/-/iobuffer-5.4.0.tgz",
+      "integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==",
+      "license": "MIT"
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true,
+      "optional": true,
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+      "license": "MIT"
+    },
+    "node_modules/js-md5": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz",
+      "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==",
+      "license": "MIT"
+    },
+    "node_modules/jsencrypt": {
+      "version": "3.5.4",
+      "resolved": "https://registry.npmmirror.com/jsencrypt/-/jsencrypt-3.5.4.tgz",
+      "integrity": "sha512-kNjfYEMNASxrDGsmcSQh/rUTmcoRfSUkxnAz+MMywM8jtGu+fFEZ3nJjHM58zscVnwR0fYmG9sGkTDjqUdpiwA==",
+      "license": "MIT"
+    },
+    "node_modules/jspdf": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-4.2.1.tgz",
+      "integrity": "sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/runtime": "^7.28.6",
+        "fast-png": "^6.2.0",
+        "fflate": "^0.8.1"
+      },
+      "optionalDependencies": {
+        "canvg": "^3.0.11",
+        "core-js": "^3.6.0",
+        "dompurify": "^3.3.1",
+        "html2canvas": "^1.0.0-rc.5"
+      }
+    },
+    "node_modules/jspdf-autotable": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmmirror.com/jspdf-autotable/-/jspdf-autotable-5.0.8.tgz",
+      "integrity": "sha512-Hy05N86yBO7CXBrnSLOge7i1ZYpKH2DjQ94iybaP7vBhSInjvRBgDc99ngKzSbSO8Jc98ZCally8I6n0tj2RJQ==",
+      "license": "MIT",
+      "peerDependencies": {
+        "jspdf": "^2 || ^3 || ^4"
+      }
+    },
+    "node_modules/jszip": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmmirror.com/jszip/-/jszip-3.10.1.tgz",
+      "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
+      "license": "(MIT OR GPL-3.0-or-later)",
+      "dependencies": {
+        "lie": "~3.3.0",
+        "pako": "~1.0.2",
+        "readable-stream": "~2.3.6",
+        "setimmediate": "^1.0.5"
+      }
+    },
+    "node_modules/lazystream": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/lazystream/-/lazystream-1.0.1.tgz",
+      "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
+      "license": "MIT",
+      "dependencies": {
+        "readable-stream": "^2.0.5"
+      },
+      "engines": {
+        "node": ">= 0.6.3"
+      }
+    },
+    "node_modules/lie": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmmirror.com/lie/-/lie-3.3.0.tgz",
+      "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+      "license": "MIT",
+      "dependencies": {
+        "immediate": "~3.0.5"
+      }
+    },
+    "node_modules/linebreak": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/linebreak/-/linebreak-1.1.0.tgz",
+      "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
+      "license": "MIT",
+      "dependencies": {
+        "base64-js": "0.0.8",
+        "unicode-trie": "^2.0.0"
+      }
+    },
+    "node_modules/linebreak/node_modules/base64-js": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-0.0.8.tgz",
+      "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/listenercount": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/listenercount/-/listenercount-1.0.1.tgz",
+      "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==",
+      "license": "ISC"
+    },
+    "node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "license": "MIT",
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+      "license": "MIT"
+    },
+    "node_modules/lodash-es": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
+      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+    },
+    "node_modules/lodash-unified": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
+      "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
+      "peerDependencies": {
+        "@types/lodash-es": "*",
+        "lodash": "*",
+        "lodash-es": "*"
+      }
+    },
+    "node_modules/lodash.defaults": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+      "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.difference": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.difference/-/lodash.difference-4.5.0.tgz",
+      "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.escaperegexp": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
+      "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmmirror.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.groupby": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmmirror.com/lodash.groupby/-/lodash.groupby-4.6.0.tgz",
+      "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.isboolean": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+      "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.isequal": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+      "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+      "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
+      "license": "MIT"
+    },
+    "node_modules/lodash.isfunction": {
+      "version": "3.0.9",
+      "resolved": "https://registry.npmmirror.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+      "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.isnil": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/lodash.isnil/-/lodash.isnil-4.0.0.tgz",
+      "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.isplainobject": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+      "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.isundefined": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz",
+      "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.union": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmmirror.com/lodash.union/-/lodash.union-4.6.0.tgz",
+      "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.uniq": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+      "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
+      "license": "MIT"
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.17",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz",
+      "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.0"
+      }
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/memoize-one": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
+      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz",
+      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "braces": "^3.0.3",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/micromatch/node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "dev": true,
+      "optional": true,
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "9.0.5",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/mkdirp": {
+      "version": "0.5.6",
+      "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
+      "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+      "license": "MIT",
+      "dependencies": {
+        "minimist": "^1.2.6"
+      },
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      }
+    },
+    "node_modules/muggle-string": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz",
+      "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
+      "dev": true
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "dev": true
+    },
+    "node_modules/node-addon-api": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz",
+      "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+      "dev": true,
+      "optional": true
+    },
+    "node_modules/node-readable-to-web-readable-stream": {
+      "version": "0.4.2",
+      "resolved": "https://registry.npmmirror.com/node-readable-to-web-readable-stream/-/node-readable-to-web-readable-stream-0.4.2.tgz",
+      "integrity": "sha512-/cMZNI34v//jUTrI+UIo4ieHAB5EZRY/+7OmXZgBxaWBMcW2tGdceIw06RFxWxrKZ5Jp3sI2i5TsRo+CBhtVLQ==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/normalize-wheel-es": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
+      "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "license": "ISC",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "license": "MIT",
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "license": "MIT",
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pako": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz",
+      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+      "license": "(MIT AND Zlib)"
+    },
+    "node_modules/particles.js": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/particles.js/-/particles.js-2.0.0.tgz",
+      "integrity": "sha512-8e0JIqkRbMMPlFBnF9f+92hX1s07jdkd3tqB8uHE9L+cwGGjIYjQM7QLgt0FQ5MZp6SFFYYDm/Y48pqK3ZvJOQ=="
+    },
+    "node_modules/path-browserify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz",
+      "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+      "dev": true
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/pdfjs-dist": {
+      "version": "5.4.624",
+      "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-5.4.624.tgz",
+      "integrity": "sha512-sm6TxKTtWv1Oh6n3C6J6a8odejb5uO4A4zo/2dgkHuC0iu8ZMAXOezEODkVaoVp8nX1Xzr+0WxFJJmUr45hQzg==",
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=20.16.0 || >=22.3.0"
+      },
+      "optionalDependencies": {
+        "@napi-rs/canvas": "^0.1.88",
+        "node-readable-to-web-readable-stream": "^0.4.2"
+      }
+    },
+    "node_modules/pdfkit": {
+      "version": "0.19.1",
+      "resolved": "https://registry.npmmirror.com/pdfkit/-/pdfkit-0.19.1.tgz",
+      "integrity": "sha512-6Gzk+wDwTs4VSxsR5rCMTnIl5nlmkye1oWB0l2hDB1EX6ZNSIBroKQEv+2+fPPn+stVjyqzmsqRJVDfB9fo5DA==",
+      "license": "MIT",
+      "dependencies": {
+        "@noble/ciphers": "^1.0.0",
+        "@noble/hashes": "^1.6.0",
+        "fontkit": "^2.0.4",
+        "js-md5": "^0.8.3",
+        "linebreak": "^1.1.0",
+        "png-js": "^1.1.0"
+      }
+    },
+    "node_modules/pdfmake": {
+      "version": "0.3.11",
+      "resolved": "https://registry.npmmirror.com/pdfmake/-/pdfmake-0.3.11.tgz",
+      "integrity": "sha512-Uc49J9hUMyuqJk+U+PxlpBpPr96A4HOOfesGx609EPr2ue82+5/Smq/KTAkEqh0/jUGSi1fumvqZ5yAWijJTJg==",
+      "license": "MIT",
+      "dependencies": {
+        "linebreak": "^1.1.0",
+        "pdfkit": "^0.19.1",
+        "xmldoc": "^2.0.3"
+      },
+      "engines": {
+        "node": ">=20"
+      }
+    },
+    "node_modules/performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+    },
+    "node_modules/picomatch": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
+      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/png-js": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/png-js/-/png-js-1.1.0.tgz",
+      "integrity": "sha512-PM/uYGzGdNSzqeOgly68+6wKQDL1SY0a/N+OEa/+br6LnHWOAJB0Npiamnodfq3jd2LS/i2fMeOKSAILjA+m5Q==",
+      "dependencies": {
+        "browserify-zlib": "^0.2.0"
+      }
+    },
+    "node_modules/pngjs": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz",
+      "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.4",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.4.tgz",
+      "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/pptx-preview": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/pptx-preview/-/pptx-preview-1.0.7.tgz",
+      "integrity": "sha512-YByocJuyxAR4YB4Q3+VAxdLfEvA5LojG1gAJsx2Mw0QU5FJPps/2fkJOupJ6oBbA+KdWRpuAk6G6T34rKCHVxw==",
+      "license": "ISC",
+      "dependencies": {
+        "echarts": "^5.5.1",
+        "jszip": "^3.10.1",
+        "lodash": "^4.17.21",
+        "tslib": "^2.7.0",
+        "uuid": "^10.0.0"
+      }
+    },
+    "node_modules/pptx-preview/node_modules/echarts": {
+      "version": "5.6.0",
+      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
+      "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "tslib": "2.3.0",
+        "zrender": "5.6.1"
+      }
+    },
+    "node_modules/pptx-preview/node_modules/echarts/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+      "license": "0BSD"
+    },
+    "node_modules/pptx-preview/node_modules/tslib": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+      "license": "0BSD"
+    },
+    "node_modules/pptx-preview/node_modules/zrender": {
+      "version": "5.6.1",
+      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz",
+      "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "tslib": "2.3.0"
+      }
+    },
+    "node_modules/pptx-preview/node_modules/zrender/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+      "license": "0BSD"
+    },
+    "node_modules/process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "license": "MIT"
+    },
+    "node_modules/proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+    },
+    "node_modules/qrcode": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.4.tgz",
+      "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
+      "license": "MIT",
+      "dependencies": {
+        "dijkstrajs": "^1.0.1",
+        "pngjs": "^5.0.0",
+        "yargs": "^15.3.1"
+      },
+      "bin": {
+        "qrcode": "bin/qrcode"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/raf": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz",
+      "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "performance-now": "^2.1.0"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz",
+      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+      "license": "MIT",
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "node_modules/readdir-glob": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmmirror.com/readdir-glob/-/readdir-glob-1.1.3.tgz",
+      "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "minimatch": "^5.1.0"
+      }
+    },
+    "node_modules/readdir-glob/node_modules/minimatch": {
+      "version": "5.1.9",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.9.tgz",
+      "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz",
+      "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 14.18.0"
+      },
+      "funding": {
+        "type": "individual",
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/regenerator-runtime": {
+      "version": "0.13.11",
+      "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+      "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/require-main-filename": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz",
+      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+      "license": "ISC"
+    },
+    "node_modules/restructure": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmmirror.com/restructure/-/restructure-3.0.2.tgz",
+      "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==",
+      "license": "MIT"
+    },
+    "node_modules/rgbcolor": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/rgbcolor/-/rgbcolor-1.0.1.tgz",
+      "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
+      "license": "MIT OR SEE LICENSE IN FEEL-FREE.md",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.8.15"
+      }
+    },
+    "node_modules/rimraf": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-2.7.1.tgz",
+      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+      "deprecated": "Rimraf versions prior to v4 are no longer supported",
+      "license": "ISC",
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      }
+    },
+    "node_modules/rollup": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.41.1.tgz",
+      "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "1.0.7"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.41.1",
+        "@rollup/rollup-android-arm64": "4.41.1",
+        "@rollup/rollup-darwin-arm64": "4.41.1",
+        "@rollup/rollup-darwin-x64": "4.41.1",
+        "@rollup/rollup-freebsd-arm64": "4.41.1",
+        "@rollup/rollup-freebsd-x64": "4.41.1",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.41.1",
+        "@rollup/rollup-linux-arm-musleabihf": "4.41.1",
+        "@rollup/rollup-linux-arm64-gnu": "4.41.1",
+        "@rollup/rollup-linux-arm64-musl": "4.41.1",
+        "@rollup/rollup-linux-loongarch64-gnu": "4.41.1",
+        "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1",
+        "@rollup/rollup-linux-riscv64-gnu": "4.41.1",
+        "@rollup/rollup-linux-riscv64-musl": "4.41.1",
+        "@rollup/rollup-linux-s390x-gnu": "4.41.1",
+        "@rollup/rollup-linux-x64-gnu": "4.41.1",
+        "@rollup/rollup-linux-x64-musl": "4.41.1",
+        "@rollup/rollup-win32-arm64-msvc": "4.41.1",
+        "@rollup/rollup-win32-ia32-msvc": "4.41.1",
+        "@rollup/rollup-win32-x64-msvc": "4.41.1",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "license": "MIT"
+    },
+    "node_modules/sass": {
+      "version": "1.89.0",
+      "resolved": "https://registry.npmmirror.com/sass/-/sass-1.89.0.tgz",
+      "integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==",
+      "dev": true,
+      "dependencies": {
+        "chokidar": "^4.0.0",
+        "immutable": "^5.0.2",
+        "source-map-js": ">=0.6.2 <2.0.0"
+      },
+      "bin": {
+        "sass": "sass.js"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "optionalDependencies": {
+        "@parcel/watcher": "^2.4.1"
+      }
+    },
+    "node_modules/sass-loader": {
+      "version": "16.0.5",
+      "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-16.0.5.tgz",
+      "integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==",
+      "dev": true,
+      "dependencies": {
+        "neo-async": "^2.6.2"
+      },
+      "engines": {
+        "node": ">= 18.12.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "@rspack/core": "0.x || 1.x",
+        "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+        "sass": "^1.3.0",
+        "sass-embedded": "*",
+        "webpack": "^5.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@rspack/core": {
+          "optional": true
+        },
+        "node-sass": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "webpack": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/sax": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/sax/-/sax-1.6.0.tgz",
+      "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
+      "license": "BlueOak-1.0.0",
+      "engines": {
+        "node": ">=11.0.0"
+      }
+    },
+    "node_modules/saxes": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/saxes/-/saxes-5.0.1.tgz",
+      "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
+      "license": "ISC",
+      "dependencies": {
+        "xmlchars": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+      "license": "ISC"
+    },
+    "node_modules/setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
+      "license": "MIT"
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/stackblur-canvas": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmmirror.com/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
+      "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=0.1.14"
+      }
+    },
+    "node_modules/string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "license": "MIT",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/svg-pathdata": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmmirror.com/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
+      "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/tar-stream": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-2.2.0.tgz",
+      "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+      "license": "MIT",
+      "dependencies": {
+        "bl": "^4.0.3",
+        "end-of-stream": "^1.4.1",
+        "fs-constants": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^3.1.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tar-stream/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/text-segmentation": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz",
+      "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "utrie": "^1.0.2"
+      }
+    },
+    "node_modules/tiny-inflate": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
+      "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
+      "license": "MIT"
+    },
+    "node_modules/tinyglobby": {
+      "version": "0.2.14",
+      "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.14.tgz",
+      "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
+      "dev": true,
+      "dependencies": {
+        "fdir": "^6.4.4",
+        "picomatch": "^4.0.2"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/SuperchupuDev"
+      }
+    },
+    "node_modules/tmp": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.7.tgz",
+      "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=14.14"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/traverse": {
+      "version": "0.3.9",
+      "resolved": "https://registry.npmmirror.com/traverse/-/traverse-0.3.9.tgz",
+      "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==",
+      "license": "MIT/X11",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+      "license": "0BSD"
+    },
+    "node_modules/typescript": {
+      "version": "5.8.3",
+      "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.8.3.tgz",
+      "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+      "devOptional": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "6.21.0",
+      "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz",
+      "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+      "dev": true
+    },
+    "node_modules/unicode-properties": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/unicode-properties/-/unicode-properties-1.4.1.tgz",
+      "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
+      "license": "MIT",
+      "dependencies": {
+        "base64-js": "^1.3.0",
+        "unicode-trie": "^2.0.0"
+      }
+    },
+    "node_modules/unicode-trie": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/unicode-trie/-/unicode-trie-2.0.0.tgz",
+      "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
+      "license": "MIT",
+      "dependencies": {
+        "pako": "^0.2.5",
+        "tiny-inflate": "^1.0.0"
+      }
+    },
+    "node_modules/unicode-trie/node_modules/pako": {
+      "version": "0.2.9",
+      "resolved": "https://registry.npmmirror.com/pako/-/pako-0.2.9.tgz",
+      "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
+      "license": "MIT"
+    },
+    "node_modules/unzipper": {
+      "version": "0.10.14",
+      "resolved": "https://registry.npmmirror.com/unzipper/-/unzipper-0.10.14.tgz",
+      "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==",
+      "license": "MIT",
+      "dependencies": {
+        "big-integer": "^1.6.17",
+        "binary": "~0.3.0",
+        "bluebird": "~3.4.1",
+        "buffer-indexof-polyfill": "~1.0.0",
+        "duplexer2": "~0.1.4",
+        "fstream": "^1.0.12",
+        "graceful-fs": "^4.2.2",
+        "listenercount": "~1.0.1",
+        "readable-stream": "~2.3.6",
+        "setimmediate": "~1.0.4"
+      }
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+      "license": "MIT"
+    },
+    "node_modules/utrie": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz",
+      "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "base64-arraybuffer": "^1.0.2"
+      }
+    },
+    "node_modules/uuid": {
+      "version": "10.0.0",
+      "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz",
+      "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
+      "funding": [
+        "https://github.com/sponsors/broofa",
+        "https://github.com/sponsors/ctavan"
+      ],
+      "license": "MIT",
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
+    "node_modules/vite": {
+      "version": "6.3.5",
+      "resolved": "https://registry.npmmirror.com/vite/-/vite-6.3.5.tgz",
+      "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
+      "dev": true,
+      "dependencies": {
+        "esbuild": "^0.25.0",
+        "fdir": "^6.4.4",
+        "picomatch": "^4.0.2",
+        "postcss": "^8.5.3",
+        "rollup": "^4.34.9",
+        "tinyglobby": "^0.2.13"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      },
+      "peerDependencies": {
+        "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+        "jiti": ">=1.21.0",
+        "less": "*",
+        "lightningcss": "^1.21.0",
+        "sass": "*",
+        "sass-embedded": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.16.0",
+        "tsx": "^4.8.1",
+        "yaml": "^2.4.2"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "jiti": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "lightningcss": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        },
+        "tsx": {
+          "optional": true
+        },
+        "yaml": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vscode-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz",
+      "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
+      "dev": true
+    },
+    "node_modules/vue": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.16.tgz",
+      "integrity": "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/compiler-sfc": "3.5.16",
+        "@vue/runtime-dom": "3.5.16",
+        "@vue/server-renderer": "3.5.16",
+        "@vue/shared": "3.5.16"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-demi": {
+      "version": "0.14.6",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
+      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-pdf-embed": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmmirror.com/vue-pdf-embed/-/vue-pdf-embed-2.1.3.tgz",
+      "integrity": "sha512-EGgZNb8HRrAloBpb8p8CugDpJpoPbQ8CFfAYdWZgq2e5qBMP9JSeLzVQIAJkXsclHXRIS3O9fp3WQbP9T5Inwg==",
+      "license": "MIT",
+      "dependencies": {
+        "pdfjs-dist": "^4.10.38"
+      },
+      "peerDependencies": {
+        "vue": "^3.3.0"
+      }
+    },
+    "node_modules/vue-pdf-embed/node_modules/pdfjs-dist": {
+      "version": "4.10.38",
+      "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-4.10.38.tgz",
+      "integrity": "sha512-/Y3fcFrXEAsMjJXeL9J8+ZG9U01LbuWaYypvDW2ycW1jL269L3js3DVBjDJ0Up9Np1uqDXsDrRihHANhZOlwdQ==",
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=20"
+      },
+      "optionalDependencies": {
+        "@napi-rs/canvas": "^0.1.65"
+      }
+    },
+    "node_modules/vue-router": {
+      "version": "4.5.1",
+      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.1.tgz",
+      "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/vue-tsc": {
+      "version": "2.2.10",
+      "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.10.tgz",
+      "integrity": "sha512-jWZ1xSaNbabEV3whpIDMbjVSVawjAyW+x1n3JeGQo7S0uv2n9F/JMgWW90tGWNFRKya4YwKMZgCtr0vRAM7DeQ==",
+      "dev": true,
+      "dependencies": {
+        "@volar/typescript": "~2.4.11",
+        "@vue/language-core": "2.2.10"
+      },
+      "bin": {
+        "vue-tsc": "bin/vue-tsc.js"
+      },
+      "peerDependencies": {
+        "typescript": ">=5.0.0"
+      }
+    },
+    "node_modules/vuex": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/vuex/-/vuex-4.1.0.tgz",
+      "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==",
+      "dependencies": {
+        "@vue/devtools-api": "^6.0.0-beta.11"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/which-module": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz",
+      "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
+      "license": "ISC"
+    },
+    "node_modules/wrap-ansi": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "license": "ISC"
+    },
+    "node_modules/xmlchars": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz",
+      "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+      "license": "MIT"
+    },
+    "node_modules/xmldoc": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/xmldoc/-/xmldoc-2.0.3.tgz",
+      "integrity": "sha512-6gRk4NY/Jvg67xn7OzJuxLRsGgiXBaPUQplVJ/9l99uIugxh4FTOewYz5ic8WScj7Xx/2WvhENiQKwkK9RpE4w==",
+      "license": "MIT",
+      "dependencies": {
+        "sax": "^1.4.3"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/y18n": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+      "license": "ISC"
+    },
+    "node_modules/yargs": {
+      "version": "15.4.1",
+      "resolved": "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz",
+      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+      "license": "MIT",
+      "dependencies": {
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^4.2.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^18.1.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/yargs-parser": {
+      "version": "18.1.3",
+      "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+      "license": "ISC",
+      "dependencies": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/zip-stream": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/zip-stream/-/zip-stream-4.1.1.tgz",
+      "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
+      "license": "MIT",
+      "dependencies": {
+        "archiver-utils": "^3.0.4",
+        "compress-commons": "^4.1.2",
+        "readable-stream": "^3.6.0"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/zip-stream/node_modules/archiver-utils": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmmirror.com/archiver-utils/-/archiver-utils-3.0.4.tgz",
+      "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
+      "license": "MIT",
+      "dependencies": {
+        "glob": "^7.2.3",
+        "graceful-fs": "^4.2.0",
+        "lazystream": "^1.0.0",
+        "lodash.defaults": "^4.2.0",
+        "lodash.difference": "^4.5.0",
+        "lodash.flatten": "^4.4.0",
+        "lodash.isplainobject": "^4.0.6",
+        "lodash.union": "^4.6.0",
+        "normalize-path": "^3.0.0",
+        "readable-stream": "^3.6.0"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/zip-stream/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/zrender": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-6.0.0.tgz",
+      "integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "tslib": "2.3.0"
+      }
+    }
+  },
+  "dependencies": {
+    "@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="
+    },
+    "@babel/helper-validator-identifier": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+      "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="
+    },
+    "@babel/parser": {
+      "version": "7.27.3",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.3.tgz",
+      "integrity": "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==",
+      "requires": {
+        "@babel/types": "^7.27.3"
+      }
+    },
+    "@babel/runtime": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.29.7.tgz",
+      "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="
+    },
+    "@babel/types": {
+      "version": "7.27.3",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.3.tgz",
+      "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==",
+      "requires": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1"
+      }
+    },
+    "@ctrl/tinycolor": {
+      "version": "3.6.1",
+      "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
+      "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA=="
+    },
+    "@element-plus/icons-vue": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
+      "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==",
+      "requires": {}
+    },
+    "@esbuild/aix-ppc64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
+      "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-arm": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
+      "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
+      "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
+      "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
+      "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
+      "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
+      "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
+      "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
+      "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
+      "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ia32": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
+      "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-loong64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
+      "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-mips64el": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
+      "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ppc64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
+      "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-riscv64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
+      "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-s390x": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
+      "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
+      "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/netbsd-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
+      "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/netbsd-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
+      "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/openbsd-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
+      "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/openbsd-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
+      "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/sunos-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
+      "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-arm64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
+      "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-ia32": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
+      "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-x64": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
+      "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
+      "dev": true,
+      "optional": true
+    },
+    "@fast-csv/format": {
+      "version": "4.3.5",
+      "resolved": "https://registry.npmmirror.com/@fast-csv/format/-/format-4.3.5.tgz",
+      "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==",
+      "requires": {
+        "@types/node": "^14.0.1",
+        "lodash.escaperegexp": "^4.1.2",
+        "lodash.isboolean": "^3.0.3",
+        "lodash.isequal": "^4.5.0",
+        "lodash.isfunction": "^3.0.9",
+        "lodash.isnil": "^4.0.0"
+      },
+      "dependencies": {
+        "@types/node": {
+          "version": "14.18.63",
+          "resolved": "https://registry.npmmirror.com/@types/node/-/node-14.18.63.tgz",
+          "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ=="
+        }
+      }
+    },
+    "@fast-csv/parse": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmmirror.com/@fast-csv/parse/-/parse-4.3.6.tgz",
+      "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==",
+      "requires": {
+        "@types/node": "^14.0.1",
+        "lodash.escaperegexp": "^4.1.2",
+        "lodash.groupby": "^4.6.0",
+        "lodash.isfunction": "^3.0.9",
+        "lodash.isnil": "^4.0.0",
+        "lodash.isundefined": "^3.0.1",
+        "lodash.uniq": "^4.5.0"
+      },
+      "dependencies": {
+        "@types/node": {
+          "version": "14.18.63",
+          "resolved": "https://registry.npmmirror.com/@types/node/-/node-14.18.63.tgz",
+          "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ=="
+        }
+      }
+    },
+    "@floating-ui/core": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.0.tgz",
+      "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==",
+      "requires": {
+        "@floating-ui/utils": "^0.2.9"
+      }
+    },
+    "@floating-ui/dom": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.0.tgz",
+      "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==",
+      "requires": {
+        "@floating-ui/core": "^1.7.0",
+        "@floating-ui/utils": "^0.2.9"
+      }
+    },
+    "@floating-ui/utils": {
+      "version": "0.2.9",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.9.tgz",
+      "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="
+    },
+    "@jridgewell/sourcemap-codec": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
+    },
+    "@napi-rs/canvas": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas/-/canvas-0.1.88.tgz",
+      "integrity": "sha512-/p08f93LEbsL5mDZFQ3DBxcPv/I4QG9EDYRRq1WNlCOXVfAHBTHMSVMwxlqG/AtnSfUr9+vgfN7MKiyDo0+Weg==",
+      "optional": true,
+      "requires": {
+        "@napi-rs/canvas-android-arm64": "0.1.88",
+        "@napi-rs/canvas-darwin-arm64": "0.1.88",
+        "@napi-rs/canvas-darwin-x64": "0.1.88",
+        "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.88",
+        "@napi-rs/canvas-linux-arm64-gnu": "0.1.88",
+        "@napi-rs/canvas-linux-arm64-musl": "0.1.88",
+        "@napi-rs/canvas-linux-riscv64-gnu": "0.1.88",
+        "@napi-rs/canvas-linux-x64-gnu": "0.1.88",
+        "@napi-rs/canvas-linux-x64-musl": "0.1.88",
+        "@napi-rs/canvas-win32-arm64-msvc": "0.1.88",
+        "@napi-rs/canvas-win32-x64-msvc": "0.1.88"
+      }
+    },
+    "@napi-rs/canvas-android-arm64": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.88.tgz",
+      "integrity": "sha512-KEaClPnZuVxJ8smUWjV1wWFkByBO/D+vy4lN+Dm5DFH514oqwukxKGeck9xcKJhaWJGjfruGmYGiwRe//+/zQQ==",
+      "optional": true
+    },
+    "@napi-rs/canvas-darwin-arm64": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.88.tgz",
+      "integrity": "sha512-Xgywz0dDxOKSgx3eZnK85WgGMmGrQEW7ZLA/E7raZdlEE+xXCozobgqz2ZvYigpB6DJFYkqnwHjqCOTSDGlFdg==",
+      "optional": true
+    },
+    "@napi-rs/canvas-darwin-x64": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.88.tgz",
+      "integrity": "sha512-Yz4wSCIQOUgNucgk+8NFtQxQxZV5NO8VKRl9ePKE6XoNyNVC8JDqtvhh3b3TPqKK8W5p2EQpAr1rjjm0mfBxdg==",
+      "optional": true
+    },
+    "@napi-rs/canvas-linux-arm-gnueabihf": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.88.tgz",
+      "integrity": "sha512-9gQM2SlTo76hYhxHi2XxWTAqpTOb+JtxMPEIr+H5nAhHhyEtNmTSDRtz93SP7mGd2G3Ojf2oF5tP9OdgtgXyKg==",
+      "optional": true
+    },
+    "@napi-rs/canvas-linux-arm64-gnu": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.88.tgz",
+      "integrity": "sha512-7qgaOBMXuVRk9Fzztzr3BchQKXDxGbY+nwsovD3I/Sx81e+sX0ReEDYHTItNb0Je4NHbAl7D0MKyd4SvUc04sg==",
+      "optional": true
+    },
+    "@napi-rs/canvas-linux-arm64-musl": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.88.tgz",
+      "integrity": "sha512-kYyNrUsHLkoGHBc77u4Unh067GrfiCUMbGHC2+OTxbeWfZkPt2o32UOQkhnSswKd9Fko/wSqqGkY956bIUzruA==",
+      "optional": true
+    },
+    "@napi-rs/canvas-linux-riscv64-gnu": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.88.tgz",
+      "integrity": "sha512-HVuH7QgzB0yavYdNZDRyAsn/ejoXB0hn8twwFnOqUbCCdkV+REna7RXjSR7+PdfW0qMQ2YYWsLvVBT5iL/mGpw==",
+      "optional": true
+    },
+    "@napi-rs/canvas-linux-x64-gnu": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.88.tgz",
+      "integrity": "sha512-hvcvKIcPEQrvvJtJnwD35B3qk6umFJ8dFIr8bSymfrSMem0EQsfn1ztys8ETIFndTwdNWJKWluvxztA41ivsEw==",
+      "optional": true
+    },
+    "@napi-rs/canvas-linux-x64-musl": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.88.tgz",
+      "integrity": "sha512-eSMpGYY2xnZSQ6UxYJ6plDboxq4KeJ4zT5HaVkUnbObNN6DlbJe0Mclh3wifAmquXfrlgTZt6zhHsUgz++AK6g==",
+      "optional": true
+    },
+    "@napi-rs/canvas-win32-arm64-msvc": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.88.tgz",
+      "integrity": "sha512-qcIFfEgHrchyYqRrxsCeTQgpJZ/GqHiqPcU/Fvw/ARVlQeDX1VyFH+X+0gCR2tca6UJrq96vnW+5o7buCq+erA==",
+      "optional": true
+    },
+    "@napi-rs/canvas-win32-x64-msvc": {
+      "version": "0.1.88",
+      "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.88.tgz",
+      "integrity": "sha512-ROVqbfS4QyZxYkqmaIBBpbz/BQvAR+05FXM5PAtTYVc0uyY8Y4BHJSMdGAaMf6TdIVRsQsiq+FG/dH9XhvWCFQ==",
+      "optional": true
+    },
+    "@noble/ciphers": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/@noble/ciphers/-/ciphers-1.3.0.tgz",
+      "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="
+    },
+    "@noble/hashes": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmmirror.com/@noble/hashes/-/hashes-1.8.0.tgz",
+      "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="
+    },
+    "@parcel/watcher": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz",
+      "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "@parcel/watcher-android-arm64": "2.5.1",
+        "@parcel/watcher-darwin-arm64": "2.5.1",
+        "@parcel/watcher-darwin-x64": "2.5.1",
+        "@parcel/watcher-freebsd-x64": "2.5.1",
+        "@parcel/watcher-linux-arm-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm-musl": "2.5.1",
+        "@parcel/watcher-linux-arm64-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm64-musl": "2.5.1",
+        "@parcel/watcher-linux-x64-glibc": "2.5.1",
+        "@parcel/watcher-linux-x64-musl": "2.5.1",
+        "@parcel/watcher-win32-arm64": "2.5.1",
+        "@parcel/watcher-win32-ia32": "2.5.1",
+        "@parcel/watcher-win32-x64": "2.5.1",
+        "detect-libc": "^1.0.3",
+        "is-glob": "^4.0.3",
+        "micromatch": "^4.0.5",
+        "node-addon-api": "^7.0.0"
+      }
+    },
+    "@parcel/watcher-android-arm64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
+      "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-darwin-arm64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
+      "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-darwin-x64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
+      "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-freebsd-x64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
+      "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-linux-arm-glibc": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
+      "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-linux-arm-musl": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
+      "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-linux-arm64-glibc": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
+      "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-linux-arm64-musl": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
+      "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-linux-x64-glibc": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
+      "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-linux-x64-musl": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
+      "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-win32-arm64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
+      "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-win32-ia32": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
+      "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@parcel/watcher-win32-x64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
+      "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
+      "dev": true,
+      "optional": true
+    },
+    "@popperjs/core": {
+      "version": "npm:@sxzz/popperjs-es@2.11.7",
+      "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
+      "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
+    },
+    "@rollup/rollup-android-arm-eabi": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz",
+      "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-android-arm64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz",
+      "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-darwin-arm64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz",
+      "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-darwin-x64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz",
+      "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-freebsd-arm64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz",
+      "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-freebsd-x64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz",
+      "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz",
+      "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz",
+      "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz",
+      "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-arm64-musl": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz",
+      "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-loongarch64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz",
+      "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-powerpc64le-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz",
+      "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz",
+      "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz",
+      "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz",
+      "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-x64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz",
+      "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-x64-musl": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz",
+      "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz",
+      "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz",
+      "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-win32-x64-msvc": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz",
+      "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==",
+      "dev": true,
+      "optional": true
+    },
+    "@swc/helpers": {
+      "version": "0.5.23",
+      "resolved": "https://registry.npmmirror.com/@swc/helpers/-/helpers-0.5.23.tgz",
+      "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==",
+      "requires": {
+        "tslib": "^2.8.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.8.1",
+          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
+          "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+        }
+      }
+    },
+    "@types/estree": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.7.tgz",
+      "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
+      "dev": true
+    },
+    "@types/lodash": {
+      "version": "4.17.17",
+      "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.17.tgz",
+      "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ=="
+    },
+    "@types/lodash-es": {
+      "version": "4.17.12",
+      "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
+      "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
+      "requires": {
+        "@types/lodash": "*"
+      }
+    },
+    "@types/node": {
+      "version": "22.15.26",
+      "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.15.26.tgz",
+      "integrity": "sha512-lgISkNrqdQ5DAzjBhnDNGKDuXDNo7/1V4FhNzsKREhWLZTOELQAptuAnJMzHtUl1qyEBBy9lNBKQ9WjyiSloTw==",
+      "dev": true,
+      "requires": {
+        "undici-types": "~6.21.0"
+      }
+    },
+    "@types/pako": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/@types/pako/-/pako-2.0.4.tgz",
+      "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw=="
+    },
+    "@types/raf": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmmirror.com/@types/raf/-/raf-3.4.3.tgz",
+      "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
+      "optional": true
+    },
+    "@types/trusted-types": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+      "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+      "optional": true
+    },
+    "@types/web-bluetooth": {
+      "version": "0.0.16",
+      "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
+      "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
+    },
+    "@vitejs/plugin-vue": {
+      "version": "5.2.4",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+      "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+      "dev": true,
+      "requires": {}
+    },
+    "@volar/language-core": {
+      "version": "2.4.14",
+      "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.14.tgz",
+      "integrity": "sha512-X6beusV0DvuVseaOEy7GoagS4rYHgDHnTrdOj5jeUb49fW5ceQyP9Ej5rBhqgz2wJggl+2fDbbojq1XKaxDi6w==",
+      "dev": true,
+      "requires": {
+        "@volar/source-map": "2.4.14"
+      }
+    },
+    "@volar/source-map": {
+      "version": "2.4.14",
+      "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.14.tgz",
+      "integrity": "sha512-5TeKKMh7Sfxo8021cJfmBzcjfY1SsXsPMMjMvjY7ivesdnybqqS+GxGAoXHAOUawQTwtdUxgP65Im+dEmvWtYQ==",
+      "dev": true
+    },
+    "@volar/typescript": {
+      "version": "2.4.14",
+      "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.14.tgz",
+      "integrity": "sha512-p8Z6f/bZM3/HyCdRNFZOEEzts51uV8WHeN8Tnfnm2EBv6FDB2TQLzfVx7aJvnl8ofKAOnS64B2O8bImBFaauRw==",
+      "dev": true,
+      "requires": {
+        "@volar/language-core": "2.4.14",
+        "path-browserify": "^1.0.1",
+        "vscode-uri": "^3.0.8"
+      }
+    },
+    "@vue-office/docx": {
+      "version": "1.6.3",
+      "resolved": "https://registry.npmmirror.com/@vue-office/docx/-/docx-1.6.3.tgz",
+      "integrity": "sha512-Cs+3CAaRBOWOiW4XAhTwwxJ0dy8cPIf6DqfNvYcD3YACiLwO4kuawLF2IAXxyijhbuOeoFsfvoVbOc16A/4bZA==",
+      "requires": {}
+    },
+    "@vue-office/excel": {
+      "version": "1.7.14",
+      "resolved": "https://registry.npmmirror.com/@vue-office/excel/-/excel-1.7.14.tgz",
+      "integrity": "sha512-pVUgt+emDQUnW7q22CfnQ+jl43mM/7IFwYzOg7lwOwPEbiVB4K4qEQf+y/bc4xGXz75w1/e3Kz3G6wAafmFBFg==",
+      "requires": {}
+    },
+    "@vue/compiler-core": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.16.tgz",
+      "integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==",
+      "requires": {
+        "@babel/parser": "^7.27.2",
+        "@vue/shared": "3.5.16",
+        "entities": "^4.5.0",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "@vue/compiler-dom": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz",
+      "integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==",
+      "requires": {
+        "@vue/compiler-core": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/compiler-sfc": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz",
+      "integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==",
+      "requires": {
+        "@babel/parser": "^7.27.2",
+        "@vue/compiler-core": "3.5.16",
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/compiler-ssr": "3.5.16",
+        "@vue/shared": "3.5.16",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.17",
+        "postcss": "^8.5.3",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "@vue/compiler-ssr": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz",
+      "integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==",
+      "requires": {
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/compiler-vue2": {
+      "version": "2.7.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz",
+      "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==",
+      "dev": true,
+      "requires": {
+        "de-indent": "^1.0.2",
+        "he": "^1.2.0"
+      }
+    },
+    "@vue/devtools-api": {
+      "version": "6.6.4",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+      "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
+    },
+    "@vue/language-core": {
+      "version": "2.2.10",
+      "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.10.tgz",
+      "integrity": "sha512-+yNoYx6XIKuAO8Mqh1vGytu8jkFEOH5C8iOv3i8Z/65A7x9iAOXA97Q+PqZ3nlm2lxf5rOJuIGI/wDtx/riNYw==",
+      "dev": true,
+      "requires": {
+        "@volar/language-core": "~2.4.11",
+        "@vue/compiler-dom": "^3.5.0",
+        "@vue/compiler-vue2": "^2.7.16",
+        "@vue/shared": "^3.5.0",
+        "alien-signals": "^1.0.3",
+        "minimatch": "^9.0.3",
+        "muggle-string": "^0.4.1",
+        "path-browserify": "^1.0.1"
+      }
+    },
+    "@vue/reactivity": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.16.tgz",
+      "integrity": "sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==",
+      "requires": {
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/runtime-core": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.16.tgz",
+      "integrity": "sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==",
+      "requires": {
+        "@vue/reactivity": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/runtime-dom": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.16.tgz",
+      "integrity": "sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==",
+      "requires": {
+        "@vue/reactivity": "3.5.16",
+        "@vue/runtime-core": "3.5.16",
+        "@vue/shared": "3.5.16",
+        "csstype": "^3.1.3"
+      }
+    },
+    "@vue/server-renderer": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.16.tgz",
+      "integrity": "sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==",
+      "requires": {
+        "@vue/compiler-ssr": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/shared": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.16.tgz",
+      "integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg=="
+    },
+    "@vue/tsconfig": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.7.0.tgz",
+      "integrity": "sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==",
+      "dev": true,
+      "requires": {}
+    },
+    "@vueuse/core": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
+      "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
+      "requires": {
+        "@types/web-bluetooth": "^0.0.16",
+        "@vueuse/metadata": "9.13.0",
+        "@vueuse/shared": "9.13.0",
+        "vue-demi": "*"
+      }
+    },
+    "@vueuse/metadata": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
+      "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ=="
+    },
+    "@vueuse/shared": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
+      "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
+      "requires": {
+        "vue-demi": "*"
+      }
+    },
+    "alien-signals": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz",
+      "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==",
+      "dev": true
+    },
+    "ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+    },
+    "ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "requires": {
+        "color-convert": "^2.0.1"
+      }
+    },
+    "archiver": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmmirror.com/archiver/-/archiver-5.3.2.tgz",
+      "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
+      "requires": {
+        "archiver-utils": "^2.1.0",
+        "async": "^3.2.4",
+        "buffer-crc32": "^0.2.1",
+        "readable-stream": "^3.6.0",
+        "readdir-glob": "^1.1.2",
+        "tar-stream": "^2.2.0",
+        "zip-stream": "^4.1.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.2",
+          "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+          "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "archiver-utils": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/archiver-utils/-/archiver-utils-2.1.0.tgz",
+      "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
+      "requires": {
+        "glob": "^7.1.4",
+        "graceful-fs": "^4.2.0",
+        "lazystream": "^1.0.0",
+        "lodash.defaults": "^4.2.0",
+        "lodash.difference": "^4.5.0",
+        "lodash.flatten": "^4.4.0",
+        "lodash.isplainobject": "^4.0.6",
+        "lodash.union": "^4.6.0",
+        "normalize-path": "^3.0.0",
+        "readable-stream": "^2.0.0"
+      }
+    },
+    "async": {
+      "version": "3.2.6",
+      "resolved": "https://registry.npmmirror.com/async/-/async-3.2.6.tgz",
+      "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="
+    },
+    "async-validator": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
+      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+    },
+    "axios": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.9.0.tgz",
+      "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
+      "requires": {
+        "follow-redirects": "^1.15.6",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
+      }
+    },
+    "balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+    },
+    "base64-arraybuffer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+      "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
+      "optional": true
+    },
+    "base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+    },
+    "big-integer": {
+      "version": "1.6.52",
+      "resolved": "https://registry.npmmirror.com/big-integer/-/big-integer-1.6.52.tgz",
+      "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="
+    },
+    "binary": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/binary/-/binary-0.3.0.tgz",
+      "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==",
+      "requires": {
+        "buffers": "~0.1.1",
+        "chainsaw": "~0.1.0"
+      }
+    },
+    "bl": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz",
+      "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+      "requires": {
+        "buffer": "^5.5.0",
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.4.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.2",
+          "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+          "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "bluebird": {
+      "version": "3.4.7",
+      "resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.4.7.tgz",
+      "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA=="
+    },
+    "brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "requires": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "fill-range": "^7.1.1"
+      }
+    },
+    "brotli": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmmirror.com/brotli/-/brotli-1.3.3.tgz",
+      "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
+      "requires": {
+        "base64-js": "^1.1.2"
+      }
+    },
+    "browserify-zlib": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmmirror.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+      "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+      "requires": {
+        "pako": "~1.0.5"
+      }
+    },
+    "buffer": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz",
+      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+      "requires": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.1.13"
+      }
+    },
+    "buffer-crc32": {
+      "version": "0.2.13",
+      "resolved": "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+      "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="
+    },
+    "buffer-indexof-polyfill": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
+      "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A=="
+    },
+    "buffers": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmmirror.com/buffers/-/buffers-0.1.1.tgz",
+      "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ=="
+    },
+    "call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "requires": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      }
+    },
+    "camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+    },
+    "canvg": {
+      "version": "3.0.11",
+      "resolved": "https://registry.npmmirror.com/canvg/-/canvg-3.0.11.tgz",
+      "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
+      "optional": true,
+      "requires": {
+        "@babel/runtime": "^7.12.5",
+        "@types/raf": "^3.4.0",
+        "core-js": "^3.8.3",
+        "raf": "^3.4.1",
+        "regenerator-runtime": "^0.13.7",
+        "rgbcolor": "^1.0.1",
+        "stackblur-canvas": "^2.0.0",
+        "svg-pathdata": "^6.0.3"
+      }
+    },
+    "chainsaw": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmmirror.com/chainsaw/-/chainsaw-0.1.0.tgz",
+      "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==",
+      "requires": {
+        "traverse": ">=0.3.0 <0.4"
+      }
+    },
+    "chokidar": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz",
+      "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+      "dev": true,
+      "requires": {
+        "readdirp": "^4.0.1"
+      }
+    },
+    "cliui": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "requires": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
+      }
+    },
+    "clone": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmmirror.com/clone/-/clone-2.1.2.tgz",
+      "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
+    },
+    "color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "requires": {
+        "color-name": "~1.1.4"
+      }
+    },
+    "color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+    },
+    "combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "compress-commons": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/compress-commons/-/compress-commons-4.1.2.tgz",
+      "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
+      "requires": {
+        "buffer-crc32": "^0.2.13",
+        "crc32-stream": "^4.0.2",
+        "normalize-path": "^3.0.0",
+        "readable-stream": "^3.6.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.2",
+          "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+          "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+    },
+    "core-js": {
+      "version": "3.49.0",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.49.0.tgz",
+      "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==",
+      "optional": true
+    },
+    "core-util-is": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz",
+      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+    },
+    "crc-32": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz",
+      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
+    },
+    "crc32-stream": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/crc32-stream/-/crc32-stream-4.0.3.tgz",
+      "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
+      "requires": {
+        "crc-32": "^1.2.0",
+        "readable-stream": "^3.4.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.2",
+          "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+          "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "css-line-break": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz",
+      "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+      "optional": true,
+      "requires": {
+        "utrie": "^1.0.2"
+      }
+    },
+    "csstype": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
+      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+    },
+    "dayjs": {
+      "version": "1.11.13",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
+      "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
+    },
+    "de-indent": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz",
+      "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
+      "dev": true
+    },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+    },
+    "detect-libc": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+      "dev": true,
+      "optional": true
+    },
+    "dfa": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/dfa/-/dfa-1.2.0.tgz",
+      "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q=="
+    },
+    "dijkstrajs": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+      "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
+    },
+    "dompurify": {
+      "version": "3.4.12",
+      "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.4.12.tgz",
+      "integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==",
+      "optional": true,
+      "requires": {
+        "@types/trusted-types": "^2.0.7"
+      }
+    },
+    "dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "requires": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      }
+    },
+    "duplexer2": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmmirror.com/duplexer2/-/duplexer2-0.1.4.tgz",
+      "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
+      "requires": {
+        "readable-stream": "^2.0.2"
+      }
+    },
+    "echarts": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-6.0.0.tgz",
+      "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==",
+      "requires": {
+        "tslib": "2.3.0",
+        "zrender": "6.0.0"
+      }
+    },
+    "element-plus": {
+      "version": "2.9.11",
+      "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.11.tgz",
+      "integrity": "sha512-x4L/6YC8de4JtuE3vpaEugJdQIeHQaHtIYKyk67IeF6dTIiVax45aX4nWOygnh+xX+0gTvL6xO+9BZhPA3G82w==",
+      "requires": {
+        "@ctrl/tinycolor": "^3.4.1",
+        "@element-plus/icons-vue": "^2.3.1",
+        "@floating-ui/dom": "^1.0.1",
+        "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
+        "@types/lodash": "^4.14.182",
+        "@types/lodash-es": "^4.17.6",
+        "@vueuse/core": "^9.1.0",
+        "async-validator": "^4.2.5",
+        "dayjs": "^1.11.13",
+        "escape-html": "^1.0.3",
+        "lodash": "^4.17.21",
+        "lodash-es": "^4.17.21",
+        "lodash-unified": "^1.0.2",
+        "memoize-one": "^6.0.0",
+        "normalize-wheel-es": "^1.2.0"
+      }
+    },
+    "emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+    },
+    "end-of-stream": {
+      "version": "1.4.5",
+      "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz",
+      "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+      "requires": {
+        "once": "^1.4.0"
+      }
+    },
+    "entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
+    },
+    "es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="
+    },
+    "es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
+    },
+    "es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "requires": {
+        "es-errors": "^1.3.0"
+      }
+    },
+    "es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "requires": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      }
+    },
+    "esbuild": {
+      "version": "0.25.5",
+      "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.5.tgz",
+      "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==",
+      "dev": true,
+      "requires": {
+        "@esbuild/aix-ppc64": "0.25.5",
+        "@esbuild/android-arm": "0.25.5",
+        "@esbuild/android-arm64": "0.25.5",
+        "@esbuild/android-x64": "0.25.5",
+        "@esbuild/darwin-arm64": "0.25.5",
+        "@esbuild/darwin-x64": "0.25.5",
+        "@esbuild/freebsd-arm64": "0.25.5",
+        "@esbuild/freebsd-x64": "0.25.5",
+        "@esbuild/linux-arm": "0.25.5",
+        "@esbuild/linux-arm64": "0.25.5",
+        "@esbuild/linux-ia32": "0.25.5",
+        "@esbuild/linux-loong64": "0.25.5",
+        "@esbuild/linux-mips64el": "0.25.5",
+        "@esbuild/linux-ppc64": "0.25.5",
+        "@esbuild/linux-riscv64": "0.25.5",
+        "@esbuild/linux-s390x": "0.25.5",
+        "@esbuild/linux-x64": "0.25.5",
+        "@esbuild/netbsd-arm64": "0.25.5",
+        "@esbuild/netbsd-x64": "0.25.5",
+        "@esbuild/openbsd-arm64": "0.25.5",
+        "@esbuild/openbsd-x64": "0.25.5",
+        "@esbuild/sunos-x64": "0.25.5",
+        "@esbuild/win32-arm64": "0.25.5",
+        "@esbuild/win32-ia32": "0.25.5",
+        "@esbuild/win32-x64": "0.25.5"
+      }
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+    },
+    "estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+    },
+    "exceljs": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmmirror.com/exceljs/-/exceljs-4.4.0.tgz",
+      "integrity": "sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==",
+      "requires": {
+        "archiver": "^5.0.0",
+        "dayjs": "^1.8.34",
+        "fast-csv": "^4.3.1",
+        "jszip": "^3.10.1",
+        "readable-stream": "^3.6.0",
+        "saxes": "^5.0.1",
+        "tmp": "^0.2.0",
+        "unzipper": "^0.10.11",
+        "uuid": "^8.3.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.2",
+          "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+          "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        },
+        "uuid": {
+          "version": "8.3.2",
+          "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
+          "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
+        }
+      }
+    },
+    "fast-csv": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmmirror.com/fast-csv/-/fast-csv-4.3.6.tgz",
+      "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==",
+      "requires": {
+        "@fast-csv/format": "4.3.5",
+        "@fast-csv/parse": "4.3.6"
+      }
+    },
+    "fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+    },
+    "fast-png": {
+      "version": "6.4.0",
+      "resolved": "https://registry.npmmirror.com/fast-png/-/fast-png-6.4.0.tgz",
+      "integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==",
+      "requires": {
+        "@types/pako": "^2.0.3",
+        "iobuffer": "^5.3.2",
+        "pako": "^2.1.0"
+      },
+      "dependencies": {
+        "pako": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmmirror.com/pako/-/pako-2.2.0.tgz",
+          "integrity": "sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w=="
+        }
+      }
+    },
+    "fdir": {
+      "version": "6.4.5",
+      "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.4.5.tgz",
+      "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==",
+      "dev": true,
+      "requires": {}
+    },
+    "fflate": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.8.3.tgz",
+      "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="
+    },
+    "fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "to-regex-range": "^5.0.1"
+      }
+    },
+    "find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "requires": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      }
+    },
+    "follow-redirects": {
+      "version": "1.15.9",
+      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
+      "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="
+    },
+    "fontkit": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/fontkit/-/fontkit-2.0.4.tgz",
+      "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==",
+      "requires": {
+        "@swc/helpers": "^0.5.12",
+        "brotli": "^1.3.2",
+        "clone": "^2.1.2",
+        "dfa": "^1.2.0",
+        "fast-deep-equal": "^3.1.3",
+        "restructure": "^3.0.0",
+        "tiny-inflate": "^1.0.3",
+        "unicode-properties": "^1.4.0",
+        "unicode-trie": "^2.0.0"
+      }
+    },
+    "form-data": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.2.tgz",
+      "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "fs-constants": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz",
+      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+    },
+    "fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "optional": true
+    },
+    "fstream": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmmirror.com/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "inherits": "~2.0.0",
+        "mkdirp": ">=0.5 0",
+        "rimraf": "2"
+      }
+    },
+    "function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+    },
+    "get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+    },
+    "get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "requires": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      }
+    },
+    "get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "requires": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      }
+    },
+    "glob": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.16",
+          "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.16.tgz",
+          "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==",
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "minimatch": {
+          "version": "3.1.5",
+          "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz",
+          "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        }
+      }
+    },
+    "gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="
+    },
+    "graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+    },
+    "has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="
+    },
+    "has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "requires": {
+        "has-symbols": "^1.0.3"
+      }
+    },
+    "hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "requires": {
+        "function-bind": "^1.1.2"
+      }
+    },
+    "he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true
+    },
+    "html2canvas": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz",
+      "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+      "optional": true,
+      "requires": {
+        "css-line-break": "^2.1.0",
+        "text-segmentation": "^1.0.3"
+      }
+    },
+    "ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
+    },
+    "immediate": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz",
+      "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
+    },
+    "immutable": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.2.tgz",
+      "integrity": "sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==",
+      "dev": true
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "iobuffer": {
+      "version": "5.4.0",
+      "resolved": "https://registry.npmmirror.com/iobuffer/-/iobuffer-5.4.0.tgz",
+      "integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA=="
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "optional": true
+    },
+    "is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+    },
+    "is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true,
+      "optional": true
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+    },
+    "js-md5": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz",
+      "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ=="
+    },
+    "jsencrypt": {
+      "version": "3.5.4",
+      "resolved": "https://registry.npmmirror.com/jsencrypt/-/jsencrypt-3.5.4.tgz",
+      "integrity": "sha512-kNjfYEMNASxrDGsmcSQh/rUTmcoRfSUkxnAz+MMywM8jtGu+fFEZ3nJjHM58zscVnwR0fYmG9sGkTDjqUdpiwA=="
+    },
+    "jspdf": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-4.2.1.tgz",
+      "integrity": "sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==",
+      "requires": {
+        "@babel/runtime": "^7.28.6",
+        "canvg": "^3.0.11",
+        "core-js": "^3.6.0",
+        "dompurify": "^3.3.1",
+        "fast-png": "^6.2.0",
+        "fflate": "^0.8.1",
+        "html2canvas": "^1.0.0-rc.5"
+      }
+    },
+    "jspdf-autotable": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmmirror.com/jspdf-autotable/-/jspdf-autotable-5.0.8.tgz",
+      "integrity": "sha512-Hy05N86yBO7CXBrnSLOge7i1ZYpKH2DjQ94iybaP7vBhSInjvRBgDc99ngKzSbSO8Jc98ZCally8I6n0tj2RJQ==",
+      "requires": {}
+    },
+    "jszip": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmmirror.com/jszip/-/jszip-3.10.1.tgz",
+      "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
+      "requires": {
+        "lie": "~3.3.0",
+        "pako": "~1.0.2",
+        "readable-stream": "~2.3.6",
+        "setimmediate": "^1.0.5"
+      }
+    },
+    "lazystream": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/lazystream/-/lazystream-1.0.1.tgz",
+      "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
+      "requires": {
+        "readable-stream": "^2.0.5"
+      }
+    },
+    "lie": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmmirror.com/lie/-/lie-3.3.0.tgz",
+      "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+      "requires": {
+        "immediate": "~3.0.5"
+      }
+    },
+    "linebreak": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/linebreak/-/linebreak-1.1.0.tgz",
+      "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
+      "requires": {
+        "base64-js": "0.0.8",
+        "unicode-trie": "^2.0.0"
+      },
+      "dependencies": {
+        "base64-js": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-0.0.8.tgz",
+          "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw=="
+        }
+      }
+    },
+    "listenercount": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/listenercount/-/listenercount-1.0.1.tgz",
+      "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ=="
+    },
+    "locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "requires": {
+        "p-locate": "^4.1.0"
+      }
+    },
+    "lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
+    "lodash-es": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
+      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+    },
+    "lodash-unified": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
+      "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
+      "requires": {}
+    },
+    "lodash.defaults": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+      "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
+    },
+    "lodash.difference": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.difference/-/lodash.difference-4.5.0.tgz",
+      "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="
+    },
+    "lodash.escaperegexp": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
+      "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw=="
+    },
+    "lodash.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmmirror.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
+    },
+    "lodash.groupby": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmmirror.com/lodash.groupby/-/lodash.groupby-4.6.0.tgz",
+      "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw=="
+    },
+    "lodash.isboolean": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+      "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
+    },
+    "lodash.isequal": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+      "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
+    },
+    "lodash.isfunction": {
+      "version": "3.0.9",
+      "resolved": "https://registry.npmmirror.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+      "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw=="
+    },
+    "lodash.isnil": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/lodash.isnil/-/lodash.isnil-4.0.0.tgz",
+      "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng=="
+    },
+    "lodash.isplainobject": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+      "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+    },
+    "lodash.isundefined": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz",
+      "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA=="
+    },
+    "lodash.union": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmmirror.com/lodash.union/-/lodash.union-4.6.0.tgz",
+      "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="
+    },
+    "lodash.uniq": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+      "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="
+    },
+    "magic-string": {
+      "version": "0.30.17",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz",
+      "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+      "requires": {
+        "@jridgewell/sourcemap-codec": "^1.5.0"
+      }
+    },
+    "math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="
+    },
+    "memoize-one": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
+      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
+    },
+    "micromatch": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz",
+      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "braces": "^3.0.3",
+        "picomatch": "^2.3.1"
+      },
+      "dependencies": {
+        "picomatch": {
+          "version": "2.3.1",
+          "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
+          "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+    },
+    "mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "requires": {
+        "mime-db": "1.52.0"
+      }
+    },
+    "minimatch": {
+      "version": "9.0.5",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^2.0.1"
+      }
+    },
+    "minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
+    },
+    "mkdirp": {
+      "version": "0.5.6",
+      "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
+      "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+      "requires": {
+        "minimist": "^1.2.6"
+      }
+    },
+    "muggle-string": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz",
+      "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
+      "dev": true
+    },
+    "nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="
+    },
+    "neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "dev": true
+    },
+    "node-addon-api": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz",
+      "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+      "dev": true,
+      "optional": true
+    },
+    "node-readable-to-web-readable-stream": {
+      "version": "0.4.2",
+      "resolved": "https://registry.npmmirror.com/node-readable-to-web-readable-stream/-/node-readable-to-web-readable-stream-0.4.2.tgz",
+      "integrity": "sha512-/cMZNI34v//jUTrI+UIo4ieHAB5EZRY/+7OmXZgBxaWBMcW2tGdceIw06RFxWxrKZ5Jp3sI2i5TsRo+CBhtVLQ==",
+      "optional": true
+    },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+    },
+    "normalize-wheel-es": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
+      "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "requires": {
+        "p-try": "^2.0.0"
+      }
+    },
+    "p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "requires": {
+        "p-limit": "^2.2.0"
+      }
+    },
+    "p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+    },
+    "pako": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz",
+      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
+    },
+    "particles.js": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/particles.js/-/particles.js-2.0.0.tgz",
+      "integrity": "sha512-8e0JIqkRbMMPlFBnF9f+92hX1s07jdkd3tqB8uHE9L+cwGGjIYjQM7QLgt0FQ5MZp6SFFYYDm/Y48pqK3ZvJOQ=="
+    },
+    "path-browserify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz",
+      "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+      "dev": true
+    },
+    "path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
+    },
+    "pdfjs-dist": {
+      "version": "5.4.624",
+      "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-5.4.624.tgz",
+      "integrity": "sha512-sm6TxKTtWv1Oh6n3C6J6a8odejb5uO4A4zo/2dgkHuC0iu8ZMAXOezEODkVaoVp8nX1Xzr+0WxFJJmUr45hQzg==",
+      "requires": {
+        "@napi-rs/canvas": "^0.1.88",
+        "node-readable-to-web-readable-stream": "^0.4.2"
+      }
+    },
+    "pdfkit": {
+      "version": "0.19.1",
+      "resolved": "https://registry.npmmirror.com/pdfkit/-/pdfkit-0.19.1.tgz",
+      "integrity": "sha512-6Gzk+wDwTs4VSxsR5rCMTnIl5nlmkye1oWB0l2hDB1EX6ZNSIBroKQEv+2+fPPn+stVjyqzmsqRJVDfB9fo5DA==",
+      "requires": {
+        "@noble/ciphers": "^1.0.0",
+        "@noble/hashes": "^1.6.0",
+        "fontkit": "^2.0.4",
+        "js-md5": "^0.8.3",
+        "linebreak": "^1.1.0",
+        "png-js": "^1.1.0"
+      }
+    },
+    "pdfmake": {
+      "version": "0.3.11",
+      "resolved": "https://registry.npmmirror.com/pdfmake/-/pdfmake-0.3.11.tgz",
+      "integrity": "sha512-Uc49J9hUMyuqJk+U+PxlpBpPr96A4HOOfesGx609EPr2ue82+5/Smq/KTAkEqh0/jUGSi1fumvqZ5yAWijJTJg==",
+      "requires": {
+        "linebreak": "^1.1.0",
+        "pdfkit": "^0.19.1",
+        "xmldoc": "^2.0.3"
+      }
+    },
+    "performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+      "optional": true
+    },
+    "picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+    },
+    "picomatch": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
+      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+      "dev": true
+    },
+    "png-js": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/png-js/-/png-js-1.1.0.tgz",
+      "integrity": "sha512-PM/uYGzGdNSzqeOgly68+6wKQDL1SY0a/N+OEa/+br6LnHWOAJB0Npiamnodfq3jd2LS/i2fMeOKSAILjA+m5Q==",
+      "requires": {
+        "browserify-zlib": "^0.2.0"
+      }
+    },
+    "pngjs": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz",
+      "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="
+    },
+    "postcss": {
+      "version": "8.5.4",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.4.tgz",
+      "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
+      "requires": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "pptx-preview": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/pptx-preview/-/pptx-preview-1.0.7.tgz",
+      "integrity": "sha512-YByocJuyxAR4YB4Q3+VAxdLfEvA5LojG1gAJsx2Mw0QU5FJPps/2fkJOupJ6oBbA+KdWRpuAk6G6T34rKCHVxw==",
+      "requires": {
+        "echarts": "^5.5.1",
+        "jszip": "^3.10.1",
+        "lodash": "^4.17.21",
+        "tslib": "^2.7.0",
+        "uuid": "^10.0.0"
+      },
+      "dependencies": {
+        "echarts": {
+          "version": "5.6.0",
+          "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
+          "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
+          "requires": {
+            "tslib": "2.3.0",
+            "zrender": "5.6.1"
+          },
+          "dependencies": {
+            "tslib": {
+              "version": "2.3.0",
+              "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+              "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+            }
+          }
+        },
+        "tslib": {
+          "version": "2.8.1",
+          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
+          "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+        },
+        "zrender": {
+          "version": "5.6.1",
+          "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz",
+          "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
+          "requires": {
+            "tslib": "2.3.0"
+          },
+          "dependencies": {
+            "tslib": {
+              "version": "2.3.0",
+              "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+              "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+            }
+          }
+        }
+      }
+    },
+    "process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+    },
+    "proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+    },
+    "qrcode": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.4.tgz",
+      "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
+      "requires": {
+        "dijkstrajs": "^1.0.1",
+        "pngjs": "^5.0.0",
+        "yargs": "^15.3.1"
+      }
+    },
+    "raf": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz",
+      "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+      "optional": true,
+      "requires": {
+        "performance-now": "^2.1.0"
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz",
+      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "readdir-glob": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmmirror.com/readdir-glob/-/readdir-glob-1.1.3.tgz",
+      "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
+      "requires": {
+        "minimatch": "^5.1.0"
+      },
+      "dependencies": {
+        "minimatch": {
+          "version": "5.1.9",
+          "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.9.tgz",
+          "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
+          "requires": {
+            "brace-expansion": "^2.0.1"
+          }
+        }
+      }
+    },
+    "readdirp": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz",
+      "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+      "dev": true
+    },
+    "regenerator-runtime": {
+      "version": "0.13.11",
+      "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+      "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+      "optional": true
+    },
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
+    },
+    "require-main-filename": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz",
+      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+    },
+    "restructure": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmmirror.com/restructure/-/restructure-3.0.2.tgz",
+      "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw=="
+    },
+    "rgbcolor": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/rgbcolor/-/rgbcolor-1.0.1.tgz",
+      "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
+      "optional": true
+    },
+    "rimraf": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-2.7.1.tgz",
+      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "rollup": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.41.1.tgz",
+      "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==",
+      "dev": true,
+      "requires": {
+        "@rollup/rollup-android-arm-eabi": "4.41.1",
+        "@rollup/rollup-android-arm64": "4.41.1",
+        "@rollup/rollup-darwin-arm64": "4.41.1",
+        "@rollup/rollup-darwin-x64": "4.41.1",
+        "@rollup/rollup-freebsd-arm64": "4.41.1",
+        "@rollup/rollup-freebsd-x64": "4.41.1",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.41.1",
+        "@rollup/rollup-linux-arm-musleabihf": "4.41.1",
+        "@rollup/rollup-linux-arm64-gnu": "4.41.1",
+        "@rollup/rollup-linux-arm64-musl": "4.41.1",
+        "@rollup/rollup-linux-loongarch64-gnu": "4.41.1",
+        "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1",
+        "@rollup/rollup-linux-riscv64-gnu": "4.41.1",
+        "@rollup/rollup-linux-riscv64-musl": "4.41.1",
+        "@rollup/rollup-linux-s390x-gnu": "4.41.1",
+        "@rollup/rollup-linux-x64-gnu": "4.41.1",
+        "@rollup/rollup-linux-x64-musl": "4.41.1",
+        "@rollup/rollup-win32-arm64-msvc": "4.41.1",
+        "@rollup/rollup-win32-ia32-msvc": "4.41.1",
+        "@rollup/rollup-win32-x64-msvc": "4.41.1",
+        "@types/estree": "1.0.7",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+    },
+    "sass": {
+      "version": "1.89.0",
+      "resolved": "https://registry.npmmirror.com/sass/-/sass-1.89.0.tgz",
+      "integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==",
+      "dev": true,
+      "requires": {
+        "@parcel/watcher": "^2.4.1",
+        "chokidar": "^4.0.0",
+        "immutable": "^5.0.2",
+        "source-map-js": ">=0.6.2 <2.0.0"
+      }
+    },
+    "sass-loader": {
+      "version": "16.0.5",
+      "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-16.0.5.tgz",
+      "integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==",
+      "dev": true,
+      "requires": {
+        "neo-async": "^2.6.2"
+      }
+    },
+    "sax": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/sax/-/sax-1.6.0.tgz",
+      "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="
+    },
+    "saxes": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/saxes/-/saxes-5.0.1.tgz",
+      "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
+      "requires": {
+        "xmlchars": "^2.2.0"
+      }
+    },
+    "set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+    },
+    "setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
+    },
+    "source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
+    },
+    "stackblur-canvas": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmmirror.com/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
+      "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
+      "optional": true
+    },
+    "string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "requires": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      }
+    },
+    "strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "requires": {
+        "ansi-regex": "^5.0.1"
+      }
+    },
+    "svg-pathdata": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmmirror.com/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
+      "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
+      "optional": true
+    },
+    "tar-stream": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-2.2.0.tgz",
+      "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+      "requires": {
+        "bl": "^4.0.3",
+        "end-of-stream": "^1.4.1",
+        "fs-constants": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^3.1.1"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.2",
+          "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+          "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "text-segmentation": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz",
+      "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+      "optional": true,
+      "requires": {
+        "utrie": "^1.0.2"
+      }
+    },
+    "tiny-inflate": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
+      "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="
+    },
+    "tinyglobby": {
+      "version": "0.2.14",
+      "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.14.tgz",
+      "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
+      "dev": true,
+      "requires": {
+        "fdir": "^6.4.4",
+        "picomatch": "^4.0.2"
+      }
+    },
+    "tmp": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.7.tgz",
+      "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw=="
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "is-number": "^7.0.0"
+      }
+    },
+    "traverse": {
+      "version": "0.3.9",
+      "resolved": "https://registry.npmmirror.com/traverse/-/traverse-0.3.9.tgz",
+      "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ=="
+    },
+    "tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+    },
+    "typescript": {
+      "version": "5.8.3",
+      "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.8.3.tgz",
+      "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+      "devOptional": true
+    },
+    "undici-types": {
+      "version": "6.21.0",
+      "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz",
+      "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+      "dev": true
+    },
+    "unicode-properties": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/unicode-properties/-/unicode-properties-1.4.1.tgz",
+      "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
+      "requires": {
+        "base64-js": "^1.3.0",
+        "unicode-trie": "^2.0.0"
+      }
+    },
+    "unicode-trie": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/unicode-trie/-/unicode-trie-2.0.0.tgz",
+      "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
+      "requires": {
+        "pako": "^0.2.5",
+        "tiny-inflate": "^1.0.0"
+      },
+      "dependencies": {
+        "pako": {
+          "version": "0.2.9",
+          "resolved": "https://registry.npmmirror.com/pako/-/pako-0.2.9.tgz",
+          "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="
+        }
+      }
+    },
+    "unzipper": {
+      "version": "0.10.14",
+      "resolved": "https://registry.npmmirror.com/unzipper/-/unzipper-0.10.14.tgz",
+      "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==",
+      "requires": {
+        "big-integer": "^1.6.17",
+        "binary": "~0.3.0",
+        "bluebird": "~3.4.1",
+        "buffer-indexof-polyfill": "~1.0.0",
+        "duplexer2": "~0.1.4",
+        "fstream": "^1.0.12",
+        "graceful-fs": "^4.2.2",
+        "listenercount": "~1.0.1",
+        "readable-stream": "~2.3.6",
+        "setimmediate": "~1.0.4"
+      }
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+    },
+    "utrie": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz",
+      "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+      "optional": true,
+      "requires": {
+        "base64-arraybuffer": "^1.0.2"
+      }
+    },
+    "uuid": {
+      "version": "10.0.0",
+      "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz",
+      "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="
+    },
+    "vite": {
+      "version": "6.3.5",
+      "resolved": "https://registry.npmmirror.com/vite/-/vite-6.3.5.tgz",
+      "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
+      "dev": true,
+      "requires": {
+        "esbuild": "^0.25.0",
+        "fdir": "^6.4.4",
+        "fsevents": "~2.3.3",
+        "picomatch": "^4.0.2",
+        "postcss": "^8.5.3",
+        "rollup": "^4.34.9",
+        "tinyglobby": "^0.2.13"
+      }
+    },
+    "vscode-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz",
+      "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
+      "dev": true
+    },
+    "vue": {
+      "version": "3.5.16",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.16.tgz",
+      "integrity": "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==",
+      "requires": {
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/compiler-sfc": "3.5.16",
+        "@vue/runtime-dom": "3.5.16",
+        "@vue/server-renderer": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "vue-demi": {
+      "version": "0.14.6",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
+      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
+      "requires": {}
+    },
+    "vue-pdf-embed": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmmirror.com/vue-pdf-embed/-/vue-pdf-embed-2.1.3.tgz",
+      "integrity": "sha512-EGgZNb8HRrAloBpb8p8CugDpJpoPbQ8CFfAYdWZgq2e5qBMP9JSeLzVQIAJkXsclHXRIS3O9fp3WQbP9T5Inwg==",
+      "requires": {
+        "pdfjs-dist": "^4.10.38"
+      },
+      "dependencies": {
+        "pdfjs-dist": {
+          "version": "4.10.38",
+          "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-4.10.38.tgz",
+          "integrity": "sha512-/Y3fcFrXEAsMjJXeL9J8+ZG9U01LbuWaYypvDW2ycW1jL269L3js3DVBjDJ0Up9Np1uqDXsDrRihHANhZOlwdQ==",
+          "requires": {
+            "@napi-rs/canvas": "^0.1.65"
+          }
+        }
+      }
+    },
+    "vue-router": {
+      "version": "4.5.1",
+      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.1.tgz",
+      "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==",
+      "requires": {
+        "@vue/devtools-api": "^6.6.4"
+      }
+    },
+    "vue-tsc": {
+      "version": "2.2.10",
+      "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.10.tgz",
+      "integrity": "sha512-jWZ1xSaNbabEV3whpIDMbjVSVawjAyW+x1n3JeGQo7S0uv2n9F/JMgWW90tGWNFRKya4YwKMZgCtr0vRAM7DeQ==",
+      "dev": true,
+      "requires": {
+        "@volar/typescript": "~2.4.11",
+        "@vue/language-core": "2.2.10"
+      }
+    },
+    "vuex": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/vuex/-/vuex-4.1.0.tgz",
+      "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==",
+      "requires": {
+        "@vue/devtools-api": "^6.0.0-beta.11"
+      }
+    },
+    "which-module": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz",
+      "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
+    },
+    "wrap-ansi": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "requires": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+    },
+    "xmlchars": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz",
+      "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
+    },
+    "xmldoc": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/xmldoc/-/xmldoc-2.0.3.tgz",
+      "integrity": "sha512-6gRk4NY/Jvg67xn7OzJuxLRsGgiXBaPUQplVJ/9l99uIugxh4FTOewYz5ic8WScj7Xx/2WvhENiQKwkK9RpE4w==",
+      "requires": {
+        "sax": "^1.4.3"
+      }
+    },
+    "y18n": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
+    },
+    "yargs": {
+      "version": "15.4.1",
+      "resolved": "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz",
+      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+      "requires": {
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^4.2.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^18.1.2"
+      }
+    },
+    "yargs-parser": {
+      "version": "18.1.3",
+      "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+      "requires": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      }
+    },
+    "zip-stream": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/zip-stream/-/zip-stream-4.1.1.tgz",
+      "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
+      "requires": {
+        "archiver-utils": "^3.0.4",
+        "compress-commons": "^4.1.2",
+        "readable-stream": "^3.6.0"
+      },
+      "dependencies": {
+        "archiver-utils": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmmirror.com/archiver-utils/-/archiver-utils-3.0.4.tgz",
+          "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
+          "requires": {
+            "glob": "^7.2.3",
+            "graceful-fs": "^4.2.0",
+            "lazystream": "^1.0.0",
+            "lodash.defaults": "^4.2.0",
+            "lodash.difference": "^4.5.0",
+            "lodash.flatten": "^4.4.0",
+            "lodash.isplainobject": "^4.0.6",
+            "lodash.union": "^4.6.0",
+            "normalize-path": "^3.0.0",
+            "readable-stream": "^3.6.0"
+          }
+        },
+        "readable-stream": {
+          "version": "3.6.2",
+          "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+          "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "zrender": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-6.0.0.tgz",
+      "integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==",
+      "requires": {
+        "tslib": "2.3.0"
+      }
+    }
+  }
+}

+ 47 - 0
package.json

@@ -0,0 +1,47 @@
+{
+  "name": "clientManageSystem",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite --mode self",
+    "build:dev": "vite build --mode dev",
+    "build:test": "vite build --mode test",
+    "build:self": "vite build --mode self",
+    "build": "vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "@element-plus/icons-vue": "^2.3.1",
+    "@vue-office/docx": "^1.6.3",
+    "@vue-office/excel": "^1.7.14",
+    "axios": "^1.9.0",
+    "echarts": "^6.0.0",
+    "element-plus": "^2.9.11",
+    "exceljs": "^4.4.0",
+    "jsencrypt": "^3.5.4",
+    "jspdf": "^4.2.1",
+    "jspdf-autotable": "^5.0.8",
+    "lodash": "^4.17.21",
+    "particles.js": "^2.0.0",
+    "pdfjs-dist": "^5.4.624",
+    "pdfmake": "^0.3.11",
+    "pptx-preview": "^1.0.7",
+    "qrcode": "^1.5.4",
+    "vue": "^3.5.13",
+    "vue-demi": "^0.14.6",
+    "vue-pdf-embed": "^2.1.3",
+    "vue-router": "^4.5.1",
+    "vuex": "^4.1.0"
+  },
+  "devDependencies": {
+    "@types/node": "^22.15.26",
+    "@vitejs/plugin-vue": "^5.2.3",
+    "@vue/tsconfig": "^0.7.0",
+    "sass": "^1.89.0",
+    "sass-loader": "^16.0.5",
+    "typescript": "~5.8.3",
+    "vite": "^6.3.5",
+    "vue-tsc": "^2.2.8"
+  }
+}

BIN
public/favicon.ico


BIN
public/font/SIMHEI.TTF


BIN
public/font/STXIHEI.TTF


+ 24 - 0
src/App.vue

@@ -0,0 +1,24 @@
+<script setup lang="ts">
+</script>
+
+<template>
+  <router-view />
+</template>
+
+<style scoped lang="scss">
+* {
+    font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
+}
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.vue:hover {
+  filter: drop-shadow(0 0 2em #42b883aa);
+}
+</style>

+ 13 - 0
src/api/demo.ts

@@ -0,0 +1,13 @@
+import request from '../utils/request.js'
+
+let teacherPrefix = import.meta.env.VITE_API_TEACHER_PRE 
+
+
+// 查询课程列表数据接口(课程列表页面)
+export const getXXX = (data:any) => {
+    return request({
+        url: `${teacherPrefix}/xxx`,
+        method: 'post',
+        data
+    })
+}

+ 30 - 0
src/api/login.ts

@@ -0,0 +1,30 @@
+// src/api/login.ts
+import request from '../utils/request.ts'
+
+let studentPrefix = import.meta.env.VITE_API_STUDENT_PRE
+
+
+// 登录接口
+export const login = (data:any) => {
+  return request({
+    url: `${studentPrefix}/api/v1/student/login`,
+    method: 'post',
+    data
+  })
+}
+// 获取用户信息
+export const getUserInfo = () => {
+  return request({
+    url: `${studentPrefix}/api/v1/student_user/find_user_info`,
+    method: 'get'
+  })
+}
+//退出登录
+export const loginOut = (data: any) => {
+  return request({
+    url: `${studentPrefix}/api/v1/student/logout`,
+    method: 'post',
+    data
+  })
+}
+

BIN
src/assets/bg/table_no_data.png


BIN
src/assets/bg/zanwushuju.png


+ 27 - 0
src/assets/icon/AddIcon.vue

@@ -0,0 +1,27 @@
+<template>
+    <svg :width="iconSize" :height="iconSize" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+        <rect x="7" y="1" width="1.8" height="14" rx="0.9" 
+            fill="var(--icon-color)"/>
+        <rect x="15" y="7" width="1.8" height="14" rx="0.9" transform="rotate(90 15 7)"
+            fill="var(--icon-color)"/>
+    </svg>
+</template>
+
+<script setup lang="ts">
+
+
+const props  = defineProps({
+    iconSize:{
+        type:Number,
+        default:16
+    }
+
+})
+
+</script>
+
+<style lang="scss" scoped>
+svg{
+    --icon-color : #2E64FA;
+}
+</style>

+ 22 - 0
src/assets/icon/DeleteIcon.vue

@@ -0,0 +1,22 @@
+<template>
+    <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+        <g clip-path="url(#clip0_7_8551)">
+        <path d="M3.21973 3.01758C3.49642 2.83507 3.87407 2.86534 4.11719 3.1084L12.8936 11.8838L12.9844 11.9951C13.1656 12.2708 13.1345 12.6487 12.8916 12.8916C12.6485 13.1347 12.2709 13.1649 11.9941 12.9824L11.8828 12.8916L3.1084 4.11719C2.83074 3.83947 2.8307 3.38609 3.1084 3.1084L3.21973 3.01758Z" 
+            fill="var(--icon-color)" stroke="var(--icon-color)" stroke-width="0.2"/>
+        <path d="M11.9951 3.0166C12.2708 2.83514 12.6486 2.86552 12.8916 3.1084L12.9824 3.21973C13.139 3.457 13.1388 3.76851 12.9824 4.00586L12.8916 4.11719L4.11719 12.8916C3.87418 13.1346 3.49641 13.1657 3.21973 12.9834L3.1084 12.8916C2.83078 12.6139 2.83072 12.1605 3.1084 11.8828L11.8838 3.10645L11.9951 3.0166Z" 
+            fill="var(--icon-color)" stroke="var(--icon-color)" stroke-width="0.2"/>
+        </g>
+        <defs>
+            <clipPath id="clip0_7_8551">
+            <rect width="16" height="16" fill="white"/>
+            </clipPath>
+        </defs>
+    </svg>
+</template>
+
+
+<style lang="scss" scoped>
+svg{
+    --icon-color : #666666;   
+}
+</style>

BIN
src/assets/icon/add.png


+ 4 - 0
src/assets/icon/add.svg

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="7" y="1" width="1.8" height="14" rx="0.9" fill="#2E64FA"/>
+<rect x="15" y="7" width="1.8" height="14" rx="0.9" transform="rotate(90 15 7)" fill="#2E64FA"/>
+</svg>

+ 11 - 0
src/assets/icon/cancel.svg

@@ -0,0 +1,11 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_7_8568)">
+<path d="M3.21973 3.01758C3.49642 2.83507 3.87407 2.86534 4.11719 3.1084L12.8936 11.8838L12.9844 11.9951C13.1656 12.2708 13.1345 12.6487 12.8916 12.8916C12.6485 13.1347 12.2709 13.1649 11.9941 12.9824L11.8828 12.8916L3.1084 4.11719C2.83074 3.83947 2.8307 3.38609 3.1084 3.1084L3.21973 3.01758Z" fill="#BBBBBB" stroke="#BBBBBB" stroke-width="0.2"/>
+<path d="M11.9951 3.0166C12.2708 2.83514 12.6486 2.86552 12.8916 3.1084L12.9824 3.21973C13.139 3.457 13.1388 3.76851 12.9824 4.00586L12.8916 4.11719L4.11719 12.8916C3.87418 13.1346 3.49641 13.1657 3.21973 12.9834L3.1084 12.8916C2.83078 12.6139 2.83072 12.1605 3.1084 11.8828L11.8838 3.10645L11.9951 3.0166Z" fill="#BBBBBB" stroke="#BBBBBB" stroke-width="0.2"/>
+</g>
+<defs>
+<clipPath id="clip0_7_8568">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 3 - 0
src/assets/icon/close.svg

@@ -0,0 +1,3 @@
+<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.84375 4.375H18.1562C18.5877 4.375 18.9375 4.02521 18.9375 3.59375C18.9375 3.16227 18.5877 2.8125 18.1562 2.8125H2.84375C2.41227 2.8125 2.0625 3.16227 2.0625 3.59375C2.0625 4.02521 2.41227 4.375 2.84375 4.375ZM18.1562 15.625H2.84375C2.41227 15.625 2.0625 15.9748 2.0625 16.4062C2.0625 16.8377 2.41227 17.1875 2.84375 17.1875H18.1562C18.5877 17.1875 18.9375 16.8377 18.9375 16.4062C18.9375 15.9748 18.5877 15.625 18.1562 15.625ZM18.1562 9.21875H9.09375C8.66227 9.21875 8.3125 9.56852 8.3125 10C8.3125 10.4315 8.66227 10.7812 9.09375 10.7812H18.1562C18.5877 10.7812 18.9375 10.4315 18.9375 10C18.9375 9.56852 18.5877 9.21875 18.1562 9.21875ZM6.52117 6.35396C6.21607 6.04887 5.72143 6.04887 5.41633 6.35396L2.32273 9.44758C2.01764 9.75268 2.01764 10.2473 2.32273 10.5524L5.41633 13.646C5.72143 13.9511 6.21607 13.9511 6.52117 13.646C6.82627 13.3409 6.82627 12.8463 6.52117 12.5412L3.98002 10L6.52117 7.45883C6.82627 7.15373 6.82627 6.65906 6.52117 6.35396Z" fill="#666666"/>
+</svg>

+ 6 - 0
src/assets/icon/close_fill.svg

@@ -0,0 +1,6 @@
+<svg  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
+<rect x="250" y="250" width="500" height="500" stroke="blue" fill="white"
+       fill-opacity="1" stroke-opacity="0"/>
+<path fill="#F56C6C" d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896m0 393.664L407.936 353.6a38.4 38.4 0 1 0-54.336 54.336L457.664 512 353.6 616.064a38.4 38.4 0 1 0 54.336 54.336L512 566.336 616.064 670.4a38.4 38.4 0 1 0 54.336-54.336L566.336 512 670.4 407.936a38.4 38.4 0 1 0-54.336-54.336z">
+</path>
+</svg>

+ 3 - 0
src/assets/icon/confirm.svg

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M13.0542 3.67993C13.352 3.43496 13.7932 3.45214 14.0718 3.73071L14.1235 3.78833C14.3503 4.06646 14.3505 4.46732 14.1235 4.74536L14.0718 4.80298L6.90674 11.968C6.50596 12.3688 5.87223 12.3961 5.43994 12.0481L5.35596 11.9739L1.73486 8.40259C1.43554 8.10732 1.43364 7.62471 1.73096 7.32739L1.78857 7.27563C2.08607 7.03294 2.52482 7.05023 2.80225 7.32739L5.99072 10.5159C6.06906 10.5942 6.1969 10.5945 6.2749 10.5159L12.9966 3.73267L13.0542 3.67993Z" fill="#2E64FA" stroke="#2E64FA" stroke-width="0.2"/>
+</svg>

+ 13 - 0
src/assets/icon/delete.svg

@@ -0,0 +1,13 @@
+
+
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_7_8551)">
+<path d="M3.21973 3.01758C3.49642 2.83507 3.87407 2.86534 4.11719 3.1084L12.8936 11.8838L12.9844 11.9951C13.1656 12.2708 13.1345 12.6487 12.8916 12.8916C12.6485 13.1347 12.2709 13.1649 11.9941 12.9824L11.8828 12.8916L3.1084 4.11719C2.83074 3.83947 2.8307 3.38609 3.1084 3.1084L3.21973 3.01758Z" fill="#666" stroke="#666" stroke-width="0.2"/>
+<path d="M11.9951 3.0166C12.2708 2.83514 12.6486 2.86552 12.8916 3.1084L12.9824 3.21973C13.139 3.457 13.1388 3.76851 12.9824 4.00586L12.8916 4.11719L4.11719 12.8916C3.87418 13.1346 3.49641 13.1657 3.21973 12.9834L3.1084 12.8916C2.83078 12.6139 2.83072 12.1605 3.1084 11.8828L11.8838 3.10645L11.9951 3.0166Z" fill="#666" stroke="#666" stroke-width="0.2"/>
+</g>
+<defs>
+<clipPath id="clip0_7_8551">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>

BIN
src/assets/icon/edit.png


BIN
src/assets/icon/exitFullScreen.png


BIN
src/assets/icon/file.png


BIN
src/assets/icon/fullScreen.png


+ 4 - 0
src/assets/icon/home_hover.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.60718 2.33667C9.4851 1.64684 10.7549 1.69676 11.5769 2.48706L17.9753 8.6355L18.0535 8.72339C18.2201 8.94004 18.2624 9.23186 18.1599 9.49097V9.49194C18.0404 9.78815 17.7522 9.9812 17.4333 9.9812H16.0271V15.8787C16.0271 17.1312 15.0131 18.1453 13.7605 18.1453H6.23315C4.98059 18.1453 3.96655 17.1312 3.96655 15.8787V9.9812H2.56812C2.24734 9.9811 1.96098 9.78811 1.84155 9.49194C1.72224 9.19572 1.79458 8.8559 2.02515 8.6355L8.43726 2.48511L8.60718 2.33667ZM10.7478 3.34937C10.3524 2.96902 9.73311 2.94851 9.31323 3.30249L9.31226 3.30151L9.26147 3.34644L9.26245 3.34741L3.58862 8.78784H4.11792C4.69206 8.78802 5.15783 9.25373 5.15796 9.82788V15.8787C5.15796 16.4472 5.60188 16.916 6.1687 16.95H6.16772L6.23218 16.9519H13.7585C14.327 16.9519 14.7958 16.5079 14.8298 15.9412L14.8318 15.8787V9.82788C14.8319 9.25364 15.2976 8.78788 15.8718 8.78784H16.4119L10.7478 3.34937Z" fill="#2E64FA" stroke="#2E64FA" stroke-width="0.08"/>
+<path d="M12.0391 13.2412C12.2308 13.2412 12.3815 13.2897 12.4844 13.3926C12.5873 13.4955 12.6357 13.6462 12.6357 13.8379C12.6357 14.0296 12.5873 14.1803 12.4844 14.2832C12.3815 14.3861 12.2308 14.4346 12.0391 14.4346H7.95703C7.76532 14.4346 7.61464 14.3861 7.51172 14.2832C7.4088 14.1803 7.36035 14.0296 7.36035 13.8379C7.36035 13.6462 7.4088 13.4955 7.51172 13.3926C7.61464 13.2897 7.76532 13.2412 7.95703 13.2412H12.0391Z" fill="#2E64FA" stroke="#2E64FA" stroke-width="0.08"/>
+</svg>

+ 4 - 0
src/assets/icon/home_light.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.60715 2.33667C9.48507 1.64684 10.7549 1.69676 11.5769 2.48706L17.9753 8.6355L18.0534 8.72339C18.2201 8.94004 18.2624 9.23186 18.1599 9.49097V9.49194C18.0404 9.78815 17.7521 9.9812 17.4333 9.9812H16.0271V15.8787C16.0271 17.1312 15.013 18.1453 13.7605 18.1453H6.23312C4.98056 18.1453 3.96652 17.1312 3.96652 15.8787V9.9812H2.56808C2.24731 9.9811 1.96094 9.78811 1.84152 9.49194C1.72221 9.19572 1.79455 8.8559 2.02512 8.6355L8.43723 2.48511L8.60715 2.33667ZM10.7478 3.34937C10.3524 2.96902 9.73308 2.94851 9.3132 3.30249L9.31223 3.30151L9.26144 3.34644L9.26242 3.34741L3.58859 8.78784H4.11789C4.69203 8.78802 5.1578 9.25373 5.15793 9.82788V15.8787C5.15793 16.4472 5.60185 16.916 6.16867 16.95H6.16769L6.23215 16.9519H13.7585C14.327 16.9519 14.7958 16.5079 14.8298 15.9412L14.8318 15.8787V9.82788C14.8319 9.25364 15.2975 8.78788 15.8718 8.78784H16.4118L10.7478 3.34937Z" fill="white" stroke="white" stroke-width="0.08"/>
+<path d="M12.0391 13.2412C12.2308 13.2412 12.3815 13.2897 12.4844 13.3926C12.5873 13.4955 12.6357 13.6462 12.6357 13.8379C12.6357 14.0296 12.5873 14.1803 12.4844 14.2832C12.3815 14.3861 12.2308 14.4346 12.0391 14.4346H7.95703C7.76532 14.4346 7.61464 14.3861 7.51172 14.2832C7.4088 14.1803 7.36035 14.0296 7.36035 13.8379C7.36035 13.6462 7.4088 13.4955 7.51172 13.3926C7.61464 13.2897 7.76532 13.2412 7.95703 13.2412H12.0391Z" fill="white" stroke="white" stroke-width="0.08"/>
+</svg>

+ 4 - 0
src/assets/icon/home_normal.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.60715 2.33667C9.48507 1.64684 10.7549 1.69676 11.5769 2.48706L17.9753 8.6355L18.0534 8.72339C18.2201 8.94004 18.2624 9.23186 18.1599 9.49097V9.49194C18.0404 9.78815 17.7521 9.9812 17.4333 9.9812H16.0271V15.8787C16.0271 17.1312 15.013 18.1453 13.7605 18.1453H6.23312C4.98056 18.1453 3.96652 17.1312 3.96652 15.8787V9.9812H2.56808C2.24731 9.9811 1.96094 9.78811 1.84152 9.49194C1.72221 9.19572 1.79455 8.8559 2.02512 8.6355L8.43723 2.48511L8.60715 2.33667ZM10.7478 3.34937C10.3524 2.96902 9.73308 2.94851 9.3132 3.30249L9.31223 3.30151L9.26144 3.34644L9.26242 3.34741L3.58859 8.78784H4.11789C4.69203 8.78802 5.1578 9.25373 5.15793 9.82788V15.8787C5.15793 16.4472 5.60185 16.916 6.16867 16.95H6.16769L6.23215 16.9519H13.7585C14.327 16.9519 14.7958 16.5079 14.8298 15.9412L14.8318 15.8787V9.82788C14.8319 9.25364 15.2975 8.78788 15.8718 8.78784H16.4118L10.7478 3.34937Z" fill="#666666" stroke="#666666" stroke-width="0.08"/>
+<path d="M12.0391 13.2412C12.2308 13.2412 12.3815 13.2897 12.4844 13.3926C12.5873 13.4955 12.6357 13.6462 12.6357 13.8379C12.6357 14.0296 12.5873 14.1803 12.4844 14.2832C12.3815 14.3861 12.2308 14.4346 12.0391 14.4346H7.95703C7.76532 14.4346 7.61464 14.3861 7.51172 14.2832C7.4088 14.1803 7.36035 14.0296 7.36035 13.8379C7.36035 13.6462 7.4088 13.4955 7.51172 13.3926C7.61464 13.2897 7.76532 13.2412 7.95703 13.2412H12.0391Z" fill="#666666" stroke="#666666" stroke-width="0.08"/>
+</svg>

+ 8 - 0
src/assets/icon/join_exam_hover.svg

@@ -0,0 +1,8 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="10" cy="5.43188" r="1.925" stroke="#2E64FA" stroke-width="1.15"/>
+<circle cx="4" cy="14.5" r="1.425" stroke="#2E64FA" stroke-width="1.15"/>
+<circle cx="10" cy="14.5" r="1.425" stroke="#2E64FA" stroke-width="1.15"/>
+<circle cx="16" cy="14.5" r="1.425" stroke="#2E64FA" stroke-width="1.15"/>
+<line x1="10.075" y1="7.5" x2="10.075" y2="13.5" stroke="#2E64FA" stroke-width="1.15"/>
+<path d="M16 13.5V12.1819C16 11.0773 15.1046 10.1819 14 10.1819H6C4.89543 10.1819 4 11.0773 4 12.1819V13.5" stroke="#2E64FA" stroke-width="1.15"/>
+</svg>

+ 8 - 0
src/assets/icon/join_exam_light.svg

@@ -0,0 +1,8 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="10" cy="5.43188" r="1.925" stroke="white" stroke-width="1.15"/>
+<circle cx="4" cy="14.5" r="1.425" stroke="white" stroke-width="1.15"/>
+<circle cx="10" cy="14.5" r="1.425" stroke="white" stroke-width="1.15"/>
+<circle cx="16" cy="14.5" r="1.425" stroke="white" stroke-width="1.15"/>
+<line x1="10.075" y1="7.5" x2="10.075" y2="13.5" stroke="white" stroke-width="1.15"/>
+<path d="M16 13.5V12.1819C16 11.0773 15.1046 10.1819 14 10.1819H6C4.89543 10.1819 4 11.0773 4 12.1819V13.5" stroke="white" stroke-width="1.15"/>
+</svg>

+ 8 - 0
src/assets/icon/join_exam_normal.svg

@@ -0,0 +1,8 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="10" cy="5.43188" r="1.925" stroke="#666666" stroke-width="1.15"/>
+<circle cx="4" cy="14.5" r="1.425" stroke="#666666" stroke-width="1.15"/>
+<circle cx="10" cy="14.5" r="1.425" stroke="#666666" stroke-width="1.15"/>
+<circle cx="16" cy="14.5" r="1.425" stroke="#666666" stroke-width="1.15"/>
+<line x1="10.075" y1="7.5" x2="10.075" y2="13.5" stroke="#666666" stroke-width="1.15"/>
+<path d="M16 13.5V12.1819C16 11.0773 15.1046 10.1819 14 10.1819H6C4.89543 10.1819 4 11.0773 4 12.1819V13.5" stroke="#666666" stroke-width="1.15"/>
+</svg>

BIN
src/assets/icon/left_back_arrow_.png


BIN
src/assets/icon/line_close_icon.webp


BIN
src/assets/icon/list.png


BIN
src/assets/icon/list_light.png


BIN
src/assets/icon/list_white.png


File diff suppressed because it is too large
+ 2 - 0
src/assets/icon/manage_hover.svg


File diff suppressed because it is too large
+ 2 - 0
src/assets/icon/manage_light.svg


File diff suppressed because it is too large
+ 2 - 0
src/assets/icon/manage_normal.svg


BIN
src/assets/icon/move_up_down.png


BIN
src/assets/icon/novolume.png


+ 3 - 0
src/assets/icon/open.svg

@@ -0,0 +1,3 @@
+<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M18.1562 4.375H2.84375C2.41227 4.375 2.0625 4.02521 2.0625 3.59375C2.0625 3.16227 2.41227 2.8125 2.84375 2.8125H18.1562C18.5877 2.8125 18.9375 3.16227 18.9375 3.59375C18.9375 4.02521 18.5877 4.375 18.1562 4.375ZM2.84375 15.625H18.1562C18.5877 15.625 18.9375 15.9748 18.9375 16.4062C18.9375 16.8377 18.5877 17.1875 18.1562 17.1875H2.84375C2.41227 17.1875 2.0625 16.8377 2.0625 16.4062C2.0625 15.9748 2.41227 15.625 2.84375 15.625ZM2.84375 9.21875H11.9062C12.3377 9.21875 12.6875 9.56852 12.6875 10C12.6875 10.4315 12.3377 10.7812 11.9062 10.7812H2.84375C2.41227 10.7812 2.0625 10.4315 2.0625 10C2.0625 9.56852 2.41227 9.21875 2.84375 9.21875ZM14.4788 6.35396C14.7839 6.04887 15.2786 6.04887 15.5837 6.35396L18.6773 9.44758C18.9824 9.75268 18.9824 10.2473 18.6773 10.5524L15.5837 13.646C15.2786 13.9511 14.7839 13.9511 14.4788 13.646C14.1737 13.3409 14.1737 12.8463 14.4788 12.5412L17.02 10L14.4788 7.45883C14.1737 7.15373 14.1737 6.65906 14.4788 6.35396Z" fill="#666666"/>
+</svg>

+ 1 - 0
src/assets/icon/password.svg

@@ -0,0 +1 @@
+<svg t="1767832180463" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4937" width="200" height="200"><path d="M768 416h-441.6v-134.4c0-115.2 89.6-204.8 204.8-204.8s204.8 89.6 204.8 204.8v64c0 19.2 19.2 38.4 38.4 38.4s38.4-19.2 38.4-38.4v-70.4c0-153.6-121.6-275.2-275.2-275.2s-275.2 128-275.2 275.2v140.8c-64 19.2-102.4 76.8-102.4 134.4v326.4c0 76.8 64 140.8 140.8 140.8h480c76.8 0 140.8-64 140.8-140.8v-326.4c-12.8-76.8-76.8-134.4-153.6-134.4z m70.4 460.8c0 38.4-25.6 64-64 64h-480c-38.4 0-64-25.6-64-64v-326.4c0-38.4 25.6-64 64-64h480c38.4 0 64 25.6 64 64v326.4z" fill="#a8abb2" p-id="4938"></path><path d="M531.2 588.8c-19.2 0-38.4 19.2-38.4 38.4v134.4c0 19.2 19.2 38.4 38.4 38.4s38.4-19.2 38.4-38.4v-140.8c0-6.4-6.4-19.2-12.8-25.6-6.4-6.4-19.2-6.4-25.6-6.4z" fill="#a8abb2" p-id="4939"></path></svg>

BIN
src/assets/icon/pause.png


BIN
src/assets/icon/play.png


BIN
src/assets/icon/publish.png


BIN
src/assets/icon/publish_light.png


+ 19 - 0
src/assets/icon/red_time_icon.svg

@@ -0,0 +1,19 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="Frame" clip-path="url(#clip0_15214_44957)">
+<path id="Vector" d="M8 0.939453C9.88552 0.939505 11.6588 1.67365 12.9922 3.00684C14.3254 4.33991 15.0596 6.11346 15.0596 7.99902C15.0596 9.88465 14.3254 11.6582 12.9922 12.9912C11.6588 14.3246 9.88552 15.0585 8 15.0586C6.11447 15.0586 4.34095 14.3246 3.00781 12.9912C1.67458 11.6582 0.94044 9.88433 0.94043 7.99902C0.94043 6.11386 1.67458 4.33991 3.00781 3.00684C4.34095 1.67358 6.11447 0.939453 8 0.939453ZM8 2.00879C6.39988 2.00884 4.89593 2.632 3.76465 3.76367C2.63294 4.89514 2.00977 6.3989 2.00977 7.99902C2.00978 9.5993 2.63287 11.103 3.76465 12.2344C4.89597 13.3662 6.39981 13.9893 8 13.9893C9.60011 13.9892 11.104 13.3661 12.2354 12.2344C13.3671 11.103 13.9902 9.59922 13.9902 7.99902C13.9902 6.39883 13.3672 4.89516 12.2354 3.76367C11.1039 2.63197 9.60018 2.00879 8 2.00879Z" fill="#F56C6C" stroke="#F56C6C" stroke-width="0.2"/>
+<g id="Vector_2">
+<mask id="path-2-outside-1_15214_44957" maskUnits="userSpaceOnUse" x="6.24121" y="2.75195" width="3" height="7" fill="black">
+<rect fill="white" x="6.24121" y="2.75195" width="3" height="7"/>
+<path d="M8.11129 8.68507V4.18707C8.11127 4.07169 8.06543 3.96104 7.98385 3.87945C7.90227 3.79785 7.79163 3.752 7.67625 3.75195C7.56087 3.752 7.45023 3.79785 7.36865 3.87945C7.28707 3.96104 7.24123 4.07169 7.24121 4.18707V8.97195C7.24116 9.05711 7.26613 9.14041 7.31303 9.21149C7.35992 9.28258 7.42667 9.33832 7.50497 9.37179"/>
+</mask>
+<path d="M8.11129 8.68507V4.18707C8.11127 4.07169 8.06543 3.96104 7.98385 3.87945C7.90227 3.79785 7.79163 3.752 7.67625 3.75195C7.56087 3.752 7.45023 3.79785 7.36865 3.87945C7.28707 3.96104 7.24123 4.07169 7.24121 4.18707V8.97195C7.24116 9.05711 7.26613 9.14041 7.31303 9.21149C7.35992 9.28258 7.42667 9.33832 7.50497 9.37179" fill="#F56C6C"/>
+<path d="M8.11129 4.18707H8.31129V4.18704L8.11129 4.18707ZM7.67625 3.75195L7.67632 3.55195L7.67618 3.55195L7.67625 3.75195ZM7.24121 4.18707L7.04121 4.18704V4.18707H7.24121ZM7.24121 8.97195L7.44121 8.97207V8.97195H7.24121ZM8.11129 8.68507H8.31129V4.18707H8.11129H7.91129V8.68507H8.11129ZM8.11129 4.18707L8.31129 4.18704C8.31126 4.01863 8.24436 3.85713 8.12529 3.73804L7.98385 3.87945L7.84242 4.02086C7.88651 4.06495 7.91128 4.12475 7.91129 4.18711L8.11129 4.18707ZM7.98385 3.87945L8.12529 3.73804C8.00622 3.61895 7.84473 3.55202 7.67632 3.55195L7.67625 3.75195L7.67618 3.95195C7.73853 3.95198 7.79833 3.97676 7.84242 4.02086L7.98385 3.87945ZM7.67625 3.75195L7.67618 3.55195C7.50777 3.55202 7.34628 3.61895 7.22722 3.73804L7.36865 3.87945L7.51008 4.02086C7.55417 3.97676 7.61397 3.95198 7.67632 3.95195L7.67625 3.75195ZM7.36865 3.87945L7.22722 3.73804C7.10815 3.85713 7.04124 4.01863 7.04121 4.18704L7.24121 4.18707L7.44121 4.18711C7.44122 4.12475 7.466 4.06495 7.51008 4.02086L7.36865 3.87945ZM7.24121 4.18707H7.04121V8.97195H7.24121H7.44121V4.18707H7.24121ZM7.24121 8.97195L7.04121 8.97184C7.04114 9.09619 7.0776 9.21782 7.14608 9.32162L7.31303 9.21149L7.47997 9.10137C7.45466 9.063 7.44118 9.01804 7.44121 8.97207L7.24121 8.97195ZM7.31303 9.21149L7.14608 9.32162C7.21455 9.42543 7.31202 9.50682 7.42636 9.5557L7.50497 9.37179L7.58358 9.18789C7.54131 9.16982 7.50529 9.13974 7.47997 9.10137L7.31303 9.21149Z" fill="#F56C6C" mask="url(#path-2-outside-1_15214_44957)"/>
+</g>
+<path id="Vector_3" d="M10.9941 8.38672C11.1493 8.3868 11.2984 8.44793 11.4082 8.55762C11.5179 8.66737 11.58 8.81649 11.5801 8.97168C11.5801 9.12695 11.518 9.27593 11.4082 9.38574C11.2984 9.49556 11.1494 9.55759 10.9941 9.55762H7.75684C7.60161 9.55751 7.45253 9.49552 7.34277 9.38574C7.23312 9.27596 7.17193 9.12685 7.17188 8.97168C7.172 8.81649 7.23305 8.66736 7.34277 8.55762C7.45252 8.44787 7.60163 8.38685 7.75684 8.38672H10.9941Z" fill="#F56C6C" stroke="#F56C6C" stroke-width="0.2"/>
+</g>
+<defs>
+<clipPath id="clip0_15214_44957">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>

File diff suppressed because it is too large
+ 2 - 0
src/assets/icon/refresh.svg


BIN
src/assets/icon/save_icon.png


File diff suppressed because it is too large
+ 2 - 0
src/assets/icon/school_hover.svg


File diff suppressed because it is too large
+ 2 - 0
src/assets/icon/school_light.svg


File diff suppressed because it is too large
+ 2 - 0
src/assets/icon/school_normal.svg


+ 4 - 0
src/assets/icon/search_line.svg

@@ -0,0 +1,4 @@
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6.41667 11.0833C8.994 11.0833 11.0833 8.994 11.0833 6.41667C11.0833 3.83934 8.994 1.75 6.41667 1.75C3.83934 1.75 1.75 3.83934 1.75 6.41667C1.75 8.994 3.83934 11.0833 6.41667 11.0833Z" stroke="#909399" stroke-linejoin="round"/>
+<path d="M12.25 12.2499L9.71252 9.7124" stroke="#909399" stroke-linejoin="round"/>
+</svg>

+ 11 - 0
src/assets/icon/user_all.svg

@@ -0,0 +1,11 @@
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="20" cy="20" r="20" fill="white"/>
+<g clip-path="url(#clip0_892_1601)">
+<path d="M28.9344 27.1029C28.6736 25.7273 28.1432 24.4595 27.3699 23.3447C26.5877 22.2118 25.5987 21.2947 24.4299 20.6204L24.4119 20.6114C24.349 20.5754 24.295 20.5485 24.2231 20.5125C24.0702 20.4316 23.9084 20.3327 23.6027 20.2068C23.2071 20.0449 22.8025 19.9101 22.3889 19.7932C22.7755 19.5774 23.1352 19.3077 23.4499 18.984C24.322 18.0939 24.7985 16.9251 24.7985 15.6843C24.7985 14.4436 24.322 13.2747 23.4499 12.3846C22.5777 11.4855 21.4269 11 20.2131 11C18.9993 11 17.8485 11.4855 16.9763 12.3756C16.1042 13.2658 15.6277 14.4346 15.6277 15.6753C15.6277 16.9161 16.1042 18.0849 16.9763 18.975C17.2371 19.2448 17.5248 19.4695 17.8305 19.6673C17.345 19.7932 16.8594 19.964 16.4009 20.1708C15.5018 20.5754 14.6746 21.1329 13.9464 21.8162C13.2181 22.4995 12.5977 23.2997 12.1032 24.1898C11.5997 25.0979 11.2491 26.0779 11.0423 27.1119C10.9434 27.5435 11.0333 28.002 11.312 28.3976L11.321 28.4156L11.33 28.4336C11.6177 28.7842 12.0582 29 12.4988 29H27.4419C27.8734 29 28.323 28.7842 28.6017 28.4426C28.9344 28.038 29.0513 27.5704 28.9344 27.1029Z" fill="#2E64FA"/>
+</g>
+<defs>
+<clipPath id="clip0_892_1601">
+<rect width="18" height="18" fill="white" transform="translate(11 11)"/>
+</clipPath>
+</defs>
+</svg>

+ 11 - 0
src/assets/icon/user_blue.svg

@@ -0,0 +1,11 @@
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="20" cy="20" r="20" fill="#2E64FA"/>
+<g clip-path="url(#clip0_892_1609)">
+<path d="M28.9344 27.1029C28.6736 25.7273 28.1432 24.4595 27.3699 23.3447C26.5877 22.2118 25.5987 21.2947 24.4299 20.6204L24.4119 20.6114C24.349 20.5754 24.295 20.5485 24.2231 20.5125C24.0702 20.4316 23.9084 20.3327 23.6027 20.2068C23.2071 20.0449 22.8025 19.9101 22.3889 19.7932C22.7755 19.5774 23.1352 19.3077 23.4499 18.984C24.322 18.0939 24.7985 16.9251 24.7985 15.6843C24.7985 14.4436 24.322 13.2747 23.4499 12.3846C22.5777 11.4855 21.4269 11 20.2131 11C18.9993 11 17.8485 11.4855 16.9763 12.3756C16.1042 13.2658 15.6277 14.4346 15.6277 15.6753C15.6277 16.9161 16.1042 18.0849 16.9763 18.975C17.2371 19.2448 17.5248 19.4695 17.8305 19.6673C17.345 19.7932 16.8594 19.964 16.4009 20.1708C15.5018 20.5754 14.6746 21.1329 13.9464 21.8162C13.2181 22.4995 12.5977 23.2997 12.1032 24.1898C11.5997 25.0979 11.2491 26.0779 11.0423 27.1119C10.9434 27.5435 11.0333 28.002 11.312 28.3976L11.321 28.4156L11.33 28.4336C11.6177 28.7842 12.0582 29 12.4988 29H27.4419C27.8734 29 28.323 28.7842 28.6017 28.4426C28.9344 28.038 29.0513 27.5704 28.9344 27.1029Z" fill="white"/>
+</g>
+<defs>
+<clipPath id="clip0_892_1609">
+<rect width="18" height="18" fill="white" transform="translate(11 11)"/>
+</clipPath>
+</defs>
+</svg>

+ 11 - 0
src/assets/icon/user_green.svg

@@ -0,0 +1,11 @@
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="20" cy="20" r="20" fill="#2BC644"/>
+<g clip-path="url(#clip0_892_1617)">
+<path d="M28.9344 27.1029C28.6736 25.7273 28.1432 24.4595 27.3699 23.3447C26.5877 22.2118 25.5987 21.2947 24.4299 20.6204L24.4119 20.6114C24.349 20.5754 24.295 20.5485 24.2231 20.5125C24.0702 20.4316 23.9084 20.3327 23.6027 20.2068C23.2071 20.0449 22.8025 19.9101 22.3889 19.7932C22.7755 19.5774 23.1352 19.3077 23.4499 18.984C24.322 18.0939 24.7985 16.9251 24.7985 15.6843C24.7985 14.4436 24.322 13.2747 23.4499 12.3846C22.5777 11.4855 21.4269 11 20.2131 11C18.9993 11 17.8485 11.4855 16.9763 12.3756C16.1042 13.2658 15.6277 14.4346 15.6277 15.6753C15.6277 16.9161 16.1042 18.0849 16.9763 18.975C17.2371 19.2448 17.5248 19.4695 17.8305 19.6673C17.345 19.7932 16.8594 19.964 16.4009 20.1708C15.5018 20.5754 14.6746 21.1329 13.9464 21.8162C13.2181 22.4995 12.5977 23.2997 12.1032 24.1898C11.5997 25.0979 11.2491 26.0779 11.0423 27.1119C10.9434 27.5435 11.0333 28.002 11.312 28.3976L11.321 28.4156L11.33 28.4336C11.6177 28.7842 12.0582 29 12.4988 29H27.4419C27.8734 29 28.323 28.7842 28.6017 28.4426C28.9344 28.038 29.0513 27.5704 28.9344 27.1029Z" fill="white"/>
+</g>
+<defs>
+<clipPath id="clip0_892_1617">
+<rect width="18" height="18" fill="white" transform="translate(11 11)"/>
+</clipPath>
+</defs>
+</svg>

+ 11 - 0
src/assets/icon/user_orange.svg

@@ -0,0 +1,11 @@
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="20" cy="20" r="20" fill="#FB9F34"/>
+<g clip-path="url(#clip0_892_1625)">
+<path d="M28.9344 27.1029C28.6736 25.7273 28.1432 24.4595 27.3699 23.3447C26.5877 22.2118 25.5987 21.2947 24.4299 20.6204L24.4119 20.6114C24.349 20.5754 24.295 20.5485 24.2231 20.5125C24.0702 20.4316 23.9084 20.3327 23.6027 20.2068C23.2071 20.0449 22.8025 19.9101 22.3889 19.7932C22.7755 19.5774 23.1352 19.3077 23.4499 18.984C24.322 18.0939 24.7985 16.9251 24.7985 15.6843C24.7985 14.4436 24.322 13.2747 23.4499 12.3846C22.5777 11.4855 21.4269 11 20.2131 11C18.9993 11 17.8485 11.4855 16.9763 12.3756C16.1042 13.2658 15.6277 14.4346 15.6277 15.6753C15.6277 16.9161 16.1042 18.0849 16.9763 18.975C17.2371 19.2448 17.5248 19.4695 17.8305 19.6673C17.345 19.7932 16.8594 19.964 16.4009 20.1708C15.5018 20.5754 14.6746 21.1329 13.9464 21.8162C13.2181 22.4995 12.5977 23.2997 12.1032 24.1898C11.5997 25.0979 11.2491 26.0779 11.0423 27.1119C10.9434 27.5435 11.0333 28.002 11.312 28.3976L11.321 28.4156L11.33 28.4336C11.6177 28.7842 12.0582 29 12.4988 29H27.4419C27.8734 29 28.323 28.7842 28.6017 28.4426C28.9344 28.038 29.0513 27.5704 28.9344 27.1029Z" fill="white"/>
+</g>
+<defs>
+<clipPath id="clip0_892_1625">
+<rect width="18" height="18" fill="white" transform="translate(11 11)"/>
+</clipPath>
+</defs>
+</svg>

BIN
src/assets/icon/view.png


BIN
src/assets/icon/view_light.png


BIN
src/assets/icon/view_white.png


BIN
src/assets/icon/volume.png


+ 1 - 0
src/assets/icon/warn.svg

@@ -0,0 +1 @@
+<svg t="1767604563413" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5502" width="200" height="200"><path d="M512 85.333333c235.648 0 426.666667 191.018667 426.666667 426.666667s-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512 276.352 85.333333 512 85.333333z m0 170.666667a42.666667 42.666667 0 0 0-42.666667 42.666667v341.333333a42.666667 42.666667 0 0 0 85.333334 0V298.666667a42.666667 42.666667 0 0 0-42.666667-42.666667z m0 554.666667a42.666667 42.666667 0 1 0 0-85.333334 42.666667 42.666667 0 0 0 0 85.333334z" fill="#FAAD14" p-id="5503"></path></svg>

BIN
src/assets/login/input_clear.webp


BIN
src/assets/login/input_eye.webp


BIN
src/assets/login/input_pass.webp


BIN
src/assets/login/input_show_pass.webp


BIN
src/assets/login/input_user.webp


BIN
src/assets/login/login_bg.webp


BIN
src/assets/login/login_bg_center.webp


BIN
src/assets/login/login_email.webp


BIN
src/assets/login/login_feishu.webp


BIN
src/assets/login/login_logo.webp


BIN
src/assets/login/login_wechat.webp


BIN
src/assets/login/logo.png


+ 9 - 0
src/assets/school/default_logo.svg

@@ -0,0 +1,9 @@
+<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="24" cy="24" r="22" fill="#c1d0ff"/>
+<path d="M13 18.1142C13 16.8463 13.797 15.7154 14.991 15.2889L24.3273 11.9545C25.6298 11.4894 27 12.4549 27 13.838V35H13V18.1142Z" fill="#6ea3fe"/>
+<path d="M27 18H32C33.6569 18 35 19.3431 35 21V35H27V18Z" fill="#7eb1ff"/>
+<rect x="17" y="20" width="6" height="1.5" rx="0.75" fill="#c1d0ff"/>
+<rect x="10" y="34" width="28" height="2" rx="1" fill="#6ea3fe"/>
+<rect x="17" y="23.5" width="6" height="1.5" rx="0.75" fill="#c1d0ff"/>
+<rect x="17" y="27" width="6" height="1.5" rx="0.75" fill="#c1d0ff"/>
+</svg>

+ 435 - 0
src/baseComponents/BarCharts.vue

@@ -0,0 +1,435 @@
+<template>
+    <div class="barCharts">
+        <div class="operation" v-if="props.showLegend">
+            <el-checkbox
+                :model-value="showAll"
+                :indeterminate="indeterminate"
+                @change="(val)=>HandleCheckAllOrNot(val)"
+            
+            >
+            显示全部
+            </el-checkbox>
+        </div>
+        <div class="render_bar_charts" ref="chartsRef" id="charts">
+        </div>
+    </div>
+
+</template>
+
+<script setup lang="ts">
+import {ref,onMounted, watch} from 'vue'
+import * as echarts from 'echarts';
+
+const props = defineProps({
+    chartData:{
+        required:true,
+        type:{
+            xAxis:Array,
+            series:Array,
+            yAxisLabelFormater:Function,
+            tooltipFormater:Function,
+        }
+    },
+    randomActiveIndex:{
+        type:Number,
+        required:true
+    },
+    showLegend:{
+        type:Boolean,
+        default:false
+    },
+    maxLabel:{
+        type:Number,
+        default:5
+    }
+})
+
+const chartsRef = ref()
+const myChart = ref()
+
+const showAll = ref(true)
+const indeterminate = ref(false)
+const selectedLegendList = ref([])
+
+const HandleCheckAllOrNot = (val)=>{
+    console.log('当前的变更值',val)
+    showAll.value = val
+    indeterminate.value = false
+    if(val){
+        myChart.value.dispatchAction({
+            type: 'legendAllSelect',
+        });
+    }else{
+        // 第一次点击没有图例值 需要调用反选
+        if(selectedLegendList.value?.length > 0){
+            selectedLegendList.value.map(item=>{
+                myChart.value.dispatchAction({
+                    type: 'legendUnSelect',
+                    name:item
+                })
+            })
+        }else{
+            // 反选
+            myChart.value.dispatchAction({
+                type: 'legendInverseSelect',
+            })
+        }
+    }
+}
+
+
+const baseOption = {
+    grid:{
+        id:'grid',
+        width:'100%',
+        left:0,
+        top:props.showLegend ?  '16%' : '7%',
+        right:0,
+        bottom:30,
+    },
+    legend: {
+        id:'legend',
+        show:props.showLegend,
+        top: '0%',
+        left: 92,
+        itemGap:15,
+        itemWidth:20,
+        padding:1,
+        itemHeight:10,
+        formatter:function (name) {
+            return name;
+        },
+        textStyle:{
+            fontSize:12,
+        },
+    },
+    title: {
+        id:'title',
+        text: ''
+    },
+    color:['#5470C6','#3BA272','#FAC858','#995FB3','#EE6666','#72C0DD','#90CB75','#EA7ACB','#FC8451','#65789B',
+          '#178BD3','#26A616','#A6129E','#D3A141','#234098','#047640','#B43535','#848BDC','#D6AF83','#84313D'],
+    tooltip:{
+        trigger: 'item',
+        borderWidth:0,
+        showContent:true,
+        textStyle:{
+            color:'#666'
+        }
+    },
+    xAxis:{
+        id:'xAxis',
+        axisPointer:{
+            show:true,
+            type: 'shadow',
+            label:{
+                show:false
+            },
+            shadowStyle:{
+                color:'rgba(46, 100, 250,0.05)'
+            },
+        },
+        axisLine: {
+            lineStyle: {
+                color: '#666',
+            }
+        },
+        axisLabel: {
+            width:100,
+            interval:0,
+            overflow:'truncate',
+            color: '#666',
+        },
+        data: [], // 初始为空,后续动态赋值
+    },
+    yAxis: {
+        id:'yAxis',
+        type: 'value',
+        axisLine: {
+            show: false
+        },
+        axisTick: {
+            show: false
+        },
+        // 分割线
+        splitLine: {
+            lineStyle: {
+                type: 'solid',
+                color: '#E4E7ED'
+            }
+        },
+        // 斑马纹
+        splitArea: {
+            show: true,
+            areaStyle: {
+            color:['#fafafa','transparent'],
+            }
+        },
+        axisLabel: {
+            color: '#666',
+        }
+    },
+    animation:false,
+    dataZoom:[
+        {
+            type: 'slider',
+            id:'slider',  // 唯一标识 
+            show: props.chartData?.dataset?.source ? props.chartData?.dataset?.source?.length > props.maxLabel : props.chartData?.series[0]?.data?.length > props.maxLabel,
+            backgroundColor:'rgba(255,255,255,0)',
+            dataBackground:{
+                lineStyle:{
+                    opacity:0,
+                },
+                areaStyle:{
+                    opacity:0,
+                }
+            },
+            selectedDataBackground:{
+                lineStyle:{
+                    opacity:0,
+                },
+                areaStyle:{
+                    opacity:0,
+                },
+            },
+            borderColor:'rgba(255,255,255,0)',
+            fillerColor:'rgba(176, 199, 249,0)',
+
+            xAxisIndex: [0],
+            // start: 1,
+            // end: 35,
+
+            // minSpan:20,
+            minValueSpan:(props.maxLabel - 1),
+            maxValueSpan:(props.maxLabel - 1),
+
+            showDetail:false,
+            height:7,
+            bottom:0,
+            throttle:0,
+            // brushSelect:false,
+            moveHandleStyle:{
+                color:'#b0c7f9'
+            },
+            handleStyle:{
+                opacity:0
+            }
+        },
+        {
+            type: 'inside',
+            id:'inside',
+            xAxisIndex: [0],
+
+            // minSpan:20,
+            minValueSpan:(props.maxLabel - 1),
+            maxValueSpan:(props.maxLabel - 1),
+        },
+  
+    ]
+}
+
+// baseOption  基础固定配置
+// baseInheritOpt  基础实际配置,可能为空
+const UpdateChart = (chartData,baseInheritOpt) =>{
+    let tmpXAxis = chartData?.xAxis?.length > 0 ? chartData?.xAxis : ['暂无数据']
+    let dynamicOption = {
+        xAxis: {
+            ...baseOption.xAxis,
+            data: [...tmpXAxis],
+        },
+        series: chartData?.series?.map(item=>{
+            return {
+                type:'bar',
+                barWidth: 30,
+                barGap:0,
+                ...item,
+                label: {
+                    show: true,
+                    position: 'top',
+                    color:'#666',
+                    ...item?.label,
+                },
+            }
+        }),
+        dataset:chartData?.dataset,
+    }
+    myChart.value.setOption({
+        ...baseOption,
+        dataZoom:[
+            {
+                ...(baseOption?.dataZoom?.[0]),
+                show:chartData?.dataset?.source ? chartData?.dataset?.source?.length > props.maxLabel :chartData?.series[0]?.data?.length > props.maxLabel,
+            },
+            {
+                 ...(baseOption?.dataZoom?.[1])
+            }
+        ],
+
+        tooltip:{
+            ...baseOption.tooltip,
+            formatter: chartData?.tooltipFormater ?  chartData?.tooltipFormater : function (params) {
+                const {name,seriesName,value,marker} = params
+                return name + '<br/>' + marker + seriesName + `<span style=\"margin-left:10px;\">${value}</span>` ;
+            }
+        },
+
+        yAxis:{
+            ...baseOption.yAxis,
+            axisLabel:{
+                ...baseOption.yAxis.axisLabel,
+                formatter:chartData?.yAxisLabelFormater ? chartData?.yAxisLabelFormater : '{value}' 
+            }
+        },
+        ...dynamicOption
+       
+    },{notMerge:true});
+}
+
+const HandleInitChart = ()=>{
+    // 基于准备好的dom,初始化echarts实例
+    myChart.value = echarts.init(chartsRef.value);
+    UpdateChart(props.chartData,baseOption)
+
+    // 系统默认 onMounted后就开始监听 dataZoom事件变化,此处onMounted后父容器无高度,报错 ???
+    //需要手动 动态监听 dataZoom的位置
+    myChart.value.on('dataZoom', function (event) {
+        console.log('缩放区域触发了---:', event);
+        // event 有 batch 是 inside  内部 滚动,
+        // event 无 batch 是  鼠标拖拽
+        let chartData = props.chartData
+        let tmpXAxis = chartData?.xAxis?.length > 0 ? chartData?.xAxis : ['暂无数据']
+        let dynamicOption = {
+            xAxis: {
+                ...baseOption.xAxis,
+                data: [...tmpXAxis],
+            },
+            series: chartData?.series?.map(item=>{
+                return {
+                    type:'bar',
+                    barWidth: 30,
+                    barGap:0,
+                    ...item,
+                    label: {
+                        show: true,
+                        position: 'top',
+                        color:'#666',
+                        ...item?.label,
+                    },
+                }
+            }),
+            dataset:chartData?.dataset,
+        }
+        myChart.value.setOption({
+            ...baseOption,
+            dataZoom:[
+                {
+                    ...(baseOption?.dataZoom?.[0]),
+                    show:chartData?.dataset?.source ? chartData?.dataset?.source?.length >props.maxLabel :chartData?.series[0]?.data?.length > props.maxLabel,
+                    start: event?.batch ? event?.batch[0].start : event?.start,
+                    end:  event?.batch ? event?.batch[0].end : event?.end,
+                },
+                {
+                    ...(baseOption?.dataZoom?.[1]),
+                    start: event?.batch ? event?.batch[0].start :  event?.start,
+                    end: event?.batch ? event?.batch[0].end : event?.end,
+                }
+            ],
+
+            tooltip:{
+                ...baseOption.tooltip,
+                formatter: chartData?.tooltipFormater ?  chartData?.tooltipFormater : function (params) {
+                    const {name,seriesName,value,marker} = params
+                    return name + '<br/>' + marker + seriesName + `<span style=\"margin-left:10px;\">${value}</span>` ;
+                }
+            },
+
+            yAxis:{
+                ...baseOption.yAxis,
+                axisLabel:{
+                    ...baseOption.yAxis.axisLabel,
+                    formatter:chartData?.yAxisLabelFormater ? chartData?.yAxisLabelFormater : '{value}' 
+                }
+            },
+            ...dynamicOption
+        
+        },{notMerge:true});
+
+    });
+
+
+    myChart.value.on('legendselectchanged', function (params) {
+        console.log('图例状态切换了',params);
+        selectedLegendList.value = Object.entries(params.selected).map(itm=>itm[0])
+
+        let selectedStatus = Object.values(params.selected)
+        let length = selectedStatus.length
+        let selectedLegendStatus =  selectedStatus.filter(item=>item === true)
+        let unSelectedLegend =  selectedStatus.filter(item=>item === false)
+
+        if(selectedLegendStatus.length === length || unSelectedLegend.length ===  length){
+            indeterminate.value = false
+            if(selectedLegendStatus.length === length){
+                showAll.value = true
+            }else{
+                showAll.value = false
+            }
+        }else{
+            indeterminate.value = true
+        }
+    });
+}
+
+onMounted(async ()=>{
+    HandleInitChart()
+})
+
+watch(()=>props.randomActiveIndex,(newVal)=>{
+    // 监听到父组件页面的容器尺寸变化后,要重新init
+    if(myChart.value){
+        myChart.value.dispose();
+        myChart.value = null
+    }
+    HandleInitChart()
+})
+
+
+
+watch(()=>props.chartData,(newVal)=>{
+    // console.log('数据变化了')
+    // // 数据变换后要重新渲染
+    // UpdateChart(newVal,{})
+
+    if(myChart.value){
+        myChart.value.dispose();
+        myChart.value = null
+    }
+    HandleInitChart()
+
+
+},{deep:true})
+
+</script>
+
+
+<style  lang="scss" scoped>
+
+.render_bar_charts{
+    position: relative;
+    width: 100%;
+    height: 270px;
+}
+
+.operation{
+    position: absolute;
+    :deep(.el-checkbox){
+        display: flex;
+        align-items: center;
+        height: auto !important;
+        .el-checkbox__label{
+            font-size: 12px !important;
+        }
+        color:#333333;
+    }
+}
+
+</style>

+ 187 - 0
src/baseComponents/CustomCheckboxForm.vue

@@ -0,0 +1,187 @@
+<template>
+    <div class="custom_check_box">
+        <div class="search_tab_head" v-if="props.showOperation && !props.disabled">
+            <span class="check_btn">
+                <span @click="HandleCheckAllOrNot">
+                    <input :checked="checkedList.length == props.selectList.length && props.selectList.length !== 0 " type="checkbox" @change="HandleCheckChange($event)">全选 
+                </span>
+                <span>
+                    已选择
+                    <span style="color: #2E64FA;">{{ checkedList.length }}</span>人
+                </span>
+
+            </span>
+
+            <FormSearchGroup 
+                @searchChange="(params)=>HandleSearchChange(params)"
+                
+                :searchList="[{
+                key:'peopleName',
+                type:'input',
+                placeholder:'请输入关键词搜索'
+            }]"/>
+        </div>
+
+        <div class="data_area">
+            <slot></slot>
+            <div  class="search_content" style="">
+                <span 
+                    v-for="item in props.selectList" 
+                    :key="item.value" 
+                    @click="props.disabled ? '' :  HandleCheckOrUncheck(item.value)"
+                    :class="{active:checkedList.includes(item.value) || props.disabled  }"
+                >{{ item.label }}</span>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup lang="ts">
+import {ref, watch} from 'vue'
+import FormSearchGroup from './FormSearchGroup.vue';
+
+interface SelectItem {
+    label:String,
+    value:String
+}
+const props = defineProps({
+    selectList:{
+        required:true,
+        type:Array<SelectItem>
+    },
+    disabled:{
+        required:false,
+        type:Boolean
+    },
+    defaultCheckedList:{
+        required:false,
+        type:Array<SelectItem>
+    },
+    showOperation:{
+        type:Boolean,
+        default:true
+    }
+})
+
+const emit  = defineEmits(['boxSearchChange','formItemChange'])
+
+
+const checkedList = ref([])
+
+const HandleCheckOrUncheck = (item)=>{
+    console.log('当前点击的元素',item)
+    if(checkedList.value.includes(item)){
+        checkedList.value = checkedList.value.filter(checkItm=>checkItm !== item)
+    }else{
+        checkedList.value.push(item)
+    }
+    console.log('最终过滤后的值',checkedList.value)
+    // 最终的结果值 通知 父组件
+    emit('formItemChange',checkedList.value)
+}
+
+const HandleCheckAllOrNot = ()=>{
+    if(checkedList.value.length == props.selectList.length){
+        checkedList.value = []
+    }else if(checkedList.value.length < props.selectList.length){
+        checkedList.value = props.selectList.map(item=>item.value)
+    }
+    // 最终的结果值 通知 父组件
+    emit('formItemChange',checkedList.value)
+}
+
+const  HandleSearchChange = (params)=>{
+    console.log('searchParams',params)
+    // 要变更搜索列表,传到父组件去变更
+    emit('boxSearchChange',params)
+
+}
+
+
+const HandleCheckChange = (e)=>{
+    console.log('选中的值:',e.target.value)
+}
+
+watch(()=>props.selectList,(newVal)=>{
+    console.log('盒子列表变化了',newVal)
+    checkedList.value = []
+})
+
+watch(()=>props.defaultCheckedList,(newVal)=>{
+    // console.log('获取到默认参数了',newVal)
+    if(newVal){
+        checkedList.value = newVal
+        emit('formItemChange',newVal)
+    }
+},{immediate:true})
+</script>
+
+
+<style lang="scss" scoped>
+
+.custom_check_box{
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    gap:10px;
+    line-height: 1.5 !important;
+
+    .search_tab_head{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        .check_btn{
+            display: flex;
+            align-items: center;
+            gap:20px;
+            >span{
+                display: flex;
+                align-items: center;
+                &:nth-child(1){
+                    gap:8px;
+                }
+            }
+        }
+    }
+
+    .data_area{
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-start;
+        gap: 10px;
+    }
+    .search_content{
+        width: 100%;
+        border:dashed #E4E7ED 1px;
+        border-radius: 6px;
+        padding:10px;
+        display: flex;
+        flex-wrap: wrap;
+        align-content: flex-start;
+        gap:10px;
+        min-height:50px;
+        max-height: calc(32px * 3 + 2 * 10px + 20px );
+        overflow: auto;
+        >span{
+            border:solid #DCDFE6 1px;
+            padding: 6px 18px;
+            height: 32px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            border-radius: 4px;
+            &.active{
+                border-color: #2E64FA;
+                color:#2E64FA;
+            }
+            &:hover{
+                cursor: pointer;
+            }
+        }
+    }
+}
+
+
+
+</style>

+ 223 - 0
src/baseComponents/CustomCheckboxForm2.vue

@@ -0,0 +1,223 @@
+<template>
+    <div class="custom_check_box">
+        <div class="search_tab_head" v-if="props.showOperation && !props.disabled">
+            <FormSearchGroup 
+                :formDisabled="formDisabled"
+                @searchChange="(params,key)=>HandleSearchChange(params,key)"
+                :searchList="searchList"/>
+        </div>
+
+        <div class="data_area">
+            <slot></slot>
+            
+            <Table  
+                class="search_content"
+                :pageSize="200"
+                :currentPage="1"
+                :totalNum="0"
+                :tableData="props.selectList" 
+                :tableColumns="tableColumns"
+                :hidePagination="true"
+            >
+                <template #header-label>
+                    已选:{{ props.selectList.length }}人
+                </template>
+                <template #operation="{row}">
+                    <div class="table_row_option">
+                        <span :class="{'el_button_delete':!formDisabled && (!row.deleteStatus), 'editor_disable':formDisabled || row.deleteStatus}" @click="(formDisabled || row.deleteStatus) ? '' : HandlePoepleDelete(row)">删除</span>
+                    </div>
+                </template>
+
+            </Table>
+        </div>
+    </div>
+</template>
+
+<script setup lang="ts">
+import {ref, watch} from 'vue'
+import FormSearchGroup from './FormSearchGroup.vue';
+
+import Table from '@/baseComponents/Table.vue'
+
+interface SelectItem {
+    label:String,
+    value:String
+}
+
+interface SearchItm {
+    key:String,
+    type:'input'|'select'|'datePicker'|'radio',
+    placeholder:String,
+    defaultValue?:any,
+    options?:{
+        label:String,
+        value:String,
+        disabled?:Boolean
+    }[] 
+}
+const props = defineProps({
+    selectList:{
+        required:true,
+        type:Array<SelectItem>
+    },
+    disabled:{
+        required:false,
+        type:Boolean
+    },
+    formDisabled:{
+        type:Boolean,
+        default:false
+    },
+  
+    showOperation:{
+        type:Boolean,
+        default:true
+    },
+    searchList:{
+        type:Array<SearchItm>,
+        default:()=>{
+            return [{
+                key:'peopleName',
+                type:'input',
+                placeholder:'请输入关键词搜索'
+            }]
+        }
+    }
+})
+
+const emit  = defineEmits(['boxSearchChange','deletePeopleChange'])
+
+
+const tableColumns = ref([
+    {
+        name:'label',
+        label:'教师姓名',
+        width:'60',
+        customHeader:true
+    },
+    {
+        name:'value',
+        label:'教师id',
+        width:'60',
+        hidden:true,
+    },
+    {
+        name:'deleteStatus',   //0 可删  1 不可删
+        label:'是否可删',
+        width:'60',
+        hidden:true,
+    },
+    {
+        name:'operation',
+        label:'',
+        width:'20',
+        custom:true
+    },
+])
+const checkedList = ref([])
+
+const HandlePoepleDelete = (params)=>{
+    console.log('当前行信息',params)
+    emit('deletePeopleChange',params.value)
+    // row.value  id
+    // row.label
+}
+
+
+const  HandleSearchChange = (params,key)=>{
+    console.log('searchParams',params,key)
+    // 要变更搜索列表,传到父组件去变更
+    emit('boxSearchChange',params,key)
+
+}
+
+
+watch(()=>props.selectList,(newVal)=>{
+    console.log('盒子列表变化了',newVal)
+    checkedList.value = []
+})
+
+</script>
+
+
+<style lang="scss" scoped>
+
+.custom_check_box{
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    gap:10px;
+    line-height: 1.5 !important;
+    .simple_filter{
+        gap:20px;
+        :deep(.el-select){
+            width: 160px;
+        }
+    }
+
+    .search_tab_head{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        .check_btn{
+            display: flex;
+            align-items: center;
+            gap:20px;
+            >span{
+                display: flex;
+                align-items: center;
+                &:nth-child(1){
+                    gap:8px;
+                }
+            }
+        }
+    }
+
+    .data_area{
+        position: relative;
+        width: 100%;
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-start;
+        gap: 10px;
+
+        .search_content{
+            flex:1 1;
+            border-radius: 6px;
+            display: flex;
+            flex-wrap: wrap;
+            align-content: flex-start;
+            gap:10px;
+            min-height:50px;
+            max-height: calc(32px * 3 + 2 * 10px + 20px );
+            overflow: auto;
+
+            :deep(.el-table__header-wrapper){
+                .el-table__header{
+                    width: 100% !important;
+                }
+                .el-table__header thead{
+                    height: 40px !important;
+                }
+                tr th.el-table__cell {
+                    border-left: none;
+                    border-right: none;
+                    border-top:none;
+                    font-size: 14px;
+                    font-weight: 400;
+                    color:#666666;
+                }
+            }
+            :deep(.el-table__inner-wrapper){
+                .el-table__cell{
+                    height: 40px;
+                }
+            }
+        }
+    }
+}
+
+
+
+</style>

+ 100 - 0
src/baseComponents/Dialog.vue

@@ -0,0 +1,100 @@
+<template>
+    <div class="page_dialog">
+        <el-dialog 
+            @close="closeDialog" 
+            v-model="props.visible" 
+            :width="props.width ? props.width : '420px'"
+            :close-on-click-modal="false"
+        >
+            <div class="dialog_default">
+                <slot name="default" >
+                    是否确认删除?
+                </slot>
+            </div>
+            <template #header>
+            <div class="custom_header">
+                <img :src="warnIcon" alt="">
+                <span>{{ props.title }}</span>
+            </div>
+            </template>
+
+            <template #footer>
+                <div style="display: flex;justify-content: space-between;">
+                    <div class="left"> 
+                        <slot name="footerLeft"></slot>
+                    </div>
+                    <div class="right">
+                        <el-button class="button_border_gray cancel" @click="closeDialog">取 消</el-button>
+                        <el-button class="button_background" :loading="props.submitLoading" @click="handleConfirm(formRef)">确 定</el-button>
+                    </div>
+                </div>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+
+<script setup lang="ts">
+import warnIcon from '@/assets/icon/warn.svg'
+const emit  = defineEmits(['close','confirm'])
+const props = defineProps({
+    visible:{
+        type:Boolean,
+        required:true
+    },
+    title:{
+        type:String,
+        default:'提示'
+    },
+    submitLoading:{
+      type:Boolean,
+      default:false,
+      required:true
+    },
+    width:{
+        type:String,
+        required:false
+    }
+})
+const closeDialog = () => {
+  emit('close')
+}
+
+const handleConfirm = ()=>{
+    emit('confirm')
+}
+</script>
+
+
+<style lang="scss" scoped>
+.dialog_default{
+    text-align: center;
+    color: #666;
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+}
+.custom_header{
+    display: flex;
+    align-items: center;
+    padding: 0 20px;
+    gap: 10px;
+    text-indent: 0;
+    font-weight: bold;
+    img{
+        width: 25px;
+    }
+}
+
+
+.page_dialog{
+  :deep(.el-dialog){
+    .el-dialog__body{
+      min-height: calc(120px);
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+  }
+}
+
+</style>

+ 414 - 0
src/baseComponents/DoughnutCharts.vue

@@ -0,0 +1,414 @@
+<template>
+    <div class="doughnut_charts">
+        <div class="operation" v-if="props.showLegend && props.showLegendOperationAll">
+            <el-checkbox
+                :model-value="showAll"
+                :indeterminate="indeterminate"
+                @change="(val)=>HandleCheckAllOrNot(val)"
+            >
+            显示全部
+            </el-checkbox>
+        </div>
+        <div class="render_doughnut_charts" :style="{height:chartHeight}" ref="chartsRef">
+        </div>
+    </div>
+
+</template>
+
+
+<script setup lang="ts">
+import {ref,onMounted, watch,computed} from 'vue'
+import * as echarts from 'echarts';
+import type { PropType } from 'vue'
+
+interface PieItm {
+    name:String,
+    value:String
+}
+interface SeiresLabelFormatter {
+    formatter:Function | String,
+    rich:Object
+
+}
+const props = defineProps({
+    chartHeight:{
+        type:String,
+        default:'270px'
+    },
+    //饼图数据
+    chartData:{
+        required:true,
+        type:Array<PieItm>
+    },
+    // 饼图扇形弧度
+    rotateAngle:{
+        type:[Number,null],
+        default:360
+    },
+    // 是否显示图例
+    showLegend:{
+        type:Boolean,
+        default:true
+    },
+    // 图例的位置
+    legendTop:{
+        type:[Number,String],
+        default:'auto'
+    },
+    legendBottom:{
+        type:[Number,String],
+        default:'auto'
+    },
+    legendLeft:{
+        type:[Number,String],
+        default:'auto'
+    },
+    legendRight:{
+        type:[Number,String],
+        default:'auto'
+    },
+    // 图例布局朝向
+    legendOrient:{
+        type:String,
+        default:'vertical'
+    },
+    // 是否一键隐藏图例或展示图例
+    showLegendOperationAll:{
+        type:Boolean,
+        default:false
+    },
+    // 图例展示文本
+    legendFormatter:{
+        type:Function
+    },  
+
+    // 扇形图位置
+    pieTop:{
+        type:[Number,String],
+        default:0
+    },
+    pieLeft:{
+        type:[Number,String],
+        default:0
+    },
+    pieBottom:{
+        type:[Number,String],
+        default:0
+    },
+    pieRight:{
+        type:[Number,String],
+        default:0
+    },
+
+    pieRadius:{
+        type:Array,
+        required:true
+    },
+
+    
+
+    //展示扇区信息
+    showSeriesLabel:{
+        type:Boolean,
+        default:true
+    },
+    // 扇形的信息展示位置
+    seriesLabelPosition:{
+        type:String,
+    },
+    // 扇区信息的格式
+    seiresLabelFormatter: {
+        type:Object as PropType<SeiresLabelFormatter>
+    },
+   
+    // 展示鼠标悬浮提示
+    showTooltip:{
+        type:Boolean,
+        default:true,
+    },
+    // 鼠标悬浮提示 展示的位置
+    tooltipPosition:{
+        type:[Array,Function],
+        default:()=>{
+            return function (point, params, dom, rect, size) {
+                // 固定在鼠标右侧
+                return [point[0], point[1]];
+            }
+        }
+    },
+    // 图表鼠标悬浮提示信息
+    tooltipFormatter:{
+        type:[Function,String] 
+    },
+
+
+    //页面动态变化的标识
+    randomIndex:{
+        type:Number,
+        required:true
+    },
+    
+})
+
+
+
+
+const chartsRef = ref(null)
+const myChart = ref()
+
+/**
+ * 图例全选/取消全选
+ */
+const showAll = ref(true)
+const indeterminate = ref(false)
+const selectedLegendList = ref([])
+const HandleCheckAllOrNot = (val)=>{
+    console.log('当前的变更值',val)
+    showAll.value = val
+    indeterminate.value = false
+    if(val){
+        myChart.value.dispatchAction({
+            type: 'legendAllSelect',
+        });
+    }else{
+        // 第一次点击没有图例值 需要调用反选
+        if(selectedLegendList.value?.length > 0){
+            selectedLegendList.value.map(item=>{
+                myChart.value.dispatchAction({
+                    type: 'legendUnSelect',
+                    name:item
+                })
+            })
+        }else{
+            // 反选
+            myChart.value.dispatchAction({
+                type: 'legendInverseSelect',
+            })
+        }
+    }
+}
+
+
+// 基础配置
+const getBaseOption = () => ({
+    tooltip: {
+        trigger: 'item',
+        borderWidth:0,
+        textStyle:{
+            color:'#666'
+        },
+    },
+    legend: {
+        itemGap:15,
+        itemWidth:20,
+        padding:1,
+        itemHeight:10,
+        textStyle:{
+            fontSize:12,
+        },
+    },
+    color:['#5470C6','#3BA272','#FAC858','#995FB3','#EE6666','#72C0DD','#90CB75','#EA7ACB','#FC8451','#65789B',
+        '#178BD3','#26A616','#A6129E','#D3A141','#234098','#047640','#B43535','#848BDC','#D6AF83','#84313D'],
+
+    series: [
+        {
+            name: '',
+            type: 'pie',
+            startAngle:90,
+            avoidLabelOverlap: false,
+            labelLine: {
+                length:15,
+                length2:10,
+            },
+            emphasis: {
+                scale:false,
+            },
+            data: [],
+        },
+        {
+            name: '',
+            type: 'pie',
+            startAngle:90,
+            endAngle:'auto',
+            avoidLabelOverlap: false,
+            label: {
+                show: false,
+            },
+            labelLine: {
+                show: false,
+            },
+            emphasis: {
+                scale:false,
+                label: {
+                    show: false,
+                }
+            },
+            data:[],
+            emptyCircleStyle:{
+                color:'#F4F5F8',
+                opacity:1
+            },
+        }
+    ]
+});
+// 动态配置
+const getDynamicOption = ()=>({
+    tooltip: {
+        showContent:props.showTooltip,
+        formatter: props.tooltipFormatter,
+        position:props.tooltipPosition
+    },
+    legend: {
+        show: props.showLegend,
+        top: props.legendTop,
+        right:props.legendRight,
+        left:props.legendLeft,
+        bottom:props.legendBottom,
+        orient:props.legendOrient,
+        // 自定义图例展示内容:名称:占比xx%
+        formatter: props.legendFormatter,
+    },
+    series: [
+        {
+            name: '',
+            radius: props.pieRadius,
+            endAngle:endAngle.value,
+            top:props.pieTop,
+            left:props.pieLeft,
+            right:props.pieRight,
+            bottom:props.pieBottom,
+            label: {
+                show: props.showSeriesLabel,
+                position:props.seriesLabelPosition,
+                ...props.seiresLabelFormatter,
+            },
+            labelLine: {
+                show: props.showSeriesLabel,
+            },
+            emphasis: {
+                disabled: !props.showTooltip,
+                label: {
+                    show: props.showSeriesLabel,
+                }
+            },
+            data: props?.chartData || [],
+        },
+        {
+            name: '',
+            radius: props.pieRadius,
+            top:props.pieTop,
+            left:props.pieLeft,
+            right:props.pieRight,
+            bottom:props.pieBottom,
+        }
+    ]
+})
+
+// 饼图的扇区结束位置
+const endAngle = computed(()=>{
+    console.log('旋转角度',props.rotateAngle)
+    if(props.rotateAngle &&  props.rotateAngle !== 360){
+        if(props.rotateAngle <= 90){
+            return  ( 90 - props.rotateAngle)
+        }else{
+            return ( 90  -  props.rotateAngle +  360)
+        }
+    }else{
+        return 'auto'
+    }
+})
+
+const UpdateChart = () =>{
+    if(!myChart.value) return
+    console.log('labelformater值',props.seiresLabelFormatter)
+    myChart.value.setOption(getBaseOption());
+    myChart.value.setOption(getDynamicOption());
+}
+
+const HandleInitChart = ()=>{
+    console.log('准备初始化了--')
+
+    if(myChart.value){
+        myChart.value?.dispose();
+        myChart.value = null
+    }
+
+    // 基于准备好的dom,初始化echarts实例
+    myChart.value = echarts.init(chartsRef.value);
+    UpdateChart()
+
+    myChart.value.on('legendselectchanged', function (params) {
+        console.log('图例状态切换了',params);
+        selectedLegendList.value = Object.entries(params.selected).map(itm=>itm[0])
+
+        let selectedStatus = Object.values(params.selected)
+        let length = selectedStatus.length
+        let selectedLegendStatus =  selectedStatus.filter(item=>item === true)
+        let unSelectedLegend =  selectedStatus.filter(item=>item === false)
+
+        if(selectedLegendStatus.length === length || unSelectedLegend.length ===  length){
+            indeterminate.value = false
+            if(selectedLegendStatus.length === length){
+                showAll.value = true
+            }else{
+                showAll.value = false
+            }
+        }else{
+            indeterminate.value = true
+        }
+    });
+}
+
+
+watch([()=>props.randomIndex,()=>props.rotateAngle],([newRandom,newRotate],[oldRandom,oldRotate])=>{
+    if(!myChart.value) return
+    // rotateAngle 实际发生变化时需要重建以应用 endAngle 变更
+    if(newRotate !== oldRotate){
+        HandleInitChart()
+        return
+    }
+    console.log('执行到了--')
+    // 仅容器尺寸/布局变化时调整大小
+    try{ myChart.value.resize() }catch(e){}
+})
+
+watch(()=>props.chartData,(newVal)=>{
+    // 数据变换后只更新 series.data
+    if(!myChart.value) return
+    try{
+        // 同步更新 series 数据并刷新 legend 和 label 的展示(使百分比同步)
+        myChart.value.setOption(getDynamicOption())
+    }catch(e){
+        HandleInitChart()
+    }
+},{deep:true})
+
+onMounted(()=>{
+    HandleInitChart()
+})
+
+</script>
+
+
+
+<style lang="scss" scoped>
+.render_doughnut_charts{
+    position: relative;
+    width: 100%;
+}
+
+.operation{
+    position: absolute;
+    :deep(.el-checkbox){
+        display: flex;
+        align-items: center;
+        height: auto !important;
+        .el-checkbox__label{
+            font-size: 12px !important;
+        }
+        color:#333333;
+    }
+}
+
+
+</style>

+ 413 - 0
src/baseComponents/FilePreview.vue

@@ -0,0 +1,413 @@
+<template>
+<div class="page_dialog">
+    <!-- v-model="previewVisible" -->
+    <el-dialog
+        @close="HandleDialogClose"
+        class="preview_dialog el_button"
+        :model-value="props.previewVisible"
+        style="max-height: 90vh;overflow: auto;max-width: 900px;"
+        :width="dialogWidth ? dialogWidth : '80%'"
+        :title="props.title || '附件预览'"
+        append-to-body
+        :align-center="true"
+    >
+        <div class="custom">
+            <!-- 内部 class="preview_introduce" -->
+            <slot></slot>
+        </div>
+
+        <div v-if="filePreviewList.includes(previewType)" class="preview_item">
+            <VuePdfEmbed 
+                class="preview_main"
+                v-if="previewType == 'pdf'"
+                annotation-layer 
+                :scale="1"
+                text-layer 
+                :source="fileUrl" 
+            />
+            <vue-office-excel
+                v-else-if="previewType == 'xlsx'"
+                :src="fileUrl"
+                :options="excelOptions"
+                style="height: 100vh;"
+                @rendered="renderedHandler"
+                @error="errorHandler"
+            />
+            <vue-office-docx
+                class="preview_main"
+                v-else-if="previewType == 'docx'"
+                :src="fileUrl"
+                @rendered="renderedHandler"
+                @error="errorHandler"
+            />
+            <video  class="preview_main"  controls width="100%" v-else-if="['mp4','avi','mpg','mpeg','wmv','mkv','mov','flv','mpg'].includes(previewType)" :src="fileUrl" />         
+        
+            <!-- <iframe
+                v-else-if="['ppt','pptx'].includes(previewType)"
+                :src="`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(fileUrl)}`"
+                width="100%"
+                height="600px"
+                frameborder="0"
+            ></iframe> -->
+
+            <div   
+                v-else-if="['pptx'].includes(previewType)" 
+                class="vue_ppt" id="vue_ppt" ref="vuePpt"
+            >
+                 
+                <div  v-if="pptLoading" class="loading_bg">
+                    <el-icon class="is-loading">
+                        <Loading />
+                    </el-icon>
+                    加载中
+                </div>
+                <!-- ppt加载中 -->
+            </div>
+
+
+
+            <img  @click="HandleImgPreview" style="text-align: center;" v-else-if="['jpg','png','jpeg','gif','svg','webp'].includes(previewType)" :src="fileUrl"/>
+        </div>
+        <div  class="preview_item" v-else-if="fileName && fileUrl">
+            <span>不支持预览,请点击下载: <a  :href="fileUrl">{{ fileName }}</a></span>
+        </div>
+       
+        <template v-if="props.customFooter" #footer>
+            <el-button @click="HandleDialogClose" class="button_border_gray cancel" >取 消</el-button>
+            <slot name="footer"></slot>
+            
+            <slot name="confirm">
+                <el-button :disabled="props.disabledConfirm" :loading="props.submitLoading"  @click="props.disabledConfirm ? '' : HandleConfirmCheck()" class="button_background"  >确 定</el-button>
+            </slot>
+        </template>
+    </el-dialog>
+
+    <el-image-viewer
+        v-if="imgVisible"
+        :url-list="[fileUrl]"
+        show-progress
+        @close="imgVisible = false"
+    />
+</div>
+</template> 
+
+<script setup lang="ts">
+import {init} from 'pptx-preview'
+import { watch ,ref } from 'vue'
+import VuePdfEmbed from 'vue-pdf-embed'
+// optional styles
+import 'vue-pdf-embed/dist/styles/annotationLayer.css'
+import 'vue-pdf-embed/dist/styles/textLayer.css'
+
+//引入VueOfficeExcel组件
+import VueOfficeExcel from '@vue-office/excel'
+//引入相关样式
+import '@vue-office/excel/lib/index.css'
+//引入VueOfficeDocx组件
+import VueOfficeDocx from '@vue-office/docx'
+//引入相关样式
+import '@vue-office/docx/lib/index.css'
+
+interface FileMsg {
+    name:String,
+    url:String
+}
+
+
+const props = defineProps({
+    fileMessage:{
+        required:true,
+        type:Object
+    },
+    title:{
+        type:String
+    },
+    customFooter:{
+        type:Boolean,
+        required:false
+    },
+    previewVisible:{
+        type:Boolean,
+        required:true
+    },
+    submitLoading:{
+      type:Boolean,
+      default:false,
+    },
+    disabledConfirm:{
+        type:Boolean,
+        default:false
+    },
+    dialogWidth:{
+        type:String,
+    }
+})
+
+const emit = defineEmits(['close','confirm'])
+
+
+const pptxPrviewer = ref()
+const vuePpt = ref()
+const pptLoading = ref(false)
+
+const fileUrl = ref()
+const fileName = ref('')
+// const previewVisible = ref(false)
+const previewType = ref('')
+const imgVisible = ref(false)
+
+const excelOptions = {
+    xls: false,       //预览xlsx文件设为false;预览xls文件设为true
+    minColLength: 0,  // excel最少渲染多少列,如果想实现xlsx文件内容有几列,就渲染几列,可以将此值设置为0.
+    minRowLength: 0,  // excel最少渲染多少行,如果想实现根据xlsx实际函数渲染,可以将此值设置为0.
+    widthOffset: 10,  //如果渲染出来的结果感觉单元格宽度不够,可以在默认渲染的列表宽度上再加 Npx宽
+    heightOffset: 10, //在默认渲染的列表高度上再加 Npx高
+    beforeTransformData: (workbookData) => {return workbookData}, //底层通过exceljs获取excel文件内容,通过该钩子函数,可以对获取的excel文件内容进行修改,比如某个单元格的数据显示不正确,可以在此自行修改每个单元格的value值。
+    transformData: (workbookData) => {return workbookData}, //将获取到的excel数据进行处理之后且渲染到页面之前,可通过transformData对即将渲染的数据及样式进行修改,此时每个单元格的text值就是即将渲染到页面上的内容
+}
+
+const  renderedHandler = ()=> {
+    console.log("渲染完成")
+}
+const errorHandler = () => {
+    console.log("渲染失败")
+}
+
+const HandleImgPreview = ()=>{
+    imgVisible.value = true
+}
+
+const HandleDialogClose = ()=>{
+    emit('close')
+    console.log('弹窗关闭===')
+    // previewVisible.value = false
+    fileUrl.value = ''
+    fileName.value = ''
+    previewType.value = ''
+}
+
+
+
+const HandleConfirmCheck = async () => {
+    emit('confirm')
+}
+
+
+
+const HandlePptPreview =(url)=>{
+  console.log('初始化ppt中')
+  if(url && vuePpt.value){
+    pptLoading.value = true
+
+    //调用库的init方法生成一个预览器
+    pptxPrviewer.value = init(vuePpt.value, {
+        // width: (vuePpt.value?.clientWidth * 0.8),
+        width: (vuePpt.value?.clientWidth),
+        // height: 540
+    })
+    //获取文件或者读取文件,获取文件的 ArrayBuffer格式数据,传给组件进行预览
+    fetch(props?.fileMessage?.url).then(response=>{
+        return response.arrayBuffer()
+    }).then(res =>{
+        console.log('获取文件完成',res)
+        // 在这里监听文档的滚动
+        let pptDom = document.querySelectorAll('.vue_ppt')
+        console.log('dom',pptDom)
+        //调用预览器的preview方法
+        pptxPrviewer.value.preview(res).then(previewRes=>{
+            // 此处数据加载成功
+            console.log('转换结果',previewRes)
+            pptLoading.value = false
+        }).catch(err=>{
+            // 解析失败
+            pptLoading.value = false
+        })
+    }).catch(err=>{
+        // 获取文件失败
+        pptLoading.value = false
+    })
+  }
+}
+
+
+
+const filePreviewList = ref(['pptx','pdf','gif','jpeg','jpg','png','svg','webp','xlsx','docx','mp4','avi','mpg','mpeg','wmv','mkv','mov','flv','mpg'])
+
+watch(()=>props.fileMessage,(newVal)=>{
+    // previewVisible.value = true
+    let suffixName = newVal?.name?.split('.').pop()
+    if(suffixName){
+        fileName.value = newVal.name
+        fileUrl.value = newVal.url
+        if(filePreviewList.value.includes(suffixName)){
+            previewType.value = suffixName
+        }
+        /*
+        else{
+            let link  = document.createElement('a')
+            link.setAttribute('href',newVal.url)
+            document.body.appendChild(link)
+            link.click()
+            console.log('link',link)
+            document.body.removeChild(link)
+        }
+        */
+    }
+})
+
+watch(()=>vuePpt.value,(newVal)=>{
+    if(newVal){
+        HandlePptPreview(props.fileMessage?.url)
+    }
+})
+</script>
+
+
+<style lang="scss" scoped>
+.preview_item{
+    background-color: #f0f4f8;
+    border-radius: 8px;
+    padding:10px;
+    
+    overflow: auto;
+    display: flex;
+    flex-direction: column;
+
+    .preview_main{
+        height: 100%;
+        overflow: auto;
+        border-radius: 8px;
+        width: 100% !important;
+    }
+}
+
+.vue_ppt{
+    display: flex;
+    position: relative;
+    flex-direction: column;
+    align-items: center;
+    justify-content: flex-start;
+    min-height: 270px;
+    // min-height: 100%;
+    overflow: auto;
+    background-color: #e8eaee;
+
+    .loading_bg{
+        width: 100%;
+        flex: 1 1;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        gap:3px;
+        color:#2e64fa;
+    }
+
+
+}
+
+</style>
+
+<style lang="scss">
+.preview_dialog{
+    overflow: auto;
+    border-radius: 8px;
+    padding: 0;
+
+    .el-dialog__headerbtn:focus .el-dialog__close, 
+    .el-dialog__headerbtn:hover .el-dialog__close {
+        color: #999;
+    }
+    .el-dialog__header {
+        width: 100%;
+        height: 48px;
+        line-height: 48px;
+        text-indent: 20px;
+        background-color: #f5f7fa;
+        border-bottom: 1px solid #f5f7fa;
+        border-top-right-radius: 8px;
+        border-top-left-radius: 8px;
+        padding: 0 !important;
+        text-align: left;
+        .el-dialog__title {
+        font-weight: 600;
+        font-size: 16px;
+        color: #303133;
+        }
+        button:focus, button:focus-visible {
+        outline: none;
+        }
+    }
+    //饿了么内容样式覆盖
+    .el-dialog__body {
+        font-weight: 400;
+        font-size: 16px;
+        color: #333;
+        padding: 20px;
+        width: 100%;
+        margin: auto;
+
+        display: flex;
+        flex-direction: column;
+        justify-content: flex-start;
+        max-height: calc(90vh - 50px - 66px);
+        img{
+            border-radius: 8px;
+            align-self: center;
+        }
+        .custom{
+            .preview_introduce{
+                background-color: #fafafa;
+                border: solid #e9e9e9 1px !important;
+                padding:10px;
+                margin-bottom: 10px;
+                border-radius: 8px;
+                display: flex;
+                flex-direction: row;
+                justify-content: flex-start;
+                align-items: flex-start;
+            }
+        }
+    }
+
+    .el-dialog__footer{
+        padding:15px 20px;
+        border-top:solid #EBEEF5 1px;
+    }
+}
+
+.preview_main{
+
+    .docx-wrapper{
+        // width: 100% !important;
+        background-color: #f0f4f8 !important;
+        overflow: auto;
+        box-sizing: border-box;
+        padding-top: 20px;
+        padding-bottom: 20px;
+        .docx{
+            width: 100% !important;
+            overflow: auto;
+        }
+    }
+    .vue-pdf-embed__page{
+        width: 100% !important;
+        overflow: auto;
+        padding:20px;
+
+        background-color: #f0f4f8 !important;
+        canvas{
+            width: 100% !important;
+            background-color: #f0f4f8 !important;
+        }
+        .textLayer{
+            width: 100% !important;
+            height: 100%  !important;
+        }
+
+        .annotationLayer{
+            width: 100% !important;
+            height: 100% !important;
+        }
+    }
+}
+</style>

+ 508 - 0
src/baseComponents/FileWatch.vue

@@ -0,0 +1,508 @@
+<template>
+    <div class="watcher_file">
+        <div v-if="filePreviewList.includes(previewType)" class="preview_item">
+            <PdfViewer 
+                :initCourseLearnPage="props.initCourseLearnPage"
+                @pageChange="(params)=>HandlePageChange('pdf',params)"
+                :showPage="props?.allowDragOrShowPage === 0 ? false : true"
+                :pdf-url="props?.fileMessage?.url" 
+                v-if="previewType == 'pdf'" 
+            />
+            <vue-office-excel
+                class="preview_main"
+                v-else-if="previewType == 'xlsx'"
+                :src="props?.fileMessage?.url"
+                :options="excelOptions"
+                @rendered="renderedHandler"
+                @error="errorHandler"
+            />
+
+            <vue-office-docx
+                class="preview_main"
+                v-else-if="previewType == 'docx'"
+                :src="props?.fileMessage?.url"
+                @rendered="renderedHandler"
+                @error="errorHandler"
+            />
+
+            <div 
+                v-else-if="['mp4','avi','mpg','mpeg','wmv','mkv','mov','flv','mpg'].includes(previewType)" 
+                class="preview_main"  
+            >
+             <!--  视频时间的执行先后顺序 
+                @loadeddata  (1) 视频初始加载一次
+                @seeking    (2)
+                @timeupdate (3)
+                videoPlayer.value.currentTime 的变更 会触发 (2)(3) 依次执行
+            -->
+                
+            <video 
+                @loadeddata="HandleVideoLoaded"
+                @seeking="props?.allowDragOrShowPage ? '' : HandleVideoDragStart()"
+                style="background-color: black;"
+                ref="videoPlayer" 
+                @timeupdate="handleTimeUpdate"
+                @ratechange="handleRateChange"
+                controls 
+                controlslist="nodownload nofullscreen"
+                :src="props?.fileMessage?.url" 
+            />
+            <img  class="full_screen" :src="isFullScreen ? exitFullScreenIcon : fullScreenIcon" alt=""  @click="HandleFullScreen">
+        </div>
+                
+           
+
+            <PptViewer
+                :initCourseLearnPage="props.initCourseLearnPage"
+                @pageChange="(params)=>HandlePageChange('ppt',params)"
+                @fileLoaded="emit('pptLoaded')"
+                v-else-if="['pptx'].includes(previewType)"    
+                :fileMessage="props?.fileMessage">
+            </PptViewer>
+
+            <img  @click="HandleImgPreview" style="text-align: center;" v-else-if="['jpg','png','jpeg','gif','svg','webp'].includes(previewType)" :src="props?.fileMessage?.url"/>
+            
+        
+        </div>
+        <div style="text-align: center;" v-else-if="previewType == '加载中'">加载中...</div>
+        <div style="text-align: center;" v-else>不支持预览 .{{ previewType }}文件</div>
+
+         <el-image-viewer
+            v-if="imgVisible"
+            :url-list="[props?.fileMessage?.url]"
+            show-progress
+            @close="imgVisible = false"
+        />
+
+        <!-- 页面指示器 -->
+        <div class="nav_group" v-if="totalPage > 0"> 
+            <span :class="['pre_nav',{'first':currentPage === 1} ]" @click="currentPage == 1 ? '' : HandlePageJump('reduce')">
+                <el-icon><ArrowLeftBold /></el-icon>
+            </span>
+            <span :class="['next_nav',{'end':currentPage === totalPage}]" @click="currentPage === totalPage ?  '' : HandlePageJump('add')">
+                <el-icon><ArrowRightBold /></el-icon>
+            </span>
+        </div>
+
+        <!-- <div v-if="previewType == 'docx'" class="pageProcess">
+           进度:{{ progressPercent }} %
+        </div> -->
+
+
+    </div>
+</template>   
+
+
+<script setup lang="ts">
+import PdfViewer from './PdfViewer/PdfViewer.vue'
+import PptViewer from './PptViewer/PptViewer.vue'
+import { ref, computed, onMounted, watch } from 'vue'
+
+import fullScreenIcon from '@/assets/icon/fullScreen.png'
+import exitFullScreenIcon from '@/assets/icon/exitFullScreen.png'
+
+
+//引入VueOfficeExcel组件
+import VueOfficeExcel from '@vue-office/excel'
+//引入相关样式
+import '@vue-office/excel/lib/index.css'
+//引入VueOfficeDocx组件
+import VueOfficeDocx from '@vue-office/docx'
+//引入相关样式
+import '@vue-office/docx/lib/index.css'
+
+interface FileMsg {
+    name:String,
+    url:String
+}
+
+
+const props = defineProps({
+    fileMessage:{
+        required:true,
+        type:Object
+    },
+    allowDragOrShowPage:{
+        type:null,
+        required:false,
+        default:true,
+    },
+    initRecord:{
+        type:null,
+        required:false,
+    },
+    updateVideoCurrentTime:{
+        type:Number
+    },
+    initCourseLearnPage:{
+        type:Number,
+        required:false,
+        default:0
+    }
+})
+
+
+const emit = defineEmits(['processChange','pptLoaded','manulFullScreen'])
+
+const videoProcessUpdateFlag = ref()  //进度更新状态标识
+const currentVideoTime = ref(0)  //只记录用户的前进,不记录回退
+
+// const videoPlayer = ref()
+const videoPlayer = defineModel('videoPlayer')
+const defaultVideoRate = ref(1)
+
+const handleRateChange = (event)=>{
+    let currentRate = event.target.playbackRate
+    console.log('当前速率',currentRate)
+    defaultVideoRate.value = currentRate
+}
+
+const handleTimeUpdate = ()=>{
+    const video = videoPlayer.value;
+    const currentTime = Math.floor(video?.currentTime); // 当前播放时间(秒)
+    const duration = Math.floor(video?.duration); // 视频总时长(秒)
+
+    // 播放的结尾的时候再触发一次 更新
+    if(videoProcessUpdateFlag.value && currentTime !== duration){
+        return
+    }
+
+    // 只记录用户的前进,不记录回放
+    if(currentVideoTime.value < currentTime){
+        currentVideoTime.value = currentTime
+    }
+
+    emit('processChange',{type:'video',
+                        videoDuration:duration,
+                        currentVideoTime:currentTime,
+                        latestWatchTime:currentVideoTime.value})  //记录 用户的实际播放位置 和 最新的前进进度
+    // 获取视频播放倍数
+    // 要保证 同步频率 和视频的播放速度一致 或者更快(整数倍)
+    videoProcessUpdateFlag.value = setTimeout(()=>{
+        console.log('进度更新了')
+        console.log('视频当前时间-总时长',currentTime,'-',duration)
+        clearTimeout(videoProcessUpdateFlag.value)
+        videoProcessUpdateFlag.value = null
+        /** 遇到小数的情况下
+         * floor:
+            同步相对快
+            速率相对慢
+            ceil:
+            同步相对慢
+            速率相对快
+         */
+        // 这个后续过程中是否会有问题,待确认 —— 待完善
+        // 确保视频前进1s同步一次
+    },Math.floor(1000 / defaultVideoRate.value))
+}
+
+
+const currentPage = ref(1)
+const totalPage = ref(0)
+
+
+const pageTotalHeight = ref(0)
+const currentReadHeight = ref(0)
+const progressPercent = computed(()=>{
+    if(currentReadHeight.value == 0 || pageTotalHeight.value == 0){
+        return 0
+    }
+    return Math.round((currentReadHeight.value / pageTotalHeight.value) * 100)
+})
+
+
+const filePreviewList = ref(['pptx','pdf','gif','jpeg','jpg','png','svg','webp','xlsx','docx','mp4','avi','mpg','mpeg','wmv','mkv','mov','flv','mpg'])
+const imgVisible = ref(false)
+
+/**
+ * 
+ */
+const previewType = ref('加载中')
+
+const excelOptions = {
+    xls: false,       //预览xlsx文件设为false;预览xls文件设为true
+    minColLength: 0,  // excel最少渲染多少列,如果想实现xlsx文件内容有几列,就渲染几列,可以将此值设置为0.
+    minRowLength: 0,  // excel最少渲染多少行,如果想实现根据xlsx实际函数渲染,可以将此值设置为0.
+    widthOffset: 10,  //如果渲染出来的结果感觉单元格宽度不够,可以在默认渲染的列表宽度上再加 Npx宽
+    heightOffset: 10, //在默认渲染的列表高度上再加 Npx高
+    beforeTransformData: (workbookData) => {return workbookData}, //底层通过exceljs获取excel文件内容,通过该钩子函数,可以对获取的excel文件内容进行修改,比如某个单元格的数据显示不正确,可以在此自行修改每个单元格的value值。
+    transformData: (workbookData) => {return workbookData}, //将获取到的excel数据进行处理之后且渲染到页面之前,可通过transformData对即将渲染的数据及样式进行修改,此时每个单元格的text值就是即将渲染到页面上的内容
+}
+
+
+const timeoutFlag = ref()
+
+const HandleScroll = (e)=>{
+    if(timeoutFlag.value){
+        clearTimeout(timeoutFlag.value)
+    }
+    timeoutFlag.value =  setTimeout(() => {
+
+        let totalHeight = e.target.scrollHeight  //总高度
+        let scrollTop = e.target.scrollTop   //滚动高度
+        let pageHeight = e.target.clientHeight // 客户端高度
+
+        // 用户阅读进度  = ( pageHeight + scrollTop ) / totalHeight
+        console.log('滚动事件',e)
+        console.log('滚动高度',scrollTop)
+        console.log('总高度',totalHeight)
+        console.log('客户端高度',pageHeight)
+
+        pageTotalHeight.value = Math.floor(Number(totalHeight)) || 0
+        currentReadHeight.value = Math.floor( Number(pageHeight) + Number(scrollTop) ) || 0
+        
+        emit('processChange',{type:'docx',currentProcess:progressPercent.value})
+
+        clearTimeout(timeoutFlag.value)
+        timeoutFlag.value = null
+    }, 200);
+}
+
+const excelScrollTimeOutFlag = ref()
+const HandleExcelScroll = (e,type)=>{
+    if(excelScrollTimeOutFlag.value){
+        clearTimeout(excelScrollTimeOutFlag.value)
+    }
+    excelScrollTimeOutFlag.value =  setTimeout(() => {
+        emit('processChange',{type:'excel'})
+        clearTimeout(excelScrollTimeOutFlag.value)
+        excelScrollTimeOutFlag.value = null
+    }, 200);
+}
+
+const HandlePageChange = (type,params)=>{
+    emit('processChange',{type,...params})
+}
+
+const isFullScreen = ref(false)
+
+const HandleVideoLoaded = ()=>{
+    if(['mp4','avi','mpg','mpeg','wmv','mkv','mov','flv','mpg'].includes(previewType.value)){
+        videoPlayer.value.currentTime = currentVideoTime.value
+    }
+    // 禁用右击事件
+    videoPlayer.value.addEventListener('contextmenu', (event) => {
+        event.preventDefault();
+    });
+
+    if (document.fullscreenElement) {
+        isFullScreen.value = true
+    }else{
+        isFullScreen.value = false
+    }
+
+
+
+
+}
+const HandleVideoDragStart = ()=>{
+    console.log('拖拽开始',videoPlayer.value.currentTime)
+    console.log('历史播放记录',currentVideoTime.value)
+    // 只能拖拽已观看部分,不能拖拽未观看部分
+    if(videoPlayer.value.currentTime > currentVideoTime.value){
+        videoPlayer.value.currentTime = currentVideoTime.value
+    }
+}
+
+const HandlePageRedirect = (dom)=>{
+     // docx 的进度重定位放到这里
+    // props.initCourseLearnPage
+    // 根据百分比 换算滚动高度
+    let totalHeight = dom.scrollHeight  //总高度
+    let pageHeight = dom.clientHeight // 客户端高度
+    let realScroll = props.initCourseLearnPage * 0.01 * totalHeight - pageHeight
+    let scrollTop = realScroll > 0 ? realScroll : 0
+
+    dom.scrollTo({
+        top: scrollTop,
+        left: 0,
+        behavior: 'smooth'
+    });
+
+    pageTotalHeight.value = Math.floor(Number(totalHeight)) || 0
+    // 用户阅读进度  = ( pageHeight + scrollTop ) / totalHeight
+    currentReadHeight.value = Math.floor( Number(pageHeight) + Number(scrollTop) ) || 0
+    emit('processChange',{type:'docx',currentProcess:progressPercent.value})
+}
+
+
+const  renderedHandler = (params)=> {
+    console.log("渲染完成",params)
+    const scrollDom = document.querySelectorAll('.preview_main')
+    if(previewType.value == 'docx'){
+        scrollDom[0].addEventListener('scroll',HandleScroll,false)
+        HandlePageRedirect(scrollDom[0])
+
+    }else if(previewType.value == 'xlsx'){
+        console.log('excel表格渲染中')
+
+        // 监听横向滚动
+        const excelDomHorizontal = document.querySelector('.vue-office-excel-main  .x-spreadsheet-sheet   .x-spreadsheet-scrollbar.horizontal ')
+        excelDomHorizontal?.addEventListener('scroll',(event)=>HandleExcelScroll(event,'horizontal'))
+
+        // 监听纵向滚动
+        const excelDomVertical = document.querySelector('.vue-office-excel-main  .x-spreadsheet-sheet   .x-spreadsheet-scrollbar.vertical ')
+        excelDomVertical?.addEventListener('scroll',(event)=>HandleExcelScroll(event,'vertical'))
+
+
+    }
+
+}
+
+const errorHandler = (err) => {
+    console.log("渲染失败",err)
+}
+
+
+const HandleImgPreview = ()=>{
+    imgVisible.value = true
+}
+
+const HandlePageJump = (type)=>{
+    switch(type){
+        case 'add':
+            currentPage.value += 1
+            break;
+        case 'reduce':
+            currentPage.value -= 1
+            break
+    }
+}
+
+const HandleFullScreen = ()=>{
+    emit('manulFullScreen')
+    isFullScreen.value = !isFullScreen.value
+}
+
+watch(()=>props?.fileMessage,(newVal)=>{
+    let suffixName = newVal?.name?.split('.').pop()
+    if(suffixName){
+        previewType.value = suffixName
+    }
+})
+
+watch(()=>props.initRecord,(newVal)=>{
+    // 重置视频的进度
+    currentVideoTime.value  = newVal
+})
+
+
+watch(()=>props.updateVideoCurrentTime,(newVal)=>{
+    // 这个不加也可以
+    // videoPlayer.value.currentTime = newVal
+})
+
+</script>
+
+
+
+<style lang="scss" scoped>
+
+.pageProcess{
+    position: fixed;
+    top:40%;
+    right: 60px;
+}
+.nav_group{
+    position: absolute;
+    width: calc(100% - 40px  - 50px);
+    
+    display: flex;
+    justify-content: space-between;
+    bottom:50%;
+    left: calc(40px);
+
+    
+    .pre_nav,
+    .next_nav{
+        line-height: 1;
+        border-radius: 20px;
+        padding:10px;
+        background-color: #415058;
+        color:white;
+    }
+    .first,
+    .end{
+        background-color: #c3c8d0;
+    }
+}
+
+.page_index{
+    position: absolute;
+    bottom: 10px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    gap:5px;
+    width: 100%;
+}
+
+.watcher_file{
+    // border:solid blue 1px;
+    width: 100%;
+    min-height: 100%;
+    // overflow: auto;
+}
+
+.preview_item{
+    min-height: 100%;
+    height: 100%;
+
+    // overflow: auto;
+    display: flex;
+    flex-direction: column;
+
+    .preview_main{
+        position: relative;
+        min-height: 100%;
+        // overflow: auto;
+        border-radius: 8px;
+
+        .full_screen{
+            width: 15px;
+            position: absolute;
+            right:65px;
+            bottom:40px;
+            background-color: rgba(0,0,0,0.5);
+            text-align: right;
+        }
+        video{
+            width: 100%;
+            min-height: 100%;
+        }
+    }
+}
+
+</style>
+
+
+<style lang="scss">
+    .preview_main{
+        .vue-office-excel-main{
+            width: 100%;
+            height: 100%;
+            .x-spreadsheet{
+                height: 100%;
+                .x-spreadsheet-sheet{
+                    height: calc(100% - 40px);
+                }
+            }
+        }
+
+        .docx-wrapper{
+            // width: 100%;
+            padding-top:20px;
+            padding-bottom: 20px;
+            background-color: #e8eaee !important;
+            overflow: auto;
+            box-sizing: border-box;
+            .docx{
+                overflow: auto;
+                margin-bottom: 0;
+                // width: 80% !important;
+                // width: auto !important;
+            }
+        }
+    }
+
+</style>

+ 635 - 0
src/baseComponents/Form.vue

@@ -0,0 +1,635 @@
+<template>
+    <el-form 
+        :inline="inlineLayout"
+        :model="formData"  
+        ref="formRef" 
+        :label-width="labelWidth"
+    >
+      <el-form-item 
+        v-for="item in finalFormItemList" 
+        :key="item.key"
+        :label="item.label ?  (item.label + ':') : ''"
+        :prop="item.key"
+        :rules="item.rules"
+        :class="[item.className,{'top_label':(item.type=='textarea'||item.type=='checkbox'||item.type=='file' || item.custom === true || item.type=='noDragFile' || item.type=='img')}]"
+      >
+        <template v-if="item.custom">
+          <slot :name="item.key" :formRef="formRef" :formData="formData"></slot>
+        </template>
+
+        <template v-else>
+          <!-- autocomplete="off" -->
+          <!-- <template > -->
+            <el-input v-if="item.type=='input'" v-model="formData[item.key]"  :disabled="item.disabled || props.formDisabled" :placeholder="item.placeholder" :style="item.style"/>
+            <el-input v-else-if="item.type=='password'" type="password" v-model="formData[item.key]"  :disabled="item.disabled || props.formDisabled" :style="item.style"/>
+            <el-input v-else-if="item.type=='textarea'" :autosize="{ minRows: item.rows, maxRows: item.rows }" v-model="formData[item.key]" type="textarea" :rows="item.rows"  :disabled="item.disabled || props.formDisabled" :placeholder="item.placeholder" :style="item.style"/>
+            <el-input v-else-if="item.type=='number'" type="number"  v-model="formData[item.key]" :rows="item.rows"  :disabled="item.disabled || props.formDisabled" :placeholder="item.placeholder" :style="item.style"/>
+            
+            <el-radio-group 
+              v-else-if="item.type=='radio'"  
+              v-model="formData[item.key]" 
+              :disabled="item.disabled || props.formDisabled" 
+              :placeholder="item.placeholder"
+              @change="(val)=>handleSelectChange(item.key,val,item.type)"
+            >
+              <el-radio v-for="radioItem in item.selectList" :key="radioItem.value" :value="radioItem.value">{{ radioItem.label }}</el-radio>
+            </el-radio-group>
+            
+            <el-select 
+              v-else-if="item.type=='select'"  
+              @change="(val)=>handleSelectChange(item.key,val)"
+              v-model="formData[item.key]"  :style="item.style" :disabled="item.disabled || props.formDisabled" :placeholder="item.placeholder"
+            >
+              <el-option
+                v-for="selectItem in item.selectList"
+                :key="selectItem.value"
+                :label="selectItem.label"
+                :value="selectItem.value"
+              />
+            </el-select>
+
+            <el-select
+              class="multipleSelect"
+              v-else-if="item.type=='multipleSelect'"
+              v-model="formData[item.key]"
+              multiple
+              @change="(val)=>handleSelectChange(item.key,val)"
+              :disabled="item.disabled || props.formDisabled" :placeholder="item.placeholder"
+            >
+              <el-option
+                v-for="selectItem in item.selectList"
+                :key="selectItem.value"
+                :label="selectItem.label"
+                :value="selectItem.value"
+                />
+            </el-select>
+
+            <el-select
+              class="multipleSelect"
+              v-else-if="item.type=='multipleSelectSearch'"
+              v-model="formData[item.key]"
+              multiple
+              filterable
+              @change="(val)=>handleSelectChange(item.key,val)"
+              :disabled="item.disabled || props.formDisabled" :placeholder="item.placeholder"
+            >
+              <el-option
+                v-for="selectItem in item.selectList"
+                :key="selectItem.value"
+                :label="selectItem.label"
+                :value="selectItem.value"
+                />
+            </el-select>
+
+
+
+            <template v-else-if="item.type == 'unionSelect'">
+              <span style="display: flex;width: 100%;gap:20px">
+                <el-select v-for="unionSubItem in item.unionSelectList"
+                  :key="unionSubItem.key"
+                  @change="(val)=>handleSelectChange(item.key,val,item.type,null,unionSubItem.key)"
+                  :model-value="formData[item.key]?.[unionSubItem.key]"
+                  :style="unionSubItem.style" :disabled="unionSubItem.disabled || props.formDisabled" :placeholder="unionSubItem.placeholder"
+                >
+                  <el-option
+                    v-for="selectItem in unionSubItem.selectList"
+                    :key="selectItem.value"
+                    :label="selectItem.label"
+                    :value="selectItem.value"
+                  />
+                </el-select>
+              </span>
+            </template>
+
+            <template v-else-if="item.type=='checkbox'" >
+              <el-checkbox
+                v-if="item?.checkAll"
+                :disabled="item.disabled || props.formDisabled"
+                :model-value="formData[item.key]?.length === item.selectList?.length"
+                :indeterminate="formData[item.key]?.length > 0 && formData[item.key]?.length < item.selectList?.length"
+                @change="(val)=>handleCheckAllOrNot(val,item.key,item.selectList)"
+              >
+                全部
+              </el-checkbox>
+
+              <el-checkbox-group  
+                class="check_group_list"
+                :disabled="item.disabled || props.formDisabled"
+                v-model="formData[item.key] "
+                @change="(val)=>handleSelectChange(item.key,val,item.type,item.selectList)"
+              >
+                <el-checkbox 
+                  v-for="checkItem in item.selectList" 
+                  :key="checkItem.value"
+                  :label="checkItem.label"
+                  :value="checkItem.value"
+                />
+              </el-checkbox-group>
+
+            </template>
+
+            <template v-else-if="item.type == 'switch'">
+              <div style="display: flex;align-items: center;gap:20px;">
+                <el-switch
+                  v-model="formData[item.key] "
+                  class="ml-2"
+                  style="--el-switch-on-color: #2e64fa; --el-switch-off-color: #E2E2E3"
+                />
+                <span style="color:#999999;font-size: 12px;">{{ item.tips }}</span>
+              </div>
+            </template>
+          
+
+            <el-date-picker
+              v-else-if="item.type=='datePicker'"
+              v-model="formData[item.key] "
+              type="daterange"
+              :range-separator="item.placeholder.rangeSeparator"
+              :start-placeholder="item.placeholder.startPlaceholder"
+              :end-placeholder="item.placeholder.endPlaceholder"
+              size="default"
+              :disabled="item.disabled || props.formDisabled"
+              @change="(val)=>handleSelectChange(item.key,val,item.type)"
+            />
+            
+            <el-date-picker
+              v-else-if="item.type=='dateTimePicker'"
+              v-model="formData[item.key]"
+              :start-placeholder="item.placeholder.startPlaceholder"
+              :end-placeholder="item.placeholder.endPlaceholder"
+              type="datetimerange"
+              format="YYYY-MM-DD HH:mm:ss"
+              date-format="YYYY/MM/DD ddd"
+              time-format="A hh:mm:ss"
+              :range-separator="item.placeholder.rangeSeparator"
+              size="default"
+              @change="(val)=>handleSelectChange(item.key,val,item.type)"
+              :disabled="item.disabled || props.formDisabled"
+            />
+
+
+            <el-date-picker
+              v-else-if="item.type=='dateTimePickerNoRange'"
+              v-model="formData[item.key]"
+              type="datetime"
+              :placeholder="item.placeholder"
+              :disabled="item.disabled || props.formDisabled"
+              style="width: 100%;"
+              @change="(val)=>handleSelectChange(item.key,val,item.type)"
+            />
+
+
+            <el-upload
+              v-else-if="item.type=='file'"
+              class="upload-demo"
+              action="#"
+              drag
+              :auto-upload="false"
+              @change="(file)=>handleFileChange(file,item.key)"
+              :disabled="item.disabled"
+              >
+                <span v-if="props.fileLoading" style="display: flex;flex-direction: row;align-items: center;gap: 3px;line-height: 1.5;color:#2e64fa">
+                  上传中<el-icon class="is-loading">
+                    <Loading />
+                  </el-icon>
+                </span>
+                
+                <span v-else-if="formData[item.key]?.name" class="file_list">
+                  <span class="el-upload__tip">
+                    <span  @click.stop.prevent="HandlePreviewFile(formData[item.key])">
+                      {{ formData[item.key]?.name  }}   
+                    </span> 
+                    <img class="delete_item"  @click="HandleRemove(item.key)" :src="deleteIcon" alt="">
+                  </span>
+                  <i  class="iconfont hjx-dui"></i>
+                </span>
+
+                <img class="no_data" v-else :src="noDataBg" alt="">
+                <el-button type="primary"><i class="iconfont hjx-daochu"></i> 上传文件</el-button>
+
+            </el-upload>
+
+
+            <el-upload
+              v-else-if="item.type == 'noDragFile'"
+              class="upload-demo"
+              action="#"
+              :auto-upload="false"
+              @change="(file)=>handleFileChange(file,item.key)"
+              :disabled="item.disabled"
+              >
+                <el-button type="primary"><i class="iconfont hjx-daochu"></i> 上传文件</el-button>
+                
+                <template #tip>
+                  <div class="no_drag_content el-upload__tip ">
+                    <span v-if="props.fileLoading" style="display: flex;flex-direction: row;align-items: center;gap: 3px;line-height: 1.5;color:#2e64fa">
+                      上传中<el-icon class="is-loading">
+                        <Loading />
+                      </el-icon>
+                    </span>
+                    
+                    <span v-else-if="formData[item.key]?.name" class="file_list">
+                      <span class="el-upload__tip">
+                        <span  @click.stop.prevent="HandlePreviewFile(formData[item.key])">
+                          {{ formData[item.key]?.name  }}   
+                        </span> 
+                        <img class="delete_item"  @click="HandleRemove(item.key)" :src="deleteIcon" alt="">
+                      </span>
+                      <i  class="iconfont hjx-dui"></i>
+                    </span>
+                  </div>
+
+                </template>
+            </el-upload>
+
+
+            <template  v-else-if="item.type=='imgFile'" >
+              <div class="img_file_area">
+                 <span v-if="props.fileLoading" class="cover"  style="gap: 3px;line-height: 1.5;color:#2e64fa">
+                  上传中
+                  <el-icon class="is-loading">
+                    <Loading />
+                  </el-icon>
+                </span>
+                <span v-else-if="formData[item.key]?.url">
+                  <img class="cover"   :src="formData[item.key]?.url" alt="">
+                  <img   class="close" @click="HandleRemove(item.key)" :src="closeFillImg">
+                </span>
+                <el-upload 
+                  v-model:file-list="fileList"
+                  action="#" 
+                  :auto-upload="false"
+                  @change="(file)=>handleFileChange(file,item.key)"
+                  :on-preview="handlePictureCardPreview"
+                  :on-remove="handleRemove"
+                >
+                  <div class="operation_area">
+                    <i class="iconfont hjx-a-Folder-uploadwenjianjia-shangchuan"></i>
+                  </div>
+                </el-upload>
+              </div>
+
+
+            </template>
+
+            <img  width="100%" v-else-if="item.type=='img'" :src="formData[item.key]?.url">
+            
+
+            <a v-else-if="item.type=='url'"  @click="HandlePreviewFile(formData[item.key])" >{{ formData[item.key]?.name }}</a>
+          <!-- </template> -->
+
+         
+
+        </template>
+      </el-form-item>
+
+      <div style="width: 100%;">
+        <slot name="submit" :formRef="formRef" :formData="formData"></slot>
+      </div>
+
+    </el-form>
+
+</template>
+
+
+<script lang="ts" setup>
+import { ref, computed, watch } from 'vue'
+import noDataBg from '@/assets/bg/table_no_data.png'
+import deleteIcon from '@/assets/icon/delete.svg'
+import {Loading} from '@element-plus/icons-vue'
+
+import closeFillImg from '@/assets/icon/close_fill.svg'
+
+
+const previewVisible = ref(false)
+const fileList = ref([
+   {
+    name: 'food.jpeg',
+    url: 'https://jtzx001.oss-accelerate.aliyuncs.com/huijiaoyan_test/20260114_50007/14091841_0834e935-5393-4981-ba53-3c37fda73a1f.jpeg',
+  },
+])
+
+const handlePictureCardPreview = ()=>{
+  console.log('预览')
+}
+
+
+const handleRemove = ()=>{
+  console.log('移除')
+}
+type  ItemType = 
+  |'input'|'password'|'textarea'|'number'|'radio'
+  |'select'|'multipleSelect'| 'multipleSelectSearch' |'unionSelect' |'checkbox'|'datePicker' | 'dateTimePickerNoRange'
+  |'dateTimePicker'|'url'|'file' | 'switch' | 'imgFile' | 'noDragFile' | 'img'
+
+
+interface formItemProperty {
+  key: String,
+  label: String,
+  type:ItemType,
+  checkAll?:Boolean
+  placeholder?:|String 
+              | {
+                rangeSeparator:String,
+                startPlaceholder:String
+                endPlaceholder:String
+              },
+  rules: any[],
+  hidden?: Boolean,
+  disabled?: Boolean,
+  custom?:Boolean,
+  style?: Record<string, any>,
+  className?:String,
+  unionSelectList?:{
+    key:String,
+    type:String,
+    placeholder:String,
+    disabled:Boolean,
+    style:Record<string, any>,
+    selectList: { label: string, value: any }[] | [],
+  }[]
+  selectList?: { label: string, value: any }[] | [],
+  rows?:number,
+  tips?:String,
+}
+
+const props = defineProps({
+    width:{
+      required:false,
+    },
+   
+    formItemList:{
+        type:Array<formItemProperty>,
+        required:true,
+        // default:()=>[]
+    },
+    
+    defaultFormData:{
+      type:Object,
+      required:true,
+    },
+    formDisabled:{
+      type:Boolean,
+      default:false
+    },
+    fileLoading:{
+      type:Boolean,
+      default:false
+    },
+    inlineLayout:{
+      type:Boolean,
+      default:true
+    },
+    labelWidth:{
+      type:String,
+      default:'auto'
+    }
+
+
+})
+const emit  = defineEmits(['close','confirm','formItemChange','fileUpload'])
+
+const formRef = defineModel('formRef')
+
+
+const fileMessage = ref({})
+const formData = ref({})
+// const formRef = ref()
+
+const finalFormItemList = computed(()=>{
+    return props.formItemList.filter(item=>!item.hidden)
+})
+
+// 是否全选
+
+watch(()=>props.defaultFormData,(newVal)=>{
+  formData.value = newVal
+},{immediate:true})
+
+const formSubmitCheck = async (formEl) => {
+  if(props.formDisabled){
+    closeDialog()
+    return
+  }
+  if (!formEl) return
+  await formEl.validate(async(valid) => {
+    if (valid) {
+      emit('confirm', {formData:formData.value,formRef:formEl})
+    }
+  }).catch(err=>{
+    console.log('报错信息',err)
+  })
+}
+
+const HandlePreviewFile = (file)=>{
+  console.log('附件信息',file)
+  previewVisible.value = true
+  fileMessage.value  = {url:file.url,name:file.name}
+}
+
+const closeDialog = () => {
+  formRef.value.resetFields()
+  emit('close')
+}
+
+const HandClosePreview = ()=>{
+  fileMessage.value = {}
+  previewVisible.value = false
+}
+
+const handleSelectChange = (key,val,type,selectList,subKey) =>{
+  if(type == 'unionSelect'){
+    if(formData.value[key]){
+      formData.value[key][subKey] = val
+    }else{
+      formData.value[key] = {}
+      formData.value[key][subKey] = val
+    }
+  }
+  emit('formItemChange',{key,val,formData:formData.value,subKey})
+}
+
+const handleCheckAllOrNot = (val,key,allData)=>{
+  let allValue = allData.map(item=>item.value)
+  let finalVal = val ? allValue : [] 
+  formData.value = {...formData.value,[key]:finalVal}
+  // 选项----
+  emit('formItemChange',{key,val:finalVal,formData:formData.value})
+}
+
+const handleFileChange = (file,formKey)=>{
+  emit('fileUpload',{key:formKey,file})
+}
+
+const HandleRemove = (formKey)=>{
+  formData.value[formKey] = null
+}
+
+</script>  
+<style lang="scss" scoped>
+.img_file_area{
+  width: 100%;
+  display: flex;
+  gap:10px;
+  align-items: center;
+
+  >span{
+    position: relative;
+    .close{
+      width: 14px;
+      height: 14px;
+      color: #F56C6C;
+      position:absolute;
+      top:-5px;
+      right: -2px;
+    }
+  }
+
+  .cover,
+  .operation_area{
+    width: 90px;
+    height: 60px;
+    border-radius: 6px;
+    background-color: #f0f4f8;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .operation_area{
+    background-color: #F0F4F8;
+    font-size: 24px;
+  }
+}
+
+.multipleSelect{
+  :deep(.el-select__wrapper){
+     height: auto;
+  }
+}
+
+.upload-demo{
+  width: 100%;
+  .file_list{
+    // 拖拽
+    width: 80%;
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    gap:5px;
+
+    .el-upload__tip{
+      flex:1 1;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      margin-top: 0;
+      // 拖拽
+      background-color: white;
+      padding:0 8px;
+      > a{
+        color: #666;
+      }
+      > img{
+        width: 15px;
+      }
+    }
+
+    .hjx-dui {
+      color: #2dab85;
+      font-size: 16px;
+    }
+  }
+  .el-button{
+    background-color: #2e64fa;
+  }
+
+ 
+
+  .no_drag_content{
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    gap: 10px;
+    align-items: flex-start;
+    .file_list{
+      width: 100%;
+      background-color: #F5F7FC;
+      .el-upload__tip{
+        background-color: transparent;
+      }
+    }
+  }
+
+  :deep(.el-upload-dragger){
+    background-color: #f0f4f7;
+    border:dashed #9a9c9e 1px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    gap: 10px;
+    .no_data{
+      width: 60px;
+    }
+  }
+}
+
+.el-form{
+  .el-form-item{
+    margin-bottom: 20px;
+  }
+}
+
+
+.check_group_list{
+  width: 100%;
+}
+
+.delete_item{
+  width: 96px;
+  height: 36px !important;
+  font-weight: 400;
+  font-size: 14px;
+  text-align: center;
+  cursor: pointer;
+}
+
+.iconfont {
+  margin-right: 5px;
+
+  &.hjx-a-Folder-uploadwenjianjia-shangchuan{
+    color: #999999;
+    font-size: 24px;
+  }
+}
+
+.page_dialog{
+  :deep(.el-dialog__body){
+    min-height: 156px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+  }
+
+  a{
+    &:hover{
+      cursor: pointer;
+    }
+  }
+}
+
+</style>
+
+<style lang="scss">
+//部分标签顶部对齐
+.top_label{
+  .el-form-item__label-wrap{
+    // border:solid red 1px;
+    align-self: flex-start;
+  }
+}
+
+
+</style>

+ 1216 - 0
src/baseComponents/FormDialog.vue

@@ -0,0 +1,1216 @@
+<template>
+  <!-- width 680px -->
+  <div class="page_dialog">
+    <el-dialog 
+      @close="closeDialog" 
+      :model-value="props.visible"  
+      :title="props.title" 
+      :width="props.width || '480px'"
+      :close-on-click-modal="false"
+      class="el_button"
+    >
+
+    <slot name="form_pre"></slot>
+  
+    <el-form 
+        v-loading="formLoading"
+        :inline="true"
+        :model="formData"  
+        ref="formRef" 
+        label-width="auto"
+    >
+      <el-form-item 
+        style="width: 100%;"
+        v-for="item in finalFormItemList" 
+        :key="item.key"
+        :label="item.label ? item.label + ':' : ''"
+        :prop="item.key"
+        :rules="item.rules"
+        :style="item.style"
+        :class="[item.className,{'top_label':(item.type=='textarea'||item.type=='checkbox'||item.type=='file' || item.type == 'checkboxButton' ||
+                                              item.custom === true || item.type=='noDragFile' || item.type=='imgFile' || 
+                                              item.type == 'fileShowList' || item.type=='radio')}]"
+      >
+        <template v-if="item.custom">
+          <slot :name="item.key" :formItem="item"></slot>
+        </template>
+
+        <template v-else>
+          <!-- autocomplete="off" -->
+          <template v-if="!props.formDisabled">
+            <el-input v-if="item.type=='input'" v-model="formData[item.key]"  :disabled="item.disabled" :placeholder="item.placeholder"/>
+            <el-input v-else-if="item.type=='password'" type="password" v-model="formData[item.key]"  :disabled="item.disabled"/>
+            <el-input v-else-if="item.type=='textarea'" :autosize="{ minRows: item.rows, maxRows: item.rows }" v-model="formData[item.key]" type="textarea" :rows="item.rows"  :disabled="item.disabled" :placeholder="item.placeholder"/>
+            <el-input v-else-if="item.type=='number'" type="number"  v-model="formData[item.key]" :rows="item.rows"  :disabled="item.disabled" :placeholder="item.placeholder"/>
+            
+            <el-radio-group 
+              v-else-if="item.type=='radio'"  
+              v-model="formData[item.key]" 
+              :disabled="item.disabled" 
+              :placeholder="item.placeholder"
+              @change="(val)=>handleSelectChange(item.key,val,item.type)"
+            >
+              <el-radio v-for="radioItem in item.selectList" :key="radioItem.value" :value="radioItem.value">{{ radioItem.label }}</el-radio>
+            </el-radio-group>
+            
+            <el-select 
+              v-else-if="item.type=='select'"  
+              @change="(val)=>handleSelectChange(item.key,val)"
+              v-model="formData[item.key]"  :style="item.style" :disabled="item.disabled" :placeholder="item.placeholder"
+            >
+              <el-option
+                v-for="selectItem in item.selectList"
+                :key="selectItem.value"
+                :label="selectItem.label"
+                :value="selectItem.value"
+              />
+            </el-select>
+
+            <el-select
+              class="multipleSelect"
+              v-else-if="item.type=='multipleSelect'"
+              v-model="formData[item.key]"
+              multiple
+              @change="(val)=>handleSelectChange(item.key,val)"
+              :disabled="item.disabled" :placeholder="item.placeholder"
+            >
+              <el-option
+                v-for="selectItem in item.selectList"
+                :key="selectItem.value"
+                :label="selectItem.label"
+                :value="selectItem.value"
+                />
+            </el-select>
+
+            <el-select
+              class="multipleSelect"
+              v-else-if="item.type=='multipleSelectSearch'"
+              v-model="formData[item.key]"
+              filterable
+              multiple
+              @change="(val)=>handleSelectChange(item.key,val)"
+              :disabled="item.disabled" :placeholder="item.placeholder"
+            >
+              <el-option
+                v-for="selectItem in item.selectList"
+                :key="selectItem.value"
+                :label="selectItem.label"
+                :value="selectItem.value"
+                />
+            </el-select>
+
+             <el-select
+              class="multipleSelect"
+              v-else-if="item.type=='singleSelectSearch'"
+              v-model="formData[item.key]"
+              filterable
+              @change="(val)=>handleSelectChange(item.key,val)"
+              :disabled="item.disabled" :placeholder="item.placeholder"
+            >
+              <el-option
+                v-for="selectItem in item.selectList"
+                :key="selectItem.value"
+                :label="selectItem.label"
+                :value="selectItem.value"
+                />
+            </el-select>
+
+
+            <template v-else-if="item.type == 'unionSelect'">
+              <span style="display: flex;width: 100%;gap:20px">
+                <el-select v-for="unionSubItem in item.unionSelectList"
+                  :key="unionSubItem.key"
+                  @change="(val)=>handleSelectChange(item.key,val,item.type,null,unionSubItem.key)"
+                  :model-value="formData[item.key]?.[unionSubItem.key]"
+                  :style="unionSubItem.style" :disabled="unionSubItem.disabled" :placeholder="unionSubItem.placeholder"
+                >
+                  <el-option
+                    v-for="selectItem in unionSubItem.selectList"
+                    :key="selectItem.value"
+                    :label="selectItem.label"
+                    :value="selectItem.value"
+                  />
+                </el-select>
+              </span>
+            </template>
+
+            <template v-else-if="item.type=='checkbox'" >
+              <el-checkbox
+                v-if="item.checkAll && item.selectList?.length > 0"
+                :model-value="formData[item.key]?.length === item.selectList?.length"
+                :indeterminate="formData[item.key]?.length > 0 && formData[item.key]?.length < item.selectList?.length"
+                @change="(val)=>handleCheckAllOrNot(val,item.key,item.selectList)"
+              >
+                全部
+              </el-checkbox>
+
+              <el-checkbox-group  
+                class="check_group_list"
+                v-model="formData[item.key] "
+                @change="(val)=>handleSelectChange(item.key,val,item.type,item.selectList)"
+              >
+                <el-checkbox 
+                  v-for="checkItem in item.selectList" 
+                  :key="checkItem.value"
+                  :label="checkItem.label"
+                  :value="checkItem.value"
+                />
+              </el-checkbox-group>
+
+            </template>
+
+
+            <template v-else-if="item.type=='checkboxButton'" >
+              <el-checkbox-group  
+                class="check_group_btn_list"
+                v-model="formData[item.key] "
+                @change="(val)=>handleSelectChange(item.key,val,item.type,item.selectList)">
+                <el-checkbox-button 
+                  v-for="checkItem in item.selectList" 
+                  :key="checkItem.value"
+                  :label="checkItem.label"
+                  :value="checkItem.value"/>
+              </el-checkbox-group>
+            </template>
+
+            
+
+
+
+            <template v-else-if="item.type == 'switch'">
+              <div style="display: flex;align-items: center;gap:20px;">
+                <el-switch
+                  v-model="formData[item.key] "
+                  class="ml-2"
+                  style="--el-switch-on-color: #2e64fa; --el-switch-off-color: #E2E2E3"
+                />
+                <span style="color:#999999;font-size: 14px;">{{ item.tips }}</span>
+              </div>
+            </template>
+          
+
+            <el-date-picker
+              v-else-if="item.type=='datePicker'"
+              v-model="formData[item.key] "
+              type="daterange"
+              :range-separator="item.placeholder.rangeSeparator"
+              :start-placeholder="item.placeholder.startPlaceholder"
+              :end-placeholder="item.placeholder.endPlaceholder"
+              size="default"
+              :disabled="item.disabled"
+            />
+
+            <el-date-picker
+              v-else-if="item.type=='datePickerNoRange'"
+              v-model="formData[item.key] "
+              type="date"
+              :range-separator="item.placeholder.rangeSeparator"
+              :start-placeholder="item.placeholder.startPlaceholder"
+              :end-placeholder="item.placeholder.endPlaceholder"
+              size="default"
+              :disabled="item.disabled"
+              :disabled-date="item.disabledDate"
+
+            />
+
+            
+            <el-date-picker
+              v-else-if="item.type=='dateTimePicker'"
+              v-model="formData[item.key]"
+              @change="(val)=>handleSelectChange(item.key,val,item.type)"
+              :start-placeholder="item.placeholder.startPlaceholder"
+              :end-placeholder="item.placeholder.endPlaceholder"
+              type="datetimerange"
+              format="YYYY-MM-DD HH:mm:ss"
+              date-format="YYYY/MM/DD ddd"
+              time-format="A hh:mm:ss"
+              :range-separator="item.placeholder.rangeSeparator"
+              size="default"
+              :disabled="item.disabled"
+              :disabled-date="item.disabledDate"
+            />
+
+            <el-date-picker
+              v-else-if="item.type=='dateTimePickerNoRange'"
+              v-model="formData[item.key]"
+              type="datetime"
+              :placeholder="item.placeholder"
+              :disabled="item.disabled"
+              style="width: 100%;"
+              :disabled-date="item.disabledDate"
+              @change="(val)=>handleSelectChange(item.key,val,item.type)"
+            />
+
+            <el-upload
+              v-else-if="item.type=='file'"
+              class="upload-demo"
+              action="#"
+              drag
+              :auto-upload="false"
+              @change="(file)=>handleFileChange(file,item)"
+              :disabled="item.disabled"
+              >
+                <span v-if="props.fileLoading" style="display: flex;flex-direction: row;align-items: center;gap: 3px;line-height: 1.5;color:#2e64fa">
+                  上传中<el-icon class="is-loading">
+                    <Loading />
+                  </el-icon>
+                </span>
+                
+                <span v-else-if="formData[item.key]?.name" class="file_list">
+                  <span class="el-upload__tip">
+                    <span  @click.stop.prevent="HandlePreviewFile(formData[item.key])">
+                      {{ formData[item.key]?.name  }}   
+                    </span> 
+                    <img class="delete_img"  @click="HandleRemove(item.key)" :src="deleteIcon" alt="">
+                  </span>
+                  <i  class="iconfont hjx-dui"></i>
+                </span>
+
+                <img class="no_data" v-else :src="noDataBg" alt="">
+                <el-button type="primary"><i class="iconfont hjx-daochu"></i> 上传文件</el-button>
+
+            </el-upload>
+
+
+            <el-upload
+              v-else-if="item.type == 'noDragFile'" 
+              class="upload-demo"
+              :style="(item.tips ? ({display: 'flex',gap:'10px',alignItems:'center'}) : '')"
+              action="#"
+              :auto-upload="false"
+              @change="(file)=>handleFileChange(file,item)"
+              :disabled="item.disabled"
+              >
+                <el-button :disabled="item.disabled" type="primary">
+                  <!-- <i class="iconfont hjx-daochu"></i> -->
+                  {{formData[item.key]?.name ? '重新上传' : '点击上传'}}
+                </el-button>
+              
+                <template #tip>
+                  <div class="no_drag_content el-upload__tip" :class="{'right_tips':item.tips}">
+                    
+                    <!-- v-if="props.fileLoading"  -->
+                    <span v-if="props.fileLoading" style="display: flex;flex-direction: row;align-items: center;gap: 3px;line-height: 1.5;color:#2e64fa">
+                      上传中<el-icon class="is-loading">
+                        <Loading />
+                      </el-icon>
+                      <span style="color:#f56c6c;cursor: pointer;" @click="HandleFileAbort">取消</span>
+                    </span>
+
+                    <template v-else-if="item.tips">
+                      <span v-if="formData[item.key]?.name" style="color:#999999;font-size: 14px;">
+                          {{ formData[item.key]?.name  }}   
+                      </span>
+                      <span v-else style="color:#999999;font-size: 14px;">{{ item.tips }}</span>
+                    </template>
+
+                    <template v-else-if="!(item.tips) && formData[item.key]?.name">
+                      <span class="file_list">
+                        <span class="el-upload__tip">
+                          <span  @click.stop.prevent="HandlePreviewFile(formData[item.key])">
+                            {{ formData[item.key]?.name  }}   
+                          </span> 
+                          <img class="delete_img"  @click="HandleRemove(item.key)" :src="deleteIcon" alt="">
+                        </span>
+                        <i  class="iconfont hjx-dui"></i>
+                      </span>
+                    </template>
+                  </div>
+                </template>
+            </el-upload>
+ 
+            <!-- imgFile 原先的组件 -->
+            <template  v-else-if="0" >
+              <div class="img_file_area">
+                <el-upload 
+                  action="#" 
+                  :auto-upload="false"
+                  @change="(file)=>handleFileChange(file,item)"
+                  :on-preview="handlePictureCardPreview"
+                  :on-remove="handleRemove"
+                >
+                  <div class="operation_area">
+                    <i class="iconfont hjx-a-Folder-uploadwenjianjia-shangchuan"></i>
+                  </div>
+                </el-upload>
+                <span v-if="props.fileLoading" class="cover"  style="gap: 3px;line-height: 1.5;color:#2e64fa">
+                  上传中
+                  <el-icon class="is-loading">
+                    <Loading />
+                  </el-icon>
+                </span>
+                <span v-else-if="formData[item.key]?.url">
+                  <img class="cover"   :src="formData[item.key]?.url" alt="">
+                  <img   class="close" @click="HandleRemove(item.key)" :src="closeFillImg">
+                </span>
+              </div>
+            </template>
+
+            <template  v-else-if="item.type=='imgFile'" >
+              <div class="img_file_area1">
+                <el-upload 
+                  action="#" 
+                  :auto-upload="false"
+                  @change="(file)=>handleFileChange(file,item)"
+                  :on-preview="handlePictureCardPreview"
+                  :on-remove="handleRemove"
+                >
+                  <div class="operation_area">
+                    <el-icon class="icon"><Plus /></el-icon>
+                    <span>{{item.uploadTips ? item.uploadTips : '上传文件'}}</span>
+                  </div>
+                </el-upload>
+
+                <span v-if="formData[item.key].fileLoading" class="cover"  style="gap: 3px;line-height: 1.5;color:#2e64fa">
+                  上传中
+                  <el-icon class="is-loading">
+                    <Loading />
+                  </el-icon>
+                </span>
+
+                <!-- 单张 -->
+                <template  v-if="item.limit == 1 && !formData[item.key].fileLoading">
+                  <span  class="img_file" v-if="formData[item.key]?.url">
+                    <img class="cover"   :src="formData[item.key]?.url" alt="">
+                    <img   class="close" @click="HandleRemove(item.key)" :src="closeFillImg">
+                  </span>
+                </template>
+
+                  <!-- 多张 -->
+                  <!-- 多张 对象结构 { files:[{name:'',url:''},{}],fileLoading:false}-->
+                  <template v-else-if="item.limit > 1">
+                    <span  class="img_file" v-for="fileItm in formData[item.key].files" :key="fileItm">
+                      <img class="cover"   :src="fileItm?.url" alt="">
+                      <div class="operation_btn">
+                        <span class="delete" @click="HandleRemoveSingleImg(item.key,fileItm)">删除</span>
+                        <span class="preview" @click="HandleImgPreview(fileItm?.url)">查看</span>
+                      </div>
+                    </span>
+                  </template>
+                  <el-image-viewer
+                    v-if="imgVisible"
+                    :url-list="[dialogImageUrl]"
+                    show-progress
+                    @close="imgVisible = false"
+                  />
+              </div>
+            </template>
+
+
+            <template  v-else-if="item.type=='fileShowList'" >
+              <div class="file_show_list">
+                <el-upload 
+                  action="#" 
+                  :auto-upload="false"
+                  @change="(file)=>handleFileChange(file,item)"
+                  :on-preview="handlePictureCardPreview"
+                  :on-remove="handleRemove"
+                >
+                  <div class="operation_area">
+                    <el-icon class="icon"><Plus /></el-icon>
+                    <span>{{item.uploadTips ? item.uploadTips : '上传文件'}}</span>
+                  </div>
+                </el-upload>
+
+                
+                <div class="file_list">
+                  <span v-if="formData[item.key].fileLoading" class="cover"  style="gap: 3px;line-height: 1.5;color:#2e64fa">
+                    上传中
+                    <el-icon class="is-loading">
+                      <Loading />
+                    </el-icon>
+                  </span>
+                  <!-- 单张 -->
+                  <template  v-if="item.limit == 1 && !formData[item.key].fileLoading">
+                    <div  class="file_desc" v-if="formData[item.key]?.url">
+                      <img class="icon" :src="fileIcon" alt="">
+                      <div class="file_msg">
+                        <span class="name" :title="formData[item.key]?.name">{{ formData[item.key]?.name }}</span>
+                        
+                        <span class="size"> 
+                          <span>{{ formData[item.key]?.fileSize }}</span>
+                          <span>{{ formData[item.key]?.time }}</span>
+                        </span>
+                      </div>
+                      <div class="table_row_option">
+                          <span class="el_button_delete" @click="HandleRemove(item.key)">删除</span>
+                          <span class="el_button_editor" @click="HandleFilePreview(formData[item.key])">预览</span>
+                          <span class="el_button_editor" @click="HandleFileDownload(formData[item.key]?.url)">下载</span>
+                        </div>
+                    </div>
+                  </template>
+
+                  <!-- 多张 对象结构 { files:[{name:'',url:''},{}],fileLoading:false}-->
+                  <template v-else-if="item.limit > 1">
+                    <div  class="file_desc" v-for="fileItm in formData[item.key].files" :key="fileItm">
+                      <img class="icon" :src="fileIcon" alt="">
+                      <div class="file_msg">
+                        <span class="name" :title="fileItm?.name">{{ fileItm?.name }}</span>
+                        <span class="size"> 
+                          <span>{{ fileItm?.fileSize }}</span>
+                          <span>{{ fileItm?.time }}</span>
+                        </span>
+                      </div>
+                      <div class="table_row_option">
+                        <span class="el_button_delete" @click="HandleRemoveSingleImg(item.key,fileItm)">删除</span>
+                        <span class="el_button_editor" @click="HandleFilePreview(fileItm)"> 预览</span>
+                        <span class="el_button_editor" @click="HandleFileDownload(fileItm?.url)">下载</span>
+                      </div>
+                    </div>
+                  </template>
+                </div>
+              </div>
+            </template>
+
+            <a v-else-if="item.type=='url'"  @click="HandlePreviewFile(formData[item.key])" >{{ formData[item.key]?.name }}</a>
+          </template>
+
+          <template v-else>
+            <el-input v-if="item.type!=='file' && item.type!=='url' &&  
+                            item.type!=='unionSelect' && item.type !== 'dateTimePicker'" 
+                      class="readonly_input" 
+                      v-model="formData[item.key]" :readonly="true" />
+
+            <span  v-else-if="item.type=='unionSelect' " style="display: flex;width: 100%;gap:20px">
+              <el-input  
+                class="readonly_input"
+                v-for="unionSubItem in item?.unionSelectList" 
+                :key="unionSubItem.key" :style="unionSubItem.style" 
+                :model-value="formData[item.key]?.[unionSubItem.key]"  
+                :readonly="true"
+              />
+            </span>
+
+            <el-date-picker
+              v-else-if="item.type=='dateTimePicker'"
+              v-model="formData[item.key]"
+              :start-placeholder="item.placeholder.startPlaceholder"
+              :end-placeholder="item.placeholder.endPlaceholder"
+              type="datetimerange"
+              format="YYYY-MM-DD HH:mm:ss"
+              date-format="YYYY/MM/DD ddd"
+              time-format="A hh:mm:ss"
+              :range-separator="item.placeholder.rangeSeparator"
+              size="default"
+              :disabled="true"
+            />
+
+            <a v-else-if="item.type=='file' "  @click= "formData[item.key]?.name ? HandlePreviewFile(formData[item.key]) : ''" >
+              {{ formData[item.key]?.name || '未选择任何文件' }}   
+            </a>
+            <a v-else-if="item.type=='url'"  @click="HandlePreviewFile(formData[item.key])" >{{ formData[item.key]?.name }}</a>
+          </template>
+
+      </template>
+
+
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="footer_bottom">
+        <div class="footer_right">
+          <slot name="footerRight" :formRef="formRef"></slot>
+        </div>
+        <div class="footer_right">
+          <el-button class="button_border_gray cancel" @click="closeDialog">取 消</el-button>
+          <slot name="footer_btn" :formRef="formRef"></slot>
+          <slot name="confirm" :formRef="formRef" :formData="formData">
+            <el-button class="button_background" :disabled="props.disabledConfirm" :loading="props.submitLoading" @click="props.disabledConfirm ? '' : formSubmitCheck(formRef)">确 定</el-button>
+          </slot>
+        </div>
+      </div>
+    </template>
+
+    <FilePreview  
+        :previewVisible="previewVisible"
+        @close="HandClosePreview"
+        :fileMessage="fileMessage" />
+    </el-dialog>
+  </div>
+  
+</template>
+
+<script lang="ts" setup>
+import { ref, computed, watch } from 'vue'
+import FilePreview from './FilePreview.vue'
+import noDataBg from '@/assets/bg/table_no_data.png'
+import deleteIcon from '@/assets/icon/delete.svg'
+import {Loading} from '@element-plus/icons-vue'
+
+import closeFillImg from '@/assets/icon/close_fill.svg'
+
+import { ElMessage } from 'element-plus'
+
+import fileIcon from '@/assets/icon/file.png'
+
+
+const previewVisible = ref(false)
+
+const handlePictureCardPreview = ()=>{
+  console.log('预览')
+}
+
+
+const handleRemove = ()=>{
+  console.log('移除')
+}
+type  ItemType = 
+  |'input'|'password'|'textarea'|'number'|'radio'
+  |'select'|'multipleSelect' | 'singleSelectSearch' | 'multipleSelectSearch' | 'unionSelect' |'checkbox'|'datePicker' | 'checkboxButton'
+  |'dateTimePicker'| 'dateTimePickerNoRange' |'datePickerNoRange' |'url'|'file' | 'switch' | 'imgFile' | 'noDragFile' | 'fileShowList' | String
+
+
+interface formItemProperty {
+  key: String,
+  label: String,
+  type?:ItemType,
+  limit?:Number, // 文件上传限制的数量
+  uploadTips?:String,
+  acceptType?:[],
+  checkAll?:Boolean,
+  placeholder?:|String 
+              | {
+                rangeSeparator:String,
+                startPlaceholder:String
+                endPlaceholder:String
+              },
+  rules?: any[],
+  hidden?: Boolean,
+  disabled?: Boolean,
+  // 日期专用
+  disabledDate?:Function,
+  custom:Boolean,
+  style: Record<string, any>,
+  className?:String,
+  unionSelectList?:{
+    key:String,
+    type:String,
+    placeholder:String,
+    disabled:Boolean,
+    style:Record<string, any>,
+    selectList: { label: string, value: any }[] | [],
+  }[]
+  selectList?: { label: string, value: any }[] | [],
+  rows?:number,
+  tips?:String,
+}
+
+const props = defineProps({
+    width:{
+      required:false,
+    },
+    visible:{
+        type:Boolean,
+        required:true
+    },
+    title:{
+        type:String,
+        required:true
+    },
+    formItemList:{
+        type:Array<formItemProperty>,
+        default:()=>[]
+    },
+    submitLoading:{
+      type:Boolean,
+      default:false,
+      required:true
+    },
+    formLoading:{
+      type:Boolean,
+      default:false
+    },
+    defaultFormData:{
+      type:Object,
+      required:true,
+      // default:()=>{}
+    },
+    formDisabled:{
+      type:Boolean,
+      default:false
+    },
+    fileLoading:{
+      type:Boolean,
+      default:false
+    },
+    disabledConfirm:{
+        type:Boolean,
+        default:false
+    }
+})
+const emit  = defineEmits(['close','confirm','formItemChange','fileUpload','abortFile'])
+
+const fileMessage = ref({})
+const formData = ref({})
+const formRef = ref()
+
+const finalFormItemList = computed(()=>{
+    return props.formItemList.filter(item=>!item.hidden)
+})
+
+const HandleFileAbort = ()=>{
+  emit('abortFile')
+}
+
+
+// 是否全选
+
+watch(()=>props.defaultFormData,(newVal)=>{
+  formData.value = newVal
+},{immediate:true})
+
+const formSubmitCheck = async (formEl) => {
+  if (!formEl) return
+  await formEl.validate(async(valid) => {
+    if (valid) {
+      emit('confirm', {formData:formData.value,formRef:formEl})
+    }
+  }).catch(err=>{
+    console.log('报错信息',err)
+  })
+}
+
+const HandlePreviewFile = (file)=>{
+  console.log('附件信息',file)
+  previewVisible.value = true
+  fileMessage.value  = {url:file.url,name:file.name}
+}
+
+const closeDialog = () => {
+  formRef.value.resetFields()
+  emit('close')
+}
+
+const HandClosePreview = ()=>{
+  fileMessage.value = {}
+  previewVisible.value = false
+}
+
+const handleSelectChange = (key,val,type,selectList,subKey) =>{
+  if(type == 'unionSelect'){
+    if(formData.value[key]){
+      formData.value[key][subKey] = val
+    }else{
+      formData.value[key] = {}
+      formData.value[key][subKey] = val
+    }
+  }
+  emit('formItemChange',{key,val,formData:formData.value,subKey})
+}
+
+const handleCheckAllOrNot = (val,key,allData)=>{
+  let allValue = allData.map(item=>item.value)
+  let finalVal = val ? allValue : [] 
+  formData.value = {...formData.value,[key]:finalVal}
+  // 选项----
+  emit('formItemChange',{key,val:finalVal,formData:formData.value})
+}
+
+const handleFileChange = (file,formItem)=>{
+  console.log('文件上传前获取到的参数',file)
+  // 在此处校验上传的文件格式
+  let suffix = file.name.split('.').pop()
+  if(formItem?.acceptType){
+    if(formItem?.acceptType?.includes(suffix)){
+      emit('fileUpload',{key:formItem.key,file})
+    }else{
+      ElMessage({
+        message: `文件支持以 ${(formItem.acceptType)?.join('、')} 为后缀结尾的文件`,
+        type: 'error',
+        duration: 5 * 1000
+      })
+    }
+  }else{
+      emit('fileUpload',{key:formItem.key,file})
+  }
+}
+
+const HandleRemove = (formKey)=>{
+  formData.value[formKey] = null
+}
+
+const HandleRemoveSingleImg = (formKey,aimFile) =>{
+  formData.value[formKey] = {
+    ...formData.value[formKey],
+    files:formData.value[formKey].files.filter(item=>{
+      return item !== aimFile
+    })
+  }
+  // formData.value[formKey].filter(item=>{
+  //   return item !== aimFile
+  // })
+}
+
+const imgVisible = ref(false)
+const dialogImageUrl = ref('')
+const HandleImgPreview = (url)=>{
+  imgVisible.value = true
+  dialogImageUrl.value = url
+}
+const HandleFileDownload = (url)=>{
+  let link = document.createElement('a')
+  link.href = url
+  link.download = url
+  link.style.display = 'none';
+  document.body.appendChild(link)
+  link.click();
+  document.body.removeChild(link)
+}
+
+const HandleFilePreview = (params)=>{
+  previewVisible.value = true
+  fileMessage.value = params
+}
+</script>  
+<style lang="scss" scoped>
+.img_file_area{
+  width: 100%;
+  display: flex;
+  gap:10px;
+  align-items: center;
+
+  >span{
+    position: relative;
+    .close{
+      width: 14px;
+      height: 14px;
+      color: #F56C6C;
+      position:absolute;
+      top:-5px;
+      right: -2px;
+    }
+  }
+
+  .cover,
+  .operation_area{
+    width: 90px;
+    height: 60px;
+    border-radius: 6px;
+    background-color: #f0f4f8;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .operation_area1{
+    width: 200px;
+    height: 117px;
+    color:#CCCED4;
+    font-size: 14px;
+
+    border-radius: 6px;
+    background-color: #f0f4f8;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+  }
+
+  .operation_area{
+    background-color: #F0F4F8;
+    font-size: 24px;
+  }
+}
+
+.img_file_area1{
+  width: 100%;
+  display: flex;
+  gap:10px;
+  align-items: center;
+  flex-wrap: wrap;
+
+  >span{
+    position: relative;
+    .close{
+      width: 14px;
+      height: 14px;
+      color: #F56C6C;
+      position:absolute;
+      top:-5px;
+      right: -2px;
+    }
+  }
+  .cover,
+  .operation_area{
+    width: 200px;
+    height: 117px;
+    color:#CCCED4;
+    font-size: 14px;
+    border-radius: 6px;
+    background-color: #f0f4f8;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .cover{
+    border:solid #CED1D8 1px
+  }
+
+  .operation_area{
+    background-color: #FAFBFF;
+    display: flex;
+    flex-direction: column;
+    border:dashed #CCCED4 1px;
+    gap:8px;
+    .icon{
+      font-size: 40px;
+    }
+  }
+
+  .img_file{
+    position: relative;
+
+    .operation_btn{
+      display: none;
+      justify-content: center;
+      align-items: center;
+      gap:10px;
+
+      background-color:rgba(0, 0, 0,0.1);
+      position: absolute;
+      width: 100%;
+      height: 100%;
+      top:0px;
+      left:0px;
+
+      .delete,
+      .preview{
+        line-height: 1;
+        padding:8px 20px;
+        background-color: white;
+        border-radius: 4px;
+        cursor: pointer;
+      }
+      
+      .delete{
+        color:#F56C6C;
+      }
+      .preview{
+        color:#2E64FA;
+      }
+    }
+
+    &:hover{
+      .operation_btn{
+        display:flex;
+      }
+    }
+  }
+}
+
+.file_show_list{
+  width: 100%;
+  display: flex;
+  gap:10px;
+  align-items: flex-start;
+  flex-wrap: now-wrap;
+  >span{
+    position: relative;
+    .close{
+      width: 14px;
+      height: 14px;
+      color: #F56C6C;
+      position:absolute;
+      top:-5px;
+      right: -2px;
+    }
+  }
+  .operation_area{
+    width: 200px;
+    height: 80px;
+    color:#CCCED4;
+    font-size: 14px;
+    border-radius: 6px;
+    background-color: #f0f4f8;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #FAFBFF;
+    display: flex;
+    flex-direction: column;
+    border:dashed #CCCED4 1px;
+    gap:8px;
+    .icon{
+      font-size: 24px;
+    }
+  }
+  .img_file{
+    position: relative;
+   
+  }
+  .file_list{
+    max-width: calc(100% -  200px - 10px);
+    flex:1 1;
+    display: flex;
+    flex-direction: column;
+    gap:20px;
+
+    .file_desc{
+      display: flex;
+      align-items: center;
+      gap:10px;
+      height: 80px;
+      width: 100%;
+      
+      border:solid #EBEEF5 1px;
+      border-radius: 10px;
+      padding:20px;
+      line-height: 1.5;
+      .icon{
+        width: 40px;
+        height: 40px;
+        vertical-align: middle;
+      }
+
+      .file_msg{
+        max-width: calc(100% - 40px - 20px - 117px);
+        flex-grow: auto;
+        flex-shrink: 0;
+        display: flex;
+        flex-direction: column;
+        gap:4px;
+        .name{
+          font-weight: 600;
+          font-size: 14px;
+          color: #333333;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          cursor: pointer;
+        }
+        .size{
+          font-size: 12px;
+          color: #999999;
+          display: flex;
+          gap:10px;
+        }
+      }
+      .table_row_option{
+        justify-content: flex-end;
+      }
+    }
+  }
+}
+
+
+
+
+.multipleSelect{
+  :deep(.el-select__wrapper){
+     height: auto;
+  }
+}
+
+.upload-demo{
+  width: 100%;
+
+  .right_tips{
+    margin-top: 0px;
+  }
+
+  .file_list{
+    // 拖拽
+    width: 80%;
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    gap:5px;
+
+    .el-upload__tip{
+      flex:1 1;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      margin-top: 0;
+      // 拖拽
+      background-color: white;
+      padding:0 8px;
+      > a{
+        color: #666;
+      }
+      > img{
+        width: 15px;
+      }
+    }
+
+    .hjx-dui {
+      color: #2dab85;
+      font-size: 16px;
+    }
+  }
+  .el-button{
+    padding:0 10px !important;
+    background-color: #2e64fa;
+    &.is-disabled{
+      background-color: #cfd2d4;
+      border:none;
+      color: white;
+      cursor: not-allowed;
+    }
+  }
+
+ 
+
+  .no_drag_content{
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    gap: 10px;
+    align-items: flex-start;
+    .file_list{
+      width: 100%;
+      background-color: #F5F7FC;
+      .el-upload__tip{
+        background-color: transparent;
+      }
+    }
+  }
+
+  :deep(.el-upload-dragger){
+    background-color: #f0f4f7;
+    border:dashed #9a9c9e 1px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    gap: 10px;
+    .no_data{
+      width: 60px;
+    }
+  }
+}
+
+
+.check_group_btn_list,
+.check_group_list{
+  width: 100%;
+}
+
+.check_group_btn_list{
+  display: flex;
+  flex-wrap: wrap;
+  gap:20px;
+
+  :deep(.el-checkbox-button){
+    .el-checkbox-button__inner{
+      border-radius: 4px;
+      border:solid #dcdfe6 1px;
+      &:hover {
+        color: #666666;
+      }
+    }
+    &.is-focus{
+      .el-checkbox-button__inner{
+        border:solid #dcdfe6 1px;
+      }
+    }
+    &.is-checked{
+      .el-checkbox-button__inner{
+        background: #2E64FA;
+        border: 1px solid  #2E64FA;
+        color: #fff;
+        &:hover {
+          background: #2E64FA;
+        }
+      }
+    }
+  }
+}
+
+
+
+.delete_img{
+  width: 96px;
+  height: 36px !important;
+  font-weight: 400;
+  font-size: 14px;
+  text-align: center;
+  cursor: pointer;
+}
+
+.iconfont {
+  margin-right: 5px;
+
+  &.hjx-a-Folder-uploadwenjianjia-shangchuan{
+    color: #999999;
+    font-size: 24px;
+  }
+}
+
+.page_dialog{
+  :deep(.el-dialog) {
+    margin: calc(min(50px,5vh)) auto calc(min(50px,5vh));
+  }
+  :deep(.el-dialog__body){
+    min-height: 156px;
+    max-height: calc(90vh - 48px - 66px);
+    display: flex;
+    flex-direction: column;
+    justify-content: flex-start;
+    overflow: auto;
+    .el-date-editor--date.el-input{
+      width: 100%;
+      border:none;
+    }
+  }
+
+  a{
+    &:hover{
+      cursor: pointer;
+    }
+  }
+
+  .el-form-item{
+    :deep(.el-form-item__content){
+      .el-date-editor.is-disabled{
+        .el-input__icon,
+        .el-range-separator{
+          color: #333;
+        }
+      }
+      .el-range-input[disabled]{
+        color: #333;
+      }
+      .readonly_input{
+        .el-input__wrapper{
+          background-color: #f5f7fa;
+          &:hover{
+            box-shadow: none;
+            border:solid #dcdfe6  1px;
+            cursor: not-allowed;
+          }   
+          .el-input__inner[readonly]{
+            color: #333;
+            &:hover{
+              cursor: not-allowed;
+            }
+          }
+        }
+      }
+    }
+  }
+
+}
+
+.footer_bottom{
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+
+</style>
+
+<style lang="scss">
+//部分标签顶部对齐
+.top_label{
+  .el-form-item__label-wrap{
+    // border:solid red 1px;
+    align-self: flex-start;
+  }
+}
+
+
+</style>

+ 171 - 0
src/baseComponents/FormSearchGroup.vue

@@ -0,0 +1,171 @@
+
+<!-- 需要配合 page_search   search_content    content_left  一起使用 -->
+ 
+<template>
+    <div class="simple_filter">
+        <template v-for="item in props.searchList" :key="item.key">
+            <el-select 
+                v-if="item.type == 'select' && !item.hidden" 
+                v-model="searchData[item.key]" 
+                @change="(val)=>HandleSearchItemChange(item.key)" 
+                :placeholder="item.placeholder"  
+                :disabled="formDisabled || item.disabled"
+            >
+                <el-option 
+                    v-for="optItm in item.options" 
+                    :key="optItm.value" :value="optItm.value" 
+                    :label="optItm.label" 
+                    :disabled="optItm.disabled ? true : false">
+                </el-option>
+            </el-select>
+
+
+
+            <!-- :size="size" -->
+            <el-date-picker
+                @change="(val)=>HandleSearchItemChange(item.key)" 
+                v-else-if="item.type == 'datePicker'"  
+                v-model="searchData[item.key]"
+                :disabeld="formDisabled || item.disabled"
+                type="daterange"
+                range-separator="-"
+                start-placeholder="开始时间"
+                end-placeholder="结束时间"
+            />
+
+
+
+            <!-- 这个输入框的搜索要动态查询 ————  -->
+            <el-input 
+                v-else-if="item.type == 'input'"  
+                v-model="searchData[item.key]" 
+
+                @input="(val,e)=>HandleInputChange(val,e,item.key)"
+
+                @keyup.enter="(event)=>HandleSearchItemChange(item.key)" 
+                :placeholder="item.placeholder"  
+                :disabled="formDisabled || item.disabled"
+            >
+                <template #append>
+                    <el-button @click="HandleSearchItemChange(item.key)" :icon="Search" />
+                </template> 
+            </el-input>
+
+
+            <el-radio-group
+                v-else-if="item.type == 'radio'" 
+                v-model="searchData[item.key]" 
+                @change="()=>HandleSearchItemChange(item.key)"
+                :disabled="formDisabled || item.disabled"
+            >
+                <el-radio v-for="radioItem in item.options" :key="radioItem.value" :value="radioItem.value">{{ radioItem.label }}</el-radio>
+            </el-radio-group>
+
+        </template>
+    </div>
+</template>
+
+<script setup lang="ts">
+import { Search } from '@element-plus/icons-vue'
+
+import { ref, watch } from 'vue'
+
+interface SearchItem {
+    key:String,
+    type:'input'|'select'|'datePicker'|'radio',
+    placeholder?:String,
+    hidden:boolean,
+    defaultValue?:any,
+    disabled?:Boolean
+    options?:{
+        label:String,
+        value:String,
+        disabled?:Boolean
+    }[] 
+}
+
+const props = defineProps({
+    searchList:{
+        type:Array<SearchItem>,
+        required:true
+    },
+    formDisabled:{
+        type:Boolean,
+        required:false
+    }
+})
+
+const emit = defineEmits(['searchChange'])
+
+const searchData = ref({})
+
+
+// 筛选条件变更触发新的查询 
+const HandleSearchItemChange = async (key)=>{
+    //   触发父级页面的查询
+    emit('searchChange',searchData.value,key)
+}
+
+const inputFlag = ref() 
+
+const HandleInputChange = (val,e,key)=>{
+    if(inputFlag.value){
+        // 还在定时器内,延迟触发
+        clearTimeout(inputFlag.value)
+        inputFlag.value = ''
+    }
+    // 要防抖
+    inputFlag.value = setTimeout(()=>{
+        console.log('input__输入的值',val)
+        //   触发父级页面的查询
+        emit('searchChange',searchData.value,key)
+    },400)
+}
+
+
+// 
+watch(()=>props.searchList, (newVal)=>{
+    searchData.value = {}
+    // console.log('查询项变更了===表单',newVal)
+    newVal.forEach(item=>{
+        if(item.defaultValue){
+            searchData.value[item.key] = item.defaultValue
+        }
+    })
+    // emit('searchChange',searchData.value)
+},{immediate:true,deep:true})
+
+</script>
+
+
+<style lang="scss" scoped>
+.simple_filter {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+
+  :deep(.el-date-editor){
+    max-width: 240px;
+  }
+  
+  :deep(.el-input){
+    width: 260px;
+  }
+
+  :deep(.el-radio-group){
+    .el-radio{
+        margin-right: 20px;
+    }
+  }
+
+}
+
+
+.page_search .search_content .content_right{
+    .el-button {
+        margin-left: -20px !important;
+        min-width: auto !important;
+    }
+}
+    
+</style>

+ 272 - 0
src/baseComponents/HeaderSmallBgComponent.vue

@@ -0,0 +1,272 @@
+<template>
+    <div :class="{'user_item':true,[iconTheme?.class]:true }">
+      <div class="comp_left">
+        <div :class="['title',{'left_border':!props.smallIcon}]">
+          {{ props.title }}
+        </div>
+        <div :class="['desc',{'subIcon':props.smallIcon}]" >
+          <img  v-if="props.smallIcon" :src="iconTheme?.subIcon" alt=""/>
+          <span >{{ props.num }}</span>
+        </div>
+      </div>
+      <img class="comp_right" :src="iconTheme?.img" alt="">
+    </div>
+</template>
+
+<script setup lang="ts">
+import {computed} from 'vue'
+
+import all_icon from '@/assets/school/all_icon.png';
+import overtime_icon from '@/assets/school/overtime_icon.png';
+import waiting_icon from '@/assets/school/waiting_icon.png';
+import average_icon from '@/assets/school/average_icon.png';
+import finished_icon from '@/assets/school/finished_icon.png';
+import watching_icon from '@/assets/school/watching_icon.png';
+import unfinished_icon from '@/assets/school/unfinished_icon.png';
+
+import total_audit_subicon from '@/assets/school/total_audit_subicon.png'
+import has_audit_subicon from '@/assets/school/has_audit_subicon.png'
+import  wait_audit_subicon from '@/assets/school/wait_audit_subicon.png'
+import reject_audit_subicon from '@/assets/school/reject_audit_subicon.png'
+import average_subicon from '@/assets/school/average_subicon.png'
+
+
+import reject_audit_img from '@/assets/school/reject_audit_icon.png'
+import has_audit_img from '@/assets/school/has_audit_icon.png'
+import wait_audit_img from '@/assets/school/wait_audit_icon.png'
+import total_audit_img from '@/assets/school/total_audit_icon.png'
+import learning_total_img from '@/assets/school/learning_total_icon.png'
+import unwatch_img from '@/assets/school/unwatch_icon.png'
+import has_learned_img from '@/assets/school/has_learned_icon.png'
+
+
+
+const props = defineProps({
+    type:{
+      type:String,
+      required:true,
+      default:'all'
+    },
+     title:{
+        type:String,
+        required:true
+    },
+    num:{
+        type:[Number,String],
+        default:0
+    },
+    cards:{
+      type:Array,
+    },
+    smallIcon:{
+      type:Boolean,
+      required:false
+    }
+})
+
+const iconTheme = computed(()=>{
+    switch(props.type){
+        case 'all':
+            return {
+              class:'all',
+              img:all_icon,
+            };
+        case 'waiting':
+            return {
+              class: 'waiting',
+              img:waiting_icon,
+            };
+        case 'watching':
+          return{
+             class:'waiting',
+              img:watching_icon,
+          }
+        case 'finished':
+        case 'ongoing':
+          return{
+              class:'finished',
+              img:finished_icon,
+          }
+       
+        case 'average':
+          return {
+            class: 'average',
+            img:average_icon,
+            subIcon:average_subicon
+          }
+        case 'overtime':
+            return {
+              class:'overtime',
+              img:overtime_icon,
+            }
+        case 'unfinished':
+            return {
+              class:'overtime',
+              img:unfinished_icon,
+            }
+
+
+        case 'totalAudit':
+            return {
+              class:'all',
+              img:total_audit_img,
+              subIcon:total_audit_subicon
+            }
+
+        case 'learningTotal':
+          return {
+              class:'all',
+              img:learning_total_img,
+              subIcon:total_audit_subicon
+
+          }
+        case 'hasAudit':
+            return {
+              class:'finished',
+              img:has_audit_img,
+              subIcon:has_audit_subicon
+            }
+        case 'hasLearned':
+            return {
+              class:'finished',
+              img:has_learned_img,
+              subIcon:has_audit_subicon
+            }
+        
+        case 'waitAudit':
+            return {
+              class:'waiting_audit',
+              img:wait_audit_img,
+              subIcon:wait_audit_subicon
+            }
+        case 'rejectAudit':
+            return {
+              class:'overtime',
+              img:reject_audit_img,
+              subIcon:reject_audit_subicon
+            }
+        case 'unwatch':
+            return {
+              class:'overtime',
+              img:unwatch_img,
+              subIcon:reject_audit_subicon
+            }
+    }
+})
+</script>
+
+<style lang="scss" scoped>
+
+.user_item {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    flex-grow: 1;
+    height: 94px;
+
+    padding:15px;
+    border-radius: 10px;
+    font-weight: 500;
+    color:#333;
+    background-size:100% 100% ;
+    background-repeat: no-repeat;
+
+    .comp_left{
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+      
+      line-height: 1;
+
+      .title{
+        font-size: 14px;
+        color:#666;
+        &.left_border{
+          padding-left: 10px;
+          border-left-style: solid;
+          border-left-width: 2px;
+        }
+      }
+      .desc {
+        display: flex;
+        align-items: center;
+        font-size: 32px;
+
+        &.subIcon{
+          display: flex;
+          align-items: center;
+          gap: 10px;
+          img{
+            width: 28px;
+            height: 28px;
+          }
+          font-size: 24px;
+        }
+      }
+    }
+
+    .comp_right{
+      align-self: center;
+      height: 80px;
+    }
+
+
+
+    &.all {
+      background-image:url('../assets/school/all_bg.png');
+      .desc{
+        color:#2E64FA;
+      }
+      .left_border{
+        border-left-color: #2E64FA ;
+      }
+    }
+    &.waiting {
+      background-color: #fef1e1;
+      .desc{
+        color:#FB9F34;
+      }
+      .left_border{
+        border-left-color:#FB9F34 ;
+      }
+    }
+    &.waiting_audit {
+      background-image:url('../assets/school/wait_audit_bg.webp');
+      .desc{
+        color:#FAC858;
+      }
+      .left_border{
+        border-left-color:#FAC858 ;
+      }
+    }
+
+    &.finished {
+      background-image:url('../assets/school/finished_bg.png');
+      .desc{
+        color:#3BA272;
+      }
+      .left_border{
+        border-left-color: #3BA272 ;
+      }
+    }
+    
+    &.average {
+      background-image:url('../assets/school/average_bg.png');
+      .desc{
+        color:#995FB3;
+      }
+      .left_border{
+        border-left-color: #995FB3 ;
+      }
+    }
+    &.overtime {
+      background-image:url('../assets/school/overtime_bg.png');
+      .desc{
+        color:#EE6666;
+      }
+      .left_border{
+        border-left-color: #EE6666 ;
+      }
+    }
+  }
+</style>

+ 72 - 0
src/baseComponents/HeaderSmallTips.vue

@@ -0,0 +1,72 @@
+<template>
+    <div class="self_alert_tips" style="flex-shrink: 0;" v-if="visible">
+        <div class="msg">
+            <i class="hjx-dui iconfont"></i>
+            <div  class="tips_title">
+                <template v-for="(item,index) in props.messageTipList" :key="item.title">
+                {{item.title}}{{item.colon === false ? '' : ':'}} {{item.num}}{{ item.unit }}
+                {{ index ==( props.messageTipList.length - 1) ? `` : `&nbsp; &nbsp; &nbsp;` }}
+                </template>
+            </div>
+        </div>
+         <i @click="visible = false" class="hjx-guanbi iconfont"></i>
+    </div>
+</template>
+
+<script lang="ts" setup>
+import {ref} from 'vue'
+
+interface messageItem {
+    title:string,
+    unit:string,
+    num:string,
+    colon?:Boolean
+
+}
+
+const props = defineProps({
+    messageTipList:{
+        required:true,
+        type:Array<messageItem>,
+        default:()=>[]
+    }
+})
+
+const visible = ref(true)
+
+
+</script>
+
+
+<style lang="scss" scoped>
+.hjx-dui{
+    color: #FB9F34;
+}
+.hjx-guanbi{
+    color: #F1DABF;
+    &:hover{
+        cursor: pointer;
+    }
+}
+
+.self_alert_tips{
+    border:solid rgba(251, 159, 52,0.1) 1px;
+    border-radius: 4px;
+    padding: 10px 12px;
+    background-color: #fff6eb;
+    font-size: 14px;
+
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .msg{
+        display: flex;  
+        align-items: center;
+        gap: 10px;
+        .tips_title{
+            color:#666666;
+        }
+    }
+}
+</style>

+ 901 - 0
src/baseComponents/MultipleBarCharts.vue

@@ -0,0 +1,901 @@
+<template>
+    <div ref="bar_echart"  class="chart_width" :style="{height: `${height}px`}">
+
+    </div>
+</template>
+<script>
+import _ from 'lodash'
+import * as echarts from 'echarts'; 
+
+  export default{
+
+    name: "barChart",//单个柱状图组件
+    data(){
+      return {
+        echart:null,//图标实例
+        colorList:[],//       
+        // datax:[1,2,3,4,5,6,7],//x轴数据
+        // datay:[50, 60, 70, 80, 70, 70, 100],//y轴数据
+        // color:'#5470C6'
+      }
+    },
+
+    props:{
+      datax:{
+        type:Array,
+        default:function(){
+          return [];
+        }
+      },//x轴数据
+      datay:{
+        type:Array,
+        default:()=>[]
+      },//y轴数据
+      color:{
+        type:String,
+        default:function(){
+          return '#5470C6';
+        }
+      },//柱状图颜色
+      height:{
+        type:Number,
+        default:380
+      },
+      unit:{
+        type:String,
+        default:'%'
+      },//单位  默认%
+
+      showNuitY:{
+        type:Boolean,
+        default:true
+      },//y轴单位是否显示
+
+      showSplitArea:{
+        type:Boolean,
+        default:false
+      },//y轴单位是否显示
+
+      showTooltip:{
+        type:Boolean,
+        default:true
+      },//是否显示浮窗
+
+      tooltipData:{
+        type:Array,
+        default:()=>[],
+      },//悬浮弹窗的数据
+
+      tooltipFormater:{
+        type:Function,
+      },
+      
+      typeName:{
+        type:String,
+        default:''
+      },//标题
+
+      average:{
+        type:[String, Number,Array],
+        default:'0'
+      },//平均分辅助线
+      markLineData:{
+        type:Array,
+        default:()=>[]
+      },//平均分辅助线
+      isShowMarkLine:{
+        type:Boolean,
+        default:true
+      },//是否显示辅助线
+
+      showMarkPoint:{
+        type:Boolean,
+        default:false
+      },//是否显示气泡  默认不显示气泡
+
+      isClick:{
+        type:Boolean,
+        default:false
+      },//是否需要可以点击柱子事件
+      answerValue:{
+        type:String,
+        default:''
+      },//正确答案  与其他柱子显示颜色不同
+      unitX:{
+        type:String,
+        default:''
+      },//x轴单位
+      fullMark:{
+        type:[String,Number],
+        default:''
+      },//满分
+      gridLeft:{
+        type:Number,
+        default:40
+      },
+      gridRight:{
+        type:Number,
+        default:60
+      },
+      gridTop:{
+        type:Number,
+        default:20
+      },
+      fontSize:{//字体大小
+        type:[Number,String],
+        default:''
+      },
+      fontColor:{
+        type:String,
+        default:''
+      },
+      showDataZoom:{//是否显示滚动条
+        type:Boolean,
+        default:true
+      },
+      barMaxWidth:{
+        type:Number,
+        default:50
+      },
+      barMinWidth:{
+        type:Number,
+        default:20
+      }
+    },
+    watch:{
+        datay:{
+            handler:'LoadEchart',
+            deep:true,
+        },//数值变化时重新加载图表
+        markLineData:{
+            handler:'LoadEchart',
+            deep:true,
+        },//数值变化时重新加载图表
+    },
+    computed:{
+        getCompareAnalysis(){
+            return this.$global.getCompareAnalysis()
+        },
+    },
+    created(){
+        window.addEventListener('resize', this.handleResize);//创建时增加监听窗口变化事件
+    },
+    beforeDestroy() {
+        // 组件销毁移除监听 防止内存泄漏
+        window.removeEventListener('resize', this.handleResize);
+    },
+    mounted(){
+      this.LoadEchart();//初始化图表
+    },
+    methods:{
+        //加载echarts
+        LoadEchart() 
+        {
+            
+            if(this.echart)
+            {
+                this.echart.dispose(); // 销毁之前的实例
+            }
+            // 定义每个柱子的颜色
+
+            const colors = [];
+            const xColors=[];
+            // console.log("打印x轴数据",this.datax);
+            const rightAnswerValue = this.answerValue || '';//正确答案
+            for (let i = 0; i < this.datax.length; i++) {
+                if(this.color){
+                    colors.push(this.color);
+                }else{
+                    const colorArr= this.$global.getScorePerformanceAnalysis()
+                    colors.push(colorArr[i]);
+                }
+                xColors.push('#666666');
+            }
+
+            // 初始化 xAxisLabels 数组
+            // this.xAxisLabels = this.datax.map((label, index) => ({
+            //     value: label,
+            //     textStyle: {
+            //         color: xColors[index],
+            //         fontSize: 14
+            //     }
+            // }));
+            const markPointColor=this.color;
+            //devicePixelRatio: 2  2表示每个逻辑像素对应 2个物理像素。这会进一步提高图表的清晰度,适用于更高分辨率的屏幕  解决高分辨率显示器文字模糊的问题
+            this.echart=echarts.init(this.$refs.bar_echart,{devicePixelRatio: 2});//获取echarts容器  如果组件同一个页面多处使用 这里不能用id获取实例
+            // 图表宽度
+            let totalWidth = this.$refs.bar_echart.clientWidth;
+            // console.log(totalWidth, '>>>>>>>>>>>totalWidth')
+            //计算每个柱的宽度 (图表宽度-左右边距)/ x轴数据长度
+            let singleSeriesWidth = Math.ceil((totalWidth - 140) / this.datax.length);
+            // console.log(singleSeriesWidth, '>>>>>>>>>>>singleSeriesWidth')
+
+            const unit = this.unit;
+            // console.log("打印datax", this.datax);
+            // console.log("打印datay", this.datay);
+
+            //计算最大值和最小值
+            const datay = this.datay.filter(num => !isNaN(num))
+            const maxValue=Math.max(...datay);
+            const minValue=Math.min(...datay);
+            let average = 0, markLineData = [],maxAverage = [];
+            if(Object.prototype.toString.call(this.average) === '[object Array]'){
+                average = this.average;
+                this.average.forEach(item=>{
+                    const itemAverage = parseFloat(item) || 0
+                    if(item > 0) {
+                        markLineData.push({symbol:'circle',type: 'value', name: '', yAxis: itemAverage})
+                    }
+                })
+                maxAverage = average.length ? Math.max(...average) : 0;
+            }else if(this.markLineData && this.markLineData.length){
+                average = [];
+                this.markLineData.forEach((item,index)=>{
+                    const itemAverage = parseFloat(item.value) || 0
+                    average.push(itemAverage)
+                    if(item.isShow){
+                        markLineData.push({symbol:'circle',type: 'value', name: '', yAxis: itemAverage,lineStyle: {color: this.getCompareAnalysis[index]},label:{color:this.getCompareAnalysis[index]}})
+                    }
+                })
+                maxAverage = average.length ? Math.max(...average) : 0;
+            }else{
+                average=parseFloat(this.average) || 0;
+                maxAverage = parseFloat(this.average) || 0;
+                markLineData = average!=0?[{symbol:'circle',type: 'value', name: '', yAxis: average}]:[];
+            }
+            
+            // console.log("打印最大值", maxValue);
+            // console.log("打印最小值", minValue);
+            // console.log("打印平均分", average);
+            const nearestValue = this.GetMaxValue(maxValue);//向上取整为最接近10的数字
+            // console.log("打印最大值的",nearestValue)
+            let yAxisUnit=this.showNuitY && this.unit == '%' ? this.unit : '';
+            let splitArea=this.showSplitArea?{ "show": true, areaStyle: {"color": ["#fafafa", "#ffffff"]}}:{}
+            // 交替颜色
+            const typeName=this.typeName || "";
+            const fullMark = this.fullMark;
+            // console.log("打印正确答案的",rightAnswerValue);
+            // console.log("打印满分",fullMark);
+
+            const barMinWidth = 30; // 最小柱子宽度 加上两边间距的宽度
+            const dataZoomNum = Math.floor((totalWidth - 140) / (barMinWidth * 1));// 当前区域内可显示的柱子的数量
+            const dataZoomEnd = Math.floor((100 / this.datax.length) * dataZoomNum); // 当前区域内可显示柱子的占比
+            let dataZoom = {
+                start: 0, //默认为0
+                end: dataZoomEnd, //  默认为100(重点)
+                type: 'slider',
+                show: true,
+                // borderColor: 'red', // 滑动条边框颜色
+                borderColor: 'transparent',// 滑动条背景颜色
+                borderCap: 'round',
+                xAxisIndex: [0],
+                height: 8, //组件高度
+                left: 20, //左边的距离
+                right: 20, //右边的距离
+                bottom: 0, //右边的距离
+                fillerColor: 'transparent',// 滑动条选中区域颜色
+                zoomLock: true,//是否锁定选择区域(或叫做数据窗口)的大小。
+                handleSize: '0',
+                handleStyle: {
+                    color: '#b8b8b8',// 滑动条手柄颜色
+                    borderWidth: 2
+                },
+                backgroundColor: 'transparent', //两边未选中的滑动条区域的颜色
+                showDataShadow: false, //是否显示数据阴影 默认auto
+                showDetail: false, //即拖拽时候是否显示详细数值信息 默认true
+                filterMode: 'filter'
+
+            };//设置滚动条的样式
+          //网格线设置隔行背景色
+            let option= {
+                tooltip: {
+                    // trigger: 'axis',
+                    // axisPointer: {
+                    //     type: 'cross',
+                    //     crossStyle: {
+                    //         color: '#999'
+                    //     }
+                    // },
+                    show: this.showTooltip,
+                    trigger: this.showTooltip?'item':'axis',
+                    triggerOn: "mousemove",
+                    renderModel:'html',//使用html渲染模式
+                    confine:true,//是否将 tooltip 框限制在图表的区域内。
+                    // extraCssText: 'border-radius: 4px;padding:5px 0px 5px 5px;white-space:normal;word-warp:break-word;max-width: 400px;', // 设置最大宽度和高度
+                    borderColor: "#fff",
+
+                    formatter:this.tooltipFormater ? this.tooltipFormater : function (params) {
+                        const {name,seriesName,value,marker} = params
+                        return name + '<br/>' + marker + seriesName + `<span style=\"margin-left:10px;\">${value}</span>` ;
+                    },
+
+                    /*
+                    formatter: (params)=>{
+                        let tooltip=`<div class='tooltip_content'>`;
+                        let title=params?.name || params[0]?.name;
+                        let value=params?.value || params[0]?.value;//得分率
+                        let unit=this.unit;
+                        tooltip += `<div class='tooltip_title'>${title}</div>`;
+                        tooltip += `<div class='tooltip_student'>${typeName}:${value}${unit}</div>`;
+                        // console.log("打印this.tooltipData",this.tooltipData);
+                        if(this.tooltipData.length>0)
+                        {
+                            let list=this.tooltipData[params[0].dataIndex].list;
+                      
+                            for(let i=0;i<list.length;i++)
+                            {
+                                let item = list[i];
+                                tooltip += `<div class='tooltip_student'>${item.name}:${item.value}</div>`;
+                            }
+                        }
+                        tooltip+=`</div>`;
+                        return tooltip;
+                    }
+                    */
+                },
+                // graphic:{
+                //     id: 'highlight-box',
+                //     type: 'rect',
+                //     shape: {
+                //         x: 2, // 根据需要调整X坐标
+                //         y: 60,
+                //         width: 100, // 根据需要调整宽度
+                //         height: containerHeight,  // 高度为图表的高度
+                //     },
+                //     style: {
+                //         fill:'red' // 设置背景色
+                //     },
+                // },
+               
+                grid: {
+                    left: this.gridLeft,
+                    right: this.gridRight,
+                    top: this.gridTop,
+                    bottom: 0,
+                    containLabel: true, //用于控制网格区域是否包含坐标轴的标签  true 可以确保所有标签都能完整显示,不会被裁剪。
+                },
+                dataZoom: this.showDataZoom ?  (singleSeriesWidth < barMinWidth ?  dataZoom : null) :  null,
+                xAxis: [
+                    {
+                        type: 'category',
+                        data: this.datax,
+
+                        axisPointer: {
+                            show:true,
+                            label:{
+                                show:false
+                            },
+                            type: 'shadow',
+                            shadowStyle:{
+                                color:'rgba(46, 100, 250,0.05)'
+                            },
+                        },
+                        axisLabel: {
+                            interval: 0, // 确保所有刻度标签都显示
+                            fontWeight: 400,
+                            rotate: singleSeriesWidth < 80 ? 45 : 0,
+                            formatter:function(value) {
+                                // console.log(value)
+                                
+                                // 文字大小设置为14px  按14算
+                                const valueWidth = value.length * 14;
+                                // console.log("文字宽度",valueWidth);
+                                // console.log("单系列宽度",singleSeriesWidth);
+                                if(valueWidth > singleSeriesWidth) {
+                                    if (singleSeriesWidth < 100) {
+                                        if(valueWidth > 80) {
+                                            // let maxLength = Math.floor(80 / 14) - 1;
+                                            return value.slice(0, 2) + '...' + value.slice(-3)
+                                        } else {
+                                            return value;
+                                        }
+                                    } else {
+                                        let maxLength = Math.floor(singleSeriesWidth / 14) - 1;
+                                        return value.slice(0, maxLength) + '...';
+                                    }
+                                } else {
+                                    return value;
+                                }
+                            },
+                            color: this.fontColor || '#666666',//y轴文字颜色
+                            // width: 80, // 控制每个标签最大宽度,超出则截断
+                            // overflow: 'truncate', // 超出宽度显示省略号
+                            // ellipsis: '...', // 自定义省略符号
+                            // margin: 20,
+                            fontSize: this.fontSize?this.fontSize:14,
+                            // rich: {
+                            //     // 定义省略样式(可选)
+                            //     text: {
+                            //         whiteSpace: 'nowrap',
+                            //         overflow: 'hidden',
+                            //         textOverflow: 'ellipsis',
+                            //         display: 'inline-block',
+                            //         width: 80, // 与上面 width 一致
+                            //         fontSize:14,
+                            //     },
+                            // },
+                            // formatter: '{text|{value}}' + this.unitX, // 使用 rich 样式渲染
+                        }
+                       
+                    }
+                ],
+                yAxis:{
+                    type: 'value',
+                    // name: '进度(%)',
+                    axisLabel: {
+                        color: this.fontColor || '#666666',//y轴文字颜色
+                        fontSize: this.fontSize?this.fontSize:14,
+                        formatter: '{value}'+yAxisUnit, // 添加 % 符号
+                    },
+                    max: maxAverage > nearestValue ? maxAverage : nearestValue,//固定y轴最高值为最大值的向上取整
+                    // splitNumber: 10, // 设置刻度线分段数
+                    // interval: 0, // 确保所有刻度标签都显示
+                    // splitLine: {
+                    //     show: true,
+                    //         lineStyle: {
+                    //         color: "#E4E7ED",
+                    //         type: "solid",
+                    //     },
+                    //     interval: (index, value) => {
+                    //         // 隐藏最大的刻度线对应的网格线
+                    //         return value !== nearestValue;
+                    //     }
+                    // }, // 横向刻度线样式设置
+                    splitArea: {
+                        show: true,
+                        areaStyle: {
+                            color: ["#fafafa", "#ffffff"], // 交替颜色
+                        },
+                    }, //网格线设置隔行背景色
+                },
+                series: [
+                    {
+                        name: '阅卷进度',
+                        type: 'bar',
+                        // showBackground: true,
+                        
+                        backgroundStyle: {
+
+                            color: 'red'
+                        },//柱子的背景色
+                        // barMinHeight:this.isClick?30:0,//柱子最小高度
+                        barMaxWidth: this.barMaxWidth, // 设置柱状图的最大宽度
+                        barMinWidth: this.barMinWidth,
+                        // barWidth: '44px', // 设置柱状图的宽度,可以是百分比或具体数值
+                        itemStyle: {
+                            color: function(params) {
+                                // console.log(params)
+                                if(params.name == rightAnswerValue || params.name == fullMark){//正确答案 或主观题满分
+                                    return '#3BA272';
+                                }if(params.name == '0'){//主观题0分
+                                    return '#EE6666';//0分显示红色
+                                }else{
+                                    // 使用颜色数组中的颜色
+                                    return colors[params.dataIndex];
+                                }
+                            },
+                            // color: (params) => {
+                            //     const value = params.value;
+                            //     if (value === maxValue) {
+                            //         return 'red'; // 最大值颜色
+                            //     } else if (value === minValue) {
+                            //         return 'green'; // 最小值颜色
+                            //     } else {
+                            //         return 'red'; // 默认颜色
+                            //     }
+                            // },
+                            
+
+                        },
+                        // tooltip: {
+                        //     valueFormatter: function (value) {
+                        //         // console.log(value);
+                        //         return value +  unit;
+                        //     }
+                        // },
+                        // label: { // 显示柱子内部的数值
+                        //     show: true,
+                        //     position: 'top', // 柱子内部显示
+                            
+                        //     formatter: '{c}'+this.unit, // 显示的格式
+                        //     color:'#666666',
+                            
+                        //     fontSize: 14
+                        // },
+                        // emphasis: {
+                        //     itemStyle: {
+                        //         color: '#2E64FA' // 设置选中时的颜色
+                        //     }
+                        // },
+                        data: this.datay.map(value => ({
+                            value: value,
+                            label: {
+                                // show: this.showMarkPoint ? (value === 0 || value === maxValue || value === minValue) : singleSeriesWidth > 26,//数值为0不显示
+                                show: true,//数值为0不显示
+                                position: "top",
+                                fontSize: this.fontSize?this.fontSize:14,
+                                formatter: '{c}'+this.unit, // 显示的格式
+                                color:"#666"
+                                // color: (value == maxValue)? "#3BA272": (value == minValue)? "#EE6666": "#666"
+                            },
+                        })),
+                        markLine: {
+                            // symbol:average==0?['none', 'none']:['circle','arrow'],//设置标记线样式  圆形'circle', 矩形'rect', 圆角矩形'roundRect', 三角形'triangle', 菱形'diamond', 图钉行'pin', 箭头行'arrow', 'none'
+                            symbolSize:[8,8],//设置标记线样式大小 宽高
+                            symbolOffset: [
+                                [0, 0],    // 起始标记偏移
+                                [0, 0]  // 结束标记偏移
+                            ],//偏移量设置
+                            label:{
+                                // formatter: '{b}: {c}',
+                                color:'#F56C6C',
+                                fontSize: this.fontSize?this.fontSize:15,
+                                formatter: '{c}'+this.unit,
+                                position: 'end',//'start', 'middle', 'end', 'insideStartTop', 'insideStartBottom', 'insideMiddleTop', 'insideMiddleBottom', 'insideEndTop', 'insideEndBottom'
+                                // distance:[-10,-40],//标签与线之间的间距。如果是数组,第一项为横向间距,第二项为纵向间距。如果是数字,则表示横向纵向使用相同的间距
+                            },
+                            tooltip: {
+                               formatter:{},
+                            },
+                            data: markLineData,
+                            lineStyle: this?.markLineData?.length?null:{
+                                color: '#F56C6C'
+                            },//辅助线的颜色
+                        
+                        },//辅助线
+                        // markPoint: this.showMarkPoint?{
+                        //     symbolSize:55,//气泡大小
+                        //     data: [
+                        //         {
+                        //             type: "max",
+                        //             name: "最大值",
+                        //             label: { color: "#fff" },
+                        //         },
+                        //         {
+                        //             type: "min",
+                        //             name: "最小值",
+                        //             label: { color: "#fff" },
+                        //         },
+                        //     ],
+                        //     label: {
+                        //         show: true,
+                        //         fontSize:8,
+                        //         formatter: '{c}'+this.unit, // 显示的格式
+                        //     },
+                        //     itemStyle: {
+                        //         color: markPointColor,
+                        //     }
+                        // }:undefined,//是否显示气泡  
+                        markPoint: this.showMarkPoint ? {
+                            data: this.datay.map((value, index) => {
+                                // console.log("index",index);
+                                if (value == maxValue || value == minValue) {
+                                    return {
+                                        name: value == maxValue ? '最大值' : '最小值',
+                                        coord: [this.datax[index], value],
+                                        symbolSize: 65,
+                                        label: {
+                                            show: true,
+                                            position: 'inside',
+                                            color: '#fff',
+                                            formatter: value + this.unit
+                                        },
+                                        itemStyle: {
+                                            color: value === maxValue ?markPointColor : markPointColor
+                                        }
+                                    };
+                                }
+                                return null;
+                            }).filter(item => item !== null), // 过滤掉非 max/min 的 null 值
+                            label: {
+                                show: true,
+                                fontSize: 10,
+                                fontWeight: 'bold',
+                                // formatter: '{c}' + this.unit
+                            }
+                        } : undefined    
+                    },
+                ]
+            };
+            // 设置 rich 样式
+            // this.xAxisLabels.forEach((label, index) => {
+            //     option.xAxis[0].axisLabel.rich[`a${index}`] = label.textStyle;
+            // });
+            this.echart.setOption(option);
+
+            //是否可以点击
+            if(this.isClick)
+            {
+               
+                const xAxisDataLength = this.datax.length;//柱子的数量
+                // 获取grid区域偏移量
+                const gridRect = this.echart.getModel().getComponent('grid').coordinateSystem.getRect();
+                let singleLabelWidth = gridRect.width / xAxisDataLength;//单个x轴系列的宽度
+                if(singleSeriesWidth < barMinWidth)
+                {
+                    singleLabelWidth=barMinWidth;
+                }
+                this.echart.on('click',(params)=>{
+                    // console.log("打印params",params);
+                    if (params.seriesType === 'bar') 
+                    {
+                        
+                        // 更新 xAxisLabels 数组
+                        // this.xAxisLabels = this.datax.map((label, index) => ({
+                        //     value: label,
+                        //     textStyle: {
+                        //         color: index === params.dataIndex ? '#2E64FA' : xColors[index],
+                        //         fontSize: 14
+                        //     }
+                        // }));
+                        // 设置 rich 样式
+                        // this.xAxisLabels.forEach((label, index) => {
+                        //     this.echart.setOption({
+                        //         xAxis: [
+                        //             {
+                        //                 axisLabel: {
+                        //                     rich: {
+                        //                         [`a${index}`]: label.textStyle
+                        //                     }
+                        //                 }
+                        //             }
+                        //         ]
+                        //     });
+                        // });
+                        this.echart.setOption({
+                            series: [
+                                {
+                                    itemStyle: {
+                                        color: function(params) {
+                                            if(params.name == rightAnswerValue || params.name == fullMark){//正确答案
+                                                return '#3BA272';
+                                            }
+                                            else if(params.name == '0'){//主观题0分
+                                                return '#EE6666';//0分显示红色
+                                            }
+                                            else{
+                                                return colors[params.dataIndex];
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        });
+                        
+                        let pixelPosition= this.echart.convertToPixel({ xAxisIndex: 0 }, params.name);
+                        // console.log("pixelPosition",pixelPosition);
+                        this.echart.setOption({
+                            graphic:{
+                                id: 'highlight-box',
+                                type: 'rect',
+                                shape: {
+                                    x: pixelPosition - singleLabelWidth/2, // 根据需要调整X坐标
+                                    y: gridRect.y,//
+                                    width: singleLabelWidth, // 根据需要调整宽度
+                                    height: gridRect.height // 
+                                },
+                                style: {
+                                    fill:params.color+'30' // 设置背景色 柱子颜色的30%
+                                },
+                            },
+                        });
+                        // console.log(params);
+                        let index=params.dataIndex;
+                        let xName=params.name;
+                        this.$emit('HandleChartClick',index,xName);
+                        // 处理点击事件的逻辑
+                        // this.HandleBarClick(paintingId);
+                    }
+                        
+                })
+                let defaultPixelPosition= this.echart.convertToPixel({ xAxisIndex: 0 }, this.datax[0]);
+                this.echart.setOption({
+                    graphic: {
+                        id: "highlight-box",
+                        type: "rect",
+                        shape: {
+                            x: defaultPixelPosition - singleLabelWidth/2, // 根据需要调整X坐标 40 是 left 的偏移量
+                            y: gridRect.y, //20是top的偏移量
+                            width:singleLabelWidth, // 根据需要调整宽度 80是x上面减去的2倍
+                            height: gridRect.height, // 40 是 top 和 bottom 的偏移量
+                        },
+                        style: {
+                            fill: "rgba(84,112,198,0.1)", // 设置背景色
+                        },
+                    },
+                });
+            }
+
+            this.echart.on('dataZoom',(event)=>{
+                console.log('触发渲染了---')
+                 this.echart.setOption(
+                    {
+                        ...option,
+                        dataZoom: this.showDataZoom ? 
+                            (singleSeriesWidth < barMinWidth ? 
+                                {
+                                    ...dataZoom,
+                                    start: event?.batch ? event?.batch[0].start : event?.start,
+                                    end:  event?.batch ? event?.batch[0].end : event?.end,
+
+                                } : 
+                                null) : 
+                            null,
+                    }
+                );
+            })
+        },
+
+        //获取最大值  计算规则  
+        GetMaxValue(value)
+        {
+            const thresholdMap =[
+                {
+                    maxThreshold:0.3,//最大阈值0-0.6
+                    bound:0.3,//边界值
+                },
+                {
+                    maxThreshold:0.6,//最大阈值0-0.6
+                    bound:0.6,//边界值
+                },
+                {
+                    maxThreshold:1,//最大阈值 0.6 - 1
+                    bound:1,//边界值
+                },
+                {
+                    maxThreshold:1.5,//最大阈值 0.6 - 1
+                    bound:1.5,//边界值
+                },
+                {
+                    maxThreshold:2,//最大阈值 
+                    bound:2,//边界值
+                },
+                {
+                    maxThreshold:4,//最大阈值
+                    bound:4,//边界值
+                },
+                {
+                    maxThreshold:8,//最大阈值
+                    bound:8,//边界值
+                },
+                {
+                    maxThreshold:10,//最大阈值
+                    bound:10,//边界值
+                },
+                {
+                    maxThreshold:40,//最大阈值
+                    bound:40,//边界值
+                },
+                {
+                    maxThreshold:50,//最大阈值
+                    bound:50,//边界值
+                },
+                {
+                    maxThreshold:60,//最大阈值
+                    bound:60,//边界值
+                },
+                {
+                    maxThreshold:70,//最大阈值
+                    bound:70,//边界值
+                },
+                {
+                    maxThreshold:80,//最大阈值
+                    bound:80,//边界值
+                },
+                {
+                    maxThreshold:90,//最大阈值
+                    bound:90,//边界值
+                },
+                {
+                    maxThreshold:100,//最大阈值
+                    bound:100,//边界值
+                },
+                {
+                    maxThreshold:120,//最大阈值
+                    bound:120,//边界值
+                },
+                {
+                    maxThreshold:150,//最大阈值
+                    bound:150,//边界值
+                },
+                {
+                    maxThreshold:180,//最大阈值
+                    bound:180,//边界值
+                },
+                {
+                    maxThreshold:200,//最大阈值
+                    bound:200,//边界值
+                },
+                {
+                    maxThreshold:250,//最大阈值
+                    bound:250,//边界值
+                },
+                {
+                    maxThreshold:200,//最大阈值
+                    bound:200,//边界值
+                },
+                {
+                    maxThreshold:300,//最大阈值
+                    bound:300,//边界值
+                },
+                {
+                    maxThreshold:350,//最大阈值
+                    bound:350,//边界值
+                },
+                {
+                    maxThreshold:400,//最大阈值
+                    bound:400,//边界值
+                },
+                {
+                    maxThreshold:450,//最大阈值
+                    bound:450,//边界值
+                },
+                {
+                    maxThreshold:500,//最大阈值
+                    bound:500,//边界值
+                },
+                {
+                    maxThreshold:600,//最大阈值
+                    bound:600,//边界值
+                },
+                {
+                    maxThreshold:700,//最大阈值
+                    bound:700,//边界值
+                },
+            ];//配置区间规则
+            //查找匹配的边界值
+            const matchedRule = thresholdMap.find(({ maxThreshold }) => value == maxThreshold || value < maxThreshold);
+
+            // 处理超过阈值的情况(≥5)
+            const bound = matchedRule 
+            ? matchedRule.bound 
+            : Math.ceil((value) / 10) * 10;
+            return  bound;
+
+        },
+        // 处理点击事件
+        HandleBarClick(paintingId)
+        {
+            // console.log("点击了柱状图",paintingId);
+            this.$emit('HandleBarClick',paintingId);
+        },
+
+
+
+        //更新颜色
+        UpdateColors()
+        {
+            const newColors = ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40', '#FF6384'];
+             // 更新 series 中的 itemStyle.color
+            this.echart.setOption({
+                series: [
+                    {
+                        itemStyle: {
+                            color: function(params) {
+                                return newColors[params.dataIndex];
+                            }
+                        }
+                    }
+                ]
+            });
+        },
+
+        // 监听窗口大小变化,重新计算表格高度 使用节流防止频繁改变窗口大小导致计算量过大而页面卡顿
+        handleResize: _.throttle(function() {
+            
+            this.$nextTick(() => {
+               
+                this.LoadEchart();
+                
+            });
+            
+        }, 500), // 节流 500 毫秒内最多执行一次
+    }
+  }
+  </script>
+<style lang="scss" scoped>
+.chart_width {
+  width: 100%;
+  height: 380px; // 设置图表高度
+}
+</style>

+ 455 - 0
src/baseComponents/PdfViewer/PdfViewer.vue

@@ -0,0 +1,455 @@
+<template>
+  
+  <!-- thumbnailUrls.length &&  -->
+  <div class="pdf-viewer" v-if="props.showPage">
+    <!-- 左侧缩略图 -->
+    <div class="thumbnails" v-if="thumbnailUrls.length && props.showPage">
+      <div
+        v-for="(thumb, index) in thumbnailUrls"
+        :key="index"
+        class="thumbnail-item"
+        :class="{ active: currentPage === index + 1 }"
+        @click="goToPage(index + 1)"
+      >
+        <img :src="thumb" alt="Page thumbnail" />
+        <!-- <span>第 {{ index + 1 }} 页</span> -->
+        <span>{{ index + 1 }}</span>
+      </div>
+    </div>
+
+    <!-- 右侧主预览区 -->
+    <div class="main-preview" >
+      <div class="pdf-container" ref="pdfContainer"></div>
+      <div class="toolbar">
+        <span :class="['pre_nav',{'first':currentPage === 1} ]"  @click="currentPage <= 1 ? '' : prevPage()">
+            <el-icon><ArrowLeftBold /></el-icon>
+        </span>
+        <span :class="['next_nav',{'end':currentPage >= totalPages}]" @click="currentPage >= totalPages ?  '' : nextPage()">
+            <el-icon><ArrowRightBold /></el-icon>
+        </span>
+        <!-- <span>第 {{ currentPage }} / {{ totalPages }} 页</span> -->
+        <!-- <input v-model.number="scale" type="number" min="0.5" max="3" step="0.1" /> 倍 -->
+      </div>
+    </div>
+  </div>
+         
+  <div class="vue_pdf" v-else>
+    <!-- <div class="progress">进度:{{ progressPercent }} %</div> -->
+    <VuePdfEmbed 
+        class="pdf_preview"
+        annotation-layer 
+        :scale="1"
+        text-layer 
+        @rendered="HandlePdfRender"
+        :source="props.pdfUrl"
+        @loaded="HandlePdfLoaded"
+    >
+        <template #after-page="{page}">
+            <span  class="page_index">
+                {{ page }} / {{ totalPages }}  
+            </span>
+        </template>
+    </VuePdfEmbed>
+  </div>
+
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, watch,computed } from 'vue';
+import pdfjsLib from './pdf.js';
+
+
+import VuePdfEmbed from 'vue-pdf-embed'
+// optional styles
+import 'vue-pdf-embed/dist/styles/annotationLayer.css'
+import 'vue-pdf-embed/dist/styles/textLayer.css'
+
+
+
+const props = defineProps({
+  pdfUrl: {
+    type: String,
+    required: true
+  },
+  showPage:{
+    type:Boolean,
+    required:false,
+    default:true
+  },
+  initCourseLearnPage:{
+      type:Number,
+      required:false,
+      default:0
+  }
+
+});
+
+
+const emit = defineEmits(['pageChange'])
+
+// const vuePdfDom = ref()
+// 响应式数据
+const currentPage = ref(1);
+const totalPages = ref(0);
+const scale = ref(1);
+const thumbnailUrls = ref([]);
+const pdfContainer = ref(null);
+let pdfDoc = null;
+
+// 加载 PDF  // 带分页
+async function loadPdf() {
+  try {
+    const loadingTask = pdfjsLib.getDocument(props.pdfUrl);
+    pdfDoc = await loadingTask.promise;
+    totalPages.value = pdfDoc.numPages;
+    let tmp = Math.floor(props.initCourseLearnPage * 0.01 * totalPages.value)
+    currentPage.value = (tmp === 0 ? 1 : tmp)
+    // 生成所有缩略图
+    thumbnailUrls.value = [];
+    for (let i = 1; i <= pdfDoc.numPages; i++) {
+      const thumbUrl = await renderPageToImageUrl(i, 0.2); // 小尺寸缩略图
+      thumbnailUrls.value.push(thumbUrl);
+    }
+
+    // 渲染第一页
+    await renderCurrentPage();
+    //  如果 pdf只有一页,默认进度显示100%,
+    if(totalPages.value <= 1){
+      emit('pageChange',{totalPage:totalPages.value,currentPage:currentPage.value})
+    }
+
+  } catch (error) {
+    console.error('加载 PDF 失败:', error);
+  }
+}
+
+// 渲染指定页为图片 URL(用于缩略图或主视图)
+async function renderPageToImageUrl(pageNum, renderScale) {
+  const page = await pdfDoc.getPage(pageNum);
+  const viewport = page.getViewport({ scale: renderScale });
+  const canvas = document.createElement('canvas');
+  const ctx = canvas.getContext('2d');
+  canvas.height = viewport.height;
+  canvas.width = viewport.width;
+
+  await page.render({
+    canvasContext: ctx,
+    viewport: viewport
+  }).promise;
+
+  return canvas.toDataURL();
+}
+
+// 渲染当前页到主区域
+const renderCurrentPage = async()=> {
+  if (!pdfDoc) return;
+  const container = pdfContainer.value;
+  container.innerHTML = ''; // 清空
+
+  const imageUrl = await renderPageToImageUrl(currentPage.value, scale.value);
+  const img = document.createElement('img');
+  img.src = imageUrl;
+  img.style.maxWidth = '100%';
+  img.style.display = 'block';
+  img.style.margin = '0 auto'
+  container.appendChild(img);
+}
+
+// 翻页
+const  prevPage=()=> {
+  console.log('点击翻页了')
+  if (currentPage.value > 1){
+    currentPage.value--;
+    renderCurrentPage()
+    emit('pageChange',{totalPage:totalPages.value,currentPage:currentPage.value})
+  }
+}
+const nextPage=()=> {
+  console.log('点击翻页了')
+  if (currentPage.value < totalPages.value){
+    currentPage.value++;
+    renderCurrentPage()
+    emit('pageChange',{totalPage:totalPages.value,currentPage:currentPage.value})
+  }
+}
+const goToPage=(page)=> {
+  currentPage.value = page;
+  renderCurrentPage()
+  emit('pageChange',{totalPage:totalPages.value,currentPage:currentPage.value})
+}
+
+
+const timeoutFlag = ref()
+const pageTotalHeight = ref(0)
+const currentReadHeight = ref(0)
+
+const progressPercent = computed(()=>{
+    if(currentReadHeight.value == 0 || pageTotalHeight.value == 0){
+        return 0
+    }
+    return Math.round((currentReadHeight.value / pageTotalHeight.value) * 100)
+})
+
+
+
+// 防抖
+// 不再连续滚动的时候,记录最后一次滚动的位置,
+// 200毫秒内没有再次滚动,就认为用户停止了滚动,此时记录用户的阅读进度
+const HandleScroll = (e)=>{
+  console.log('页面监听滚动')
+    if(timeoutFlag.value){
+      clearTimeout(timeoutFlag.value)
+    }
+    timeoutFlag.value =  setTimeout(() => {
+
+        let totalHeight = e.target.scrollHeight  //总高度
+        let scrollTop = e.target.scrollTop   //滚动高度
+        let pageHeight = e.target.clientHeight // 客户端高度
+
+        // 用户阅读进度  = ( pageHeight + scrollTop ) / totalHeight
+        console.log('滚动事件',e)
+        console.log('滚动高度',scrollTop)
+        console.log('总高度',totalHeight)
+        console.log('客户端高度',pageHeight)
+
+        pageTotalHeight.value = Math.floor(Number(totalHeight)) || 0
+        currentReadHeight.value = Math.floor( Number(pageHeight) + Number(scrollTop) ) || 0
+
+        emit('pageChange',{currentProcess:progressPercent.value})
+        
+        clearTimeout(timeoutFlag.value)
+        timeoutFlag.value = null
+
+    }, 200);
+}
+
+// pdf 的重定向
+const HandlePageRedirect = (dom)=>{
+  // props.initCourseLearnPage
+  // 根据百分比 换算滚动高度
+  let totalHeight = dom.scrollHeight  //总高度
+  let pageHeight = dom.clientHeight // 客户端高度
+
+  let realScroll =  props.initCourseLearnPage * 0.01 * totalHeight - pageHeight
+  let scrollTop =  realScroll  > 0 ? realScroll : 0
+
+  console.log('高度 - / -',pageHeight,totalHeight)
+  console.log('触发滚动了',scrollTop)
+    dom.scrollTo({
+        top: scrollTop,
+        left: 0,
+        behavior: 'smooth'
+    });
+
+  pageTotalHeight.value = Math.floor(Number(totalHeight)) || 0
+  // 用户阅读进度  = ( pageHeight + scrollTop ) / totalHeight
+  currentReadHeight.value = Math.floor( Number(pageHeight) + Number(scrollTop) ) || 0
+  emit('pageChange',{currentProcess:progressPercent.value})
+}
+
+
+
+// 渲染在后
+const HandlePdfRender = ()=>{
+  console.log('pdf渲染完成')
+
+  let vuePdfDom = document.querySelectorAll('.pdf_preview')
+  console.log('dom',vuePdfDom)
+  HandlePageRedirect(vuePdfDom[0])
+}
+// 加载在前
+const HandlePdfLoaded = ({_pdfInfo,_transport})=>{
+    console.log('pdf加载',_pdfInfo)
+    // pdf的总页数
+    totalPages.value = _pdfInfo.numPages
+
+    let vuePdfDom = document.querySelectorAll('.pdf_preview')
+    console.log('dom',vuePdfDom)
+
+    vuePdfDom[0]?.addEventListener('scroll',
+    (e)=>{
+      // emit('pageChange',{currentProcess:`${progressPercent.value}%`})
+
+      HandleScroll(e)
+    },false)
+
+
+
+}
+
+
+// 监听变化
+watch(() => props.pdfUrl, ()=>{
+  if(props.showPage){
+    loadPdf()
+  }
+});
+watch(scale, ()=>{
+  if(props.showPage){
+    renderCurrentPage()
+  }
+});
+
+// 初始化
+onMounted(() => {
+  if(props.showPage){
+    loadPdf();
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+.pdf-viewer {
+  display: flex;
+  background-color: #e8eaee;
+  height: 100%;
+  overflow: auto;
+}
+
+.thumbnails {
+  width: 120px;
+  overflow-y: auto;
+  border-right: 1px solid #eee;
+  padding:20px 0 20px 10px;
+  scrollbar-width:none;
+  &::-webkit-scrollbar {
+    display: none; /* Chrome, Safari, Opera*/
+  }
+    
+  .thumbnail-item {
+    cursor: pointer;
+    margin-bottom: 10px;
+    text-align: center;
+    font-size: 12px;
+    color: #333;
+    position: relative;
+    display: flex;
+
+
+    img {
+      width: 100%;
+      border: 1px solid white;
+      border-radius: 4px;
+    }
+
+    span{
+      position: absolute;
+      bottom: 10px;
+      left: 10px;
+      display: flex; 
+      align-items: center;
+      justify-content: center;
+      width: 20px;
+      height: 20px;
+      background-color:rgba(0, 0, 0,0.2);
+      color: white;
+    }
+
+    &.active {
+      border-radius: 4px;
+      img{
+        border-color: #2E64FA;
+      }
+      span{
+        background-color:rgba(0, 0, 0,0.5);
+      }
+    }
+  }
+}
+
+.main-preview {
+  position: relative;
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+
+    
+  .toolbar {
+    display: flex;
+    justify-content: space-between;
+    position: absolute;
+    width: calc(100% - 100px);
+    bottom:50%;
+    left: calc( 50px);
+
+    .pre_nav,
+    .next_nav{
+        line-height: 1;
+        border-radius: 20px;
+        padding:10px;
+        background-color: #415058;
+        color:white;
+    }
+    .first,
+    .end{
+        background-color: #c3c8d0;
+    }
+  }
+    
+  .pdf-container {
+    position: relative;
+    width: 100%;
+    flex: 1;
+    margin: 0 auto;
+    padding: 20px;
+    overflow: auto;
+  }
+}
+
+
+.page_index{
+  position: absolute;
+  bottom: 50px;
+  display: inline-block;
+  width: 100%;
+  text-align: center;
+}
+
+.vue_pdf{
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  overflow: auto;
+  .progress{
+    z-index: 100;
+    background-color: rgb(241, 235, 235);
+    position: absolute;
+    top:50px;
+    right: 50px;
+  }
+}
+
+.vue-pdf-embed.pdf_preview{
+    width: 100% !important;
+    height: 100% !important;
+    box-sizing: border-box;
+    overflow: auto;
+    > :deep(div){
+      position: relative;
+      overflow: auto;
+      width: 100%;
+
+      .vue-pdf-embed__page{
+        position: relative;
+        overflow: auto;
+        width: 100% !important;
+        height: 100% !important;
+        box-sizing: border-box;
+        padding: 20px;
+        background-color: #e8eaee !important;
+
+        canvas{
+            width: 100% !important;
+            height: 100%;
+            background-color: #e8eaee !important;
+        }
+        .annotationLayer,
+        .textLayer{
+            width: 100% !important;
+            height: 100% !important;
+        }
+      }
+    }
+}
+
+</style>

+ 9 - 0
src/baseComponents/PdfViewer/pdf.js

@@ -0,0 +1,9 @@
+// src/utils/pdfjs.js
+import * as pdfjsLib from 'pdfjs-dist';
+// 设置 worker 路径(根据你的构建工具调整)
+pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
+  'pdfjs-dist/build/pdf.worker.min.mjs',
+  import.meta.url
+).toString();
+
+export default pdfjsLib;

+ 200 - 0
src/baseComponents/PptViewer/PptViewer.vue

@@ -0,0 +1,200 @@
+<template>
+  <div class="vue_ppt" id="vue_ppt" ref="vuePpt">
+     <!-- 上下两地址都能用 ——不稳定 -->
+      <!-- :src="`https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(props?.fileMessage?.url)}`" -->
+      <!-- <iframe
+          class="ppt_iframe"
+          v-else-if="['ppt','pptx'].includes(previewType)"
+          :src="`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(props?.fileMessage?.url)}`"
+          width="100%"
+          height="100%"
+          frameborder="0"
+      ></iframe> -->
+
+    <div  v-if="pptLoading" class="loading_bg">
+        <el-icon class="is-loading">
+            <Loading />
+        </el-icon>
+        加载中
+    </div>
+
+
+  </div>
+</template>
+
+<script setup lang="ts">
+import {init} from 'pptx-preview'
+import { onMounted, ref,computed} from 'vue'
+
+const props = defineProps({
+  fileMessage:{
+    type:{
+      url:String,
+      name:String,
+    }
+  },
+  initCourseLearnPage:{
+      type:Number,
+      required:false,
+      default:0
+  }
+
+})
+
+const emit = defineEmits(['pageChange','fileLoaded'])
+
+const vuePpt =  ref()
+const pptLoading = ref(false)
+
+const pptxPrviewer = ref()
+const timeoutFlag = ref()
+const pageTotalHeight = ref()
+const currentReadHeight = ref()
+
+const progressPercent = computed(()=>{
+    if(currentReadHeight.value == 0 || pageTotalHeight.value == 0){
+        return 0
+    }
+    return Math.round((currentReadHeight.value / pageTotalHeight.value) * 100)
+})
+
+
+// 防抖
+// 不再连续滚动的时候,记录最后一次滚动的位置,
+// 200毫秒内没有再次滚动,就认为用户停止了滚动,此时记录用户的阅读进度
+const HandleScroll = (e)=>{
+  console.log('页面监听滚动',e)
+    if(timeoutFlag.value){
+      clearTimeout(timeoutFlag.value)
+    }
+    timeoutFlag.value =  setTimeout(() => {
+
+        let totalHeight = e.target.scrollHeight  //总高度
+        let scrollTop = e.target.scrollTop   //滚动高度
+        let pageHeight = e.target.clientHeight // 客户端高度
+
+        // 用户阅读进度  = ( pageHeight + scrollTop ) / totalHeight
+        console.log('滚动事件',e)
+        console.log('滚动高度',scrollTop)
+        console.log('总高度',totalHeight)
+        console.log('客户端高度',pageHeight)
+
+        pageTotalHeight.value = Math.floor(Number(totalHeight)) || 0
+        currentReadHeight.value = Math.floor( Number(pageHeight) + Number(scrollTop) ) || 0
+
+        emit('pageChange',{currentProcess:progressPercent.value})
+        
+        clearTimeout(timeoutFlag.value)
+        timeoutFlag.value = null
+    }, 200);
+}
+
+
+const HandlePageRedirect = (dom)=>{
+  console.log('滚动dom',dom)
+  console.log('当前滚动进度--',props.initCourseLearnPage)
+  // props.initCourseLearnPage
+  // 根据百分比 换算滚动高度
+  let totalHeight = dom.scrollHeight  //总高度
+  let pageHeight = dom.clientHeight // 客户端高度
+
+  let realScroll = props.initCourseLearnPage * 0.01 * totalHeight - pageHeight
+  let scrollTop = realScroll > 0 ? realScroll : 0
+
+  console.log('高度 pageHeight / totalHeight',pageHeight,totalHeight)
+  console.log('触发滚动了',scrollTop)
+    dom.scrollTo({
+        top: scrollTop,
+        left: 0,
+        behavior: 'smooth'
+    });
+  
+  pageTotalHeight.value = Math.floor(Number(totalHeight)) || 0
+  // 用户阅读进度  = ( pageHeight + scrollTop ) / totalHeight
+  currentReadHeight.value = Math.floor( Number(pageHeight) + Number(scrollTop) ) || 0
+  emit('pageChange',{currentProcess:progressPercent.value})
+}
+
+
+
+const HandlePptPreview =()=>{
+  pptLoading.value = true
+  //调用库的init方法生成一个预览器
+  pptxPrviewer.value = init(vuePpt.value, {
+      width: (vuePpt.value?.clientWidth * 0.8),
+      // height: 540
+  })
+
+  //获取文件或者读取文件,获取文件的 ArrayBuffer格式数据,传给组件进行预览
+  fetch(props?.fileMessage?.url).then(response=>{
+      return response.arrayBuffer()
+  }).then(res =>{
+    console.log('获取文件完成',res)
+    // 在这里监听文档的滚动
+    let pptDom = document.querySelectorAll('.vue_ppt')
+    console.log('dom',pptDom)
+
+    //调用预览器的preview方法
+    pptxPrviewer.value.preview(res).then(previewRes=>{
+      console.log('转换结果',previewRes)
+      HandlePageRedirect(pptDom[0])
+      pptLoading.value = false
+      emit('fileLoaded')
+
+    }).catch(err=>{
+      // 解析失败
+      pptLoading.value = false
+    })
+
+    pptDom[0]?.addEventListener('scroll',
+      (e)=>{
+        HandleScroll(e)
+      },false)
+      
+  }).catch(err=>{
+    // 获取文件失败
+    pptLoading.value = false
+  })
+}
+
+onMounted(()=>{
+  console.log('加载中')
+  HandlePptPreview()
+})
+
+</script>
+
+<style lang="scss" scoped>
+
+.vue_ppt{
+  display: flex;
+  position: relative;
+  flex-direction: column;
+  align-items: center;
+  justify-content: flex-start;
+  min-height: 100%;
+  overflow: auto;
+  background-color: #e8eaee;
+
+  .loading_bg{
+    width: 100%;
+    flex: 1 1;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    gap:3px;
+    color:#2e64fa;
+  }
+}
+
+
+</style>
+
+<style lang="scss">
+.vue_ppt{
+  .pptx-preview-wrapper{
+    height: auto !important;
+    width: 80% !important;  //主体宽度
+  }
+}
+</style>

+ 189 - 0
src/baseComponents/SearchBlock.vue

@@ -0,0 +1,189 @@
+<template>
+    <div class="page_search" >
+        <ul class=" search_content  ">
+
+            <template  v-for="item in props.searchList" :key="item.key">
+                <!-- v-for="item in props.searchList" :key="item.key" -->
+                <li class="content_left" v-if="!item.hidden">
+                    <template v-if="item.type=='single'">
+                        <span class="label">{{ item.label }}:</span>
+                        <div class="search_option">
+                            <span 
+                                v-for="categoryItem in item.options" 
+                                :key="categoryItem?.value"
+                                @click="HandleBtnSearchItemChange(item.key,categoryItem?.value)"
+                                :class="[{'active':categoryItem?.value == buttonSearchData[item.key]}]"
+                            >
+                                {{ categoryItem?.label }}
+                                <!-- && categoryItem.value == buttonSearchData[item.key] -->
+                                <span v-if="categoryItem?.bubbleVal" class="bubble">{{ categoryItem?.bubbleVal }}</span>
+                            </span>
+                        </div>
+                        <div>   
+                            <slot :name="item.key"></slot>
+                        </div>
+                    </template>
+
+                    <template v-else-if="item.type == 'form'">
+                        <span v-if="item.label" class="label" style="line-height: 36px !important;">{{ item.label }}:</span>
+                        <FormSearchGroup :searchList="item.searchFormItems" @searchChange="(params,key)=>HandleSearchChange(params,key)"/>
+                    </template>
+                </li>
+
+            </template>
+        </ul>
+    </div>
+
+</template>
+
+
+<script lang="ts" setup>
+import { ref, watch } from 'vue'
+import FormSearchGroup from '@/baseComponents/FormSearchGroup.vue';
+
+interface Options {
+    label:String,
+    value:String,
+    bubbleVal?:String,
+}
+interface searchFormItem {
+    key:String,
+    type:'select'|'input' ,
+    placeholder?:String,
+    options?:Options,
+    defaultValue?:String,
+}
+interface SearchBlockItem {
+    label:String,
+    key:String,
+    type:'form' | 'single',
+    searchFormItems?:Array<searchFormItem>,
+    options?:Array<Options>,
+    defaultValue?:String,
+    hidden?:Boolean
+}
+
+const props = defineProps({
+    searchList:{
+        required:true,
+        type:Array<SearchBlockItem>
+    }
+})
+const emit = defineEmits(['searchChange'])
+
+
+const formSearchData = ref({})
+const buttonSearchData = ref({})
+
+const HandleSearchChange = (params,key)=>{
+    formSearchData.value = params
+    emit('searchChange',{...formSearchData.value,...buttonSearchData.value},key)
+}
+
+const HandleBtnSearchItemChange = (key,val)=>{
+    console.log('按钮触发')
+    buttonSearchData.value[key] = val
+    emit('searchChange',{...formSearchData.value,...buttonSearchData.value},key)
+}
+
+
+// 只做初始化,不传递数据,初始数据传递的触发要等子组件触发,
+// 带form表单的要等 子组件触发
+// 不带form表单的要自己触发
+watch(()=>props.searchList,(newVal)=>{
+    // console.log('watch触发')
+    buttonSearchData.value = {}
+    newVal.forEach(item=>{
+        if(item.type == 'single'){
+            if(item.defaultValue || item.defaultValue === 0){
+                buttonSearchData.value[item.key] = item.defaultValue
+            }
+        }
+        // else if(item.type == 'form'){
+        //     // 
+        //     // formSearchData.value[item.key]
+        // }
+    })
+    /*
+    let findRes = newVal.find(item=>item.type == 'form')
+    if(!findRes){
+        // 判断是否有form表单的信息,如果没有,则自己触发
+        emit('searchChange',{...formSearchData.value,...buttonSearchData.value})
+    }
+    */
+},{
+    immediate:true,
+    deep:true,
+})
+
+</script>
+
+<style lang="scss" scoped>
+.search_content{
+    display: flex;
+    flex-direction: column;
+    gap:16px;
+
+    li.content_left{
+        width: 100% !important;
+        display: flex;
+        gap:8px !important;
+        font-size: 14px;
+        align-items: flex-start;
+        line-height: 28px !important;
+
+        :deep(.el-button) img{
+            width: 16px;
+            height: 16px;
+            margin-right: 4px;
+            vertical-align: middle;
+            /* 使图标垂直居中 */
+        }
+
+        .label{
+            font-weight: bold;
+        }
+
+        .search_option{
+            display: flex;
+            gap: 8px;
+            flex-wrap: wrap;
+            flex:1 1;
+            span{
+                position: relative;
+                .bubble{
+                    padding:1px 2px;
+                    background-color: #F56C6C;
+                    border-radius: 50%;
+                    min-width: 20px;
+                    height: 20px;
+                    text-align: center;
+                    font-size: 12px;
+                    color: white;
+                    position: absolute;
+                    top:-4px;
+                }
+                line-height: 20px;
+                padding:4px 8px;
+                font-size: 14px;
+                color:#999;
+                border-radius: 4px;
+                &:hover{
+                    cursor: pointer;
+                }
+                &.active{
+                    background-color: rgba(71, 113, 203,0.1);
+                    color:#2E64FA;
+                }
+            }
+        }
+        .simple_filter{
+            flex:1 1;
+        }
+    }
+  
+   
+}
+
+
+</style>

+ 155 - 0
src/baseComponents/TabSearch.vue

@@ -0,0 +1,155 @@
+<template>
+    <div :class="{'box_tab':props.tabType == 'box','line_tab':props.tabType == 'line'}">
+        <span 
+            v-for="item in props.tabList" 
+            :key="item.key"  
+            :class="{ 
+                      'selected': activedId == item.key, 
+                      'un_selected': activedId !== item.key,
+                      'prefix':item.prefix,
+                      'disabled':disabled
+                    }"
+             @click="disabled ? '' : HandleTabChange(item.key)"
+        >
+            <img v-if="item.prefix" :src="activedId==item.key ? item.prefixLight : item.prefix" alt="" class="prefix" />
+            {{ item.label }}
+            <span  v-if="item.suffix || item.suffix === 0" class="suffix">{{item.suffix}}</span>
+        </span>
+      </div>
+</template>
+
+<script setup lang="ts">
+import { ref, watch} from 'vue';
+
+interface TabItem {
+    label:String,
+    key:String,
+    prefix?:String,
+    prefixLight?:String,
+    suffix?:String,
+}
+
+type TabType = 'box'|'line'
+const props = defineProps({
+    tabList:{
+        required:true,
+        type:Array<TabItem>
+    },
+    tabType:{
+        required:true,
+        type:String
+    },
+    defaultTabKey:{
+        required:true,
+        type:String
+    },
+    disabled:{
+        type:Boolean,
+        default:false
+    }
+})
+const emit = defineEmits(['tabChange'])
+const activedId = ref(props.defaultTabKey)
+
+watch([()=>props.defaultTabKey,()=>props.tabList],([newVal,newValList])=>{
+    activedId.value = newVal
+},{immediate:true,deep:true})
+
+const HandleTabChange = async (params) =>{
+    activedId.value = params
+    emit('tabChange',activedId.value)
+}
+</script>
+
+
+<style lang="scss" scoped>
+ 
+.box_tab  {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    font-size: 14px;
+
+    > span{
+      height: 36px;
+      display: flex;
+      gap:4px;
+      justify-content: center;
+      align-items: center;
+
+      line-height: 1.5 !important;
+      padding:7px 12px;
+      cursor: pointer;
+
+      .prefix{
+        width: 16px;
+        height: 16px;
+      }
+    }
+
+    .un_selected{
+      border: 1px solid  #dcdfe6;
+      color: #666;
+    }
+    
+    .selected{
+      background:  #2E64FA;
+      color: #fff;
+      + span{
+        border-left: transparent;
+      }
+
+      &.prefix{
+        background-color: rgba(46, 100, 250,0.1);
+        color:rgba(46, 100, 250);
+        border:solid #2E64FA 1px;
+      }
+    }
+
+    > span:nth-child(1){
+      border-radius: 4px 0 0 4px;
+    }
+    > span:last-child{
+      border-radius:0 4px 4px 0;
+    }
+    >span:nth-child(n):not(:last-child):not(.selected){
+        border-right: transparent;
+    }
+}
+
+
+.line_tab{
+    display: flex;
+    gap:24px;
+    padding-bottom: 10px;
+    color:#666666;
+    font-size:14px;
+
+    >span{
+        cursor: pointer;
+    }
+
+    .selected{
+        position: relative;
+        color: #2E64FA;
+        font-weight: bold;
+        &::after{
+            position: absolute;
+            left: 0;
+            bottom: -10px;
+            content:'';
+            width: 100%;
+            height: 2px;
+            background-color: #2E64FA;
+        }
+    }
+}
+
+.box_tab,
+.line_tab{
+    .disabled{
+        cursor: not-allowed;
+    }
+}
+
+</style>

+ 186 - 0
src/baseComponents/Table.vue

@@ -0,0 +1,186 @@
+<template>
+    <div class="page_table">
+        <!-- :height="tableHeight" -->
+          <!-- border -->
+        <el-table 
+          class="el-table--border"
+          :show-header="showHeader"
+          :data="props.tableData" stripe v-loading="props.loading" element-loading-text="拼命加载中……" 
+          element-loading-spinner="el-icon-loading" element-loading-background="#ffffff"
+          element-loading-custom-class="loading_icon"
+          :row-class-name="props.tableRowClassName"
+          @row-click="(row,column)=> emit('rowClick',row)"
+          :span-method="props.spanMethod">
+            <!-- show-overflow-tooltip -->
+            <template 
+                v-for="(item,index) in props.tableColumns" 
+                :key="item.name"
+            >
+                <el-table-column 
+                  v-if="!item.hidden"
+                  :prop="item.name" 
+                  :min-width="item.width" 
+                  :label="item.label" 
+                  :fixed="item.fixed ? item.fixed : false" 
+                  :align="item.align" >
+
+                  <template v-if="item.customHeader" #header>
+                    <slot :name="'header-'+item.name"></slot>
+                  </template>
+                
+                  <template v-if="item.custom" #default="row">
+                    <slot :name="item.name" :row="row.row" :currentIndex="(row.$index + 1)">
+                    </slot>
+                  </template>
+              </el-table-column>
+
+            </template>
+            
+        </el-table>
+
+        <div class="page_pagination" v-if="!(hidePagination)">
+          <!-- background layout="sizes, prev, pager, next"  -->
+          <el-pagination 
+            :hide-on-single-page="props.hidesinglePage"
+            :current-page="props.currentPage" 
+            :page-size="props.pageSize" 
+            :page-sizes="[20, 50, 100]" 
+            background layout="prev, pager, next" 
+            :total="Number(props.totalNum)" 
+            @current-change="(val)=>emit('paginationChange',{type:'currentPage',val})" 
+            @size-change="(val)=>emit('paginationChange',{type:'pageSize',val})" />
+        </div>
+    </div>
+</template>
+
+<script setup lang="ts">
+interface ColumnProperty  {
+  name:String,
+  label:String,
+  width?:String,
+  fixed?:String,
+  align?:String,
+  minWidth?:String,
+  custom:String,
+  customHeader?:Boolean,
+  hidden:Boolean,
+}
+const props = defineProps({
+  tableData:{
+    required:true,
+    type:Array
+  },
+  tableColumns:{
+    required:true,
+    type:Array<ColumnProperty>
+  },
+  currentPage:{
+    type:Number,
+    default:1
+  },
+  pageSize:{
+    type:Number,
+    default:20
+  },
+  totalNum:{
+    type:Number,
+    default:0
+  },
+  loading:{
+    type:Boolean,
+    default:false
+  },
+  hidesinglePage:{
+    type:Boolean,
+  },
+  hidePagination:{
+    type:Boolean,
+    default:false
+  },
+  spanMethod:{
+    type:Function,
+    required:false
+  },
+  tableRowClassName:{
+    type:Function,
+    required:false
+  },
+  showHeader:{
+    type:Boolean,
+    default:true
+  }
+})
+const emit = defineEmits(['paginationChange','rowClick'])
+
+/*  
+//demo
+const HandleSpanMethod = ({row,column,rowIndex,columnIndex}) => {
+    if(['type'].includes(column.property)){
+        return {
+        rowspan: row.sameRow,
+        colspan: 1,
+        }
+    }
+}
+const HandleTableRowClassName = ({row,rowIndex}) => {
+  if(row.parentIndex % 2 == 0){
+    // 偶数行
+    return 'even_row'
+  }else{
+    // 奇数行
+    return 'odd_row'
+  }
+}
+*/
+
+</script>
+
+<style lang="scss" scoped>
+.page_table{
+  overflow: auto;
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  .el-table{
+    flex-grow: 1;
+    :deep(.el-scrollbar__view){
+      height: 100%;
+    }
+  }
+
+  // 表头缺失的时候,某些浏览器上的表格-border-top 渲染失效 ———— 待完善
+  :deep(.el-table__inner-wrapper){
+      // border:solid #ebeef5 1px;
+      // border:solid red 1px;
+      // ::before{
+
+      // }
+  }
+
+  :deep(.el-table__body){
+      tbody tr.even_row td{
+        background-color: white;
+      }
+      tbody tr.odd_row td{
+        background-color: rgb(250, 250, 250);
+      }
+      // .hover-fixed-row
+      tbody tr.hover-row td{
+        background-color: rgb(245,247,250);
+      }
+      tbody tr td:last-child:not([rowspan="1"]){
+        border-left:solid rgba(235,238,245) 1px;
+      }
+  }
+}
+
+:deep(.loading_icon){
+  .el-loading-spinner{
+    .el-loading-text{
+      color:#2e64fa;
+    }
+  }
+}
+
+
+</style>

+ 45 - 0
src/baseComponents/TableRowStatus.vue

@@ -0,0 +1,45 @@
+<template>
+  <span class="table_row_status">
+    <span :class=" statusNumToName(props.useStatus)?.themeClass "></span>
+    {{ statusNumToName(props.useStatus)?.title  }}
+  </span>
+</template>  
+
+<script setup lang="ts">
+interface statusItm {
+  statusFlag:Number | String,
+  title:String,
+  themeClass: 'not_included_icon' | 'no_release_icon' 
+              | 'normal_icon' | 'abnormal_icon' | 'audit_icon' 
+              | 'yes_release_icon' | 'right_icon' | 'ready_close_icon' | 'need_summary_icon'
+}
+
+const props = defineProps({
+    useStatus:{
+        required:true,
+        type:[String,Number,null],
+        default:null
+    },
+    statusMsg:{
+      required:true,
+      type:Array<statusItm>
+    }
+})
+    
+const statusNumToName=(useStatus)=>{
+  let result =  props?.statusMsg?.find(item=>item.statusFlag == useStatus)
+  if(result){
+    return result
+  }else{
+    return {
+      title:'',
+      themeClass:''
+    }
+  }
+}
+
+</script>
+
+<style lang="scss" scoped>
+
+</style>

Some files were not shown because too many files changed in this diff