Browse Source

Merge branch 'beta' of https://git.cocorobo.cn/jack/PPT into beta

jack 1 week ago
parent
commit
41a1816378

+ 5107 - 0
package-lock.json

@@ -13,6 +13,7 @@
         "animate.css": "^4.1.1",
         "animate.css": "^4.1.1",
         "axios": "^1.7.9",
         "axios": "^1.7.9",
         "clipboard": "^2.0.11",
         "clipboard": "^2.0.11",
+        "convertapi-js": "^1.0.8",
         "crypto-js": "^4.2.0",
         "crypto-js": "^4.2.0",
         "dexie": "^4.0.11",
         "dexie": "^4.0.11",
         "echarts": "^5.6.0",
         "echarts": "^5.6.0",
@@ -29,6 +30,7 @@
         "nanoid": "^5.0.7",
         "nanoid": "^5.0.7",
         "number-precision": "^1.6.0",
         "number-precision": "^1.6.0",
         "pinia": "^3.0.2",
         "pinia": "^3.0.2",
+        "pptist": "file:",
         "pptxgenjs": "^3.12.0",
         "pptxgenjs": "^3.12.0",
         "pptxtojson": "1.12.0",
         "pptxtojson": "1.12.0",
         "prosemirror-commands": "^1.6.0",
         "prosemirror-commands": "^1.6.0",
@@ -2893,6 +2895,11 @@
       "dev": true,
       "dev": true,
       "license": "MIT"
       "license": "MIT"
     },
     },
+    "node_modules/convertapi-js": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/convertapi-js/-/convertapi-js-1.0.8.tgz",
+      "integrity": "sha512-iuwiXXyUEL4MqQgW7j/wRkxtaN4QrY1D9P/XEcumTHOEUSgvUe7idzvmDxAP+6eO+ZJ4FHQmZ8D9wjKDPy08bg=="
+    },
     "node_modules/copy-anything": {
     "node_modules/copy-anything": {
       "version": "3.0.5",
       "version": "3.0.5",
       "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
       "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
@@ -5430,6 +5437,10 @@
         "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
         "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
       }
       }
     },
     },
+    "node_modules/pptist": {
+      "resolved": "",
+      "link": true
+    },
     "node_modules/pptxgenjs": {
     "node_modules/pptxgenjs": {
       "version": "3.12.0",
       "version": "3.12.0",
       "resolved": "https://registry.npmmirror.com/pptxgenjs/-/pptxgenjs-3.12.0.tgz",
       "resolved": "https://registry.npmmirror.com/pptxgenjs/-/pptxgenjs-3.12.0.tgz",
@@ -8918,6 +8929,11 @@
       "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
       "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
       "dev": true
       "dev": true
     },
     },
+    "convertapi-js": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/convertapi-js/-/convertapi-js-1.0.8.tgz",
+      "integrity": "sha512-iuwiXXyUEL4MqQgW7j/wRkxtaN4QrY1D9P/XEcumTHOEUSgvUe7idzvmDxAP+6eO+ZJ4FHQmZ8D9wjKDPy08bg=="
+    },
     "copy-anything": {
     "copy-anything": {
       "version": "3.0.5",
       "version": "3.0.5",
       "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
       "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
@@ -10811,6 +10827,5097 @@
         "util-deprecate": "^1.0.2"
         "util-deprecate": "^1.0.2"
       }
       }
     },
     },
+    "pptist": {
+      "version": "file:",
+      "requires": {
+        "@commitlint/cli": "^18.4.3",
+        "@commitlint/config-conventional": "^18.4.3",
+        "@icon-park/vue-next": "^1.4.2",
+        "@microsoft/fetch-event-source": "^2.0.1",
+        "@rushstack/eslint-patch": "^1.3.3",
+        "@tsconfig/node18": "^18.2.2",
+        "@types/crypto-js": "^4.2.1",
+        "@types/file-saver": "^2.0.7",
+        "@types/html2canvas": "^1.0.0",
+        "@types/lodash": "^4.14.202",
+        "@types/markdown-it": "^14.1.2",
+        "@types/node": "^18.19.3",
+        "@types/qs": "^6.14.0",
+        "@types/svg-arc-to-cubic-bezier": "^3.2.2",
+        "@types/tinycolor2": "^1.4.6",
+        "@vitejs/plugin-vue": "^5.1.0",
+        "@vue/eslint-config-typescript": "^12.0.0",
+        "@vue/tsconfig": "^0.5.0",
+        "animate.css": "^4.1.1",
+        "axios": "^1.7.9",
+        "clipboard": "^2.0.11",
+        "convertapi-js": "^1.0.8",
+        "crypto-js": "^4.2.0",
+        "dexie": "^4.0.11",
+        "echarts": "^5.6.0",
+        "echarts-wordcloud": "^2.1.0",
+        "eslint": "^8.49.0",
+        "eslint-plugin-vue": "^9.17.0",
+        "file-saver": "^2.0.5",
+        "hfmath": "^0.0.2",
+        "html-to-image": "^1.11.13",
+        "html2canvas": "^1.4.1",
+        "husky": "^8.0.3",
+        "jszip": "^3.10.1",
+        "katex": "^0.16.22",
+        "lodash": "^4.17.21",
+        "markdown-it": "^14.1.1",
+        "mitt": "^3.0.1",
+        "nanoid": "^5.0.7",
+        "npm-run-all2": "^6.1.1",
+        "number-precision": "^1.6.0",
+        "pinia": "^3.0.2",
+        "pptist": "file:",
+        "pptxgenjs": "^3.12.0",
+        "pptxtojson": "1.12.0",
+        "prosemirror-commands": "^1.6.0",
+        "prosemirror-dropcursor": "^1.8.1",
+        "prosemirror-gapcursor": "^1.3.2",
+        "prosemirror-history": "^1.3.2",
+        "prosemirror-inputrules": "^1.4.0",
+        "prosemirror-keymap": "^1.2.2",
+        "prosemirror-model": "^1.22.2",
+        "prosemirror-schema-basic": "^1.2.3",
+        "prosemirror-schema-list": "^1.4.1",
+        "prosemirror-state": "^1.4.3",
+        "prosemirror-view": "^1.33.9",
+        "qs": "^6.14.0",
+        "rtf.js": "^3.0.9",
+        "sass": "1.69.6",
+        "svg-arc-to-cubic-bezier": "^3.2.0",
+        "svg-pathdata": "^7.2.0",
+        "tinycolor2": "^1.6.0",
+        "tippy.js": "^6.3.7",
+        "typescript": "~5.3.0",
+        "utif": "^3.1.0",
+        "utif2": "^4.1.0",
+        "uuid": "^13.0.0",
+        "vite": "^5.3.5",
+        "vite-plugin-vue-inspector": "^5.4.0",
+        "vue": "^3.5.17",
+        "vue-tsc": "^2.0.29",
+        "vuedraggable": "^4.1.0",
+        "wangeditor": "^4.7.15",
+        "webcodecs-encoder": "^0.3.2",
+        "y-websocket": "^3.0.0",
+        "yjs": "^13.6.27"
+      },
+      "dependencies": {
+        "@aashutoshrathi/word-wrap": {
+          "version": "1.2.6",
+          "resolved": "https://registry.npmmirror.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+          "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+          "dev": true
+        },
+        "@babel/code-frame": {
+          "version": "7.29.0",
+          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+          "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.28.5",
+            "js-tokens": "^4.0.0",
+            "picocolors": "^1.1.1"
+          }
+        },
+        "@babel/compat-data": {
+          "version": "7.29.0",
+          "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
+          "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+          "dev": true
+        },
+        "@babel/core": {
+          "version": "7.29.0",
+          "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+          "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.29.0",
+            "@babel/generator": "^7.29.0",
+            "@babel/helper-compilation-targets": "^7.28.6",
+            "@babel/helper-module-transforms": "^7.28.6",
+            "@babel/helpers": "^7.28.6",
+            "@babel/parser": "^7.29.0",
+            "@babel/template": "^7.28.6",
+            "@babel/traverse": "^7.29.0",
+            "@babel/types": "^7.29.0",
+            "@jridgewell/remapping": "^2.3.5",
+            "convert-source-map": "^2.0.0",
+            "debug": "^4.1.0",
+            "gensync": "^1.0.0-beta.2",
+            "json5": "^2.2.3",
+            "semver": "^6.3.1"
+          },
+          "dependencies": {
+            "semver": {
+              "version": "6.3.1",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+              "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+              "dev": true
+            }
+          }
+        },
+        "@babel/generator": {
+          "version": "7.29.1",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+          "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+          "dev": true,
+          "requires": {
+            "@babel/parser": "^7.29.0",
+            "@babel/types": "^7.29.0",
+            "@jridgewell/gen-mapping": "^0.3.12",
+            "@jridgewell/trace-mapping": "^0.3.28",
+            "jsesc": "^3.0.2"
+          }
+        },
+        "@babel/helper-annotate-as-pure": {
+          "version": "7.27.3",
+          "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
+          "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.27.3"
+          }
+        },
+        "@babel/helper-compilation-targets": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+          "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+          "dev": true,
+          "requires": {
+            "@babel/compat-data": "^7.28.6",
+            "@babel/helper-validator-option": "^7.27.1",
+            "browserslist": "^4.24.0",
+            "lru-cache": "^5.1.1",
+            "semver": "^6.3.1"
+          },
+          "dependencies": {
+            "lru-cache": {
+              "version": "5.1.1",
+              "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+              "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+              "dev": true,
+              "requires": {
+                "yallist": "^3.0.2"
+              }
+            },
+            "semver": {
+              "version": "6.3.1",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+              "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+              "dev": true
+            },
+            "yallist": {
+              "version": "3.1.1",
+              "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+              "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+              "dev": true
+            }
+          }
+        },
+        "@babel/helper-create-class-features-plugin": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz",
+          "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-annotate-as-pure": "^7.27.3",
+            "@babel/helper-member-expression-to-functions": "^7.28.5",
+            "@babel/helper-optimise-call-expression": "^7.27.1",
+            "@babel/helper-replace-supers": "^7.28.6",
+            "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+            "@babel/traverse": "^7.28.6",
+            "semver": "^6.3.1"
+          },
+          "dependencies": {
+            "semver": {
+              "version": "6.3.1",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+              "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+              "dev": true
+            }
+          }
+        },
+        "@babel/helper-globals": {
+          "version": "7.28.0",
+          "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+          "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+          "dev": true
+        },
+        "@babel/helper-member-expression-to-functions": {
+          "version": "7.28.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz",
+          "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==",
+          "dev": true,
+          "requires": {
+            "@babel/traverse": "^7.28.5",
+            "@babel/types": "^7.28.5"
+          }
+        },
+        "@babel/helper-module-imports": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+          "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+          "dev": true,
+          "requires": {
+            "@babel/traverse": "^7.28.6",
+            "@babel/types": "^7.28.6"
+          }
+        },
+        "@babel/helper-module-transforms": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+          "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-module-imports": "^7.28.6",
+            "@babel/helper-validator-identifier": "^7.28.5",
+            "@babel/traverse": "^7.28.6"
+          }
+        },
+        "@babel/helper-optimise-call-expression": {
+          "version": "7.27.1",
+          "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz",
+          "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==",
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.27.1"
+          }
+        },
+        "@babel/helper-plugin-utils": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+          "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
+          "dev": true
+        },
+        "@babel/helper-replace-supers": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz",
+          "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-member-expression-to-functions": "^7.28.5",
+            "@babel/helper-optimise-call-expression": "^7.27.1",
+            "@babel/traverse": "^7.28.6"
+          }
+        },
+        "@babel/helper-skip-transparent-expression-wrappers": {
+          "version": "7.27.1",
+          "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz",
+          "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==",
+          "dev": true,
+          "requires": {
+            "@babel/traverse": "^7.27.1",
+            "@babel/types": "^7.27.1"
+          }
+        },
+        "@babel/helper-string-parser": {
+          "version": "7.27.1",
+          "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+          "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="
+        },
+        "@babel/helper-validator-identifier": {
+          "version": "7.28.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+          "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="
+        },
+        "@babel/helper-validator-option": {
+          "version": "7.27.1",
+          "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+          "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+          "dev": true
+        },
+        "@babel/helpers": {
+          "version": "7.29.2",
+          "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
+          "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
+          "dev": true,
+          "requires": {
+            "@babel/template": "^7.28.6",
+            "@babel/types": "^7.29.0"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.29.2",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
+          "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
+          "requires": {
+            "@babel/types": "^7.29.0"
+          }
+        },
+        "@babel/plugin-proposal-decorators": {
+          "version": "7.29.0",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.0.tgz",
+          "integrity": "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-create-class-features-plugin": "^7.28.6",
+            "@babel/helper-plugin-utils": "^7.28.6",
+            "@babel/plugin-syntax-decorators": "^7.28.6"
+          }
+        },
+        "@babel/plugin-syntax-decorators": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.28.6.tgz",
+          "integrity": "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.28.6"
+          }
+        },
+        "@babel/plugin-syntax-import-attributes": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz",
+          "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.28.6"
+          }
+        },
+        "@babel/plugin-syntax-import-meta": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+          "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.10.4"
+          }
+        },
+        "@babel/plugin-syntax-jsx": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
+          "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.28.6"
+          }
+        },
+        "@babel/plugin-syntax-typescript": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
+          "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.28.6"
+          }
+        },
+        "@babel/plugin-transform-typescript": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz",
+          "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-annotate-as-pure": "^7.27.3",
+            "@babel/helper-create-class-features-plugin": "^7.28.6",
+            "@babel/helper-plugin-utils": "^7.28.6",
+            "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+            "@babel/plugin-syntax-typescript": "^7.28.6"
+          }
+        },
+        "@babel/runtime": {
+          "version": "7.28.4",
+          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
+          "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="
+        },
+        "@babel/runtime-corejs3": {
+          "version": "7.28.4",
+          "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.4.tgz",
+          "integrity": "sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==",
+          "requires": {
+            "core-js-pure": "^3.43.0"
+          }
+        },
+        "@babel/template": {
+          "version": "7.28.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+          "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.28.6",
+            "@babel/parser": "^7.28.6",
+            "@babel/types": "^7.28.6"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.29.0",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+          "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.29.0",
+            "@babel/generator": "^7.29.0",
+            "@babel/helper-globals": "^7.28.0",
+            "@babel/parser": "^7.29.0",
+            "@babel/template": "^7.28.6",
+            "@babel/types": "^7.29.0",
+            "debug": "^4.3.1"
+          }
+        },
+        "@babel/types": {
+          "version": "7.29.0",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+          "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+          "requires": {
+            "@babel/helper-string-parser": "^7.27.1",
+            "@babel/helper-validator-identifier": "^7.28.5"
+          }
+        },
+        "@commitlint/cli": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/cli/-/cli-18.4.3.tgz",
+          "integrity": "sha512-zop98yfB3A6NveYAZ3P1Mb6bIXuCeWgnUfVNkH4yhIMQpQfzFwseadazOuSn0OOfTt0lWuFauehpm9GcqM5lww==",
+          "dev": true,
+          "requires": {
+            "@commitlint/format": "^18.4.3",
+            "@commitlint/lint": "^18.4.3",
+            "@commitlint/load": "^18.4.3",
+            "@commitlint/read": "^18.4.3",
+            "@commitlint/types": "^18.4.3",
+            "execa": "^5.0.0",
+            "lodash.isfunction": "^3.0.9",
+            "resolve-from": "5.0.0",
+            "resolve-global": "1.0.0",
+            "yargs": "^17.0.0"
+          },
+          "dependencies": {
+            "resolve-from": {
+              "version": "5.0.0",
+              "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz",
+              "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+              "dev": true
+            }
+          }
+        },
+        "@commitlint/config-conventional": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/config-conventional/-/config-conventional-18.4.3.tgz",
+          "integrity": "sha512-729eRRaNta7JZF07qf6SAGSghoDEp9mH7yHU0m7ff0q89W97wDrWCyZ3yoV3mcQJwbhlmVmZPTkPcm7qiAu8WA==",
+          "dev": true,
+          "requires": {
+            "conventional-changelog-conventionalcommits": "^7.0.2"
+          }
+        },
+        "@commitlint/config-validator": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/config-validator/-/config-validator-18.4.3.tgz",
+          "integrity": "sha512-FPZZmTJBARPCyef9ohRC9EANiQEKSWIdatx5OlgeHKu878dWwpyeFauVkhzuBRJFcCA4Uvz/FDtlDKs008IHcA==",
+          "dev": true,
+          "requires": {
+            "@commitlint/types": "^18.4.3",
+            "ajv": "^8.11.0"
+          },
+          "dependencies": {
+            "ajv": {
+              "version": "8.12.0",
+              "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz",
+              "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+              "dev": true,
+              "requires": {
+                "fast-deep-equal": "^3.1.1",
+                "json-schema-traverse": "^1.0.0",
+                "require-from-string": "^2.0.2",
+                "uri-js": "^4.2.2"
+              }
+            },
+            "json-schema-traverse": {
+              "version": "1.0.0",
+              "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+              "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+              "dev": true
+            }
+          }
+        },
+        "@commitlint/ensure": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/ensure/-/ensure-18.4.3.tgz",
+          "integrity": "sha512-MI4fwD9TWDVn4plF5+7JUyLLbkOdzIRBmVeNlk4dcGlkrVA+/l5GLcpN66q9LkFsFv6G2X31y89ApA3hqnqIFg==",
+          "dev": true,
+          "requires": {
+            "@commitlint/types": "^18.4.3",
+            "lodash.camelcase": "^4.3.0",
+            "lodash.kebabcase": "^4.1.1",
+            "lodash.snakecase": "^4.1.1",
+            "lodash.startcase": "^4.4.0",
+            "lodash.upperfirst": "^4.3.1"
+          }
+        },
+        "@commitlint/execute-rule": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/execute-rule/-/execute-rule-18.4.3.tgz",
+          "integrity": "sha512-t7FM4c+BdX9WWZCPrrbV5+0SWLgT3kCq7e7/GhHCreYifg3V8qyvO127HF796vyFql75n4TFF+5v1asOOWkV1Q==",
+          "dev": true
+        },
+        "@commitlint/format": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/format/-/format-18.4.3.tgz",
+          "integrity": "sha512-8b+ItXYHxAhRAXFfYki5PpbuMMOmXYuzLxib65z2XTqki59YDQJGpJ/wB1kEE5MQDgSTQWtKUrA8n9zS/1uIDQ==",
+          "dev": true,
+          "requires": {
+            "@commitlint/types": "^18.4.3",
+            "chalk": "^4.1.0"
+          }
+        },
+        "@commitlint/is-ignored": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/is-ignored/-/is-ignored-18.4.3.tgz",
+          "integrity": "sha512-ZseOY9UfuAI32h9w342Km4AIaTieeFskm2ZKdrG7r31+c6zGBzuny9KQhwI9puc0J3GkUquEgKJblCl7pMnjwg==",
+          "dev": true,
+          "requires": {
+            "@commitlint/types": "^18.4.3",
+            "semver": "7.5.4"
+          }
+        },
+        "@commitlint/lint": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/lint/-/lint-18.4.3.tgz",
+          "integrity": "sha512-18u3MRgEXNbnYkMOWoncvq6QB8/90m9TbERKgdPqVvS+zQ/MsuRhdvHYCIXGXZxUb0YI4DV2PC4bPneBV/fYuA==",
+          "dev": true,
+          "requires": {
+            "@commitlint/is-ignored": "^18.4.3",
+            "@commitlint/parse": "^18.4.3",
+            "@commitlint/rules": "^18.4.3",
+            "@commitlint/types": "^18.4.3"
+          }
+        },
+        "@commitlint/load": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/load/-/load-18.4.3.tgz",
+          "integrity": "sha512-v6j2WhvRQJrcJaj5D+EyES2WKTxPpxENmNpNG3Ww8MZGik3jWRXtph0QTzia5ZJyPh2ib5aC/6BIDymkUUM58Q==",
+          "dev": true,
+          "requires": {
+            "@commitlint/config-validator": "^18.4.3",
+            "@commitlint/execute-rule": "^18.4.3",
+            "@commitlint/resolve-extends": "^18.4.3",
+            "@commitlint/types": "^18.4.3",
+            "@types/node": "^18.11.9",
+            "chalk": "^4.1.0",
+            "cosmiconfig": "^8.3.6",
+            "cosmiconfig-typescript-loader": "^5.0.0",
+            "lodash.isplainobject": "^4.0.6",
+            "lodash.merge": "^4.6.2",
+            "lodash.uniq": "^4.5.0",
+            "resolve-from": "^5.0.0"
+          },
+          "dependencies": {
+            "resolve-from": {
+              "version": "5.0.0",
+              "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz",
+              "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+              "dev": true
+            }
+          }
+        },
+        "@commitlint/message": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/message/-/message-18.4.3.tgz",
+          "integrity": "sha512-ddJ7AztWUIoEMAXoewx45lKEYEOeOlBVWjk8hDMUGpprkuvWULpaXczqdjwVtjrKT3JhhN+gMs8pm5G3vB2how==",
+          "dev": true
+        },
+        "@commitlint/parse": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/parse/-/parse-18.4.3.tgz",
+          "integrity": "sha512-eoH7CXM9L+/Me96KVcfJ27EIIbA5P9sqw3DqjJhRYuhaULIsPHFs5S5GBDCqT0vKZQDx0DgxhMpW6AQbnKrFtA==",
+          "dev": true,
+          "requires": {
+            "@commitlint/types": "^18.4.3",
+            "conventional-changelog-angular": "^7.0.0",
+            "conventional-commits-parser": "^5.0.0"
+          }
+        },
+        "@commitlint/read": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/read/-/read-18.4.3.tgz",
+          "integrity": "sha512-H4HGxaYA6OBCimZAtghL+B+SWu8ep4X7BwgmedmqWZRHxRLcX2q0bWBtUm5FsMbluxbOfrJwOs/Z0ah4roP/GQ==",
+          "dev": true,
+          "requires": {
+            "@commitlint/top-level": "^18.4.3",
+            "@commitlint/types": "^18.4.3",
+            "fs-extra": "^11.0.0",
+            "git-raw-commits": "^2.0.11",
+            "minimist": "^1.2.6"
+          }
+        },
+        "@commitlint/resolve-extends": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/resolve-extends/-/resolve-extends-18.4.3.tgz",
+          "integrity": "sha512-30sk04LZWf8+SDgJrbJCjM90gTg2LxsD9cykCFeFu+JFHvBFq5ugzp2eO/DJGylAdVaqxej3c7eTSE64hR/lnw==",
+          "dev": true,
+          "requires": {
+            "@commitlint/config-validator": "^18.4.3",
+            "@commitlint/types": "^18.4.3",
+            "import-fresh": "^3.0.0",
+            "lodash.mergewith": "^4.6.2",
+            "resolve-from": "^5.0.0",
+            "resolve-global": "^1.0.0"
+          },
+          "dependencies": {
+            "resolve-from": {
+              "version": "5.0.0",
+              "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz",
+              "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+              "dev": true
+            }
+          }
+        },
+        "@commitlint/rules": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/rules/-/rules-18.4.3.tgz",
+          "integrity": "sha512-8KIeukDf45BiY+Lul1T0imSNXF0sMrlLG6JpLLKolkmYVQ6PxxoNOriwyZ3UTFFpaVbPy0rcITaV7U9JCAfDTA==",
+          "dev": true,
+          "requires": {
+            "@commitlint/ensure": "^18.4.3",
+            "@commitlint/message": "^18.4.3",
+            "@commitlint/to-lines": "^18.4.3",
+            "@commitlint/types": "^18.4.3",
+            "execa": "^5.0.0"
+          }
+        },
+        "@commitlint/to-lines": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/to-lines/-/to-lines-18.4.3.tgz",
+          "integrity": "sha512-fy1TAleik4Zfru1RJ8ZU6cOSvgSVhUellxd3WZV1D5RwHZETt1sZdcA4mQN2y3VcIZsUNKkW0Mq8CM9/L9harQ==",
+          "dev": true
+        },
+        "@commitlint/top-level": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/top-level/-/top-level-18.4.3.tgz",
+          "integrity": "sha512-E6fJPBLPFL5R8+XUNSYkj4HekIOuGMyJo3mIx2PkYc3clel+pcWQ7TConqXxNWW4x1ugigiIY2RGot55qUq1hw==",
+          "dev": true,
+          "requires": {
+            "find-up": "^5.0.0"
+          }
+        },
+        "@commitlint/types": {
+          "version": "18.4.3",
+          "resolved": "https://registry.npmmirror.com/@commitlint/types/-/types-18.4.3.tgz",
+          "integrity": "sha512-cvzx+vtY/I2hVBZHCLrpoh+sA0hfuzHwDc+BAFPimYLjJkpHnghQM+z8W/KyLGkygJh3BtI3xXXq+dKjnSWEmA==",
+          "dev": true,
+          "requires": {
+            "chalk": "^4.1.0"
+          }
+        },
+        "@esbuild/aix-ppc64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+          "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/android-arm": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+          "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/android-arm64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+          "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/android-x64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+          "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/darwin-arm64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+          "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/darwin-x64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+          "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/freebsd-arm64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+          "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/freebsd-x64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+          "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/linux-arm": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+          "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/linux-arm64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+          "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/linux-ia32": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+          "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/linux-loong64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+          "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/linux-mips64el": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+          "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/linux-ppc64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+          "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/linux-riscv64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+          "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/linux-s390x": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+          "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/linux-x64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+          "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/netbsd-x64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+          "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/openbsd-x64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+          "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/sunos-x64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+          "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/win32-arm64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+          "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/win32-ia32": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+          "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+          "dev": true,
+          "optional": true
+        },
+        "@esbuild/win32-x64": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+          "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+          "dev": true,
+          "optional": true
+        },
+        "@eslint-community/eslint-utils": {
+          "version": "4.4.0",
+          "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+          "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+          "dev": true,
+          "requires": {
+            "eslint-visitor-keys": "^3.3.0"
+          }
+        },
+        "@eslint-community/regexpp": {
+          "version": "4.10.0",
+          "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+          "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+          "dev": true
+        },
+        "@eslint/eslintrc": {
+          "version": "2.1.4",
+          "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+          "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.12.4",
+            "debug": "^4.3.2",
+            "espree": "^9.6.0",
+            "globals": "^13.19.0",
+            "ignore": "^5.2.0",
+            "import-fresh": "^3.2.1",
+            "js-yaml": "^4.1.0",
+            "minimatch": "^3.1.2",
+            "strip-json-comments": "^3.1.1"
+          },
+          "dependencies": {
+            "brace-expansion": {
+              "version": "1.1.11",
+              "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
+              "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+              "dev": true,
+              "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+              }
+            },
+            "minimatch": {
+              "version": "3.1.2",
+              "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
+              "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+              "dev": true,
+              "requires": {
+                "brace-expansion": "^1.1.7"
+              }
+            }
+          }
+        },
+        "@eslint/js": {
+          "version": "8.56.0",
+          "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-8.56.0.tgz",
+          "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
+          "dev": true
+        },
+        "@humanwhocodes/config-array": {
+          "version": "0.11.13",
+          "resolved": "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
+          "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
+          "dev": true,
+          "requires": {
+            "@humanwhocodes/object-schema": "^2.0.1",
+            "debug": "^4.1.1",
+            "minimatch": "^3.0.5"
+          },
+          "dependencies": {
+            "brace-expansion": {
+              "version": "1.1.11",
+              "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
+              "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+              "dev": true,
+              "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+              }
+            },
+            "minimatch": {
+              "version": "3.1.2",
+              "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
+              "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+              "dev": true,
+              "requires": {
+                "brace-expansion": "^1.1.7"
+              }
+            }
+          }
+        },
+        "@humanwhocodes/module-importer": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+          "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+          "dev": true
+        },
+        "@humanwhocodes/object-schema": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
+          "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
+          "dev": true
+        },
+        "@icon-park/vue-next": {
+          "version": "1.4.2",
+          "resolved": "https://registry.npmmirror.com/@icon-park/vue-next/-/vue-next-1.4.2.tgz",
+          "integrity": "sha512-+QklF255wkfBOabY+xw6FAI0Bwln/RhdwCunNy/9sKdKuChtaU67QZqU67KGAvZUTeeBgsL+yaHHxqfQeGZXEQ==",
+          "requires": {}
+        },
+        "@jridgewell/gen-mapping": {
+          "version": "0.3.13",
+          "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+          "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+          "dev": true,
+          "requires": {
+            "@jridgewell/sourcemap-codec": "^1.5.0",
+            "@jridgewell/trace-mapping": "^0.3.24"
+          }
+        },
+        "@jridgewell/remapping": {
+          "version": "2.3.5",
+          "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+          "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+          "dev": true,
+          "requires": {
+            "@jridgewell/gen-mapping": "^0.3.5",
+            "@jridgewell/trace-mapping": "^0.3.24"
+          }
+        },
+        "@jridgewell/resolve-uri": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+          "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+          "dev": true
+        },
+        "@jridgewell/sourcemap-codec": {
+          "version": "1.5.5",
+          "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+          "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="
+        },
+        "@jridgewell/trace-mapping": {
+          "version": "0.3.31",
+          "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+          "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+          "dev": true,
+          "requires": {
+            "@jridgewell/resolve-uri": "^3.1.0",
+            "@jridgewell/sourcemap-codec": "^1.4.14"
+          }
+        },
+        "@microsoft/fetch-event-source": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/@microsoft/fetch-event-source/-/fetch-event-source-2.0.1.tgz",
+          "integrity": "sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA=="
+        },
+        "@nodelib/fs.scandir": {
+          "version": "2.1.5",
+          "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+          "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+          "dev": true,
+          "requires": {
+            "@nodelib/fs.stat": "2.0.5",
+            "run-parallel": "^1.1.9"
+          }
+        },
+        "@nodelib/fs.stat": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+          "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+          "dev": true
+        },
+        "@nodelib/fs.walk": {
+          "version": "1.2.8",
+          "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+          "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+          "dev": true,
+          "requires": {
+            "@nodelib/fs.scandir": "2.1.5",
+            "fastq": "^1.6.0"
+          }
+        },
+        "@popperjs/core": {
+          "version": "2.11.8",
+          "resolved": "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.8.tgz",
+          "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
+        },
+        "@rollup/rollup-android-arm-eabi": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz",
+          "integrity": "sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-android-arm64": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.0.tgz",
+          "integrity": "sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-darwin-arm64": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz",
+          "integrity": "sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-darwin-x64": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.0.tgz",
+          "integrity": "sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-linux-arm-gnueabihf": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.0.tgz",
+          "integrity": "sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-linux-arm-musleabihf": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.0.tgz",
+          "integrity": "sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-linux-arm64-gnu": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.0.tgz",
+          "integrity": "sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-linux-arm64-musl": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.0.tgz",
+          "integrity": "sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-linux-powerpc64le-gnu": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.0.tgz",
+          "integrity": "sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-linux-riscv64-gnu": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.0.tgz",
+          "integrity": "sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-linux-s390x-gnu": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.0.tgz",
+          "integrity": "sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-linux-x64-gnu": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.0.tgz",
+          "integrity": "sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-linux-x64-musl": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.0.tgz",
+          "integrity": "sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-win32-arm64-msvc": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.0.tgz",
+          "integrity": "sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-win32-ia32-msvc": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.0.tgz",
+          "integrity": "sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==",
+          "dev": true,
+          "optional": true
+        },
+        "@rollup/rollup-win32-x64-msvc": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.0.tgz",
+          "integrity": "sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==",
+          "dev": true,
+          "optional": true
+        },
+        "@rushstack/eslint-patch": {
+          "version": "1.6.1",
+          "resolved": "https://registry.npmmirror.com/@rushstack/eslint-patch/-/eslint-patch-1.6.1.tgz",
+          "integrity": "sha512-UY+FGM/2jjMkzQLn8pxcHGMaVLh9aEitG3zY2CiY7XHdLiz3bZOwa6oDxNqEMv7zZkV+cj5DOdz0cQ1BP5Hjgw==",
+          "dev": true
+        },
+        "@tsconfig/node18": {
+          "version": "18.2.2",
+          "resolved": "https://registry.npmmirror.com/@tsconfig/node18/-/node18-18.2.2.tgz",
+          "integrity": "sha512-d6McJeGsuoRlwWZmVIeE8CUA27lu6jLjvv1JzqmpsytOYYbVi1tHZEnwCNVOXnj4pyLvneZlFlpXUK+X9wBWyw==",
+          "dev": true
+        },
+        "@types/crypto-js": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmmirror.com/@types/crypto-js/-/crypto-js-4.2.1.tgz",
+          "integrity": "sha512-FSPGd9+OcSok3RsM0UZ/9fcvMOXJ1ENE/ZbLfOPlBWj7BgXtEAM8VYfTtT760GiLbQIMoVozwVuisjvsVwqYWw==",
+          "dev": true
+        },
+        "@types/dom-webcodecs": {
+          "version": "0.1.18",
+          "resolved": "https://registry.npmmirror.com/@types/dom-webcodecs/-/dom-webcodecs-0.1.18.tgz",
+          "integrity": "sha512-vAvE8C9DGWR+tkb19xyjk1TSUlJ7RUzzp4a9Anu7mwBT+fpyePWK1UxmH14tMO5zHmrnrRIMg5NutnnDztLxgg=="
+        },
+        "@types/estree": {
+          "version": "1.0.5",
+          "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz",
+          "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+          "dev": true
+        },
+        "@types/file-saver": {
+          "version": "2.0.7",
+          "resolved": "https://registry.npmmirror.com/@types/file-saver/-/file-saver-2.0.7.tgz",
+          "integrity": "sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==",
+          "dev": true
+        },
+        "@types/html2canvas": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/@types/html2canvas/-/html2canvas-1.0.0.tgz",
+          "integrity": "sha512-BJpVf+FIN9UERmzhbtUgpXj6XBZpG67FMgBLLoj9HZKd9XifcCpSV+UnFcwTZfEyun4U/KmCrrVOG7829L589w==",
+          "dev": true,
+          "requires": {
+            "html2canvas": "*"
+          }
+        },
+        "@types/json-schema": {
+          "version": "7.0.15",
+          "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
+          "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+          "dev": true
+        },
+        "@types/linkify-it": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
+          "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
+          "dev": true
+        },
+        "@types/lodash": {
+          "version": "4.14.202",
+          "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.202.tgz",
+          "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==",
+          "dev": true
+        },
+        "@types/markdown-it": {
+          "version": "14.1.2",
+          "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
+          "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
+          "dev": true,
+          "requires": {
+            "@types/linkify-it": "^5",
+            "@types/mdurl": "^2"
+          }
+        },
+        "@types/mdurl": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
+          "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
+          "dev": true
+        },
+        "@types/minimist": {
+          "version": "1.2.5",
+          "resolved": "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.5.tgz",
+          "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
+          "dev": true
+        },
+        "@types/node": {
+          "version": "18.19.4",
+          "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.4.tgz",
+          "integrity": "sha512-xNzlUhzoHotIsnFoXmJB+yWmBvFZgKCI9TtPIEdYIMM1KWfwuY8zh7wvc1u1OAXlC7dlf6mZVx/s+Y5KfFz19A==",
+          "requires": {
+            "undici-types": "~5.26.4"
+          }
+        },
+        "@types/normalize-package-data": {
+          "version": "2.4.4",
+          "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
+          "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
+          "dev": true
+        },
+        "@types/qs": {
+          "version": "6.14.0",
+          "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
+          "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
+          "dev": true
+        },
+        "@types/semver": {
+          "version": "7.5.6",
+          "resolved": "https://registry.npmmirror.com/@types/semver/-/semver-7.5.6.tgz",
+          "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==",
+          "dev": true
+        },
+        "@types/svg-arc-to-cubic-bezier": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmmirror.com/@types/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.2.tgz",
+          "integrity": "sha512-XQtKy9lmkKlV+c3Jelo7kxNPw7qOqIq3GcnOhywGZHF7zw5D5m+Ssigbmf3Turbe/A8Ur+lRh8TYjuxXKvyivw==",
+          "dev": true
+        },
+        "@types/tinycolor2": {
+          "version": "1.4.6",
+          "resolved": "https://registry.npmmirror.com/@types/tinycolor2/-/tinycolor2-1.4.6.tgz",
+          "integrity": "sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==",
+          "dev": true
+        },
+        "@types/wicg-file-system-access": {
+          "version": "2020.9.8",
+          "resolved": "https://registry.npmmirror.com/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.8.tgz",
+          "integrity": "sha512-ggMz8nOygG7d/stpH40WVaNvBwuyYLnrg5Mbyf6bmsj/8+gb6Ei4ZZ9/4PNpcPNTT8th9Q8sM8wYmWGjMWLX/A=="
+        },
+        "@typescript-eslint/eslint-plugin": {
+          "version": "6.16.0",
+          "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.16.0.tgz",
+          "integrity": "sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ==",
+          "dev": true,
+          "requires": {
+            "@eslint-community/regexpp": "^4.5.1",
+            "@typescript-eslint/scope-manager": "6.16.0",
+            "@typescript-eslint/type-utils": "6.16.0",
+            "@typescript-eslint/utils": "6.16.0",
+            "@typescript-eslint/visitor-keys": "6.16.0",
+            "debug": "^4.3.4",
+            "graphemer": "^1.4.0",
+            "ignore": "^5.2.4",
+            "natural-compare": "^1.4.0",
+            "semver": "^7.5.4",
+            "ts-api-utils": "^1.0.1"
+          }
+        },
+        "@typescript-eslint/parser": {
+          "version": "6.16.0",
+          "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-6.16.0.tgz",
+          "integrity": "sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/scope-manager": "6.16.0",
+            "@typescript-eslint/types": "6.16.0",
+            "@typescript-eslint/typescript-estree": "6.16.0",
+            "@typescript-eslint/visitor-keys": "6.16.0",
+            "debug": "^4.3.4"
+          }
+        },
+        "@typescript-eslint/scope-manager": {
+          "version": "6.16.0",
+          "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz",
+          "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "6.16.0",
+            "@typescript-eslint/visitor-keys": "6.16.0"
+          }
+        },
+        "@typescript-eslint/type-utils": {
+          "version": "6.16.0",
+          "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-6.16.0.tgz",
+          "integrity": "sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/typescript-estree": "6.16.0",
+            "@typescript-eslint/utils": "6.16.0",
+            "debug": "^4.3.4",
+            "ts-api-utils": "^1.0.1"
+          }
+        },
+        "@typescript-eslint/types": {
+          "version": "6.16.0",
+          "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-6.16.0.tgz",
+          "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==",
+          "dev": true
+        },
+        "@typescript-eslint/typescript-estree": {
+          "version": "6.16.0",
+          "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz",
+          "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "6.16.0",
+            "@typescript-eslint/visitor-keys": "6.16.0",
+            "debug": "^4.3.4",
+            "globby": "^11.1.0",
+            "is-glob": "^4.0.3",
+            "minimatch": "9.0.3",
+            "semver": "^7.5.4",
+            "ts-api-utils": "^1.0.1"
+          }
+        },
+        "@typescript-eslint/utils": {
+          "version": "6.16.0",
+          "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-6.16.0.tgz",
+          "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==",
+          "dev": true,
+          "requires": {
+            "@eslint-community/eslint-utils": "^4.4.0",
+            "@types/json-schema": "^7.0.12",
+            "@types/semver": "^7.5.0",
+            "@typescript-eslint/scope-manager": "6.16.0",
+            "@typescript-eslint/types": "6.16.0",
+            "@typescript-eslint/typescript-estree": "6.16.0",
+            "semver": "^7.5.4"
+          }
+        },
+        "@typescript-eslint/visitor-keys": {
+          "version": "6.16.0",
+          "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz",
+          "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "6.16.0",
+            "eslint-visitor-keys": "^3.4.1"
+          }
+        },
+        "@ungap/structured-clone": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+          "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+          "dev": true
+        },
+        "@vitejs/plugin-vue": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.1.0.tgz",
+          "integrity": "sha512-QMRxARyrdiwi1mj3AW4fLByoHTavreXq0itdEW696EihXglf1MB3D4C2gBvE0jMPH29ZjC3iK8aIaUMLf4EOGA==",
+          "dev": true,
+          "requires": {}
+        },
+        "@volar/language-core": {
+          "version": "2.4.0-alpha.18",
+          "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.0-alpha.18.tgz",
+          "integrity": "sha512-JAYeJvYQQROmVRtSBIczaPjP3DX4QW1fOqW1Ebs0d3Y3EwSNRglz03dSv0Dm61dzd0Yx3WgTW3hndDnTQqgmyg==",
+          "dev": true,
+          "requires": {
+            "@volar/source-map": "2.4.0-alpha.18"
+          }
+        },
+        "@volar/source-map": {
+          "version": "2.4.0-alpha.18",
+          "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.0-alpha.18.tgz",
+          "integrity": "sha512-MTeCV9MUwwsH0sNFiZwKtFrrVZUK6p8ioZs3xFzHc2cvDXHWlYN3bChdQtwKX+FY2HG6H3CfAu1pKijolzIQ8g==",
+          "dev": true
+        },
+        "@volar/typescript": {
+          "version": "2.4.0-alpha.18",
+          "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.0-alpha.18.tgz",
+          "integrity": "sha512-sXh5Y8sqGUkgxpMWUGvRXggxYHAVxg0Pa1C42lQZuPDrW6vHJPR0VCK8Sr7WJsAW530HuNQT/ZIskmXtxjybMQ==",
+          "dev": true,
+          "requires": {
+            "@volar/language-core": "2.4.0-alpha.18",
+            "path-browserify": "^1.0.1",
+            "vscode-uri": "^3.0.8"
+          }
+        },
+        "@vue/babel-helper-vue-transform-on": {
+          "version": "1.5.0",
+          "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz",
+          "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==",
+          "dev": true
+        },
+        "@vue/babel-plugin-jsx": {
+          "version": "1.5.0",
+          "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz",
+          "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-module-imports": "^7.27.1",
+            "@babel/helper-plugin-utils": "^7.27.1",
+            "@babel/plugin-syntax-jsx": "^7.27.1",
+            "@babel/template": "^7.27.2",
+            "@babel/traverse": "^7.28.0",
+            "@babel/types": "^7.28.2",
+            "@vue/babel-helper-vue-transform-on": "1.5.0",
+            "@vue/babel-plugin-resolve-type": "1.5.0",
+            "@vue/shared": "^3.5.18"
+          },
+          "dependencies": {
+            "@vue/shared": {
+              "version": "3.5.31",
+              "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.31.tgz",
+              "integrity": "sha512-nBxuiuS9Lj5bPkPbWogPUnjxxWpkRniX7e5UBQDWl6Fsf4roq9wwV+cR7ezQ4zXswNvPIlsdj1slcLB7XCsRAw==",
+              "dev": true
+            }
+          }
+        },
+        "@vue/babel-plugin-resolve-type": {
+          "version": "1.5.0",
+          "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz",
+          "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==",
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.27.1",
+            "@babel/helper-module-imports": "^7.27.1",
+            "@babel/helper-plugin-utils": "^7.27.1",
+            "@babel/parser": "^7.28.0",
+            "@vue/compiler-sfc": "^3.5.18"
+          },
+          "dependencies": {
+            "@vue/compiler-core": {
+              "version": "3.5.31",
+              "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.31.tgz",
+              "integrity": "sha512-k/ueL14aNIEy5Onf0OVzR8kiqF/WThgLdFhxwa4e/KF/0qe38IwIdofoSWBTvvxQOesaz6riAFAUaYjoF9fLLQ==",
+              "dev": true,
+              "requires": {
+                "@babel/parser": "^7.29.2",
+                "@vue/shared": "3.5.31",
+                "entities": "^7.0.1",
+                "estree-walker": "^2.0.2",
+                "source-map-js": "^1.2.1"
+              }
+            },
+            "@vue/compiler-dom": {
+              "version": "3.5.31",
+              "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.31.tgz",
+              "integrity": "sha512-BMY/ozS/xxjYqRFL+tKdRpATJYDTTgWSo0+AJvJNg4ig+Hgb0dOsHPXvloHQ5hmlivUqw1Yt2pPIqp4e0v1GUw==",
+              "dev": true,
+              "requires": {
+                "@vue/compiler-core": "3.5.31",
+                "@vue/shared": "3.5.31"
+              }
+            },
+            "@vue/compiler-sfc": {
+              "version": "3.5.31",
+              "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.31.tgz",
+              "integrity": "sha512-M8wpPgR9UJ8MiRGjppvx9uWJfLV7A/T+/rL8s/y3QG3u0c2/YZgff3d6SuimKRIhcYnWg5fTfDMlz2E6seUW8Q==",
+              "dev": true,
+              "requires": {
+                "@babel/parser": "^7.29.2",
+                "@vue/compiler-core": "3.5.31",
+                "@vue/compiler-dom": "3.5.31",
+                "@vue/compiler-ssr": "3.5.31",
+                "@vue/shared": "3.5.31",
+                "estree-walker": "^2.0.2",
+                "magic-string": "^0.30.21",
+                "postcss": "^8.5.8",
+                "source-map-js": "^1.2.1"
+              }
+            },
+            "@vue/compiler-ssr": {
+              "version": "3.5.31",
+              "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.31.tgz",
+              "integrity": "sha512-h0xIMxrt/LHOvJKMri+vdYT92BrK3HFLtDqq9Pr/lVVfE4IyKZKvWf0vJFW10Yr6nX02OR4MkJwI0c1HDa1hog==",
+              "dev": true,
+              "requires": {
+                "@vue/compiler-dom": "3.5.31",
+                "@vue/shared": "3.5.31"
+              }
+            },
+            "@vue/shared": {
+              "version": "3.5.31",
+              "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.31.tgz",
+              "integrity": "sha512-nBxuiuS9Lj5bPkPbWogPUnjxxWpkRniX7e5UBQDWl6Fsf4roq9wwV+cR7ezQ4zXswNvPIlsdj1slcLB7XCsRAw==",
+              "dev": true
+            },
+            "entities": {
+              "version": "7.0.1",
+              "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
+              "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+              "dev": true
+            }
+          }
+        },
+        "@vue/compiler-core": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.17.tgz",
+          "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==",
+          "requires": {
+            "@babel/parser": "^7.27.5",
+            "@vue/shared": "3.5.17",
+            "entities": "^4.5.0",
+            "estree-walker": "^2.0.2",
+            "source-map-js": "^1.2.1"
+          }
+        },
+        "@vue/compiler-dom": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz",
+          "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==",
+          "requires": {
+            "@vue/compiler-core": "3.5.17",
+            "@vue/shared": "3.5.17"
+          }
+        },
+        "@vue/compiler-sfc": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz",
+          "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==",
+          "requires": {
+            "@babel/parser": "^7.27.5",
+            "@vue/compiler-core": "3.5.17",
+            "@vue/compiler-dom": "3.5.17",
+            "@vue/compiler-ssr": "3.5.17",
+            "@vue/shared": "3.5.17",
+            "estree-walker": "^2.0.2",
+            "magic-string": "^0.30.17",
+            "postcss": "^8.5.6",
+            "source-map-js": "^1.2.1"
+          }
+        },
+        "@vue/compiler-ssr": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz",
+          "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==",
+          "requires": {
+            "@vue/compiler-dom": "3.5.17",
+            "@vue/shared": "3.5.17"
+          }
+        },
+        "@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": "7.7.2",
+          "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.2.tgz",
+          "integrity": "sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA==",
+          "requires": {
+            "@vue/devtools-kit": "^7.7.2"
+          }
+        },
+        "@vue/devtools-kit": {
+          "version": "7.7.2",
+          "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz",
+          "integrity": "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==",
+          "requires": {
+            "@vue/devtools-shared": "^7.7.2",
+            "birpc": "^0.2.19",
+            "hookable": "^5.5.3",
+            "mitt": "^3.0.1",
+            "perfect-debounce": "^1.0.0",
+            "speakingurl": "^14.0.1",
+            "superjson": "^2.2.1"
+          }
+        },
+        "@vue/devtools-shared": {
+          "version": "7.7.2",
+          "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz",
+          "integrity": "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==",
+          "requires": {
+            "rfdc": "^1.4.1"
+          }
+        },
+        "@vue/eslint-config-typescript": {
+          "version": "12.0.0",
+          "resolved": "https://registry.npmmirror.com/@vue/eslint-config-typescript/-/eslint-config-typescript-12.0.0.tgz",
+          "integrity": "sha512-StxLFet2Qe97T8+7L8pGlhYBBr8Eg05LPuTDVopQV6il+SK6qqom59BA/rcFipUef2jD8P2X44Vd8tMFytfvlg==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/eslint-plugin": "^6.7.0",
+            "@typescript-eslint/parser": "^6.7.0",
+            "vue-eslint-parser": "^9.3.1"
+          }
+        },
+        "@vue/language-core": {
+          "version": "2.0.29",
+          "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.0.29.tgz",
+          "integrity": "sha512-o2qz9JPjhdoVj8D2+9bDXbaI4q2uZTHQA/dbyZT4Bj1FR9viZxDJnLcKVHfxdn6wsOzRgpqIzJEEmSSvgMvDTQ==",
+          "dev": true,
+          "requires": {
+            "@volar/language-core": "~2.4.0-alpha.18",
+            "@vue/compiler-dom": "^3.4.0",
+            "@vue/compiler-vue2": "^2.7.16",
+            "@vue/shared": "^3.4.0",
+            "computeds": "^0.0.1",
+            "minimatch": "^9.0.3",
+            "muggle-string": "^0.4.1",
+            "path-browserify": "^1.0.1"
+          }
+        },
+        "@vue/reactivity": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.17.tgz",
+          "integrity": "sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==",
+          "requires": {
+            "@vue/shared": "3.5.17"
+          }
+        },
+        "@vue/runtime-core": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.17.tgz",
+          "integrity": "sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==",
+          "requires": {
+            "@vue/reactivity": "3.5.17",
+            "@vue/shared": "3.5.17"
+          }
+        },
+        "@vue/runtime-dom": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz",
+          "integrity": "sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==",
+          "requires": {
+            "@vue/reactivity": "3.5.17",
+            "@vue/runtime-core": "3.5.17",
+            "@vue/shared": "3.5.17",
+            "csstype": "^3.1.3"
+          }
+        },
+        "@vue/server-renderer": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.17.tgz",
+          "integrity": "sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==",
+          "requires": {
+            "@vue/compiler-ssr": "3.5.17",
+            "@vue/shared": "3.5.17"
+          }
+        },
+        "@vue/shared": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.17.tgz",
+          "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg=="
+        },
+        "@vue/tsconfig": {
+          "version": "0.5.1",
+          "resolved": "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.5.1.tgz",
+          "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==",
+          "dev": true
+        },
+        "@yarnpkg/lockfile": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmmirror.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+          "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ=="
+        },
+        "acorn": {
+          "version": "8.11.3",
+          "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.11.3.tgz",
+          "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+          "dev": true
+        },
+        "acorn-jsx": {
+          "version": "5.3.2",
+          "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+          "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+          "dev": true,
+          "requires": {}
+        },
+        "ajv": {
+          "version": "6.12.6",
+          "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
+          "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "animate.css": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmmirror.com/animate.css/-/animate.css-4.1.1.tgz",
+          "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ=="
+        },
+        "ansi-regex": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
+          "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+          "dev": true
+        },
+        "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"
+          }
+        },
+        "anymatch": {
+          "version": "3.1.3",
+          "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz",
+          "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+          "dev": true,
+          "requires": {
+            "normalize-path": "^3.0.0",
+            "picomatch": "^2.0.4"
+          }
+        },
+        "argparse": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
+          "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+        },
+        "array-ify": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/array-ify/-/array-ify-1.0.0.tgz",
+          "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==",
+          "dev": true
+        },
+        "array-union": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz",
+          "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+          "dev": true
+        },
+        "arrify": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmmirror.com/arrify/-/arrify-1.0.1.tgz",
+          "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
+          "dev": true
+        },
+        "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.7.9",
+          "resolved": "https://registry.npmmirror.com/axios/-/axios-1.7.9.tgz",
+          "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
+          "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==",
+          "dev": true
+        },
+        "base64-arraybuffer": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+          "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="
+        },
+        "baseline-browser-mapping": {
+          "version": "2.10.13",
+          "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.13.tgz",
+          "integrity": "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw==",
+          "dev": true
+        },
+        "binary-extensions": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
+          "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+          "dev": true
+        },
+        "birpc": {
+          "version": "0.2.19",
+          "resolved": "https://registry.npmmirror.com/birpc/-/birpc-0.2.19.tgz",
+          "integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ=="
+        },
+        "boolbase": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz",
+          "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+          "dev": true
+        },
+        "brace-expansion": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
+          "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0"
+          }
+        },
+        "braces": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz",
+          "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+          "requires": {
+            "fill-range": "^7.0.1"
+          }
+        },
+        "browserslist": {
+          "version": "4.28.2",
+          "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
+          "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+          "dev": true,
+          "requires": {
+            "baseline-browser-mapping": "^2.10.12",
+            "caniuse-lite": "^1.0.30001782",
+            "electron-to-chromium": "^1.5.328",
+            "node-releases": "^2.0.36",
+            "update-browserslist-db": "^1.2.3"
+          }
+        },
+        "call-bind": {
+          "version": "1.0.8",
+          "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.8.tgz",
+          "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+          "requires": {
+            "call-bind-apply-helpers": "^1.0.0",
+            "es-define-property": "^1.0.0",
+            "get-intrinsic": "^1.2.4",
+            "set-function-length": "^1.2.2"
+          }
+        },
+        "call-bind-apply-helpers": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/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"
+          }
+        },
+        "call-bound": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+          "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+          "requires": {
+            "call-bind-apply-helpers": "^1.0.2",
+            "get-intrinsic": "^1.3.0"
+          }
+        },
+        "callsites": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
+          "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+          "dev": true
+        },
+        "camelcase": {
+          "version": "5.3.1",
+          "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz",
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+          "dev": true
+        },
+        "camelcase-keys": {
+          "version": "6.2.2",
+          "resolved": "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+          "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+          "dev": true,
+          "requires": {
+            "camelcase": "^5.3.1",
+            "map-obj": "^4.0.0",
+            "quick-lru": "^4.0.1"
+          }
+        },
+        "caniuse-lite": {
+          "version": "1.0.30001782",
+          "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001782.tgz",
+          "integrity": "sha512-dZcaJLJeDMh4rELYFw1tvSn1bhZWYFOt468FcbHHxx/Z/dFidd1I6ciyFdi3iwfQCyOjqo9upF6lGQYtMiJWxw==",
+          "dev": true
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "chokidar": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz",
+          "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+          "dev": true,
+          "requires": {
+            "anymatch": "~3.1.2",
+            "braces": "~3.0.2",
+            "fsevents": "~2.3.2",
+            "glob-parent": "~5.1.2",
+            "is-binary-path": "~2.1.0",
+            "is-glob": "~4.0.1",
+            "normalize-path": "~3.0.0",
+            "readdirp": "~3.6.0"
+          },
+          "dependencies": {
+            "glob-parent": {
+              "version": "5.1.2",
+              "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
+              "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+              "dev": true,
+              "requires": {
+                "is-glob": "^4.0.1"
+              }
+            }
+          }
+        },
+        "ci-info": {
+          "version": "3.9.0",
+          "resolved": "https://registry.npmmirror.com/ci-info/-/ci-info-3.9.0.tgz",
+          "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="
+        },
+        "clipboard": {
+          "version": "2.0.11",
+          "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
+          "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
+          "requires": {
+            "good-listener": "^1.2.2",
+            "select": "^1.1.2",
+            "tiny-emitter": "^2.0.0"
+          }
+        },
+        "cliui": {
+          "version": "8.0.1",
+          "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz",
+          "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+          "dev": true,
+          "requires": {
+            "string-width": "^4.2.0",
+            "strip-ansi": "^6.0.1",
+            "wrap-ansi": "^7.0.0"
+          }
+        },
+        "codepage": {
+          "version": "1.15.0",
+          "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
+          "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA=="
+        },
+        "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"
+          }
+        },
+        "commander": {
+          "version": "8.3.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+          "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
+        },
+        "compare-func": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmmirror.com/compare-func/-/compare-func-2.0.0.tgz",
+          "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==",
+          "dev": true,
+          "requires": {
+            "array-ify": "^1.0.0",
+            "dot-prop": "^5.1.0"
+          }
+        },
+        "computeds": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmmirror.com/computeds/-/computeds-0.0.1.tgz",
+          "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==",
+          "dev": true
+        },
+        "concat-map": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
+          "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+          "dev": true
+        },
+        "conventional-changelog-angular": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmmirror.com/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz",
+          "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==",
+          "dev": true,
+          "requires": {
+            "compare-func": "^2.0.0"
+          }
+        },
+        "conventional-changelog-conventionalcommits": {
+          "version": "7.0.2",
+          "resolved": "https://registry.npmmirror.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz",
+          "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==",
+          "dev": true,
+          "requires": {
+            "compare-func": "^2.0.0"
+          }
+        },
+        "conventional-commits-parser": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmmirror.com/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz",
+          "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==",
+          "dev": true,
+          "requires": {
+            "is-text-path": "^2.0.0",
+            "JSONStream": "^1.3.5",
+            "meow": "^12.0.1",
+            "split2": "^4.0.0"
+          }
+        },
+        "convert-source-map": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+          "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+          "dev": true
+        },
+        "convertapi-js": {
+          "version": "1.0.8",
+          "resolved": "https://registry.npmjs.org/convertapi-js/-/convertapi-js-1.0.8.tgz",
+          "integrity": "sha512-iuwiXXyUEL4MqQgW7j/wRkxtaN4QrY1D9P/XEcumTHOEUSgvUe7idzvmDxAP+6eO+ZJ4FHQmZ8D9wjKDPy08bg=="
+        },
+        "copy-anything": {
+          "version": "3.0.5",
+          "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
+          "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
+          "requires": {
+            "is-what": "^4.1.8"
+          }
+        },
+        "core-js-pure": {
+          "version": "3.47.0",
+          "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.47.0.tgz",
+          "integrity": "sha512-BcxeDbzUrRnXGYIVAGFtcGQVNpFcUhVjr6W7F8XktvQW2iJP9e66GP6xdKotCRFlrxBvNIBrhwKteRXqMV86Nw=="
+        },
+        "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=="
+        },
+        "cosmiconfig": {
+          "version": "8.3.6",
+          "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
+          "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
+          "dev": true,
+          "requires": {
+            "import-fresh": "^3.3.0",
+            "js-yaml": "^4.1.0",
+            "parse-json": "^5.2.0",
+            "path-type": "^4.0.0"
+          },
+          "dependencies": {
+            "json-parse-even-better-errors": {
+              "version": "2.3.1",
+              "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+              "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+              "dev": true
+            },
+            "lines-and-columns": {
+              "version": "1.2.4",
+              "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+              "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+              "dev": true
+            },
+            "parse-json": {
+              "version": "5.2.0",
+              "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz",
+              "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+              "dev": true,
+              "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "error-ex": "^1.3.1",
+                "json-parse-even-better-errors": "^2.3.0",
+                "lines-and-columns": "^1.1.6"
+              }
+            }
+          }
+        },
+        "cosmiconfig-typescript-loader": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmmirror.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz",
+          "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==",
+          "dev": true,
+          "requires": {
+            "jiti": "^1.19.1"
+          }
+        },
+        "cross-spawn": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz",
+          "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+          "requires": {
+            "path-key": "^3.1.0",
+            "shebang-command": "^2.0.0",
+            "which": "^2.0.1"
+          }
+        },
+        "crypto-js": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
+          "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
+        },
+        "css-line-break": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
+          "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+          "requires": {
+            "utrie": "^1.0.2"
+          }
+        },
+        "cssesc": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz",
+          "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+          "dev": true
+        },
+        "csstype": {
+          "version": "3.1.3",
+          "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
+          "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+        },
+        "dargs": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmmirror.com/dargs/-/dargs-7.0.0.tgz",
+          "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
+          "dev": true
+        },
+        "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
+        },
+        "debug": {
+          "version": "4.3.4",
+          "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz",
+          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+          "dev": true,
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "decamelize": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
+          "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+          "dev": true
+        },
+        "decamelize-keys": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmmirror.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
+          "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
+          "dev": true,
+          "requires": {
+            "decamelize": "^1.1.0",
+            "map-obj": "^1.0.0"
+          },
+          "dependencies": {
+            "map-obj": {
+              "version": "1.0.1",
+              "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-1.0.1.tgz",
+              "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
+              "dev": true
+            }
+          }
+        },
+        "deep-is": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz",
+          "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+          "dev": true
+        },
+        "define-data-property": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz",
+          "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+          "requires": {
+            "es-define-property": "^1.0.0",
+            "es-errors": "^1.3.0",
+            "gopd": "^1.0.1"
+          }
+        },
+        "delayed-stream": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+          "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+        },
+        "delegate": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
+          "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+        },
+        "dexie": {
+          "version": "4.0.11",
+          "resolved": "https://registry.npmmirror.com/dexie/-/dexie-4.0.11.tgz",
+          "integrity": "sha512-SOKO002EqlvBYYKQSew3iymBoN2EQ4BDw/3yprjh7kAfFzjBYkaMNa/pZvcA7HSWlcKSQb9XhPe3wKyQ0x4A8A=="
+        },
+        "dir-glob": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz",
+          "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+          "dev": true,
+          "requires": {
+            "path-type": "^4.0.0"
+          }
+        },
+        "doctrine": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz",
+          "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+          "dev": true,
+          "requires": {
+            "esutils": "^2.0.2"
+          }
+        },
+        "dot-prop": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmmirror.com/dot-prop/-/dot-prop-5.3.0.tgz",
+          "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+          "dev": true,
+          "requires": {
+            "is-obj": "^2.0.0"
+          }
+        },
+        "dunder-proto": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/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"
+          }
+        },
+        "echarts": {
+          "version": "5.6.0",
+          "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.6.0.tgz",
+          "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
+          "requires": {
+            "tslib": "2.3.0",
+            "zrender": "5.6.1"
+          }
+        },
+        "echarts-wordcloud": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/echarts-wordcloud/-/echarts-wordcloud-2.1.0.tgz",
+          "integrity": "sha512-Kt1JmbcROgb+3IMI48KZECK2AP5lG6bSsOEs+AsuwaWJxQom31RTNd6NFYI01E/YaI1PFZeueaupjlmzSQasjQ==",
+          "requires": {}
+        },
+        "electron-to-chromium": {
+          "version": "1.5.330",
+          "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.330.tgz",
+          "integrity": "sha512-jFNydB5kFtYUobh4IkWUnXeyDbjf/r9gcUEXe1xcrcUxIGfTdzPXA+ld6zBRbwvgIGVzDll/LTIiDztEtckSnA==",
+          "dev": true
+        },
+        "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==",
+          "dev": true
+        },
+        "entities": {
+          "version": "4.5.0",
+          "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
+          "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
+        },
+        "error-ex": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz",
+          "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+          "dev": true,
+          "requires": {
+            "is-arrayish": "^0.2.1"
+          }
+        },
+        "es-define-property": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+          "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="
+        },
+        "es-errors": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+          "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
+        },
+        "es-object-atoms": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+          "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+          "requires": {
+            "es-errors": "^1.3.0"
+          }
+        },
+        "esbuild": {
+          "version": "0.21.5",
+          "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz",
+          "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+          "dev": true,
+          "requires": {
+            "@esbuild/aix-ppc64": "0.21.5",
+            "@esbuild/android-arm": "0.21.5",
+            "@esbuild/android-arm64": "0.21.5",
+            "@esbuild/android-x64": "0.21.5",
+            "@esbuild/darwin-arm64": "0.21.5",
+            "@esbuild/darwin-x64": "0.21.5",
+            "@esbuild/freebsd-arm64": "0.21.5",
+            "@esbuild/freebsd-x64": "0.21.5",
+            "@esbuild/linux-arm": "0.21.5",
+            "@esbuild/linux-arm64": "0.21.5",
+            "@esbuild/linux-ia32": "0.21.5",
+            "@esbuild/linux-loong64": "0.21.5",
+            "@esbuild/linux-mips64el": "0.21.5",
+            "@esbuild/linux-ppc64": "0.21.5",
+            "@esbuild/linux-riscv64": "0.21.5",
+            "@esbuild/linux-s390x": "0.21.5",
+            "@esbuild/linux-x64": "0.21.5",
+            "@esbuild/netbsd-x64": "0.21.5",
+            "@esbuild/openbsd-x64": "0.21.5",
+            "@esbuild/sunos-x64": "0.21.5",
+            "@esbuild/win32-arm64": "0.21.5",
+            "@esbuild/win32-ia32": "0.21.5",
+            "@esbuild/win32-x64": "0.21.5"
+          }
+        },
+        "escalade": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+          "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+          "dev": true
+        },
+        "escape-string-regexp": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+          "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+          "dev": true
+        },
+        "eslint": {
+          "version": "8.56.0",
+          "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.56.0.tgz",
+          "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
+          "dev": true,
+          "requires": {
+            "@eslint-community/eslint-utils": "^4.2.0",
+            "@eslint-community/regexpp": "^4.6.1",
+            "@eslint/eslintrc": "^2.1.4",
+            "@eslint/js": "8.56.0",
+            "@humanwhocodes/config-array": "^0.11.13",
+            "@humanwhocodes/module-importer": "^1.0.1",
+            "@nodelib/fs.walk": "^1.2.8",
+            "@ungap/structured-clone": "^1.2.0",
+            "ajv": "^6.12.4",
+            "chalk": "^4.0.0",
+            "cross-spawn": "^7.0.2",
+            "debug": "^4.3.2",
+            "doctrine": "^3.0.0",
+            "escape-string-regexp": "^4.0.0",
+            "eslint-scope": "^7.2.2",
+            "eslint-visitor-keys": "^3.4.3",
+            "espree": "^9.6.1",
+            "esquery": "^1.4.2",
+            "esutils": "^2.0.2",
+            "fast-deep-equal": "^3.1.3",
+            "file-entry-cache": "^6.0.1",
+            "find-up": "^5.0.0",
+            "glob-parent": "^6.0.2",
+            "globals": "^13.19.0",
+            "graphemer": "^1.4.0",
+            "ignore": "^5.2.0",
+            "imurmurhash": "^0.1.4",
+            "is-glob": "^4.0.0",
+            "is-path-inside": "^3.0.3",
+            "js-yaml": "^4.1.0",
+            "json-stable-stringify-without-jsonify": "^1.0.1",
+            "levn": "^0.4.1",
+            "lodash.merge": "^4.6.2",
+            "minimatch": "^3.1.2",
+            "natural-compare": "^1.4.0",
+            "optionator": "^0.9.3",
+            "strip-ansi": "^6.0.1",
+            "text-table": "^0.2.0"
+          },
+          "dependencies": {
+            "brace-expansion": {
+              "version": "1.1.11",
+              "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
+              "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+              "dev": true,
+              "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+              }
+            },
+            "minimatch": {
+              "version": "3.1.2",
+              "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
+              "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+              "dev": true,
+              "requires": {
+                "brace-expansion": "^1.1.7"
+              }
+            }
+          }
+        },
+        "eslint-plugin-vue": {
+          "version": "9.19.2",
+          "resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.19.2.tgz",
+          "integrity": "sha512-CPDqTOG2K4Ni2o4J5wixkLVNwgctKXFu6oBpVJlpNq7f38lh9I80pRTouZSJ2MAebPJlINU/KTFSXyQfBUlymA==",
+          "dev": true,
+          "requires": {
+            "@eslint-community/eslint-utils": "^4.4.0",
+            "natural-compare": "^1.4.0",
+            "nth-check": "^2.1.1",
+            "postcss-selector-parser": "^6.0.13",
+            "semver": "^7.5.4",
+            "vue-eslint-parser": "^9.3.1",
+            "xml-name-validator": "^4.0.0"
+          }
+        },
+        "eslint-scope": {
+          "version": "7.2.2",
+          "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.2.tgz",
+          "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+          "dev": true,
+          "requires": {
+            "esrecurse": "^4.3.0",
+            "estraverse": "^5.2.0"
+          }
+        },
+        "eslint-visitor-keys": {
+          "version": "3.4.3",
+          "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+          "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+          "dev": true
+        },
+        "espree": {
+          "version": "9.6.1",
+          "resolved": "https://registry.npmmirror.com/espree/-/espree-9.6.1.tgz",
+          "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+          "dev": true,
+          "requires": {
+            "acorn": "^8.9.0",
+            "acorn-jsx": "^5.3.2",
+            "eslint-visitor-keys": "^3.4.1"
+          }
+        },
+        "esquery": {
+          "version": "1.5.0",
+          "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.5.0.tgz",
+          "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+          "dev": true,
+          "requires": {
+            "estraverse": "^5.1.0"
+          }
+        },
+        "esrecurse": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz",
+          "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+          "dev": true,
+          "requires": {
+            "estraverse": "^5.2.0"
+          }
+        },
+        "estraverse": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
+          "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+          "dev": true
+        },
+        "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=="
+        },
+        "esutils": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz",
+          "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+          "dev": true
+        },
+        "execa": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmmirror.com/execa/-/execa-5.1.1.tgz",
+          "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "^7.0.3",
+            "get-stream": "^6.0.0",
+            "human-signals": "^2.1.0",
+            "is-stream": "^2.0.0",
+            "merge-stream": "^2.0.0",
+            "npm-run-path": "^4.0.1",
+            "onetime": "^5.1.2",
+            "signal-exit": "^3.0.3",
+            "strip-final-newline": "^2.0.0"
+          }
+        },
+        "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==",
+          "dev": true
+        },
+        "fast-glob": {
+          "version": "3.3.2",
+          "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz",
+          "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+          "dev": true,
+          "requires": {
+            "@nodelib/fs.stat": "^2.0.2",
+            "@nodelib/fs.walk": "^1.2.3",
+            "glob-parent": "^5.1.2",
+            "merge2": "^1.3.0",
+            "micromatch": "^4.0.4"
+          },
+          "dependencies": {
+            "glob-parent": {
+              "version": "5.1.2",
+              "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
+              "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+              "dev": true,
+              "requires": {
+                "is-glob": "^4.0.1"
+              }
+            }
+          }
+        },
+        "fast-json-stable-stringify": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+          "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+          "dev": true
+        },
+        "fast-levenshtein": {
+          "version": "2.0.6",
+          "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+          "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+          "dev": true
+        },
+        "fastq": {
+          "version": "1.16.0",
+          "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.16.0.tgz",
+          "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
+          "dev": true,
+          "requires": {
+            "reusify": "^1.0.4"
+          }
+        },
+        "file-entry-cache": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+          "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+          "dev": true,
+          "requires": {
+            "flat-cache": "^3.0.4"
+          }
+        },
+        "file-saver": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz",
+          "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
+        },
+        "fill-range": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz",
+          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+          "requires": {
+            "to-regex-range": "^5.0.1"
+          }
+        },
+        "find-up": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz",
+          "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^6.0.0",
+            "path-exists": "^4.0.0"
+          }
+        },
+        "find-yarn-workspace-root": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmmirror.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
+          "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
+          "requires": {
+            "micromatch": "^4.0.2"
+          }
+        },
+        "flat-cache": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.2.0.tgz",
+          "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+          "dev": true,
+          "requires": {
+            "flatted": "^3.2.9",
+            "keyv": "^4.5.3",
+            "rimraf": "^3.0.2"
+          }
+        },
+        "flatted": {
+          "version": "3.2.9",
+          "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.2.9.tgz",
+          "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+          "dev": true
+        },
+        "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=="
+        },
+        "form-data": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.1.tgz",
+          "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+          "requires": {
+            "asynckit": "^0.4.0",
+            "combined-stream": "^1.0.8",
+            "mime-types": "^2.1.12"
+          }
+        },
+        "fs-extra": {
+          "version": "11.2.0",
+          "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.2.0.tgz",
+          "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.2.0",
+            "jsonfile": "^6.0.1",
+            "universalify": "^2.0.0"
+          }
+        },
+        "fs.realpath": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
+          "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+          "dev": true
+        },
+        "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
+        },
+        "function-bind": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+          "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+        },
+        "gensync": {
+          "version": "1.0.0-beta.2",
+          "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+          "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+          "dev": true
+        },
+        "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==",
+          "dev": true
+        },
+        "get-intrinsic": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/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.npmjs.org/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"
+          }
+        },
+        "get-stream": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz",
+          "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+          "dev": true
+        },
+        "git-raw-commits": {
+          "version": "2.0.11",
+          "resolved": "https://registry.npmmirror.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz",
+          "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==",
+          "dev": true,
+          "requires": {
+            "dargs": "^7.0.0",
+            "lodash": "^4.17.15",
+            "meow": "^8.0.0",
+            "split2": "^3.0.0",
+            "through2": "^4.0.0"
+          },
+          "dependencies": {
+            "hosted-git-info": {
+              "version": "4.1.0",
+              "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+              "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+              "dev": true,
+              "requires": {
+                "lru-cache": "^6.0.0"
+              }
+            },
+            "lru-cache": {
+              "version": "6.0.0",
+              "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz",
+              "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+              "dev": true,
+              "requires": {
+                "yallist": "^4.0.0"
+              }
+            },
+            "meow": {
+              "version": "8.1.2",
+              "resolved": "https://registry.npmmirror.com/meow/-/meow-8.1.2.tgz",
+              "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==",
+              "dev": true,
+              "requires": {
+                "@types/minimist": "^1.2.0",
+                "camelcase-keys": "^6.2.2",
+                "decamelize-keys": "^1.1.0",
+                "hard-rejection": "^2.1.0",
+                "minimist-options": "4.1.0",
+                "normalize-package-data": "^3.0.0",
+                "read-pkg-up": "^7.0.1",
+                "redent": "^3.0.0",
+                "trim-newlines": "^3.0.0",
+                "type-fest": "^0.18.0",
+                "yargs-parser": "^20.2.3"
+              }
+            },
+            "normalize-package-data": {
+              "version": "3.0.3",
+              "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+              "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+              "dev": true,
+              "requires": {
+                "hosted-git-info": "^4.0.1",
+                "is-core-module": "^2.5.0",
+                "semver": "^7.3.4",
+                "validate-npm-package-license": "^3.0.1"
+              }
+            },
+            "readable-stream": {
+              "version": "3.6.2",
+              "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+              "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+              "dev": true,
+              "requires": {
+                "inherits": "^2.0.3",
+                "string_decoder": "^1.1.1",
+                "util-deprecate": "^1.0.1"
+              }
+            },
+            "split2": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmmirror.com/split2/-/split2-3.2.2.tgz",
+              "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
+              "dev": true,
+              "requires": {
+                "readable-stream": "^3.0.0"
+              }
+            },
+            "through2": {
+              "version": "4.0.2",
+              "resolved": "https://registry.npmmirror.com/through2/-/through2-4.0.2.tgz",
+              "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
+              "dev": true,
+              "requires": {
+                "readable-stream": "3"
+              }
+            },
+            "type-fest": {
+              "version": "0.18.1",
+              "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.18.1.tgz",
+              "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
+              "dev": true
+            },
+            "yargs-parser": {
+              "version": "20.2.9",
+              "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz",
+              "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+              "dev": true
+            }
+          }
+        },
+        "glob": {
+          "version": "7.2.3",
+          "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
+          "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+          "dev": true,
+          "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.11",
+              "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
+              "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+              "dev": true,
+              "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+              }
+            },
+            "minimatch": {
+              "version": "3.1.2",
+              "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
+              "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+              "dev": true,
+              "requires": {
+                "brace-expansion": "^1.1.7"
+              }
+            }
+          }
+        },
+        "glob-parent": {
+          "version": "6.0.2",
+          "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz",
+          "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+          "dev": true,
+          "requires": {
+            "is-glob": "^4.0.3"
+          }
+        },
+        "global-dirs": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmmirror.com/global-dirs/-/global-dirs-0.1.1.tgz",
+          "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==",
+          "dev": true,
+          "requires": {
+            "ini": "^1.3.4"
+          }
+        },
+        "globals": {
+          "version": "13.24.0",
+          "resolved": "https://registry.npmmirror.com/globals/-/globals-13.24.0.tgz",
+          "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+          "dev": true,
+          "requires": {
+            "type-fest": "^0.20.2"
+          }
+        },
+        "globby": {
+          "version": "11.1.0",
+          "resolved": "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz",
+          "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+          "dev": true,
+          "requires": {
+            "array-union": "^2.1.0",
+            "dir-glob": "^3.0.1",
+            "fast-glob": "^3.2.9",
+            "ignore": "^5.2.0",
+            "merge2": "^1.4.1",
+            "slash": "^3.0.0"
+          }
+        },
+        "good-listener": {
+          "version": "1.2.2",
+          "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
+          "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+          "requires": {
+            "delegate": "^3.1.2"
+          }
+        },
+        "gopd": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/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=="
+        },
+        "graphemer": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz",
+          "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+          "dev": true
+        },
+        "hard-rejection": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmmirror.com/hard-rejection/-/hard-rejection-2.1.0.tgz",
+          "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+        },
+        "has-property-descriptors": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+          "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+          "requires": {
+            "es-define-property": "^1.0.0"
+          }
+        },
+        "has-symbols": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+          "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="
+        },
+        "hasown": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/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
+        },
+        "hfmath": {
+          "version": "0.0.2",
+          "resolved": "https://registry.npmmirror.com/hfmath/-/hfmath-0.0.2.tgz",
+          "integrity": "sha512-cKUi0yiQLGfLgs8+3Iw5nAiqSH13Knp7vCf0G1vlF5nfiKKO1XmxNagMvyp0F4ZvUNaHpRGTkmc7nowCy1S58g=="
+        },
+        "hookable": {
+          "version": "5.5.3",
+          "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
+          "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
+        },
+        "hosted-git-info": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-7.0.1.tgz",
+          "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^10.0.1"
+          }
+        },
+        "html-to-image": {
+          "version": "1.11.13",
+          "resolved": "https://registry.npmmirror.com/html-to-image/-/html-to-image-1.11.13.tgz",
+          "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg=="
+        },
+        "html2canvas": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
+          "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+          "requires": {
+            "css-line-break": "^2.1.0",
+            "text-segmentation": "^1.0.3"
+          }
+        },
+        "https": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/https/-/https-1.0.0.tgz",
+          "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg=="
+        },
+        "human-signals": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz",
+          "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+          "dev": true
+        },
+        "husky": {
+          "version": "8.0.3",
+          "resolved": "https://registry.npmmirror.com/husky/-/husky-8.0.3.tgz",
+          "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
+          "dev": true
+        },
+        "ignore": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.0.tgz",
+          "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
+          "dev": true
+        },
+        "image-size": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmmirror.com/image-size/-/image-size-1.1.0.tgz",
+          "integrity": "sha512-asnTHw2K8OlqT5kVnQwX+AGKQqpvLo95LbNzQ/C0ln3yzentZmAdd0ygoD004VC4Kkd4PV7J2iaPQkqwp9yuTw==",
+          "requires": {
+            "queue": "6.0.2"
+          }
+        },
+        "immediate": {
+          "version": "3.0.6",
+          "resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz",
+          "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
+        },
+        "immutable": {
+          "version": "4.3.7",
+          "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.7.tgz",
+          "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==",
+          "dev": true
+        },
+        "import-fresh": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
+          "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+          "dev": true,
+          "requires": {
+            "parent-module": "^1.0.0",
+            "resolve-from": "^4.0.0"
+          }
+        },
+        "imurmurhash": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz",
+          "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+          "dev": true
+        },
+        "indent-string": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz",
+          "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+          "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==",
+          "dev": true,
+          "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=="
+        },
+        "ini": {
+          "version": "1.3.8",
+          "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz",
+          "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+          "dev": true
+        },
+        "is-arrayish": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz",
+          "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+          "dev": true
+        },
+        "is-binary-path": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
+          "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+          "dev": true,
+          "requires": {
+            "binary-extensions": "^2.0.0"
+          }
+        },
+        "is-core-module": {
+          "version": "2.13.1",
+          "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.13.1.tgz",
+          "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+          "dev": true,
+          "requires": {
+            "hasown": "^2.0.0"
+          }
+        },
+        "is-docker": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz",
+          "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="
+        },
+        "is-extglob": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+          "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+          "dev": 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==",
+          "dev": true
+        },
+        "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,
+          "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=="
+        },
+        "is-obj": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmmirror.com/is-obj/-/is-obj-2.0.0.tgz",
+          "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+          "dev": true
+        },
+        "is-path-inside": {
+          "version": "3.0.3",
+          "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz",
+          "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+          "dev": true
+        },
+        "is-plain-obj": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+          "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
+          "dev": true
+        },
+        "is-stream": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz",
+          "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+          "dev": true
+        },
+        "is-text-path": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmmirror.com/is-text-path/-/is-text-path-2.0.0.tgz",
+          "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==",
+          "dev": true,
+          "requires": {
+            "text-extensions": "^2.0.0"
+          }
+        },
+        "is-what": {
+          "version": "4.1.16",
+          "resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz",
+          "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="
+        },
+        "is-wsl": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz",
+          "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+          "requires": {
+            "is-docker": "^2.0.0"
+          }
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+        },
+        "isexe": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
+          "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+        },
+        "isomorphic.js": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz",
+          "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw=="
+        },
+        "jiti": {
+          "version": "1.21.0",
+          "resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.21.0.tgz",
+          "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
+          "dev": true
+        },
+        "js-tokens": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+          "dev": true
+        },
+        "js-yaml": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz",
+          "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+          "dev": true,
+          "requires": {
+            "argparse": "^2.0.1"
+          }
+        },
+        "jsesc": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+          "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+          "dev": true
+        },
+        "json-buffer": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz",
+          "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+          "dev": true
+        },
+        "json-parse-even-better-errors": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz",
+          "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==",
+          "dev": true
+        },
+        "json-schema-traverse": {
+          "version": "0.4.1",
+          "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+          "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+          "dev": true
+        },
+        "json-stable-stringify": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmmirror.com/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
+          "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==",
+          "requires": {
+            "call-bind": "^1.0.8",
+            "call-bound": "^1.0.4",
+            "isarray": "^2.0.5",
+            "jsonify": "^0.0.1",
+            "object-keys": "^1.1.1"
+          },
+          "dependencies": {
+            "isarray": {
+              "version": "2.0.5",
+              "resolved": "https://registry.npmmirror.com/isarray/-/isarray-2.0.5.tgz",
+              "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
+            }
+          }
+        },
+        "json-stable-stringify-without-jsonify": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+          "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+          "dev": true
+        },
+        "json5": {
+          "version": "2.2.3",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+          "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+          "dev": true
+        },
+        "jsonfile": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz",
+          "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+          "requires": {
+            "graceful-fs": "^4.1.6",
+            "universalify": "^2.0.0"
+          }
+        },
+        "jsonify": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmmirror.com/jsonify/-/jsonify-0.0.1.tgz",
+          "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg=="
+        },
+        "jsonparse": {
+          "version": "1.3.1",
+          "resolved": "https://registry.npmmirror.com/jsonparse/-/jsonparse-1.3.1.tgz",
+          "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+          "dev": true
+        },
+        "JSONStream": {
+          "version": "1.3.5",
+          "resolved": "https://registry.npmmirror.com/JSONStream/-/JSONStream-1.3.5.tgz",
+          "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+          "dev": true,
+          "requires": {
+            "jsonparse": "^1.2.0",
+            "through": ">=2.2.7 <3"
+          }
+        },
+        "jszip": {
+          "version": "3.10.1",
+          "resolved": "https://registry.npmjs.org/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"
+          }
+        },
+        "katex": {
+          "version": "0.16.22",
+          "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz",
+          "integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==",
+          "requires": {
+            "commander": "^8.3.0"
+          }
+        },
+        "keyv": {
+          "version": "4.5.4",
+          "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
+          "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+          "dev": true,
+          "requires": {
+            "json-buffer": "3.0.1"
+          }
+        },
+        "kind-of": {
+          "version": "6.0.3",
+          "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz",
+          "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+          "dev": true
+        },
+        "klaw-sync": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmmirror.com/klaw-sync/-/klaw-sync-6.0.0.tgz",
+          "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
+          "requires": {
+            "graceful-fs": "^4.1.11"
+          }
+        },
+        "kolorist": {
+          "version": "1.8.0",
+          "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
+          "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==",
+          "dev": true
+        },
+        "levn": {
+          "version": "0.4.1",
+          "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",
+          "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+          "dev": true,
+          "requires": {
+            "prelude-ls": "^1.2.1",
+            "type-check": "~0.4.0"
+          }
+        },
+        "lib0": {
+          "version": "0.2.114",
+          "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.114.tgz",
+          "integrity": "sha512-gcxmNFzA4hv8UYi8j43uPlQ7CGcyMJ2KQb5kZASw6SnAKAf10hK12i2fjrS3Cl/ugZa5Ui6WwIu1/6MIXiHttQ==",
+          "requires": {
+            "isomorphic.js": "^0.2.4"
+          }
+        },
+        "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"
+          }
+        },
+        "lines-and-columns": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-2.0.4.tgz",
+          "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==",
+          "dev": true
+        },
+        "linkify-it": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+          "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+          "requires": {
+            "uc.micro": "^2.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz",
+          "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^5.0.0"
+          }
+        },
+        "lodash": {
+          "version": "4.17.21",
+          "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
+          "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+        },
+        "lodash.camelcase": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+          "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+          "dev": true
+        },
+        "lodash.isfunction": {
+          "version": "3.0.9",
+          "resolved": "https://registry.npmmirror.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+          "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==",
+          "dev": true
+        },
+        "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==",
+          "dev": true
+        },
+        "lodash.kebabcase": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmmirror.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
+          "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
+          "dev": true
+        },
+        "lodash.merge": {
+          "version": "4.6.2",
+          "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
+          "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+          "dev": true
+        },
+        "lodash.mergewith": {
+          "version": "4.6.2",
+          "resolved": "https://registry.npmmirror.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
+          "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
+          "dev": true
+        },
+        "lodash.snakecase": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmmirror.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
+          "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
+          "dev": true
+        },
+        "lodash.startcase": {
+          "version": "4.4.0",
+          "resolved": "https://registry.npmmirror.com/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
+          "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
+          "dev": true
+        },
+        "lodash.uniq": {
+          "version": "4.5.0",
+          "resolved": "https://registry.npmmirror.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+          "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
+          "dev": true
+        },
+        "lodash.upperfirst": {
+          "version": "4.3.1",
+          "resolved": "https://registry.npmmirror.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz",
+          "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==",
+          "dev": true
+        },
+        "lru-cache": {
+          "version": "10.1.0",
+          "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.1.0.tgz",
+          "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==",
+          "dev": true
+        },
+        "magic-string": {
+          "version": "0.30.21",
+          "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+          "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+          "requires": {
+            "@jridgewell/sourcemap-codec": "^1.5.5"
+          }
+        },
+        "map-obj": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-4.3.0.tgz",
+          "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
+          "dev": true
+        },
+        "markdown-it": {
+          "version": "14.1.1",
+          "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz",
+          "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==",
+          "requires": {
+            "argparse": "^2.0.1",
+            "entities": "^4.4.0",
+            "linkify-it": "^5.0.0",
+            "mdurl": "^2.0.0",
+            "punycode.js": "^2.3.1",
+            "uc.micro": "^2.1.0"
+          }
+        },
+        "math-intrinsics": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+          "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="
+        },
+        "mdurl": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+          "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="
+        },
+        "memorystream": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmmirror.com/memorystream/-/memorystream-0.3.1.tgz",
+          "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+          "dev": true
+        },
+        "meow": {
+          "version": "12.1.1",
+          "resolved": "https://registry.npmmirror.com/meow/-/meow-12.1.1.tgz",
+          "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==",
+          "dev": true
+        },
+        "merge-stream": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz",
+          "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+          "dev": true
+        },
+        "merge2": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz",
+          "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+          "dev": true
+        },
+        "micromatch": {
+          "version": "4.0.5",
+          "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz",
+          "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+          "requires": {
+            "braces": "^3.0.2",
+            "picomatch": "^2.3.1"
+          }
+        },
+        "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"
+          }
+        },
+        "mimic-fn": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz",
+          "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+          "dev": true
+        },
+        "min-indent": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz",
+          "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+          "dev": true
+        },
+        "minimatch": {
+          "version": "9.0.3",
+          "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.3.tgz",
+          "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+          "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=="
+        },
+        "minimist-options": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmmirror.com/minimist-options/-/minimist-options-4.1.0.tgz",
+          "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+          "dev": true,
+          "requires": {
+            "arrify": "^1.0.1",
+            "is-plain-obj": "^1.1.0",
+            "kind-of": "^6.0.3"
+          }
+        },
+        "mitt": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
+          "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
+        },
+        "mp4-muxer": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmmirror.com/mp4-muxer/-/mp4-muxer-2.3.0.tgz",
+          "integrity": "sha512-eupg1QMfcVJy/nZ2smUbC4OcEKdKBaLxKe+oeoDlklB5Dkb+4mv4CdPVYtzo1ZnzBKuVCclDk/znQwFQJIC32g==",
+          "requires": {
+            "@types/dom-webcodecs": "^0.1.6",
+            "@types/wicg-file-system-access": "^2020.9.5"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        },
+        "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": "5.0.7",
+          "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-5.0.7.tgz",
+          "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ=="
+        },
+        "natural-compare": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz",
+          "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+          "dev": true
+        },
+        "node-releases": {
+          "version": "2.0.36",
+          "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
+          "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
+          "dev": true
+        },
+        "normalize-package-data": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-6.0.0.tgz",
+          "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==",
+          "dev": true,
+          "requires": {
+            "hosted-git-info": "^7.0.0",
+            "is-core-module": "^2.8.1",
+            "semver": "^7.3.5",
+            "validate-npm-package-license": "^3.0.4"
+          }
+        },
+        "normalize-path": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
+          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+          "dev": true
+        },
+        "npm-run-all2": {
+          "version": "6.1.1",
+          "resolved": "https://registry.npmmirror.com/npm-run-all2/-/npm-run-all2-6.1.1.tgz",
+          "integrity": "sha512-lWLbkPZ5BSdXtN8lR+0rc8caKoPdymycpZksyDEC9MOBvfdwTXZ0uVhb7bMcGeXv2/BKtfQuo6Zn3zfc8rxNXA==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^6.2.1",
+            "cross-spawn": "^7.0.3",
+            "memorystream": "^0.3.1",
+            "minimatch": "^9.0.0",
+            "pidtree": "^0.6.0",
+            "read-pkg": "^8.0.0",
+            "shell-quote": "^1.7.3"
+          },
+          "dependencies": {
+            "ansi-styles": {
+              "version": "6.2.1",
+              "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz",
+              "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+              "dev": true
+            }
+          }
+        },
+        "npm-run-path": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz",
+          "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+          "dev": true,
+          "requires": {
+            "path-key": "^3.0.0"
+          }
+        },
+        "nth-check": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz",
+          "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+          "dev": true,
+          "requires": {
+            "boolbase": "^1.0.0"
+          }
+        },
+        "number-precision": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmmirror.com/number-precision/-/number-precision-1.6.0.tgz",
+          "integrity": "sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ=="
+        },
+        "object-inspect": {
+          "version": "1.13.4",
+          "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+          "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="
+        },
+        "object-keys": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz",
+          "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+        },
+        "once": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
+          "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+          "dev": true,
+          "requires": {
+            "wrappy": "1"
+          }
+        },
+        "onetime": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz",
+          "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+          "dev": true,
+          "requires": {
+            "mimic-fn": "^2.1.0"
+          }
+        },
+        "open": {
+          "version": "7.4.2",
+          "resolved": "https://registry.npmmirror.com/open/-/open-7.4.2.tgz",
+          "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+          "requires": {
+            "is-docker": "^2.0.0",
+            "is-wsl": "^2.1.1"
+          }
+        },
+        "optionator": {
+          "version": "0.9.3",
+          "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.3.tgz",
+          "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+          "dev": true,
+          "requires": {
+            "@aashutoshrathi/word-wrap": "^1.2.3",
+            "deep-is": "^0.1.3",
+            "fast-levenshtein": "^2.0.6",
+            "levn": "^0.4.1",
+            "prelude-ls": "^1.2.1",
+            "type-check": "^0.4.0"
+          }
+        },
+        "orderedmap": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmmirror.com/orderedmap/-/orderedmap-2.1.1.tgz",
+          "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g=="
+        },
+        "p-limit": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz",
+          "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+          "dev": true,
+          "requires": {
+            "yocto-queue": "^0.1.0"
+          }
+        },
+        "p-locate": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz",
+          "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^3.0.2"
+          }
+        },
+        "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==",
+          "dev": true
+        },
+        "pako": {
+          "version": "1.0.11",
+          "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz",
+          "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
+        },
+        "parent-module": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz",
+          "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+          "dev": true,
+          "requires": {
+            "callsites": "^3.0.0"
+          }
+        },
+        "parse-json": {
+          "version": "7.1.1",
+          "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-7.1.1.tgz",
+          "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==",
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.21.4",
+            "error-ex": "^1.3.2",
+            "json-parse-even-better-errors": "^3.0.0",
+            "lines-and-columns": "^2.0.3",
+            "type-fest": "^3.8.0"
+          },
+          "dependencies": {
+            "type-fest": {
+              "version": "3.13.1",
+              "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-3.13.1.tgz",
+              "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
+              "dev": true
+            }
+          }
+        },
+        "patch-package": {
+          "version": "8.0.1",
+          "resolved": "https://registry.npmmirror.com/patch-package/-/patch-package-8.0.1.tgz",
+          "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==",
+          "requires": {
+            "@yarnpkg/lockfile": "^1.1.0",
+            "chalk": "^4.1.2",
+            "ci-info": "^3.7.0",
+            "cross-spawn": "^7.0.3",
+            "find-yarn-workspace-root": "^2.0.0",
+            "fs-extra": "^10.0.0",
+            "json-stable-stringify": "^1.0.2",
+            "klaw-sync": "^6.0.0",
+            "minimist": "^1.2.6",
+            "open": "^7.4.2",
+            "semver": "^7.5.3",
+            "slash": "^2.0.0",
+            "tmp": "^0.2.4",
+            "yaml": "^2.2.2"
+          },
+          "dependencies": {
+            "fs-extra": {
+              "version": "10.1.0",
+              "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz",
+              "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+              "requires": {
+                "graceful-fs": "^4.2.0",
+                "jsonfile": "^6.0.1",
+                "universalify": "^2.0.0"
+              }
+            },
+            "slash": {
+              "version": "2.0.0",
+              "resolved": "https://registry.npmmirror.com/slash/-/slash-2.0.0.tgz",
+              "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A=="
+            }
+          }
+        },
+        "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==",
+          "dev": true
+        },
+        "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==",
+          "dev": true
+        },
+        "path-key": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz",
+          "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
+        },
+        "path-parse": {
+          "version": "1.0.7",
+          "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
+          "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+          "dev": true
+        },
+        "path-type": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz",
+          "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+          "dev": true
+        },
+        "perfect-debounce": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+          "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="
+        },
+        "picocolors": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+          "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+        },
+        "picomatch": {
+          "version": "2.3.1",
+          "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
+          "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
+        },
+        "pidtree": {
+          "version": "0.6.0",
+          "resolved": "https://registry.npmmirror.com/pidtree/-/pidtree-0.6.0.tgz",
+          "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+          "dev": true
+        },
+        "pinia": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmmirror.com/pinia/-/pinia-3.0.2.tgz",
+          "integrity": "sha512-sH2JK3wNY809JOeiiURUR0wehJ9/gd9qFN2Y828jCbxEzKEmEt0pzCXwqiSTfuRsK9vQsOflSdnbdBOGrhtn+g==",
+          "requires": {
+            "@vue/devtools-api": "^7.7.2"
+          }
+        },
+        "postcss": {
+          "version": "8.5.8",
+          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
+          "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+          "requires": {
+            "nanoid": "^3.3.11",
+            "picocolors": "^1.1.1",
+            "source-map-js": "^1.2.1"
+          },
+          "dependencies": {
+            "nanoid": {
+              "version": "3.3.11",
+              "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
+              "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="
+            }
+          }
+        },
+        "postcss-selector-parser": {
+          "version": "6.0.15",
+          "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz",
+          "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==",
+          "dev": true,
+          "requires": {
+            "cssesc": "^3.0.0",
+            "util-deprecate": "^1.0.2"
+          }
+        },
+        "pptxgenjs": {
+          "version": "3.12.0",
+          "resolved": "https://registry.npmmirror.com/pptxgenjs/-/pptxgenjs-3.12.0.tgz",
+          "integrity": "sha512-ZozkYKWb1MoPR4ucw3/aFYlHkVIJxo9czikEclcUVnS4Iw/M+r+TEwdlB3fyAWO9JY1USxJDt0Y0/r15IR/RUA==",
+          "requires": {
+            "@types/node": "^18.7.3",
+            "https": "^1.0.0",
+            "image-size": "^1.0.0",
+            "jszip": "^3.7.1"
+          }
+        },
+        "pptxtojson": {
+          "version": "1.12.0",
+          "resolved": "https://registry.npmmirror.com/pptxtojson/-/pptxtojson-1.12.0.tgz",
+          "integrity": "sha512-kXdCqXlCLdiGpM3womaQIpGYrQEzl8/jdxSpWWtYNj3Pxvr9n39tGpuBxeZSdenttwzM7Fb/yBKUPzxMFXLIJQ==",
+          "requires": {
+            "jszip": "^3.10.1",
+            "tinycolor2": "1.6.0",
+            "txml": "^5.1.1"
+          }
+        },
+        "prelude-ls": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz",
+          "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+          "dev": true
+        },
+        "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=="
+        },
+        "prosemirror-commands": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmmirror.com/prosemirror-commands/-/prosemirror-commands-1.6.0.tgz",
+          "integrity": "sha512-xn1U/g36OqXn2tn5nGmvnnimAj/g1pUx2ypJJIe8WkVX83WyJVC5LTARaxZa2AtQRwntu9Jc5zXs9gL9svp/mg==",
+          "requires": {
+            "prosemirror-model": "^1.0.0",
+            "prosemirror-state": "^1.0.0",
+            "prosemirror-transform": "^1.0.0"
+          }
+        },
+        "prosemirror-dropcursor": {
+          "version": "1.8.1",
+          "resolved": "https://registry.npmmirror.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.1.tgz",
+          "integrity": "sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==",
+          "requires": {
+            "prosemirror-state": "^1.0.0",
+            "prosemirror-transform": "^1.1.0",
+            "prosemirror-view": "^1.1.0"
+          }
+        },
+        "prosemirror-gapcursor": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmmirror.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz",
+          "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==",
+          "requires": {
+            "prosemirror-keymap": "^1.0.0",
+            "prosemirror-model": "^1.0.0",
+            "prosemirror-state": "^1.0.0",
+            "prosemirror-view": "^1.0.0"
+          }
+        },
+        "prosemirror-history": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmmirror.com/prosemirror-history/-/prosemirror-history-1.3.2.tgz",
+          "integrity": "sha512-/zm0XoU/N/+u7i5zepjmZAEnpvjDtzoPWW6VmKptcAnPadN/SStsBjMImdCEbb3seiNTpveziPTIrXQbHLtU1g==",
+          "requires": {
+            "prosemirror-state": "^1.2.2",
+            "prosemirror-transform": "^1.0.0",
+            "prosemirror-view": "^1.31.0",
+            "rope-sequence": "^1.3.0"
+          }
+        },
+        "prosemirror-inputrules": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmmirror.com/prosemirror-inputrules/-/prosemirror-inputrules-1.4.0.tgz",
+          "integrity": "sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==",
+          "requires": {
+            "prosemirror-state": "^1.0.0",
+            "prosemirror-transform": "^1.0.0"
+          }
+        },
+        "prosemirror-keymap": {
+          "version": "1.2.2",
+          "resolved": "https://registry.npmmirror.com/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz",
+          "integrity": "sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==",
+          "requires": {
+            "prosemirror-state": "^1.0.0",
+            "w3c-keyname": "^2.2.0"
+          }
+        },
+        "prosemirror-model": {
+          "version": "1.22.2",
+          "resolved": "https://registry.npmmirror.com/prosemirror-model/-/prosemirror-model-1.22.2.tgz",
+          "integrity": "sha512-I4lS7HHIW47D0Xv/gWmi4iUWcQIDYaJKd8Hk4+lcSps+553FlQrhmxtItpEvTr75iAruhzVShVp6WUwsT6Boww==",
+          "requires": {
+            "orderedmap": "^2.0.0"
+          }
+        },
+        "prosemirror-schema-basic": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmmirror.com/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.3.tgz",
+          "integrity": "sha512-h+H0OQwZVqMon1PNn0AG9cTfx513zgIG2DY00eJ00Yvgb3UD+GQ/VlWW5rcaxacpCGT1Yx8nuhwXk4+QbXUfJA==",
+          "requires": {
+            "prosemirror-model": "^1.19.0"
+          }
+        },
+        "prosemirror-schema-list": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmmirror.com/prosemirror-schema-list/-/prosemirror-schema-list-1.4.1.tgz",
+          "integrity": "sha512-jbDyaP/6AFfDfu70VzySsD75Om2t3sXTOdl5+31Wlxlg62td1haUpty/ybajSfJ1pkGadlOfwQq9kgW5IMo1Rg==",
+          "requires": {
+            "prosemirror-model": "^1.0.0",
+            "prosemirror-state": "^1.0.0",
+            "prosemirror-transform": "^1.7.3"
+          }
+        },
+        "prosemirror-state": {
+          "version": "1.4.3",
+          "resolved": "https://registry.npmmirror.com/prosemirror-state/-/prosemirror-state-1.4.3.tgz",
+          "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==",
+          "requires": {
+            "prosemirror-model": "^1.0.0",
+            "prosemirror-transform": "^1.0.0",
+            "prosemirror-view": "^1.27.0"
+          }
+        },
+        "prosemirror-transform": {
+          "version": "1.8.0",
+          "resolved": "https://registry.npmmirror.com/prosemirror-transform/-/prosemirror-transform-1.8.0.tgz",
+          "integrity": "sha512-BaSBsIMv52F1BVVMvOmp1yzD3u65uC3HTzCBQV1WDPqJRQ2LuHKcyfn0jwqodo8sR9vVzMzZyI+Dal5W9E6a9A==",
+          "requires": {
+            "prosemirror-model": "^1.0.0"
+          }
+        },
+        "prosemirror-view": {
+          "version": "1.33.9",
+          "resolved": "https://registry.npmmirror.com/prosemirror-view/-/prosemirror-view-1.33.9.tgz",
+          "integrity": "sha512-xV1A0Vz9cIcEnwmMhKKFAOkfIp8XmJRnaZoPqNXrPS7EK5n11Ov8V76KhR0RsfQd/SIzmWY+bg+M44A2Lx/Nnw==",
+          "requires": {
+            "prosemirror-model": "^1.20.0",
+            "prosemirror-state": "^1.0.0",
+            "prosemirror-transform": "^1.1.0"
+          }
+        },
+        "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=="
+        },
+        "punycode": {
+          "version": "2.3.1",
+          "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
+          "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+          "dev": true
+        },
+        "punycode.js": {
+          "version": "2.3.1",
+          "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+          "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="
+        },
+        "qs": {
+          "version": "6.14.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
+          "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
+          "requires": {
+            "side-channel": "^1.1.0"
+          }
+        },
+        "queue": {
+          "version": "6.0.2",
+          "resolved": "https://registry.npmmirror.com/queue/-/queue-6.0.2.tgz",
+          "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+          "requires": {
+            "inherits": "~2.0.3"
+          }
+        },
+        "queue-microtask": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
+          "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+          "dev": true
+        },
+        "quick-lru": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmmirror.com/quick-lru/-/quick-lru-4.0.1.tgz",
+          "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
+          "dev": true
+        },
+        "read-pkg": {
+          "version": "8.1.0",
+          "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-8.1.0.tgz",
+          "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==",
+          "dev": true,
+          "requires": {
+            "@types/normalize-package-data": "^2.4.1",
+            "normalize-package-data": "^6.0.0",
+            "parse-json": "^7.0.0",
+            "type-fest": "^4.2.0"
+          },
+          "dependencies": {
+            "type-fest": {
+              "version": "4.9.0",
+              "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-4.9.0.tgz",
+              "integrity": "sha512-KS/6lh/ynPGiHD/LnAobrEFq3Ad4pBzOlJ1wAnJx9N4EYoqFhMfLIBjUT2UEx4wg5ZE+cC1ob6DCSpppVo+rtg==",
+              "dev": true
+            }
+          }
+        },
+        "read-pkg-up": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+          "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+          "dev": true,
+          "requires": {
+            "find-up": "^4.1.0",
+            "read-pkg": "^5.2.0",
+            "type-fest": "^0.8.1"
+          },
+          "dependencies": {
+            "find-up": {
+              "version": "4.1.0",
+              "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz",
+              "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+              "dev": true,
+              "requires": {
+                "locate-path": "^5.0.0",
+                "path-exists": "^4.0.0"
+              }
+            },
+            "hosted-git-info": {
+              "version": "2.8.9",
+              "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+              "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+              "dev": true
+            },
+            "json-parse-even-better-errors": {
+              "version": "2.3.1",
+              "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+              "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+              "dev": true
+            },
+            "lines-and-columns": {
+              "version": "1.2.4",
+              "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+              "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+              "dev": true
+            },
+            "locate-path": {
+              "version": "5.0.0",
+              "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
+              "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+              "dev": true,
+              "requires": {
+                "p-locate": "^4.1.0"
+              }
+            },
+            "normalize-package-data": {
+              "version": "2.5.0",
+              "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+              "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+              "dev": true,
+              "requires": {
+                "hosted-git-info": "^2.1.4",
+                "resolve": "^1.10.0",
+                "semver": "2 || 3 || 4 || 5",
+                "validate-npm-package-license": "^3.0.1"
+              }
+            },
+            "p-limit": {
+              "version": "2.3.0",
+              "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz",
+              "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+              "dev": true,
+              "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==",
+              "dev": true,
+              "requires": {
+                "p-limit": "^2.2.0"
+              }
+            },
+            "parse-json": {
+              "version": "5.2.0",
+              "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz",
+              "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+              "dev": true,
+              "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "error-ex": "^1.3.1",
+                "json-parse-even-better-errors": "^2.3.0",
+                "lines-and-columns": "^1.1.6"
+              }
+            },
+            "read-pkg": {
+              "version": "5.2.0",
+              "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-5.2.0.tgz",
+              "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+              "dev": true,
+              "requires": {
+                "@types/normalize-package-data": "^2.4.0",
+                "normalize-package-data": "^2.5.0",
+                "parse-json": "^5.0.0",
+                "type-fest": "^0.6.0"
+              },
+              "dependencies": {
+                "type-fest": {
+                  "version": "0.6.0",
+                  "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.6.0.tgz",
+                  "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+                  "dev": true
+                }
+              }
+            },
+            "semver": {
+              "version": "5.7.2",
+              "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz",
+              "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+              "dev": true
+            },
+            "type-fest": {
+              "version": "0.8.1",
+              "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.8.1.tgz",
+              "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+              "dev": true
+            }
+          }
+        },
+        "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"
+          }
+        },
+        "readdirp": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
+          "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+          "dev": true,
+          "requires": {
+            "picomatch": "^2.2.1"
+          }
+        },
+        "redent": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmmirror.com/redent/-/redent-3.0.0.tgz",
+          "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+          "dev": true,
+          "requires": {
+            "indent-string": "^4.0.0",
+            "strip-indent": "^3.0.0"
+          }
+        },
+        "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==",
+          "dev": true
+        },
+        "require-from-string": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz",
+          "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+          "dev": true
+        },
+        "resolve": {
+          "version": "1.22.8",
+          "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz",
+          "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+          "dev": true,
+          "requires": {
+            "is-core-module": "^2.13.0",
+            "path-parse": "^1.0.7",
+            "supports-preserve-symlinks-flag": "^1.0.0"
+          }
+        },
+        "resolve-from": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz",
+          "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+          "dev": true
+        },
+        "resolve-global": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/resolve-global/-/resolve-global-1.0.0.tgz",
+          "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==",
+          "dev": true,
+          "requires": {
+            "global-dirs": "^0.1.1"
+          }
+        },
+        "reusify": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz",
+          "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+          "dev": true
+        },
+        "rfdc": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
+          "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
+        },
+        "rimraf": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
+          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+          "dev": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
+        "rollup": {
+          "version": "4.19.0",
+          "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.19.0.tgz",
+          "integrity": "sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==",
+          "dev": true,
+          "requires": {
+            "@rollup/rollup-android-arm-eabi": "4.19.0",
+            "@rollup/rollup-android-arm64": "4.19.0",
+            "@rollup/rollup-darwin-arm64": "4.19.0",
+            "@rollup/rollup-darwin-x64": "4.19.0",
+            "@rollup/rollup-linux-arm-gnueabihf": "4.19.0",
+            "@rollup/rollup-linux-arm-musleabihf": "4.19.0",
+            "@rollup/rollup-linux-arm64-gnu": "4.19.0",
+            "@rollup/rollup-linux-arm64-musl": "4.19.0",
+            "@rollup/rollup-linux-powerpc64le-gnu": "4.19.0",
+            "@rollup/rollup-linux-riscv64-gnu": "4.19.0",
+            "@rollup/rollup-linux-s390x-gnu": "4.19.0",
+            "@rollup/rollup-linux-x64-gnu": "4.19.0",
+            "@rollup/rollup-linux-x64-musl": "4.19.0",
+            "@rollup/rollup-win32-arm64-msvc": "4.19.0",
+            "@rollup/rollup-win32-ia32-msvc": "4.19.0",
+            "@rollup/rollup-win32-x64-msvc": "4.19.0",
+            "@types/estree": "1.0.5",
+            "fsevents": "~2.3.2"
+          }
+        },
+        "rope-sequence": {
+          "version": "1.3.4",
+          "resolved": "https://registry.npmmirror.com/rope-sequence/-/rope-sequence-1.3.4.tgz",
+          "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ=="
+        },
+        "rtf.js": {
+          "version": "3.0.9",
+          "resolved": "https://registry.npmjs.org/rtf.js/-/rtf.js-3.0.9.tgz",
+          "integrity": "sha512-I1GpDat4i548WzmeZXv27f/743984fvEeeBS8BC01/Sop17pMlUl3M7DYcdcB3PUvOZTrFIMxGZx8qw7cSMAKQ==",
+          "requires": {
+            "codepage": "^1.15.0"
+          }
+        },
+        "run-parallel": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz",
+          "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+          "dev": true,
+          "requires": {
+            "queue-microtask": "^1.2.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.69.6",
+          "resolved": "https://registry.npmmirror.com/sass/-/sass-1.69.6.tgz",
+          "integrity": "sha512-qbRr3k9JGHWXCvZU77SD2OTwUlC+gNT+61JOLcmLm+XqH4h/5D+p4IIsxvpkB89S9AwJOyb5+rWNpIucaFxSFQ==",
+          "dev": true,
+          "requires": {
+            "chokidar": ">=3.0.0 <4.0.0",
+            "immutable": "^4.0.0",
+            "source-map-js": ">=0.6.2 <2.0.0"
+          }
+        },
+        "select": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+          "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+        },
+        "semver": {
+          "version": "7.5.4",
+          "resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz",
+          "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+          "requires": {
+            "lru-cache": "^6.0.0"
+          },
+          "dependencies": {
+            "lru-cache": {
+              "version": "6.0.0",
+              "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz",
+              "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+              "requires": {
+                "yallist": "^4.0.0"
+              }
+            }
+          }
+        },
+        "set-function-length": {
+          "version": "1.2.2",
+          "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
+          "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+          "requires": {
+            "define-data-property": "^1.1.4",
+            "es-errors": "^1.3.0",
+            "function-bind": "^1.1.2",
+            "get-intrinsic": "^1.2.4",
+            "gopd": "^1.0.1",
+            "has-property-descriptors": "^1.0.2"
+          }
+        },
+        "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=="
+        },
+        "shebang-command": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
+          "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+          "requires": {
+            "shebang-regex": "^3.0.0"
+          }
+        },
+        "shebang-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz",
+          "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
+        },
+        "shell-quote": {
+          "version": "1.8.1",
+          "resolved": "https://registry.npmmirror.com/shell-quote/-/shell-quote-1.8.1.tgz",
+          "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+          "dev": true
+        },
+        "side-channel": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+          "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+          "requires": {
+            "es-errors": "^1.3.0",
+            "object-inspect": "^1.13.3",
+            "side-channel-list": "^1.0.0",
+            "side-channel-map": "^1.0.1",
+            "side-channel-weakmap": "^1.0.2"
+          }
+        },
+        "side-channel-list": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+          "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+          "requires": {
+            "es-errors": "^1.3.0",
+            "object-inspect": "^1.13.3"
+          }
+        },
+        "side-channel-map": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+          "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+          "requires": {
+            "call-bound": "^1.0.2",
+            "es-errors": "^1.3.0",
+            "get-intrinsic": "^1.2.5",
+            "object-inspect": "^1.13.3"
+          }
+        },
+        "side-channel-weakmap": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+          "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+          "requires": {
+            "call-bound": "^1.0.2",
+            "es-errors": "^1.3.0",
+            "get-intrinsic": "^1.2.5",
+            "object-inspect": "^1.13.3",
+            "side-channel-map": "^1.0.1"
+          }
+        },
+        "signal-exit": {
+          "version": "3.0.7",
+          "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz",
+          "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+          "dev": true
+        },
+        "slash": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz",
+          "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+          "dev": true
+        },
+        "sortablejs": {
+          "version": "1.14.0",
+          "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.14.0.tgz",
+          "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
+        },
+        "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=="
+        },
+        "spdx-correct": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz",
+          "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+          "dev": true,
+          "requires": {
+            "spdx-expression-parse": "^3.0.0",
+            "spdx-license-ids": "^3.0.0"
+          }
+        },
+        "spdx-exceptions": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+          "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+          "dev": true
+        },
+        "spdx-expression-parse": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+          "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+          "dev": true,
+          "requires": {
+            "spdx-exceptions": "^2.1.0",
+            "spdx-license-ids": "^3.0.0"
+          }
+        },
+        "spdx-license-ids": {
+          "version": "3.0.16",
+          "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
+          "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
+          "dev": true
+        },
+        "speakingurl": {
+          "version": "14.0.1",
+          "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
+          "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="
+        },
+        "split2": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmmirror.com/split2/-/split2-4.2.0.tgz",
+          "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+          "dev": 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==",
+          "dev": true,
+          "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==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.1"
+          }
+        },
+        "strip-final-newline": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+          "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+          "dev": true
+        },
+        "strip-indent": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-3.0.0.tgz",
+          "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+          "dev": true,
+          "requires": {
+            "min-indent": "^1.0.0"
+          }
+        },
+        "strip-json-comments": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+          "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+          "dev": true
+        },
+        "superjson": {
+          "version": "2.2.2",
+          "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.2.tgz",
+          "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
+          "requires": {
+            "copy-anything": "^3.0.2"
+          }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        },
+        "supports-preserve-symlinks-flag": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+          "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+          "dev": true
+        },
+        "svg-arc-to-cubic-bezier": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmmirror.com/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz",
+          "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g=="
+        },
+        "svg-pathdata": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-7.2.0.tgz",
+          "integrity": "sha512-qd+AxqMpfRrRQaWb2SrNFvn69cvl6piqY8TxhYl2Li1g4/LO5F9NJb5wI4vNwRryqgSgD43gYKLm/w3ag1bKvQ=="
+        },
+        "text-extensions": {
+          "version": "2.4.0",
+          "resolved": "https://registry.npmmirror.com/text-extensions/-/text-extensions-2.4.0.tgz",
+          "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==",
+          "dev": true
+        },
+        "text-segmentation": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
+          "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+          "requires": {
+            "utrie": "^1.0.2"
+          }
+        },
+        "text-table": {
+          "version": "0.2.0",
+          "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz",
+          "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+          "dev": true
+        },
+        "through": {
+          "version": "2.3.8",
+          "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz",
+          "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+          "dev": true
+        },
+        "through2": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmmirror.com/through2/-/through2-3.0.2.tgz",
+          "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
+          "requires": {
+            "inherits": "^2.0.4",
+            "readable-stream": "2 || 3"
+          }
+        },
+        "tiny-emitter": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+          "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+        },
+        "tinycolor2": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz",
+          "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
+        },
+        "tippy.js": {
+          "version": "6.3.7",
+          "resolved": "https://registry.npmmirror.com/tippy.js/-/tippy.js-6.3.7.tgz",
+          "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==",
+          "requires": {
+            "@popperjs/core": "^2.9.0"
+          }
+        },
+        "tmp": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.5.tgz",
+          "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="
+        },
+        "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==",
+          "requires": {
+            "is-number": "^7.0.0"
+          }
+        },
+        "trim-newlines": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-3.0.1.tgz",
+          "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
+          "dev": true
+        },
+        "ts-api-utils": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
+          "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
+          "dev": true,
+          "requires": {}
+        },
+        "tslib": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+          "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+        },
+        "txml": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmmirror.com/txml/-/txml-5.1.1.tgz",
+          "integrity": "sha512-TwMDLnXQ09enNaxybLVvKZU7rqog8LgnuAs4ZYXM0nV0eu10iLsSFwlX3AEknAXXtH1wT3CYfoiXAjyBexcmuw==",
+          "requires": {
+            "through2": "^3.0.1"
+          }
+        },
+        "type-check": {
+          "version": "0.4.0",
+          "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
+          "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+          "dev": true,
+          "requires": {
+            "prelude-ls": "^1.2.1"
+          }
+        },
+        "type-fest": {
+          "version": "0.20.2",
+          "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz",
+          "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+          "dev": true
+        },
+        "typescript": {
+          "version": "5.3.3",
+          "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.3.3.tgz",
+          "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
+          "devOptional": true
+        },
+        "uc.micro": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+          "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="
+        },
+        "undici-types": {
+          "version": "5.26.5",
+          "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz",
+          "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
+        },
+        "universalify": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz",
+          "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="
+        },
+        "update-browserslist-db": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+          "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+          "dev": true,
+          "requires": {
+            "escalade": "^3.2.0",
+            "picocolors": "^1.1.1"
+          }
+        },
+        "uri-js": {
+          "version": "4.4.1",
+          "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
+          "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+          "dev": true,
+          "requires": {
+            "punycode": "^2.1.0"
+          }
+        },
+        "utif": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/utif/-/utif-3.1.0.tgz",
+          "integrity": "sha512-WEo4D/xOvFW53K5f5QTaTbbiORcm2/pCL9P6qmJnup+17eYfKaEhDeX9PeQkuyEoIxlbGklDuGl8xwuXYMrrXQ==",
+          "requires": {
+            "pako": "^1.0.5"
+          }
+        },
+        "utif2": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz",
+          "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==",
+          "requires": {
+            "pako": "^1.0.11"
+          }
+        },
+        "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.npmjs.org/utrie/-/utrie-1.0.2.tgz",
+          "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+          "requires": {
+            "base64-arraybuffer": "^1.0.2"
+          }
+        },
+        "uuid": {
+          "version": "13.0.0",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
+          "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w=="
+        },
+        "validate-npm-package-license": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+          "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+          "dev": true,
+          "requires": {
+            "spdx-correct": "^3.0.0",
+            "spdx-expression-parse": "^3.0.0"
+          }
+        },
+        "vite": {
+          "version": "5.3.5",
+          "resolved": "https://registry.npmmirror.com/vite/-/vite-5.3.5.tgz",
+          "integrity": "sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==",
+          "dev": true,
+          "requires": {
+            "esbuild": "^0.21.3",
+            "fsevents": "~2.3.3",
+            "postcss": "^8.4.39",
+            "rollup": "^4.13.0"
+          }
+        },
+        "vite-plugin-vue-inspector": {
+          "version": "5.4.0",
+          "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.4.0.tgz",
+          "integrity": "sha512-Iq/024CydcE46FZqWPU4t4lw4uYOdLnFSO1RNxJVt2qY9zxIjmnkBqhHnYaReWM82kmNnaXs7OkfgRrV2GEjyw==",
+          "dev": true,
+          "requires": {
+            "@babel/core": "^7.23.0",
+            "@babel/plugin-proposal-decorators": "^7.23.0",
+            "@babel/plugin-syntax-import-attributes": "^7.22.5",
+            "@babel/plugin-syntax-import-meta": "^7.10.4",
+            "@babel/plugin-transform-typescript": "^7.22.15",
+            "@vue/babel-plugin-jsx": "^1.1.5",
+            "@vue/compiler-dom": "^3.3.4",
+            "kolorist": "^1.8.0",
+            "magic-string": "^0.30.4"
+          }
+        },
+        "vscode-uri": {
+          "version": "3.0.8",
+          "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.0.8.tgz",
+          "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==",
+          "dev": true
+        },
+        "vue": {
+          "version": "3.5.17",
+          "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.17.tgz",
+          "integrity": "sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==",
+          "requires": {
+            "@vue/compiler-dom": "3.5.17",
+            "@vue/compiler-sfc": "3.5.17",
+            "@vue/runtime-dom": "3.5.17",
+            "@vue/server-renderer": "3.5.17",
+            "@vue/shared": "3.5.17"
+          }
+        },
+        "vue-eslint-parser": {
+          "version": "9.3.2",
+          "resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.3.2.tgz",
+          "integrity": "sha512-q7tWyCVaV9f8iQyIA5Mkj/S6AoJ9KBN8IeUSf3XEmBrOtxOZnfTg5s4KClbZBCK3GtnT/+RyCLZyDHuZwTuBjg==",
+          "dev": true,
+          "requires": {
+            "debug": "^4.3.4",
+            "eslint-scope": "^7.1.1",
+            "eslint-visitor-keys": "^3.3.0",
+            "espree": "^9.3.1",
+            "esquery": "^1.4.0",
+            "lodash": "^4.17.21",
+            "semver": "^7.3.6"
+          }
+        },
+        "vue-tsc": {
+          "version": "2.0.29",
+          "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.0.29.tgz",
+          "integrity": "sha512-MHhsfyxO3mYShZCGYNziSbc63x7cQ5g9kvijV7dRe1TTXBRLxXyL0FnXWpUF1xII2mJ86mwYpYsUmMwkmerq7Q==",
+          "dev": true,
+          "requires": {
+            "@volar/typescript": "~2.4.0-alpha.18",
+            "@vue/language-core": "2.0.29",
+            "semver": "^7.5.4"
+          }
+        },
+        "vuedraggable": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz",
+          "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==",
+          "requires": {
+            "sortablejs": "1.14.0"
+          }
+        },
+        "w3c-keyname": {
+          "version": "2.2.8",
+          "resolved": "https://registry.npmmirror.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
+          "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
+        },
+        "wangeditor": {
+          "version": "4.7.15",
+          "resolved": "https://registry.npmjs.org/wangeditor/-/wangeditor-4.7.15.tgz",
+          "integrity": "sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==",
+          "requires": {
+            "@babel/runtime": "^7.11.2",
+            "@babel/runtime-corejs3": "^7.11.2",
+            "tslib": "^2.1.0"
+          }
+        },
+        "webcodecs-encoder": {
+          "version": "0.3.2",
+          "resolved": "https://registry.npmmirror.com/webcodecs-encoder/-/webcodecs-encoder-0.3.2.tgz",
+          "integrity": "sha512-F4XKzafAxVNhtnaQ5F8Q6xVn+bRrzLiUQs3p4PpogN3svBqGPR1y5OK66bunXEULOJ0XVJ0HqlJ/TSGGZTZ0AQ==",
+          "requires": {
+            "mp4-muxer": "^2.0.2",
+            "patch-package": "^8.0.0",
+            "webm-muxer": "^1.2.0"
+          }
+        },
+        "webm-muxer": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmmirror.com/webm-muxer/-/webm-muxer-1.2.1.tgz",
+          "integrity": "sha512-FaH7GVeK9tOZoWEW0gT/ryR9EoZnDe/RplJlTkG6zPWfEdrIy24PaXwEiyUnKwwO3zsjJWzFq4DLHECqGdJXIw==",
+          "requires": {
+            "@types/dom-webcodecs": "^0.1.4",
+            "@types/wicg-file-system-access": "^2020.9.5"
+          }
+        },
+        "which": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
+          "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        },
+        "wrap-ansi": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+          "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+          "dev": true,
+          "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==",
+          "dev": true
+        },
+        "xml-name-validator": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+          "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+          "dev": true
+        },
+        "y-protocols": {
+          "version": "1.0.6",
+          "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.6.tgz",
+          "integrity": "sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q==",
+          "requires": {
+            "lib0": "^0.2.85"
+          }
+        },
+        "y-websocket": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/y-websocket/-/y-websocket-3.0.0.tgz",
+          "integrity": "sha512-mUHy7AzkOZ834T/7piqtlA8Yk6AchqKqcrCXjKW8J1w2lPtRDjz8W5/CvXz9higKAHgKRKqpI3T33YkRFLkPtg==",
+          "requires": {
+            "lib0": "^0.2.102",
+            "y-protocols": "^1.0.5"
+          }
+        },
+        "y18n": {
+          "version": "5.0.8",
+          "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",
+          "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+          "dev": true
+        },
+        "yallist": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
+          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+        },
+        "yaml": {
+          "version": "2.8.3",
+          "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.3.tgz",
+          "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="
+        },
+        "yargs": {
+          "version": "17.7.2",
+          "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz",
+          "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+          "dev": true,
+          "requires": {
+            "cliui": "^8.0.1",
+            "escalade": "^3.1.1",
+            "get-caller-file": "^2.0.5",
+            "require-directory": "^2.1.1",
+            "string-width": "^4.2.3",
+            "y18n": "^5.0.5",
+            "yargs-parser": "^21.1.1"
+          }
+        },
+        "yargs-parser": {
+          "version": "21.1.1",
+          "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz",
+          "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+          "dev": true
+        },
+        "yjs": {
+          "version": "13.6.27",
+          "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.27.tgz",
+          "integrity": "sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==",
+          "requires": {
+            "lib0": "^0.2.99"
+          }
+        },
+        "yocto-queue": {
+          "version": "0.1.0",
+          "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",
+          "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+          "dev": true
+        },
+        "zrender": {
+          "version": "5.6.1",
+          "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.6.1.tgz",
+          "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
+          "requires": {
+            "tslib": "2.3.0"
+          }
+        }
+      }
+    },
     "pptxgenjs": {
     "pptxgenjs": {
       "version": "3.12.0",
       "version": "3.12.0",
       "resolved": "https://registry.npmmirror.com/pptxgenjs/-/pptxgenjs-3.12.0.tgz",
       "resolved": "https://registry.npmmirror.com/pptxgenjs/-/pptxgenjs-3.12.0.tgz",

+ 2 - 0
package.json

@@ -33,6 +33,7 @@
     "animate.css": "^4.1.1",
     "animate.css": "^4.1.1",
     "axios": "^1.7.9",
     "axios": "^1.7.9",
     "clipboard": "^2.0.11",
     "clipboard": "^2.0.11",
+    "convertapi-js": "^1.0.8",
     "crypto-js": "^4.2.0",
     "crypto-js": "^4.2.0",
     "dexie": "^4.0.11",
     "dexie": "^4.0.11",
     "echarts": "^5.6.0",
     "echarts": "^5.6.0",
@@ -49,6 +50,7 @@
     "nanoid": "^5.0.7",
     "nanoid": "^5.0.7",
     "number-precision": "^1.6.0",
     "number-precision": "^1.6.0",
     "pinia": "^3.0.2",
     "pinia": "^3.0.2",
+    "pptist": "file:",
     "pptxgenjs": "^3.12.0",
     "pptxgenjs": "^3.12.0",
     "pptxtojson": "1.12.0",
     "pptxtojson": "1.12.0",
     "prosemirror-commands": "^1.6.0",
     "prosemirror-commands": "^1.6.0",

+ 1 - 1
src/App.vue

@@ -146,7 +146,7 @@ const switchViewMode = (mode: string) => {
 provide('switchViewMode', switchViewMode)
 provide('switchViewMode', switchViewMode)
 
 
 if (import.meta.env.MODE !== 'development') {
 if (import.meta.env.MODE !== 'development') {
-  window.onbeforeunload = () => false
+  // window.onbeforeunload = () => false
 }
 }
 
 
 onMounted(async () => {
 onMounted(async () => {

BIN
src/assets/img/sixHatBanner.jpg


+ 1 - 0
src/components/CollapsibleToolbar/cocolearnCom/KwlDetail.vue

@@ -381,6 +381,7 @@ const handleAddToSlide = () => {
   overflow: hidden;
   overflow: hidden;
   // width: 100%;
   // width: 100%;
   height: 140px;
   height: 140px;
+  min-height: 140px;
   position: relative;
   position: relative;
   box-sizing: border-box;
   box-sizing: border-box;
 
 

+ 795 - 0
src/components/CollapsibleToolbar/cocolearnCom/SixHatDetail.vue

@@ -0,0 +1,795 @@
+<template>
+  <div class="six-hat-detail">
+    <!-- 头部导航 -->
+    <div class="detail-header">
+      <div class="back-btn" @click="$emit('back')">
+        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+          <path d="M15 18l-6-6 6-6" />
+        </svg>
+      </div>
+      <div class="detail-title">{{ lang.ssSixHatTitle }}</div>
+    </div>
+
+    <!-- Banner 区域 -->
+    <div class="detail-banner">
+      <img :src="sixHat" :alt="lang.ssSixHatTitle" />
+      <div class="tool-overly"></div>
+      <div class="tool-icon-badge">
+        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+          <path d="M9 18h6M10 22h4M12 2a7 7 0 00-4 12.7c.6.5 1 1.3 1 2.3h6c0-1 .4-1.8 1-2.3A7 7 0 0012 2z"></path>
+        </svg>
+      </div>
+    </div>
+
+    <!-- 描述与标签 -->
+    <div class="detail-desc-row">
+      <div class="detail-desc-text">{{ lang.ssSixHatDesc }}</div>
+      <div class="help-icon" @mouseenter="showHelp = true" @mouseleave="showHelp = false">
+        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+          <circle cx="12" cy="12" r="10" />
+          <path d="M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3" />
+          <line x1="12" y1="17" x2="12.01" y2="17" />
+        </svg>
+        <!-- 帮助气泡 -->
+        <div v-if="showHelp" class="help-tooltip">
+          <div class="help-title">{{ lang.ssSixHatUsageScenario }}</div>
+          <div class="help-text">{{ lang.ssSixHatScenarioText }}</div>
+          <div class="help-title">{{ lang.ssSixHatSteps }}</div>
+          <div class="help-list">
+            <div class="help-step"><span class="step-num">1</span><span>{{ lang.ssSixHatStep1 }}</span></div>
+            <div class="help-step"><span class="step-num">2</span><span>{{ lang.ssSixHatStep2 }}</span></div>
+            <div class="help-step"><span class="step-num">3</span><span>{{ lang.ssSixHatStep3 }}</span></div>
+            <div class="help-step"><span class="step-num">4</span><span>{{ lang.ssSixHatStep4 }}</span></div>
+            <div class="help-step"><span class="step-num">5</span><span>{{ lang.ssSixHatStep5 }}</span></div>
+            <div class="help-step"><span class="step-num">6</span><span>{{ lang.ssSixHatStep6 }}</span></div>
+          </div>
+          <div class="help-source">{{ lang.ssSixHatSource }}</div>
+          <div class="help-purpose">{{ lang.ssSixHatPurpose }}</div>
+        </div>
+      </div>
+    </div>
+    <div class="detail-tags">
+      <span class="detail-tag">{{ lang.ssSixHatGradeRange }}</span>
+    </div>
+
+    <!-- 工具配置区 -->
+    <div class="config-section">
+      <div class="config-title">{{ lang.ssKwlToolConfig }}</div>
+      <div class="config-subtitle">{{ lang.ssKwlConfigSubtitle }}</div>
+    </div>
+
+    <!-- 配置项卡片 -->
+    <div class="config-card">
+      <!-- 工具内容由使用者配置 -->
+      <div class="config-row config-row-highlight">
+        <div class="form-text-block">
+          <div class="form-label">{{ lang.ssSixHatUserConfig }}</div>
+          <div class="form-sublabel">{{ lang.ssSixHatUserConfigDesc }}</div>
+        </div>
+        <div class="toggle-switch" :class="{ active: formData.enableContentConfigurable }"
+          @click="formData.enableContentConfigurable = !formData.enableContentConfigurable">
+          <div class="toggle-thumb"></div>
+        </div>
+      </div>
+
+      <!-- 小组合作 -->
+      <div class="config-row">
+        <div class="form-text-block">
+          <div class="form-label">{{ lang.ssSixHatGroupWork }}</div>
+          <div class="form-sublabel">{{ lang.ssSixHatGroupWorkDesc }}</div>
+        </div>
+        <div class="toggle-switch" :class="{ active: formData.enableMemberSelect }"
+          @click="formData.enableMemberSelect = !formData.enableMemberSelect">
+          <div class="toggle-thumb"></div>
+        </div>
+      </div>
+
+      <!-- 默认展开操作提示 -->
+      <div class="config-row">
+        <div class="form-text-block">
+          <div class="form-label">{{ lang.ssKwlShowHowTo }}</div>
+          <div class="form-sublabel">{{ lang.ssKwlShowHowToDesc }}</div>
+        </div>
+        <div class="toggle-switch" :class="{ active: formData.autoExpandHowTo }"
+          @click="formData.autoExpandHowTo = !formData.autoExpandHowTo">
+          <div class="toggle-thumb"></div>
+        </div>
+      </div>
+
+      <!-- 高级配置 -->
+      <div class="advanced-section">
+        <div class="advanced-header" @click="showAdvanced = !showAdvanced">
+          <span class="advanced-title">{{ lang.ssKwlAdvanced }}</span>
+          <svg class="advanced-arrow" :class="{ expanded: showAdvanced }" width="16" height="16" viewBox="0 0 24 24"
+            fill="none" stroke="currentColor" stroke-width="2">
+            <polyline points="6 9 12 15 18 9" />
+          </svg>
+        </div>
+
+        <div v-if="showAdvanced" class="advanced-body">
+          <!-- 显示计时器 -->
+          <div class="config-row config-row-borderless">
+            <div class="form-text-block">
+              <div class="form-label">{{ lang.ssSixHatShowTimer }}</div>
+            </div>
+            <div class="toggle-switch" :class="{ active: formData.timerEnabled }"
+              @click="formData.timerEnabled = !formData.timerEnabled">
+              <div class="toggle-thumb"></div>
+            </div>
+          </div>
+
+          <!-- 计时时长 -->
+          <div v-if="formData.timerEnabled" class="timer-duration">
+            <div class="duration-label">{{ lang.ssSixHatTimerDuration }}</div>
+            <div class="duration-options">
+              <div v-for="item in timerOptions" :key="item" class="duration-chip"
+                :class="{ active: !customTimerActive && formData.timerDuration === item }"
+                @click="selectTimerDuration(item)">
+                {{ item }}{{ lang.ssSixHatTimerSeconds }}
+              </div>
+              <div class="duration-chip" :class="{ active: customTimerActive }" @click="selectCustomTimer">
+                {{ lang.ssCustom }}
+              </div>
+            </div>
+            <!-- 自定义时长输入 -->
+            <div v-if="customTimerActive" class="custom-timer">
+              <input v-model="customTimerInput" type="number" min="10" max="3600" step="10"
+                @change="handleCustomTimerInput" @keyup.enter="handleCustomTimerInput" />
+              <span class="custom-unit">{{ lang.ssSixHatTimerSeconds }}</span>
+            </div>
+          </div>
+
+          <!-- 思考帽选择 -->
+          <div class="hats-select">
+            <div class="duration-label">{{ lang.ssSixHatSelectHats }}</div>
+            <div class="hats-options">
+              <div v-for="hat in hatList" :key="hat.key" class="hat-chip"
+                :class="[`hat-${hat.key}`, { active: formData.hats.includes(hat.key) }]"
+                @click="toggleHat(hat.key)">
+                <span class="hat-dot"></span>
+                {{ hat.label }}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 添加到幻灯片按钮 -->
+    <div class="footer-btn">
+      <div class="add-btn" @click="handleAddToSlide">{{ lang.ssKwlAddToSlide }}</div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive } from 'vue'
+import sixHat from '@/assets/img/sixHatBanner.jpg'
+import { lang } from '@/main'
+
+const emit = defineEmits<{
+  (e: 'back'): void
+  (e: 'add', data: any): void
+}>()
+
+const showHelp = ref(false)
+const showAdvanced = ref(false)
+
+const timerOptions = [30, 60, 120, 180, 300]
+const customTimerActive = ref(false)
+const customTimerInput = ref<number>(60)
+
+const hatList = [
+  { key: 'white', label: lang.ssSixHatWhite },
+  { key: 'red', label: lang.ssSixHatRed },
+  { key: 'black', label: lang.ssSixHatBlack },
+  { key: 'yellow', label: lang.ssSixHatYellow },
+  { key: 'green', label: lang.ssSixHatGreen },
+  { key: 'blue', label: lang.ssSixHatBlue }
+]
+
+const formData = reactive({
+  stage: 'member',
+  members: [] as string[],
+  scenario: '',
+  timerEnabled: true,
+  timerDuration: 60,
+  timerCustomValue: 60,
+  hats: ['white', 'red', 'black', 'yellow', 'green', 'blue'] as string[],
+  hatContent: {} as Record<string, string>,
+  enableMemberSelect: false,
+  enableContentConfigurable: true,
+  autoExpandHowTo: false,
+  customScenario: '',
+  customTimerEnabled: true,
+  customTimerDuration: 60,
+  customHats: null as string[] | null
+})
+
+const CUSTOM_TIMER_MIN = 10
+const CUSTOM_TIMER_MAX = 3600
+
+const selectTimerDuration = (value: number) => {
+  customTimerActive.value = false
+  formData.timerDuration = value
+  formData.timerCustomValue = value
+}
+
+const selectCustomTimer = () => {
+  customTimerActive.value = true
+  applyCustomTimer()
+}
+
+const applyCustomTimer = () => {
+  formData.timerCustomValue = customTimerInput.value
+  formData.timerDuration = customTimerInput.value
+}
+
+const handleCustomTimerInput = () => {
+  let val = Number(customTimerInput.value)
+  if (!val || Number.isNaN(val)) val = 60
+  val = Math.round(val)
+  val = Math.max(CUSTOM_TIMER_MIN, Math.min(CUSTOM_TIMER_MAX, val))
+  customTimerInput.value = val
+  applyCustomTimer()
+}
+
+const toggleHat = (key: string) => {
+  const index = formData.hats.indexOf(key)
+  if (index > -1) {
+    // 至少保留一顶帽子
+    if (formData.hats.length === 1) return
+    formData.hats.splice(index, 1)
+  }
+  else {
+    // 按固定顺序插入,保持帽子次序
+    const order = hatList.map(h => h.key)
+    formData.hats.push(key)
+    formData.hats.sort((a, b) => order.indexOf(a) - order.indexOf(b))
+  }
+}
+
+const handleAddToSlide = () => {
+  emit('add', {
+    ...formData,
+    members: [...formData.members],
+    hats: [...formData.hats],
+    hatContent: { ...formData.hatContent }
+  })
+}
+</script>
+
+<style lang="scss" scoped>
+.six-hat-detail {
+  display: flex;
+  flex-direction: column;
+  height: calc(100% - 75px);
+  overflow-y: auto;
+  overflow-x: hidden;
+  padding: 0 0 20px;
+}
+
+/* 头部 */
+.detail-header {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  padding: 0 14px;
+  position: sticky;
+  top: 0;
+  background: #fff;
+  z-index: 10;
+  margin-bottom: 20px;
+
+  .back-btn {
+    width: 32px;
+    height: 32px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 8px;
+    cursor: pointer;
+    color: #6b7280;
+    transition: all 0.2s ease;
+
+    &:hover {
+      background: #f3f4f6;
+      color: #374151;
+    }
+  }
+
+  .detail-title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #1f2937;
+  }
+}
+
+/* Banner */
+.detail-banner {
+  margin: 0 14px 14px;
+  border-radius: 12px;
+  overflow: hidden;
+  height: 140px;
+  min-height: 140px;
+  position: relative;
+  box-sizing: border-box;
+
+  .tool-overly {
+    position: absolute;
+    inset: 0;
+    background-color: #f59e0b;
+    opacity: .35;
+    pointer-events: none;
+  }
+
+  .tool-icon-badge {
+    position: absolute;
+    top: 10px;
+    left: 10px;
+    width: 32px;
+    height: 32px;
+    border-radius: 8px;
+    background: rgba(255, 255, 255, 0.95);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
+
+    svg {
+      width: 18px;
+      height: 18px;
+      color: #f59e0b;
+    }
+  }
+
+  img {
+    width: 100%;
+    height: 140px;
+    object-fit: cover;
+    display: block;
+  }
+}
+
+/* 描述 */
+.detail-desc-row {
+  display: flex;
+  align-items: flex-start;
+  gap: 8px;
+  padding: 0 14px;
+
+  .detail-desc-text {
+    flex: 1;
+    font-size: 13px;
+    color: #4b5563;
+    line-height: 1.6;
+  }
+
+  .help-icon {
+    position: relative;
+    color: #9ca3af;
+    cursor: pointer;
+    flex-shrink: 0;
+    margin-top: 2px;
+
+    &:hover {
+      color: #FF9300;
+    }
+
+    .help-tooltip {
+      position: absolute;
+      top: 100%;
+      right: 0;
+      margin-top: 8px;
+      width: 250px;
+      background: #fff;
+      border: 1px solid #e5e7eb;
+      border-radius: 10px;
+      padding: 14px;
+      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
+      z-index: 100;
+
+      .help-title {
+        font-size: 13px;
+        font-weight: 600;
+        color: #1f2937;
+        margin-bottom: 4px;
+        margin-top: 8px;
+
+        &:first-child {
+          margin-top: 0;
+        }
+      }
+
+      .help-text {
+        font-size: 12px;
+        color: #6b7280;
+        margin-bottom: 4px;
+      }
+
+      .help-list {
+        font-size: 12px;
+        color: #4b5563;
+        line-height: 1.6;
+
+        .help-step {
+          display: flex;
+          align-items: flex-start;
+          gap: 8px;
+          padding: 3px 0;
+
+          .step-num {
+            flex-shrink: 0;
+            width: 18px;
+            height: 18px;
+            margin-top: 1px;
+            border-radius: 50%;
+            background: #FF9300;
+            color: #fff;
+            font-size: 11px;
+            font-weight: 600;
+            line-height: 1;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+          }
+        }
+      }
+
+      .help-source,
+      .help-purpose {
+        font-size: 11px;
+        color: #9ca3af;
+        margin-top: 8px;
+        line-height: 1.5;
+      }
+    }
+  }
+}
+
+.detail-tags {
+  display: flex;
+  gap: 6px;
+  padding: 10px 14px 0;
+
+  .detail-tag {
+    display: inline-block;
+    padding: 3px 10px;
+    font-size: 11px;
+    color: #3b82f6;
+    background: #eff6ff;
+    border-radius: 4px;
+    font-weight: 500;
+  }
+}
+
+/* 配置区 */
+.config-section {
+  padding: 20px 14px 12px;
+
+  .config-title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #1f2937;
+    margin-bottom: 6px;
+  }
+
+  .config-subtitle {
+    font-size: 12px;
+    color: #6b7280;
+    line-height: 1.6;
+  }
+}
+
+/* 配置卡片 */
+.config-card {
+  margin: 0 14px;
+  background: #f8f9fb;
+  border-radius: 14px;
+  padding: 8px 14px;
+}
+
+.config-row {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 12px;
+  padding: 16px 0;
+  border-bottom: 1px solid #eceef2;
+
+  &:last-child {
+    border-bottom: none;
+  }
+
+  .form-label {
+    font-size: 14px;
+    font-weight: 500;
+    color: #374151;
+  }
+
+  .form-sublabel {
+    font-size: 12px;
+    color: #9ca3af;
+    margin-top: 3px;
+    line-height: 1.5;
+  }
+
+  &.config-row-borderless {
+    border-bottom: none;
+    padding-bottom: 8px;
+  }
+}
+
+/* 使用者配置高亮行 */
+.config-row-highlight {
+  background: #fff4e8;
+  border-radius: 12px;
+  border-bottom: none;
+  padding: 16px;
+  margin: 6px 0;
+
+  .form-label {
+    color: #1f2937;
+    font-weight: 600;
+  }
+
+  .form-sublabel {
+    color: #b0825c;
+  }
+}
+
+/* 开关 */
+.toggle-switch {
+  width: 44px;
+  height: 24px;
+  border-radius: 12px;
+  background: #d1d5db;
+  position: relative;
+  cursor: pointer;
+  transition: background 0.25s ease;
+  flex-shrink: 0;
+
+  .toggle-thumb {
+    width: 20px;
+    height: 20px;
+    border-radius: 50%;
+    background: #fff;
+    position: absolute;
+    top: 2px;
+    left: 2px;
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
+    transition: transform 0.25s ease;
+  }
+
+  &.active {
+    background: #FF9300;
+
+    .toggle-thumb {
+      transform: translateX(20px);
+    }
+  }
+}
+
+/* 高级配置 */
+.advanced-section {
+  .advanced-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 12px 0;
+    cursor: pointer;
+
+    .advanced-title {
+      font-size: 14px;
+      font-weight: 600;
+      color: #6b7280;
+    }
+
+    .advanced-arrow {
+      color: #9ca3af;
+      transition: transform 0.2s ease;
+
+      &.expanded {
+        transform: rotate(180deg);
+      }
+    }
+  }
+
+  .advanced-body {
+    display: flex;
+    flex-direction: column;
+  }
+}
+
+/* 计时时长 / 帽子选择 */
+.timer-duration,
+.hats-select {
+  padding: 4px 0 14px;
+
+  .duration-label {
+    font-size: 13px;
+    font-weight: 500;
+    color: #374151;
+    margin-bottom: 10px;
+  }
+}
+
+.duration-options {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+
+.duration-chip {
+  padding: 6px 14px;
+  font-size: 12px;
+  color: #6b7280;
+  background: #fff;
+  border: 1px solid #e5e7eb;
+  border-radius: 999px;
+  cursor: pointer;
+  transition: all 0.2s ease;
+
+  &:hover {
+    border-color: #FF9300;
+    color: #FF9300;
+  }
+
+  &.active {
+    background: #FF9300;
+    border-color: #FF9300;
+    color: #fff;
+    font-weight: 600;
+  }
+}
+
+/* 自定义时长输入 */
+.custom-timer {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-top: 10px;
+
+  input {
+    width: 96px;
+    padding: 8px 12px;
+    border: 1px solid #e5e7eb;
+    border-radius: 10px;
+    font-size: 13px;
+    color: #374151;
+    background: #fff;
+    outline: none;
+    transition: border-color 0.2s ease;
+    box-sizing: border-box;
+
+    &::placeholder {
+      color: #9ca3af;
+    }
+
+    &:focus {
+      border-color: #FF9300;
+    }
+
+    // 隐藏 number 输入框的上下箭头
+    &::-webkit-outer-spin-button,
+    &::-webkit-inner-spin-button {
+      -webkit-appearance: none;
+      margin: 0;
+    }
+
+    &[type='number'] {
+      -moz-appearance: textfield;
+      appearance: textfield;
+    }
+  }
+
+  .custom-unit {
+    font-size: 13px;
+    color: #6b7280;
+  }
+}
+
+.hats-options {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+
+.hat-chip {
+  display: inline-flex;
+  align-items: center;
+  gap: 6px;
+  padding: 6px 12px;
+  font-size: 12px;
+  color: #9ca3af;
+  background: #fff;
+  border: 1px solid #e5e7eb;
+  border-radius: 999px;
+  cursor: pointer;
+  transition: all 0.2s ease;
+
+  .hat-dot {
+    width: 10px;
+    height: 10px;
+    border-radius: 50%;
+    background: #d1d5db;
+    transition: background 0.2s ease;
+  }
+
+  &.hat-white.active {
+    color: #374151;
+    border-color: #d1d5db;
+    background: #fff;
+
+    .hat-dot { background: #f3f4f6; border: 1px solid #d1d5db; }
+  }
+
+  &.hat-red.active {
+    color: #ef4444;
+    border-color: #fecaca;
+    background: #fef2f2;
+
+    .hat-dot { background: #ef4444; }
+  }
+
+  &.hat-black.active {
+    color: #fff;
+    border-color: #374151;
+    background: #4b5563;
+
+    .hat-dot { background: #1f2937; }
+  }
+
+  &.hat-yellow.active {
+    color: #b45309;
+    border-color: #fde68a;
+    background: #fffbeb;
+
+    .hat-dot { background: #f59e0b; }
+  }
+
+  &.hat-green.active {
+    color: #15803d;
+    border-color: #bbf7d0;
+    background: #f0fdf4;
+
+    .hat-dot { background: #22c55e; }
+  }
+
+  &.hat-blue.active {
+    color: #1d4ed8;
+    border-color: #bfdbfe;
+    background: #eff6ff;
+
+    .hat-dot { background: #3b82f6; }
+  }
+}
+
+/* 底部按钮 */
+.footer-btn {
+  padding: 16px 14px 0;
+
+  .add-btn {
+    width: 100%;
+    padding: 14px;
+    background: #FF9300;
+    color: #fff;
+    font-size: 15px;
+    font-weight: 600;
+    text-align: center;
+    border-radius: 12px;
+    cursor: pointer;
+    transition: all 0.2s ease;
+
+    &:hover {
+      background: #f57c00;
+      transform: translateY(-1px);
+      box-shadow: 0 4px 12px rgba(255, 147, 0, 0.3);
+    }
+
+    &:active {
+      transform: translateY(0);
+    }
+  }
+}
+</style>

+ 76 - 5
src/components/CollapsibleToolbar/componets/aiChat.vue

@@ -1,4 +1,4 @@
-<template>
+<template>
   <div class="ai-chat-container">
   <div class="ai-chat-container">
     <div class="message-quick-box">
     <div class="message-quick-box">
       <div class="message-quick-box-item" :class="{ 'active': isQuickActions.includes('quick') }">
       <div class="message-quick-box-item" :class="{ 'active': isQuickActions.includes('quick') }">
@@ -294,6 +294,8 @@ const quickActions = [
   lang.ssAiChatQuickAction6,
   lang.ssAiChatQuickAction6,
   lang.ssAiChatQuickAction7,
   lang.ssAiChatQuickAction7,
   lang.ssAiChatQuickAction4,
   lang.ssAiChatQuickAction4,
+  lang.ssAiChatQuickAction8,
+  lang.ssAiChatQuickAction9,
 ]
 ]
 
 
 // 监听输入变化,当输入"/"时显示快捷操作
 // 监听输入变化,当输入"/"时显示快捷操作
@@ -473,7 +475,7 @@ const sendAction = async (action: string) => {
       gType.value = 'chat'
       gType.value = 'chat'
     }
     }
 
 
-    // generate_qa // generate_choice_question // generate_photo // generate_poll
+    // generate_qa // generate_choice_question // generate_take_photo // generate_poll
     if (gType.value !== 'chat' && gType.value !== 'generate_interactive_web' && gType.value !== 'trigger_batch_tool') {
     if (gType.value !== 'chat' && gType.value !== 'generate_interactive_web' && gType.value !== 'trigger_batch_tool') {
       messages.value.at(-1).jsonData = {
       messages.value.at(-1).jsonData = {
         gType: gType.value,
         gType: gType.value,
@@ -581,6 +583,7 @@ const sendAction = async (action: string) => {
       79: lang.ssPhoto,
       79: lang.ssPhoto,
       84: lang.ssFile,
       84: lang.ssFile,
       831: lang.ssKwlTitle,
       831: lang.ssKwlTitle,
+      832: lang.ssSixHatTitle,
     }
     }
     return typeMap[type || 0] || lang.ssUnknown
     return typeMap[type || 0] || lang.ssUnknown
   }
   }
@@ -769,7 +772,7 @@ const sendAction = async (action: string) => {
 import useCreateElement from '@/hooks/useCreateElement'
 import useCreateElement from '@/hooks/useCreateElement'
 import useSlideHandler from '@/hooks/useSlideHandler'
 import useSlideHandler from '@/hooks/useSlideHandler'
 const { createSlide } = useSlideHandler()
 const { createSlide } = useSlideHandler()
-const { createFrameElement } = useCreateElement()
+const { createFrameElement, createImageElement } = useCreateElement()
 
 
 
 
 const katexZ = (str) => {
 const katexZ = (str) => {
@@ -826,7 +829,7 @@ const setUrl = () => {
   return url
   return url
 }
 }
 
 
-const generate = (message: ChatMessage) => {
+const generate = async (message: ChatMessage) => {
   if (message.gLoading || message.jsonData?.isGenerate) {
   if (message.gLoading || message.jsonData?.isGenerate) {
     return
     return
   }
   }
@@ -894,7 +897,7 @@ const generate = (message: ChatMessage) => {
       })
       })
     })
     })
   }
   }
-  else if (message.jsonData?.gType === 'generate_photo') {
+  else if (message.jsonData?.gType === 'generate_take_photo') {
     console.log(message.jsonData?.gType)
     console.log(message.jsonData?.gType)
     const prompt = [
     const prompt = [
       {
       {
@@ -915,6 +918,65 @@ const generate = (message: ChatMessage) => {
       })
       })
     })
     })
   }
   }
+  else if (message.jsonData?.gType === 'generate_file') {
+    console.log(message.jsonData?.gType)
+    const prompt = [
+      {
+        role: 'user',
+        content: `这是用户输入的内容:“${message.aiContent}”,根据用户输入的内容,生成文件上传的json。输出一个json格式的回复,格式如下:{"answerQ":"问题","answer":"","fileList":[]}。`, // ,"imageList":[],"evaluationCriteria":"评价标准" 输出语言为${lang.lang === 'en' ? '英文' : lang.lang === 'hk' ? '繁体中文' : '简体中文'}
+      },
+    ]
+    chat_no_stream2(prompt, { type: 'json_object' }).then((res: any) => {
+      console.log('文件上传', JSON.parse(res))
+      gType.value = 'chat'
+      setPageId(84, res).then(res => {
+        const baseUrl = setUrl()
+        const url = `${baseUrl}/pbl-teacher-table/dist/workPage.html#/setWorkPage?id=${res}&type=${84}&userid=${props.userid || ''}`
+        createSlide()
+        createFrameElement(url, 84)
+        message.gLoading = false
+        message.jsonData.isGenerate = true
+      })
+    })
+  }
+  else if (message.jsonData?.gType === 'generate_image') {
+    console.log(message.jsonData?.gType)
+    const prompt = `${message.aiContent} 根据用户的内容,生成图片`
+    const result = chat_no_stream(prompt, agentidPhoto.value, props.userid || '', lang.lang)
+    console.log('图片', result)
+    const content = await result.promise
+    console.log('event.data', content)
+    // content为空时结束loading并退出,避免后续处理报错
+    if (!content) {
+      message.gLoading = false
+      message.chatloading = false
+      chatLoading.value = false
+      stopMessage()
+      return
+    }
+    // 让AI从返回内容中提取图片链接
+    chat_no_stream2([{
+      role: 'user',
+      content: `这是返回的内容:"${content}",从中提取图片链接。输出一个json格式的回复,格式如下:{"url":"图片链接"},如果没有图片链接则url为空字符串。`,
+    }], { type: 'json_object' }).then((res: any) => {
+      const imageUrl = JSON.parse(res).url || ''
+      if (imageUrl) {
+        // 判断当前页面是否是工具页(含frame元素)
+        const isToolPage = (currentSlide.value?.elements || []).some((el: any) => el.type === 'frame')
+        // 如果当前页不是工具页则直接加图片,是工具页则新建页面再加图片
+        if (!isToolPage) {
+          createImageElement(imageUrl)
+        }
+        else {
+          createSlide()
+          createImageElement(imageUrl)
+        }
+      }
+      gType.value = 'chat'
+      message.gLoading = false
+      message.jsonData.isGenerate = true
+    })
+  }
   else if (message.jsonData?.gType === 'trigger_batch_tool') {
   else if (message.jsonData?.gType === 'trigger_batch_tool') {
     console.log(message.jsonData?.gType)
     console.log(message.jsonData?.gType)
     const prompt = [
     const prompt = [
@@ -1009,6 +1071,10 @@ const createTool = async (array: any[], tool: any, index: number, slide: any) =>
     action = lang.ssAiChatQuickAction7
     action = lang.ssAiChatQuickAction7
     type = 79
     type = 79
   }
   }
+  else if (tool.tool_id === 'file') {
+    action = lang.ssAiChatQuickAction9
+    type = 84
+  }
   
   
   const textContents = slide?.elements
   const textContents = slide?.elements
     .filter((element: any) => element.type === 'text' || (element.type === 'shape' && element.text && element.text.content))
     .filter((element: any) => element.type === 'text' || (element.type === 'shape' && element.text && element.text.content))
@@ -1048,6 +1114,9 @@ const createTool = async (array: any[], tool: any, index: number, slide: any) =>
   else if (tool.tool_id === 'photo') {
   else if (tool.tool_id === 'photo') {
     jsonFormat = `{"answerQ":"问题","answer":"","fileList":[]}`
     jsonFormat = `{"answerQ":"问题","answer":"","fileList":[]}`
   }
   }
+  else if (tool.tool_id === 'file') {
+    jsonFormat = `{"answerQ":"问题","answer":"","fileList":[]}`
+  }
   
   
   const res = await chat_no_stream2([{
   const res = await chat_no_stream2([{
     role: 'user',
     role: 'user',
@@ -1127,6 +1196,7 @@ const agentid2 = ref('f86aa63c-b7b7-4d03-9b37-b59f116d36f3')// 生成内容
 const agentid3 = ref('caaa43ab-41a5-466a-94bc-74e0c9265068')// 互动工具推荐
 const agentid3 = ref('caaa43ab-41a5-466a-94bc-74e0c9265068')// 互动工具推荐
 const agentid4 = ref('b41bc650-9861-468c-a624-b52269dfff22')// 批量生成工具
 const agentid4 = ref('b41bc650-9861-468c-a624-b52269dfff22')// 批量生成工具
 const agentid5 = ref('939d28ef-3a1b-442b-871f-3894eb67ac9c')// 互动网页
 const agentid5 = ref('939d28ef-3a1b-442b-871f-3894eb67ac9c')// 互动网页
+const agentidPhoto = ref('7d65e2a9-ac2e-4c42-9ee2-3af6cad8ed82')// 互动图片
 
 
 const isQuickActions = ref<string[]>([])
 const isQuickActions = ref<string[]>([])
 const toggleQuickActions = (section: string) => {
 const toggleQuickActions = (section: string) => {
@@ -1241,6 +1311,7 @@ onMounted(() => {
   getAgentModel(agentid3.value)
   getAgentModel(agentid3.value)
   getAgentModel(agentid4.value)
   getAgentModel(agentid4.value)
   getAgentModel(agentid5.value)
   getAgentModel(agentid5.value)
+  getAgentModel(agentidPhoto.value)
 
 
   for (let i = 0; i < slidesStore.slides.length; i++) {
   for (let i = 0; i < slidesStore.slides.length; i++) {
     const slide = slidesStore.slides[i]
     const slide = slidesStore.slides[i]

+ 3 - 1
src/components/CollapsibleToolbar/index.vue

@@ -294,6 +294,7 @@ const getTypeLabel = (type?: number) => {
     79: lang.ssPhoto,
     79: lang.ssPhoto,
     84: lang.ssFile,
     84: lang.ssFile,
     831: lang.ssKwlTitle,
     831: lang.ssKwlTitle,
+    832: lang.ssKwlTitle,
   }
   }
   return typeMap[type || 0] || lang.ssUnknown
   return typeMap[type || 0] || lang.ssUnknown
 }
 }
@@ -307,7 +308,8 @@ const getTypeClass = (type?: number) => {
     74: 'type-video',
     74: 'type-video',
     75: 'type-bilibili',
     75: 'type-bilibili',
     76: 'type-app-center',
     76: 'type-app-center',
-    831: 'type-kwl'
+    831: 'type-kwl',
+    832: 'type-kwl-title'
   }
   }
   return classMap[type || 0] || 'type-default'
   return classMap[type || 0] || 'type-default'
 }
 }

+ 68 - 11
src/components/CollapsibleToolbar/index2.vue

@@ -94,7 +94,7 @@
           </svg>
           </svg>
           <span class="item-label">{{ lang.ssMultimedia }}</span>
           <span class="item-label">{{ lang.ssMultimedia }}</span>
         </div>
         </div>
-        <div class="sidebar-item" :class="{ active: activeSubmenu === 'english' }" @click="toggleSubmenu('english')">
+        <div class="sidebar-item" :class="{ active: activeSubmenu === 'english' }" @click="toggleSubmenu('english')" v-if="userJson.org == '00bc1e79-b627-11f1-b66d-005056924926' || userJson.organizeid == '45facc0a-1211-11ec-80ad-005056b86db5'">
           <svg class="item-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
           <svg class="item-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
             <path d="M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z"></path>
             <path d="M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z"></path>
             <path d="M19 10v2a7 7 0 01-14 0v-2"></path>
             <path d="M19 10v2a7 7 0 01-14 0v-2"></path>
@@ -103,7 +103,7 @@
           </svg>
           </svg>
           <span class="item-label">{{ lang.ssEnglish }}</span>
           <span class="item-label">{{ lang.ssEnglish }}</span>
         </div>
         </div>
-        <div class="sidebar-item" v-if="!onlyEnglish" :class="{ active: activeSubmenu === 'cocoLearn' }"
+        <div class="sidebar-item" v-if="!onlyEnglish && (userJson.organizeid == '3d2d45b1-703b-11f1-9985-005056924926' || userJson.organizeid == '45facc0a-1211-11ec-80ad-005056b86db5' || props.userid == '5943e08c-b7d4-11ed-8d51-005056b86db5')" :class="{ active: activeSubmenu === 'cocoLearn' }"
           @click="toggleSubmenu('cocoLearn')">
           @click="toggleSubmenu('cocoLearn')">
           <svg class="item-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"></circle><path d="M12 1v6m0 6v6"></path><path d="M1 12h6m6 0h6"></path></svg>
           <svg class="item-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"></circle><path d="M12 1v6m0 6v6"></path><path d="M1 12h6m6 0h6"></path></svg>
           <span class="item-label">{{ lang.ssCrossSubject }}</span>
           <span class="item-label">{{ lang.ssCrossSubject }}</span>
@@ -148,7 +148,7 @@
           </div>
           </div>
         </template>
         </template>
         <template v-else-if="!showFileConfirmModal && !exportingDialog">
         <template v-else-if="!showFileConfirmModal && !exportingDialog">
-          <FileInput accept=".pptx" @change="handleFileUpload">
+          <FileInput accept=".pptx,.ppt,.pdf" @change="handleFileUpload">
             <div class="upload-dropzone">
             <div class="upload-dropzone">
               <div class="upload-dropzone-icon">
               <div class="upload-dropzone-icon">
                 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
                 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
@@ -737,7 +737,7 @@
           </svg>
           </svg>
         </div>
         </div>
       </div>
       </div>
-      <div class="submenu-item-box2" v-if="!showKwlDetail">
+      <div class="submenu-item-box2" v-if="!showKwlDetail && !showSixHatDetail">
         <div class="tool-card kwl-card" @click="handleToolClick('kwl')">
         <div class="tool-card kwl-card" @click="handleToolClick('kwl')">
           <div class="tool-banner">
           <div class="tool-banner">
             <img :src="kwl" :alt="lang.ssKwlTitle" />
             <img :src="kwl" :alt="lang.ssKwlTitle" />
@@ -759,8 +759,30 @@
               <span>{{ lang.ssClickToViewDetail }}</span>
               <span>{{ lang.ssClickToViewDetail }}</span>
           </div>
           </div>
         </div>
         </div>
+        <div class="tool-card six-hat-card" @click="handleToolClick('sixHat')">
+          <div class="tool-banner">
+            <img :src="sixHat" :alt="lang.ssSixHatTitle" />
+            <div class="tool-overly"></div>
+            <div class="tool-icon-badge">
+              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+                <path d="M9 18h6M10 22h4M12 2a7 7 0 00-4 12.7c.6.5 1 1.3 1 2.3h6c0-1 .4-1.8 1-2.3A7 7 0 0012 2z"></path>
+              </svg>
+            </div>
+          </div>
+          <div class="tool-info">
+            <div class="tool-title">{{ lang.ssSixHatTitle }}</div>
+            <div class="tool-desc">{{ lang.ssSixHatDesc }}</div>
+            <div class="tool-tags">
+              <span class="tool-tag">{{ lang.ssSixHatGradeRange }}</span>
+            </div>
+          </div>
+          <div class="tool-hover-overlay">
+              <span>{{ lang.ssClickToViewDetail }}</span>
+          </div>
+        </div>
       </div>
       </div>
-      <KwlDetail :banner="kwl" v-else @back="showKwlDetail = false" @add="handleKwlAdd" />
+      <KwlDetail :banner="kwl" v-else-if="showKwlDetail" @back="showKwlDetail = false" @add="handleKwlAdd" />
+      <SixHatDetail v-else @back="showSixHatDetail = false" @add="handleSixHatAdd" />
     </div>
     </div>
 
 
 
 
@@ -769,7 +791,7 @@
 </template>
 </template>
 
 
 <script lang="ts" setup>
 <script lang="ts" setup>
-import { ref, watch, computed, useTemplateRef, nextTick } from 'vue'
+import { ref, watch, computed, useTemplateRef, nextTick, onMounted } from 'vue'
 import { storeToRefs } from 'pinia'
 import { storeToRefs } from 'pinia'
 import useCreateElement from '@/hooks/useCreateElement'
 import useCreateElement from '@/hooks/useCreateElement'
 import useSlideHandler from '@/hooks/useSlideHandler'
 import useSlideHandler from '@/hooks/useSlideHandler'
@@ -789,7 +811,9 @@ import toolPhoto from '@/assets/img/tool_photo.png'
 import toolFile from '@/assets/img/tool_file.png'
 import toolFile from '@/assets/img/tool_file.png'
 import axios from '@/services/config'
 import axios from '@/services/config'
 import kwl from '@/assets/img/kwlBanner.jpg'
 import kwl from '@/assets/img/kwlBanner.jpg'
+import sixHat from '@/assets/img/sixHatBanner.jpg'
 import KwlDetail from './cocolearnCom/KwlDetail.vue'
 import KwlDetail from './cocolearnCom/KwlDetail.vue'
+import SixHatDetail from './cocolearnCom/SixHatDetail.vue'
 
 
 interface ContentItem {
 interface ContentItem {
   tool?: number
   tool?: number
@@ -814,14 +838,17 @@ const props = withDefaults(defineProps<{
   onlyEnglish: false,
   onlyEnglish: false,
 })
 })
 
 
+const getUserInfo = async (userid: string) => {
+  const res = await axios.get('https://pbl.cocorobo.cn/api/pbl/selectUser2', {
+    params: { userid }
+  })
+  return res[0][0] || {}
+}
 
 
 const userJson = ref<any>({})
 const userJson = ref<any>({})
 watch(() => props.userid, async (newVal) => {
 watch(() => props.userid, async (newVal) => {
   if (!newVal) return
   if (!newVal) return
-  const res = await axios.get('https://pbl.cocorobo.cn/api/pbl/selectUser', {
-    params: { userid: newVal }
-  })
-  userJson.value = res[0][0] || {}
+  userJson.value = await getUserInfo(newVal)
 })
 })
 
 
 const emit = defineEmits<{
 const emit = defineEmits<{
@@ -834,6 +861,7 @@ const activeSubmenu = ref<string | null>(props.onlyEnglish ? 'english' : null)
 const contentList = ref<ContentItem[]>([])
 const contentList = ref<ContentItem[]>([])
 const hoveredTool = ref<string | null>(null)
 const hoveredTool = ref<string | null>(null)
 const showKwlDetail = ref(false)
 const showKwlDetail = ref(false)
+const showSixHatDetail = ref(false)
 const webpageUrl = ref('')
 const webpageUrl = ref('')
 const isLoading = ref(false)
 const isLoading = ref(false)
 const isValidUrl = ref<boolean | null>(null) // null: 未输入, true: 有效, false: 无效
 const isValidUrl = ref<boolean | null>(null) // null: 未输入, true: 有效, false: 无效
@@ -1176,6 +1204,9 @@ const handleToolClick = _.debounce((tool: string) => {
   else if (tool === 'kwl') {
   else if (tool === 'kwl') {
     showKwlDetail.value = true
     showKwlDetail.value = true
   }
   }
+  else if (tool === 'sixHat') {
+    showSixHatDetail.value = true
+  }
 }, 300)
 }, 300)
 
 
 const handleKwlAdd = (data: any) => {
 const handleKwlAdd = (data: any) => {
@@ -1188,6 +1219,14 @@ const handleKwlAdd = (data: any) => {
   parentWindow?.addTool2?.(831, data)
   parentWindow?.addTool2?.(831, data)
 }
 }
 
 
+const handleSixHatAdd = (data: any) => {
+  interface ParentWindowWithToolList extends Window {
+    addTool2?: (id: number, data: any) => void;
+  }
+  const parentWindow = window.parent as ParentWindowWithToolList
+  parentWindow?.addTool2?.(832, data)
+}
+
 const loadContentList = () => {
 const loadContentList = () => {
   try {
   try {
     interface ParentWindowWithToolList extends Window {
     interface ParentWindowWithToolList extends Window {
@@ -1207,7 +1246,7 @@ const insertContent = (item: ContentItem) => {
   createFrameElement(item.url, item.tool)
   createFrameElement(item.url, item.tool)
 }
 }
 
 
-const toolTypeArray = ref([45, 15, 78, 79, 84, 831])
+const toolTypeArray = ref([45, 15, 78, 79, 84, 831, 832])
 
 
 const addContent = (data: ContentItem, type: number) => {
 const addContent = (data: ContentItem, type: number) => {
   // contentList.value.push(data)
   // contentList.value.push(data)
@@ -1279,6 +1318,7 @@ const getTypeLabel = (type?: number) => {
     79: lang.ssPhoto,
     79: lang.ssPhoto,
     84: lang.ssFile,
     84: lang.ssFile,
     831: lang.ssKwlTitle,
     831: lang.ssKwlTitle,
+    832: lang.ssSixHatTitle,
   }
   }
   return typeMap[type || 0] || lang.ssUnknown
   return typeMap[type || 0] || lang.ssUnknown
 }
 }
@@ -1293,6 +1333,7 @@ const getTypeClass = (type?: number) => {
     75: 'type-bilibili',
     75: 'type-bilibili',
     76: 'type-app-center',
     76: 'type-app-center',
     831: 'type-kwl',
     831: 'type-kwl',
+    832: 'type-six-hat',
     84: 'type-file',
     84: 'type-file',
   }
   }
   return classMap[type || 0] || 'type-default'
   return classMap[type || 0] || 'type-default'
@@ -1555,6 +1596,11 @@ const addAiWeb = async (code: string) => {
   webId.value = ''
   webId.value = ''
   isEdit.value = false
   isEdit.value = false
 }
 }
+
+onMounted(async () => {
+  if (!props.userid) return
+  userJson.value = await getUserInfo(props.userid)
+})
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
@@ -2107,6 +2153,17 @@ const addAiWeb = async (code: string) => {
   }
   }
 }
 }
 
 
+// 六顶思考帽专属样式(琥珀色主题)
+.six-hat-card {
+  .tool-icon-badge svg{
+    color: #f59e0b;
+  }
+
+  .tool-overly {
+    background-color: #f59e0b;
+  }
+}
+
 .submenu-upload {
 .submenu-upload {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;

+ 17 - 16
src/components/CreateCourseDialog.vue

@@ -12,7 +12,7 @@
       <h2>{{ lang.ssCreateCourse }}</h2>
       <h2>{{ lang.ssCreateCourse }}</h2>
       <p class="subtitle">{{ lang.ssCreateCourseSubtitle }}</p>
       <p class="subtitle">{{ lang.ssCreateCourseSubtitle }}</p>
       <div class="options-grid">
       <div class="options-grid">
-        <FileInput accept="application/vnd.openxmlformats-officedocument.presentationml.presentation"
+        <FileInput accept=".pptx,.ppt,.pdf"
           @change="handleFileUpload">
           @change="handleFileUpload">
           <div class="option-card">
           <div class="option-card">
             <div class="option-icon">
             <div class="option-icon">
@@ -106,7 +106,7 @@ import { useMainStore } from '@/store'
 const emit = defineEmits<{
 const emit = defineEmits<{
   (e: 'close'): void
   (e: 'close'): void
   (e: 'select', option: string): void
   (e: 'select', option: string): void
-  (e: 'setTitle', title: string): void
+  (e: 'setTitle', title: string, type: number): void
 }>()
 }>()
 
 
 const { importPPTXFile, exporting } = useImport()
 const { importPPTXFile, exporting } = useImport()
@@ -142,20 +142,21 @@ const handleFileUpload = async (files: FileList) => {
 
 
     // 调用importPPTXFile并传入signal
     // 调用importPPTXFile并传入signal
     await importPPTXFile(files, { signal, onclose: () => {
     await importPPTXFile(files, { signal, onclose: () => {
-      emit('setTitle', file.name.replace(/\.[^/.]+$/, ''), 2); emit('close')
-      showConfirmDialog({
-        title: lang.ssUploadSuccess,
-        content: lang.ssBatchInteractiveWebConfirm,
-        confirmText: lang.ssBatchInteractiveWebConfirmDesc,
-        cancelText: lang.ssBatchInteractiveWebConfirmDesc2,
-        width: 400,
-        onConfirm: () => {
-          setRunningState(true)
-        },
-        onCancel: () => {
-          console.log('取消删除')
-        },
-      })
+      emit('setTitle', file.name.replace(/\.[^/.]+$/, ''), 2) 
+      emit('close')
+      // showConfirmDialog({
+      //   title: lang.ssUploadSuccess,
+      //   content: lang.ssBatchInteractiveWebConfirm,
+      //   confirmText: lang.ssBatchInteractiveWebConfirmDesc,
+      //   cancelText: lang.ssBatchInteractiveWebConfirmDesc2,
+      //   width: 400,
+      //   onConfirm: () => {
+      //     setRunningState(true)
+      //   },
+      //   onCancel: () => {
+      //     console.log('取消删除')
+      //   },
+      // })
     } })
     } })
   }
   }
   catch (error) {
   catch (error) {

+ 51 - 1
src/hooks/useImport.ts

@@ -1,4 +1,4 @@
-import { ref, nextTick } from 'vue'
+import { ref, nextTick } from 'vue'
 import { storeToRefs } from 'pinia'
 import { storeToRefs } from 'pinia'
 import { parse, type Shape, type Element, type ChartItem, type BaseElement } from 'pptxtojson'
 import { parse, type Shape, type Element, type ChartItem, type BaseElement } from 'pptxtojson'
 import { nanoid } from 'nanoid'
 import { nanoid } from 'nanoid'
@@ -1666,6 +1666,56 @@ export default () => {
     const file = files[0]
     const file = files[0]
     if (!file) return
     if (!file) return
 
 
+    // ppt / pdf 文件先通过 convertapi 转为 pptx
+    const fileName = file.name.toLowerCase()
+    const needConvert = fileName.endsWith('.ppt') || fileName.endsWith('.pdf')
+    if (needConvert) {
+      const fromFormat = fileName.endsWith('.ppt') ? 'ppt' : 'pdf'
+      const secret = 'UQB8F8GjADHxXfW544FmAl0qb3EsIkDO'
+      exporting.value = true
+      imgExporting.value = true
+      startTimer?.()
+      const oneHour = 60 * 60 * 1000
+      // 1. 上传文件到 ConvertAPI
+      fetch(`https://v2.convertapi.com/upload?filename=${encodeURIComponent(file.name)}`, {
+        method: 'POST',
+        body: file,
+        signal: AbortSignal.timeout(oneHour),
+      })
+        .then(r => r.json())
+        .then(uploadRes => {
+          if (!uploadRes.FileId) throw new Error('文件上传失败')
+          // 2. 调用转换接口
+          const body = { Parameters: [{ Name: 'File', FileValue: { Id: uploadRes.FileId } }] }
+          return fetch(`https://v2.convertapi.com/convert/${fromFormat}/to/pptx?secret=${secret}&StoreFile=true`, {
+            method: 'POST',
+            headers: { 'Content-Type': 'application/json' },
+            body: JSON.stringify(body),
+            signal: AbortSignal.timeout(oneHour),
+          }).then(r => r.json())
+        })
+        .then(convRes => {
+          const fileUrl = convRes?.Files?.[0]?.Url
+          console.log('转换成功:', fileUrl)
+          if (!fileUrl) throw new Error('转换失败:未获取到文件')
+          return fetch(fileUrl, { signal: AbortSignal.timeout(oneHour) })
+        })
+        .then(res => res.arrayBuffer())
+        .then(buffer => {
+          const convertedFile = new File([buffer], file.name.replace(/\.(ppt|pdf)$/i, '.pptx'), { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' })
+          const dt = new DataTransfer()
+          dt.items.add(convertedFile)
+          importPPTXFile(dt.files, options)
+        })
+        .catch((err: any) => {
+          console.error('转换失败:', err)
+          message.error(lang.ssFileReadFail)
+          exporting.value = false
+          imgExporting.value = false
+        })
+      return
+    }
+
     exporting.value = true // 假设 exporting 是一个全局 ref
     exporting.value = true // 假设 exporting 是一个全局 ref
     imgExporting.value = true // 假设 imgExporting 是一个全局 ref
     imgExporting.value = true // 假设 imgExporting 是一个全局 ref
     startTimer?.()
     startTimer?.()

+ 16 - 0
src/services/config.ts

@@ -79,9 +79,16 @@ instance.interceptors.request.use(
 
 
 instance.interceptors.response.use(
 instance.interceptors.response.use(
   (response) => {
   (response) => {
+    console.log('响应数据')
+    console.log(response)
+
+    if (response.status == 201) {
+      return Promise.resolve(response.status)
+    }
     if (response.status >= 200 && response.status < 400) {
     if (response.status >= 200 && response.status < 400) {
       return Promise.resolve(response.data)
       return Promise.resolve(response.data)
     }
     }
+
     message.error(response.config.url || '')
     message.error(response.config.url || '')
     message.error('未知的请求错误!')
     message.error('未知的请求错误!')
     return Promise.reject(response)
     return Promise.reject(response)
@@ -128,6 +135,13 @@ instance.interceptors.response.use(
       message.error('服务器遇到未知错误!')
       message.error('服务器遇到未知错误!')
       return Promise.reject(error.message)
       return Promise.reject(error.message)
     }
     }
+
+    // 无 response 的 Network Error(CORS 拦截的 403 等),判定为登录态过期
+    if (error.code === 'ERR_NETWORK' && config?.withCredentials) {
+      // message.error('登录已过期,请重新登录')
+      return Promise.reject(123)
+    }
+
     if (fullUrl !== 'https://r2rserver.cocorobo.cn/v3/documents') {
     if (fullUrl !== 'https://r2rserver.cocorobo.cn/v3/documents') {
       message.error(fullUrl)
       message.error(fullUrl)
       message.error(error)
       message.error(error)
@@ -136,6 +150,8 @@ instance.interceptors.response.use(
       console.error(fullUrl)
       console.error(fullUrl)
       console.error(error)
       console.error(error)
     }
     }
+    console.log('报错输出')
+    console.log(fullUrl, error)
     return Promise.reject(error)
     return Promise.reject(error)
   }
   }
 )
 )

+ 12 - 0
src/services/course.ts

@@ -243,6 +243,17 @@ export const addPPTOp = (params: any): Promise<any> => {
   return axios.post(`${API_URL}addPPTOp`, [params])
   return axios.post(`${API_URL}addPPTOp`, [params])
 }
 }
 
 
+/**
+ * 
+ * 新增操作记录
+ * @param any id VARCHAR(3000),userid VARCHAR(36), type VARCHAR(36), `index` INT, `json` LONGTEXT
+ * @returns Promise<any>
+ */
+
+export const addPPTOp2 = (params: any): Promise<any> => {
+  return axios.post(`${API_URL}addPPTOp2`, [params])
+}
+
 
 
 export default {
 export default {
   getCourseDetail,
   getCourseDetail,
@@ -266,5 +277,6 @@ export default {
   getClassById,
   getClassById,
   selectPPTOp,
   selectPPTOp,
   addPPTOp,
   addPPTOp,
+  addPPTOp2,
 }
 }
 
 

+ 24 - 15
src/views/Editor/Canvas/ChildPageDisplay.vue

@@ -53,14 +53,14 @@ const { childPageToolsArray, userid, courseTitle, childPageIndex } = storeToRefs
 const { setChildPageState } = mainStore
 const { setChildPageState } = mainStore
 const { currentSlide, slideIndex } = storeToRefs(slidesStore)
 const { currentSlide, slideIndex } = storeToRefs(slidesStore)
 
 
-const toolsArray = childPageToolsArray.value
+const toolsArray = ref(childPageToolsArray.value.filter(t => !t.isSet))
 const selectedToolIndex = ref(0)
 const selectedToolIndex = ref(0)
 const agentid2 = ref('f86aa63c-b7b7-4d03-9b37-b59f116d36f3')// 生成内容
 const agentid2 = ref('f86aa63c-b7b7-4d03-9b37-b59f116d36f3')// 生成内容
 const loading = ref(true)
 const loading = ref(true)
 
 
 
 
 const toolsJson = computed(() => {
 const toolsJson = computed(() => {
-  return toolsArray[selectedToolIndex.value] || {}
+  return toolsArray.value[selectedToolIndex.value] || {}
 })
 })
 
 
 const formatHint = (str: string, count: number) => {
 const formatHint = (str: string, count: number) => {
@@ -69,20 +69,20 @@ const formatHint = (str: string, count: number) => {
 
 
 const selectTool = (index: number) => {
 const selectTool = (index: number) => {
   selectedToolIndex.value = index
   selectedToolIndex.value = index
-  console.log('👶 选中工具:', toolsArray[index])
+  console.log('👶 选中工具:', toolsArray.value[index])
 }
 }
 
 
 onMounted(() => {
 onMounted(() => {
-  console.log('👶 带选页打开,toolsArray:', toolsArray)
-  const toolsToCreate = toolsArray.filter(t => !t.url)
+  console.log('👶 带选页打开,toolsArray:', toolsArray.value)
+  const toolsToCreate = toolsArray.value.filter(t => !t.url)
   if (toolsToCreate.length === 0) {
   if (toolsToCreate.length === 0) {
     loading.value = false
     loading.value = false
     // return
     // return
   }
   }
   
   
   // const createPromises = toolsToCreate.map((tool) => {
   // const createPromises = toolsToCreate.map((tool) => {
-  //   const originalIndex = toolsArray.findIndex(t => t.tool_id === tool.tool_id)
-  //   return createTool(toolsArray, tool, originalIndex)
+  //   const originalIndex = toolsArray.value.findIndex(t => t.tool_id === tool.tool_id)
+  //   return createTool(toolsArray.value, tool, originalIndex)
   // })
   // })
   
   
   // await Promise.all(createPromises)
   // await Promise.all(createPromises)
@@ -183,16 +183,20 @@ const createTool = async (array: any[], tool: any, index: number) => {
 
 
 const setTool = () => {
 const setTool = () => {
   const slide = currentSlide.value
   const slide = currentSlide.value
-  slidesStore.updateSlide({ toolsArray: toolsArray }, slide.id)
+  slidesStore.updateSlide({ toolsArray: toolsArray.value }, slide.id)
   console.log(slide)
   console.log(slide)
 
 
   // 判断所有工具是否都已保留
   // 判断所有工具是否都已保留
-  const allToolsSet = toolsArray.every(t => t.isSet)
+  const allToolsSet = toolsArray.value.every(t => t.isSet)
   if (allToolsSet) {
   if (allToolsSet) {
     const slide = currentSlide.value
     const slide = currentSlide.value
     slidesStore.updateSlide({ toolsArray: [] }, slide.id) 
     slidesStore.updateSlide({ toolsArray: [] }, slide.id) 
     setChildPageState(false, [], slideIndex.value || 0)
     setChildPageState(false, [], slideIndex.value || 0)
   }
   }
+
+  // 过滤掉已处理(保留/放弃)的工具,剩余未处理的供继续选择
+  toolsArray.value = toolsArray.value.filter(t => !t.isSet)
+  selectedToolIndex.value = 0
 }
 }
 
 
 const setUrl = () => {
 const setUrl = () => {
@@ -241,31 +245,36 @@ const saveTool = (url: string, type: any, index: number) => {
   createSlide()
   createSlide()
   createFrameElement(url, type)
   createFrameElement(url, type)
   changeSlideIndex(childPageIndex.value)
   changeSlideIndex(childPageIndex.value)
-  toolsArray[index].isSet = true
+  toolsArray.value[index].isSet = true
   setTool()
   setTool()
   setTimeout(() => {
   setTimeout(() => {
     changeSlideIndex(childPageIndex.value + 1)
     changeSlideIndex(childPageIndex.value + 1)
     setChildPageState(false, [], slideIndex.value || 0)
     setChildPageState(false, [], slideIndex.value || 0)
   }, 100)
   }, 100)
-  console.log('保留工具', toolsArray)
+  console.log('保留工具', toolsArray.value)
 }
 }
 
 
 // 放弃工具
 // 放弃工具
 const discardTool = (index: number) => {
 const discardTool = (index: number) => {
-  toolsArray[index].isSet = true
+  toolsArray.value[index].isSet = true
   setTool()
   setTool()
-  console.log('放弃工具', toolsArray)
+  // 丢弃后自动切换到下一个未处理的题;全部处理完时 setTool 内已关闭带选页
+  if (toolsArray.value.length > 0) {
+    selectedToolIndex.value = Math.min(index, toolsArray.value.length - 1)
+  }
+  console.log('放弃工具', toolsArray.value)
 }
 }
 
 
 // 保留所有工具
 // 保留所有工具
 const keepAllTools = () => {
 const keepAllTools = () => {
-  toolsArray.forEach(tool => {
+  toolsArray.value.forEach(tool => {
     if (!tool.isSet) {
     if (!tool.isSet) {
       createSlide()
       createSlide()
       createFrameElement(tool.url, getToolType(tool.tool_id))
       createFrameElement(tool.url, getToolType(tool.tool_id))
       tool.isSet = true
       tool.isSet = true
     }
     }
   })
   })
+
   changeSlideIndex(childPageIndex.value)
   changeSlideIndex(childPageIndex.value)
   setTool()
   setTool()
   setTimeout(() => {
   setTimeout(() => {
@@ -283,7 +292,7 @@ const toolTypeMap: Record<string, number> = {
 }
 }
 
 
 const currentToolType = computed(() => {
 const currentToolType = computed(() => {
-  const toolId = toolsArray[selectedToolIndex.value]?.tool_id
+  const toolId = toolsArray.value[selectedToolIndex.value]?.tool_id
   return toolId ? toolTypeMap[toolId] || 0 : 0
   return toolId ? toolTypeMap[toolId] || 0 : 0
 })
 })
 
 

+ 2 - 0
src/views/Editor/CanvasTool/WebpageInput.vue

@@ -112,6 +112,7 @@ const getTypeLabel = (type: number) => {
     79: lang.ssPhoto,
     79: lang.ssPhoto,
     84: lang.ssFile,
     84: lang.ssFile,
     831: lang.ssKwlTitle,
     831: lang.ssKwlTitle,
+    832: lang.ssSixHatTitle,
   }
   }
   return typeMap[type] || lang.ssUnknown
   return typeMap[type] || lang.ssUnknown
 }
 }
@@ -127,6 +128,7 @@ const getTypeClass = (type: number) => {
     75: 'type-bilibili',
     75: 'type-bilibili',
     76: 'type-app-center',
     76: 'type-app-center',
     831: 'type-kwl',
     831: 'type-kwl',
+    832: 'type-kwl-title',
   }
   }
   return classMap[type] || 'type-default'
   return classMap[type] || 'type-default'
 }
 }

+ 28 - 11
src/views/Editor/CanvasTool/index2.vue

@@ -70,7 +70,7 @@
           </svg>
           </svg>
         </div>
         </div>
       </Popover>
       </Popover>
-      <!-- 工具iframe字号缩放:比例1~24,每±1对应字号±1px,初始16px -->
+      <!-- 工具iframe字号缩放:初始100%,每±1对应±20% -->
       <div class="handler-item font-scale-ctrl" v-if="hasInteractiveTool">
       <div class="handler-item font-scale-ctrl" v-if="hasInteractiveTool">
         <span class="scale-btn" :class="{ disable: fontScale <= MIN_FONT_SCALE }" @click="changeFontScale(-1)">
         <span class="scale-btn" :class="{ disable: fontScale <= MIN_FONT_SCALE }" @click="changeFontScale(-1)">
           <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
           <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
@@ -78,7 +78,8 @@
             <line x1="5" y1="12" x2="19" y2="12" />
             <line x1="5" y1="12" x2="19" y2="12" />
           </svg>
           </svg>
         </span>
         </span>
-        <span class="scale-value">{{ fontScale }}</span>
+        <span class="scale-label">{{ lang.ssFontScale }}</span>
+        <span class="scale-value">{{ fontScalePercent }}%</span>
         <span class="scale-btn" :class="{ disable: fontScale >= MAX_FONT_SCALE }" @click="changeFontScale(1)">
         <span class="scale-btn" :class="{ disable: fontScale >= MAX_FONT_SCALE }" @click="changeFontScale(1)">
           <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
           <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
             stroke-linecap="round">
             stroke-linecap="round">
@@ -152,7 +153,7 @@
           <span>{{ lang.ssShape }}</span>
           <span>{{ lang.ssShape }}</span>
         </div>
         </div>
       </Popover>
       </Popover>
-      <RichTextBase  v-if="handleElement?.type == 'text'"/>
+      <RichTextBase  v-if="handleElement?.type == 'text' || handleElement?.type == 'shape'"/>
       <div style="display: flex; align-items: center;" v-if="handleElement?.type == 'shape'">
       <div style="display: flex; align-items: center;" v-if="handleElement?.type == 'shape'">
         <Select 
         <Select 
           style="flex: 1;" 
           style="flex: 1;" 
@@ -358,21 +359,28 @@ const hasInteractiveTool = computed(() => {
   return elements.some((el: any) => el.type === 'frame' && toolTypeArray.value.includes(el.toolType))
   return elements.some((el: any) => el.type === 'frame' && toolTypeArray.value.includes(el.toolType))
 })
 })
 
 
-// 工具iframe字号缩放:比例最小1最大24,每±1对应字号±1px,初始16px
-const MIN_FONT_SCALE = 1
-const MAX_FONT_SCALE = 24
+// 工具iframe字号缩放:初始100%,每±1对应±20%,sessionStorage 同会话内保持,重新进入课程清空
+const MIN_FONT_SCALE = -3 // 40%
+const MAX_FONT_SCALE = 5 // 200%
 const BASE_FONT_SIZE = 16
 const BASE_FONT_SIZE = 16
-const fontScale = ref(1)
+const STORAGE_KEY = 'toolIframeFontScale'
+const fontScale = ref(parseInt(sessionStorage.getItem(STORAGE_KEY) || '0', 10))
+const fontScalePercent = computed(() => 100 + fontScale.value * 20)
 
 
 const setToolIframeFontSize = () => {
 const setToolIframeFontSize = () => {
   try {
   try {
     const iframe = document.getElementsByTagName('iframe')[0] as HTMLIFrameElement | undefined
     const iframe = document.getElementsByTagName('iframe')[0] as HTMLIFrameElement | undefined
     const iframeDoc = iframe?.contentWindow?.document
     const iframeDoc = iframe?.contentWindow?.document
     if (iframeDoc?.documentElement) {
     if (iframeDoc?.documentElement) {
-      iframeDoc.documentElement.style.fontSize = `${BASE_FONT_SIZE + fontScale.value - 1}px`
+      const fontSize = BASE_FONT_SIZE * (1 + fontScale.value * 0.2)
+      console.log(fontSize)
+      
+      iframeDoc.documentElement.style.fontSize = `${fontSize}px`
     }
     }
   }
   }
   catch (error) {
   catch (error) {
+    const fontSize = BASE_FONT_SIZE * (1 + fontScale.value * 0.2)
+    console.log(fontSize)
     console.warn('设置iframe字号失败:', error)
     console.warn('设置iframe字号失败:', error)
   }
   }
 }
 }
@@ -381,12 +389,15 @@ const changeFontScale = (delta: number) => {
   const next = fontScale.value + delta
   const next = fontScale.value + delta
   if (next < MIN_FONT_SCALE || next > MAX_FONT_SCALE) return
   if (next < MIN_FONT_SCALE || next > MAX_FONT_SCALE) return
   fontScale.value = next
   fontScale.value = next
+  sessionStorage.setItem(STORAGE_KEY, String(next))
   setToolIframeFontSize()
   setToolIframeFontSize()
 }
 }
 
 
-// 切换页码时重置缩放比例回1
-watch(slideIndex, () => {
-  fontScale.value = 1
+// iframe 加载后应用持久化的缩放比例
+watch(hasInteractiveTool, (val) => {
+  if (val) {
+    setTimeout(() => setToolIframeFontSize(), 500)
+  }
 })
 })
 
 
 const iframeLabel = computed(() => {
 const iframeLabel = computed(() => {
@@ -415,6 +426,7 @@ const getTypeLabel = (type: number) => {
     79: lang.ssPhoto,
     79: lang.ssPhoto,
     84: lang.ssFile,
     84: lang.ssFile,
     831: lang.ssKwlTitle,
     831: lang.ssKwlTitle,
+    832: lang.ssSixHatTitle,
   }
   }
   return typeMap[type] || lang.ssUnknown
   return typeMap[type] || lang.ssUnknown
 }
 }
@@ -801,6 +813,11 @@ const updateGradientColors = (color: string) => {
     }
     }
   }
   }
 
 
+  .scale-label {
+    font-size: 13px;
+    color: #6b7280;
+  }
+
   .scale-value {
   .scale-value {
     min-width: 20px;
     min-width: 20px;
     text-align: center;
     text-align: center;

+ 16 - 4
src/views/Student/components/DialoguePanel.vue

@@ -184,11 +184,13 @@ import { lang } from '@/main'
 interface Props {
 interface Props {
   courseid?: string | null
   courseid?: string | null
   userid?: string | null
   userid?: string | null
+  fileid?: string | ''
 }
 }
 
 
 const props = withDefaults(defineProps<Props>(), {
 const props = withDefaults(defineProps<Props>(), {
   courseid: null,
   courseid: null,
   userid: null,
   userid: null,
+  fileid: '',
 })
 })
 
 
 interface Message {
 interface Message {
@@ -284,8 +286,9 @@ const sendMessage = () => {
     message: userInput,
     message: userInput,
     userId: props.userid,
     userId: props.userid,
     // model: node.properties.item.modelType,
     // model: node.properties.item.modelType,
-    model: 'open-gpt-4.1',
-    file_ids: [],
+    // model: 'qwen3.5-flash',
+    model: agentData.value.modelType,
+    file_ids: [props.fileid],
     sound_url: '',
     sound_url: '',
     temperature: 0.2,
     temperature: 0.2,
     top_p: 1,
     top_p: 1,
@@ -437,7 +440,7 @@ const clearChatHistory = async () => {
 
 
   try {
   try {
     const params = {
     const params = {
-      model: 'open-gpt-4.1',
+      model: agentData.value.modelType,
       thread_id: agentData.value.thread_id,
       thread_id: agentData.value.thread_id,
       groupid: `${props.courseid?.slice(0, 31)}${props.userid?.slice(0, 5)}`,
       groupid: `${props.courseid?.slice(0, 31)}${props.userid?.slice(0, 5)}`,
       userid: props.userid,
       userid: props.userid,
@@ -547,6 +550,8 @@ onMounted(() => {
           margin-top: 5px;
           margin-top: 5px;
           display: flex;
           display: flex;
           flex-direction: column;
           flex-direction: column;
+          overflow: hidden;
+
           .dp_ml_i_m_ma_name{
           .dp_ml_i_m_ma_name{
             max-width: 100%;
             max-width: 100%;
             overflow: hidden;
             overflow: hidden;
@@ -558,12 +563,19 @@ onMounted(() => {
             margin-bottom: 5px;
             margin-bottom: 5px;
           }
           }
           .dp_ml_i_m_ma_textBlok{
           .dp_ml_i_m_ma_textBlok{
-            width: fit-content;
+            max-width: 100%;
             display: block;
             display: block;
             background-color: #F8F9FA;
             background-color: #F8F9FA;
             padding: 10px;
             padding: 10px;
             border: solid 1px #E9ECEF;
             border: solid 1px #E9ECEF;
             border-radius: 4px;
             border-radius: 4px;
+            box-sizing: border-box;
+
+            * {
+              word-break: break-word;
+              white-space: unset;
+            }
+
             &>svg{
             &>svg{
               width: 17px;
               width: 17px;
               height: 17px;
               height: 17px;

+ 17 - 3
src/views/Student/components/aiChat.vue

@@ -3,7 +3,7 @@
     <div class="fullscreen-spin mask2" v-if="agentlistloading">
     <div class="fullscreen-spin mask2" v-if="agentlistloading">
       <div class="spin">
       <div class="spin">
         <div class="spinner"></div>
         <div class="spinner"></div>
-        <div class="text">加载中...</div>
+        <div class="text">loading...</div>
       </div>
       </div>
     </div>
     </div>
     <!-- 弹窗头部 -->
     <!-- 弹窗头部 -->
@@ -117,7 +117,7 @@ import { chat_no_stream, chat_stream, getAgentModel, chat_no_stream2, getAgentCh
 import { useSlidesStore } from '@/store'
 import { useSlidesStore } from '@/store'
 import { lang } from '@/main'
 import { lang } from '@/main'
 import MarkdownIt from 'markdown-it'
 import MarkdownIt from 'markdown-it'
-import { getWorkPageId, getClassById } from '@/services/course'
+import { getWorkPageId, getClassById, addPPTOp2 } from '@/services/course'
 import FileInput from '@/components/FileInput2.vue'
 import FileInput from '@/components/FileInput2.vue'
 import axios from '@/services/config'
 import axios from '@/services/config'
 import message from '@/utils/message'
 import message from '@/utils/message'
@@ -172,12 +172,14 @@ const props = withDefaults(defineProps<{
   workJson?: any
   workJson?: any
   visible?: boolean
   visible?: boolean
   cid?: string | null
   cid?: string | null
+  courseid?: string | null
 }>(), {
 }>(), {
   userid: null,
   userid: null,
   position: () => ({ x: 0, y: 0 }),
   position: () => ({ x: 0, y: 0 }),
   workJson: () => ({}),
   workJson: () => ({}),
   visible: false,
   visible: false,
-  cid: null
+  cid: null,
+  courseid: null
 })
 })
 
 
 const emit = defineEmits(['close'])
 const emit = defineEmits(['close'])
@@ -310,6 +312,16 @@ const sendMessage = () => {
   if (chatLoading.value) {
   if (chatLoading.value) {
     return
     return
   }
   }
+
+  addPPTOp2({
+    id: props.courseid,
+    userid: props.userid || '',
+    type: '2',
+    index: currentSlide.value.id, // 获取当前ppt页面的id
+    data: inputText.value
+  }).then(res => {
+    console.log('res', res)
+  })
   // 检查是否有文件正在处理中
   // 检查是否有文件正在处理中
   const hasProcessingFile = files.value.some(file => file.isProcessing)
   const hasProcessingFile = files.value.some(file => file.isProcessing)
   if (hasProcessingFile) {
   if (hasProcessingFile) {
@@ -592,6 +604,8 @@ const addChat = () => {
 
 
 import useCreateElement from '@/hooks/useCreateElement'
 import useCreateElement from '@/hooks/useCreateElement'
 import useSlideHandler from '@/hooks/useSlideHandler'
 import useSlideHandler from '@/hooks/useSlideHandler'
+import { storeToRefs } from 'pinia'
+const { slides, slideIndex, currentSlide, viewportSize, viewportRatio } = storeToRefs(slidesStore)
 const { createSlide } = useSlideHandler()
 const { createSlide } = useSlideHandler()
 const { createFrameElement } = useCreateElement()
 const { createFrameElement } = useCreateElement()
 
 

+ 624 - 20
src/views/Student/components/choiceQuestionDetailDialog.vue

@@ -15,13 +15,14 @@
             <span>{{
             <span>{{
               props.showData.choiceQuestionListData[props.showData.workIndex]
               props.showData.choiceQuestionListData[props.showData.workIndex]
                 .teststitle
                 .teststitle
-              }}</span>
+            }}</span>
           </div>
           </div>
           <div class="c_t45_msg" v-if="props.roleType == 1">
           <div class="c_t45_msg" v-if="props.roleType == 1">
             <div>{{ lang.ssAnswerCount }} {{ props.workArray.length }}<span
             <div>{{ lang.ssAnswerCount }} {{ props.workArray.length }}<span
                 v-if="props.unsubmittedStudents.length > 0">/{{ props.workArray.length +
                 v-if="props.unsubmittedStudents.length > 0">/{{ props.workArray.length +
                   props.unsubmittedStudents.length
                   props.unsubmittedStudents.length
                 }}</span></div>
                 }}</span></div>
+            <div v-if="correctRate !== null" class="c_t45_correct_rate">{{ lang.ssAccuracy2 }} {{ correctRate }}%</div>
             <span v-if="props.unsubmittedStudents.length > 0" @click.stop="viewUnsubmittedStudents()">{{
             <span v-if="props.unsubmittedStudents.length > 0" @click.stop="viewUnsubmittedStudents()">{{
               lang.ssViewSubmitStatus2 }}</span>
               lang.ssViewSubmitStatus2 }}</span>
             <div class="switch_btn" v-if="props.isCreator && props.roleType == 1">
             <div class="switch_btn" v-if="props.isCreator && props.roleType == 1">
@@ -120,7 +121,7 @@
             <span>{{
             <span>{{
               props.showData.choiceQuestionListData[props.showData.workIndex]
               props.showData.choiceQuestionListData[props.showData.workIndex]
                 .teststitle
                 .teststitle
-              }}</span>
+            }}</span>
           </div>
           </div>
           <div class="c_t45_msg" v-if="props.roleType == 1">
           <div class="c_t45_msg" v-if="props.roleType == 1">
             <div>{{ lang.ssAnswerCount }} {{ props.workArray.length }}<span
             <div>{{ lang.ssAnswerCount }} {{ props.workArray.length }}<span
@@ -493,21 +494,15 @@
           </div>
           </div>
           <div class="c_t79_wd_content">
           <div class="c_t79_wd_content">
             <!-- 图片 -->
             <!-- 图片 -->
-            <img
-              v-if="getFileType(lookWorkData.content.fileList[lookWorkIndex].url) === 'image'"
+            <img v-if="getFileType(lookWorkData.content.fileList[lookWorkIndex].url) === 'image'"
               :src="lookWorkData.content.fileList[lookWorkIndex].url"
               :src="lookWorkData.content.fileList[lookWorkIndex].url"
               @click.stop="lookImage(lookWorkData.content.fileList[lookWorkIndex])" />
               @click.stop="lookImage(lookWorkData.content.fileList[lookWorkIndex])" />
             <!-- 视频 -->
             <!-- 视频 -->
-            <video
-              v-else-if="getFileType(lookWorkData.content.fileList[lookWorkIndex].url) === 'video'"
-              :src="lookWorkData.content.fileList[lookWorkIndex].url"
-              controls
+            <video v-else-if="getFileType(lookWorkData.content.fileList[lookWorkIndex].url) === 'video'"
+              :src="lookWorkData.content.fileList[lookWorkIndex].url" controls
               @click.stop="lookImage(lookWorkData.content.fileList[lookWorkIndex])" />
               @click.stop="lookImage(lookWorkData.content.fileList[lookWorkIndex])" />
             <!-- 文档/PDF/Office -->
             <!-- 文档/PDF/Office -->
-            <div
-              v-else
-              class="file-preview-card"
-              @click.stop="lookImage(lookWorkData.content.fileList[lookWorkIndex])">
+            <div v-else class="file-preview-card" @click.stop="lookImage(lookWorkData.content.fileList[lookWorkIndex])">
               <div class="file-preview-icon">
               <div class="file-preview-icon">
                 {{ getFileIcon(getFileType(lookWorkData.content.fileList[lookWorkIndex].url)) }}
                 {{ getFileIcon(getFileType(lookWorkData.content.fileList[lookWorkIndex].url)) }}
               </div>
               </div>
@@ -776,6 +771,37 @@
           </div>
           </div>
         </div>
         </div>
 
 
+        <div class="aiAnalysis" style="margin-top:1rem ;"
+            v-if="processedWorkArray.length > 0 && lookWorkData === null && props.showData.toolType == '831' && props.roleType == 1"
+            @click.stop="clickContent(false)">
+            <div class="ai_header">
+              <div class="ai_title">
+                <svg viewBox="0 0 1024 1024" width="200" height="200">
+                  <path
+                    d="M512 170.666667C323.477333 170.666667 170.666667 323.477333 170.666667 512s152.810667 341.333333 341.333333 341.333333 341.333333-152.810667 341.333333-341.333333S700.522667 170.666667 512 170.666667zM85.333333 512C85.333333 276.352 276.352 85.333333 512 85.333333s426.666667 191.018667 426.666667 426.666667-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512z">
+                  </path>
+                  <path
+                    d="M693.013333 330.986667a42.666667 42.666667 0 0 1 10.304 43.648l-75.413333 226.282666a42.666667 42.666667 0 0 1-26.986667 26.986667l-226.282666 75.413333a42.666667 42.666667 0 0 1-53.973334-53.973333l75.434667-226.261333a42.666667 42.666667 0 0 1 26.986667-26.986667l226.282666-75.413333a42.666667 42.666667 0 0 1 43.648 10.304z m-222.72 139.306666l-41.685333 125.098667 125.077333-41.706667 41.706667-125.077333-125.077333 41.706667z">
+                  </path>
+                </svg>{{ lang.ssAnalysis }}
+              </div>
+              <div class="ai_refresh" :class="{ 'disabled': currentAnalysis && currentAnalysis.loading }"
+                @click.stop="aiAnalysisRefresh831()">
+                {{ lang.ssAIGenerate }}
+                <svg viewBox="0 0 1024 1024" width="200" height="200">
+                  <path
+                    d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z">
+                  </path>
+                </svg>
+
+              </div>
+            </div>
+            <div class="ai_content" v-if="currentAnalysis && currentAnalysis.json" v-html="currentAnalysis.json.text">
+            </div>
+            <div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}
+            </div>
+          </div>
+
         <div class="c_t72_workDetail" v-if="lookWorkData" @click.stop="clickContent(false)">
         <div class="c_t72_workDetail" v-if="lookWorkData" @click.stop="clickContent(false)">
           <div class="c_t72_wd_top">
           <div class="c_t72_wd_top">
             <img src="../../../assets/img/arrow_left.png" @click.stop="lookWork('')" v-if="!isCastScreen" />
             <img src="../../../assets/img/arrow_left.png" @click.stop="lookWork('')" v-if="!isCastScreen" />
@@ -787,6 +813,8 @@
               {{ lang.ssExitCastScreen }}
               {{ lang.ssExitCastScreen }}
             </div>
             </div>
           </div>
           </div>
+
+
           <div class="c_t831_wd_content">
           <div class="c_t831_wd_content">
             <!-- KWL 三栏 -->
             <!-- KWL 三栏 -->
             <div class="kwl-grid" v-if="lookWorkData.content">
             <div class="kwl-grid" v-if="lookWorkData.content">
@@ -828,7 +856,8 @@
                 </div>
                 </div>
                 <div class="kwl-col__body">
                 <div class="kwl-col__body">
                   <template v-if="lookWorkData.content.learned.length">
                   <template v-if="lookWorkData.content.learned.length">
-                    <div v-for="(item, idx) in lookWorkData.content.learned" :key="'l-' + idx" class="kwl-item">{{ item }}
+                    <div v-for="(item, idx) in lookWorkData.content.learned" :key="'l-' + idx" class="kwl-item">{{ item
+                      }}
                     </div>
                     </div>
                   </template>
                   </template>
                   <div v-else class="kwl-empty">{{ lang.ssNone }}</div>
                   <div v-else class="kwl-empty">{{ lang.ssNone }}</div>
@@ -849,7 +878,132 @@
               </div>
               </div>
             </div>
             </div>
           </div>
           </div>
+
+
+        </div>
+        
+      </div>
+
+      <!-- 六顶思考帽 -->
+      <div class="c_t72" v-if="props.showData && props.showData.toolType === 832">
+        <div class="c_t72_title">
+          <div class="c_title">
+            <span>{{ lang.ssSixHatTitle }}</span>
+          </div>
+        </div>
+        <span class="c_t72_type">{{ lang.ssSixHatTitle }}</span>
+        <div class="c_t72_msg" v-if="props.roleType == 1">
+          <div>{{ lang.ssAnswerCount }} {{ props.workArray.length }}<span
+              v-if="props.unsubmittedStudents.length > 0">/{{
+                props.workArray.length +
+                props.unsubmittedStudents.length
+              }}</span></div>
+          <span v-if="props.unsubmittedStudents.length > 0" @click.stop="viewUnsubmittedStudents()">{{
+            lang.ssViewSubmitStatus2 }}</span>
+        </div>
+        <div class="c_t72_content" v-show="!lookWorkData">
+          <div class="c_t72_c_item" v-for="item in processedWorkArray" :key="item.id" @click.stop="lookWork(item.id)">
+            <div class="c_t72_c_i_top">
+              <span>{{ item.name.charAt(0) }}</span>
+              <div>{{ item.name }}</div>
+              <div class="cast_sreen_btn" @click.stop="castScreen(item)"
+                v-if="props.isCreator && props.roleType == 1 && isFollowModeActive && canValue">
+                <IconCastScreen />
+                {{ lang.ssCastScreen }}
+              </div>
+            </div>
+            <div class="bottom_btn" v-if="likeValue">
+              <div class="bottom_like" :class="{ 'active': item.isLikes }" @click.stop="handleLikeClick(item)">
+                <IconThumbsUp />
+                <span>{{ item.likesCount }}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+<!-- processedWorkArray.length > 0 && lookWorkData === null && props.showData.toolType == '832' && props.roleType == 1 -->
+        <div class="aiAnalysis" style="margin-top:1rem ;"
+            v-if="processedWorkArray.length > 0 && lookWorkData === null && props.showData.toolType == '832' && props.roleType == 1"
+            @click.stop="clickContent(false)">
+            <div class="ai_header">
+              <div class="ai_title">
+                <svg viewBox="0 0 1024 1024" width="200" height="200">
+                  <path
+                    d="M512 170.666667C323.477333 170.666667 170.666667 323.477333 170.666667 512s152.810667 341.333333 341.333333 341.333333 341.333333-152.810667 341.333333-341.333333S700.522667 170.666667 512 170.666667zM85.333333 512C85.333333 276.352 276.352 85.333333 512 85.333333s426.666667 191.018667 426.666667 426.666667-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512z">
+                  </path>
+                  <path
+                    d="M693.013333 330.986667a42.666667 42.666667 0 0 1 10.304 43.648l-75.413333 226.282666a42.666667 42.666667 0 0 1-26.986667 26.986667l-226.282666 75.413333a42.666667 42.666667 0 0 1-53.973334-53.973333l75.434667-226.261333a42.666667 42.666667 0 0 1 26.986667-26.986667l226.282666-75.413333a42.666667 42.666667 0 0 1 43.648 10.304z m-222.72 139.306666l-41.685333 125.098667 125.077333-41.706667 41.706667-125.077333-125.077333 41.706667z">
+                  </path>
+                </svg>{{ lang.ssAnalysis }}
+              </div>
+              <div class="ai_refresh" :class="{ 'disabled': currentAnalysis && currentAnalysis.loading }"
+                @click.stop="aiAnalysisRefresh832()">
+                {{ lang.ssAIGenerate }}
+                <svg viewBox="0 0 1024 1024" width="200" height="200">
+                  <path
+                    d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z">
+                  </path>
+                </svg>
+
+              </div>
+            </div>
+            <div class="ai_content" v-if="currentAnalysis && currentAnalysis.json" v-html="currentAnalysis.json.text">
+            </div>
+            <div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}
+            </div>
+          </div>
+
+        <div class="c_t72_workDetail" v-if="lookWorkData" @click.stop="clickContent(false)">
+          <div class="c_t72_wd_top">
+            <img src="../../../assets/img/arrow_left.png" @click.stop="lookWork('')" v-if="!isCastScreen" />
+            <span>{{ lookWorkData.name.charAt(0) }}</span>
+            <div>{{ lookWorkData.name }}</div>
+            <div class="cast_sreen_btn" @click.stop="exitCastScreen"
+              v-if="(props.isCreator && props.roleType == 1 && isCastScreen) || (!isFollowModeActive && isCastScreen)">
+              <IconCastScreen />
+              {{ lang.ssExitCastScreen }}
+            </div>
+          </div>
+
+
+          <div class="c_t832_wd_content" v-if="lookWorkData.content">
+            <!-- 成员列表 -->
+            <div class="sixhat-members" v-if="lookWorkData.content.members && lookWorkData.content.members.length">
+              <div class="sixhat-members__header">
+                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+                  <path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
+                  <circle cx="9" cy="7" r="4" />
+                  <path d="M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75" />
+                </svg>
+                <span>{{ lang.ssSixHatGroupWork }}</span>
+              </div>
+              <div class="sixhat-members__list">
+                <span v-for="(m, idx) in lookWorkData.content.members" :key="'m-' + idx" class="sixhat-member-chip">{{ m.name }}</span>
+              </div>
+            </div>
+
+            <!-- 场景描述 -->
+            <div class="sixhat-scenario" v-if="lookWorkData.content.scenario">
+              <div class="sixhat-scenario__text">{{ lookWorkData.content.scenario }}</div>
+            </div>
+
+            <!-- 六顶思考帽内容 -->
+            <div class="sixhat-grid">
+              <div v-for="hat in sixHatList" :key="hat.key" class="sixhat-col" :class="'sixhat-col--' + hat.key">
+                <div class="sixhat-col__header">
+                  <span class="sixhat-col__dot"></span>
+                  <span class="sixhat-col__label">{{ hat.label }}</span>
+                </div>
+                <div class="sixhat-col__body">
+                  <div v-if="hat.content" class="sixhat-item">{{ hat.content }}</div>
+                  <div v-else class="kwl-empty">{{ lang.ssNone }}</div>
+                </div>
+              </div>
+            </div>
+          </div>
+
+
         </div>
         </div>
+        
       </div>
       </div>
     </div>
     </div>
     <previewImageTool ref="previewImageToolRef" />
     <previewImageTool ref="previewImageToolRef" />
@@ -876,12 +1030,8 @@
             <line x1="6" y1="6" x2="18" y2="18" />
             <line x1="6" y1="6" x2="18" y2="18" />
           </svg>
           </svg>
         </div>
         </div>
-        <iframe
-          v-if="docPreviewType === 'pdf' || docPreviewType === 'office'"
-          :src="getDocPreviewUrl(docPreviewType, docPreviewUrl)"
-          class="file-preview-frame"
-          frameborder="0"
-        ></iframe>
+        <iframe v-if="docPreviewType === 'pdf' || docPreviewType === 'office'"
+          :src="getDocPreviewUrl(docPreviewType, docPreviewUrl)" class="file-preview-frame" frameborder="0"></iframe>
         <div v-else class="file-preview-office">
         <div v-else class="file-preview-office">
           <div class="file-preview-office-icon">📎</div>
           <div class="file-preview-office-icon">📎</div>
           <div class="file-preview-office-name">{{ docPreviewUrl.split('/').pop() }}</div>
           <div class="file-preview-office-name">{{ docPreviewUrl.split('/').pop() }}</div>
@@ -953,6 +1103,21 @@ const workDetail = computed(() => {
 
 
 const canValue = ref(props.resultArray?.can ?? false)
 const canValue = ref(props.resultArray?.can ?? false)
 
 
+// 选择题正确率
+const correctRate = computed(() => {
+  if (!props.showData?.choiceQuestionListData?.length) return null
+  const _work = props.showData.choiceQuestionListData[props.showData.workIndex]
+  if (!_work?.choiceUser?.length) return null
+  let total = 0
+  let correct = 0
+  _work.choiceUser.forEach((op: any) => {
+    total += (op.user?.length || 0)
+    if (op.isAnswer) correct += (op.user?.length || 0)
+  })
+  if (total === 0) return null
+  return Math.round((correct / total) * 100)
+})
+
 watch(() => props.resultArray?.can, (newVal) => {
 watch(() => props.resultArray?.can, (newVal) => {
   canValue.value = newVal
   canValue.value = newVal
 })
 })
@@ -1080,7 +1245,7 @@ const processWorkContent = async (content: string, toolType: number): Promise<an
   }
   }
 
 
   try {
   try {
-    if ([45, 15, 78, 79, 84, 831].includes(toolType)) {
+    if ([45, 15, 78, 79, 84, 831, 832].includes(toolType)) {
       return JSON.parse(decodeURIComponent(contentToParse))
       return JSON.parse(decodeURIComponent(contentToParse))
     }
     }
     else if (toolType === 72) {
     else if (toolType === 72) {
@@ -1184,6 +1349,26 @@ const lookWorkData = computed(() => {
   return _result
   return _result
 })
 })
 
 
+// 六顶思考帽配置
+const hatConfig = [
+  { key: 'white', label: lang.ssSixHatWhite, color: '#9ca3af', bg: '#f3f4f6' },
+  { key: 'red', label: lang.ssSixHatRed, color: '#ef4444', bg: '#fef2f2' },
+  { key: 'black', label: lang.ssSixHatBlack, color: '#1f2937', bg: '#374151' },
+  { key: 'yellow', label: lang.ssSixHatYellow, color: '#f59e0b', bg: '#fffbeb' },
+  { key: 'green', label: lang.ssSixHatGreen, color: '#22c55e', bg: '#f0fdf4' },
+  { key: 'blue', label: lang.ssSixHatBlue, color: '#3b82f6', bg: '#eff6ff' },
+]
+
+// 六顶思考帽内容列表(根据学生选择 hats 过滤)
+const sixHatList = computed(() => {
+  if (!lookWorkData.value?.content) return []
+  const hats = lookWorkData.value.content.hats || []
+  const c = lookWorkData.value.content.hatContent || {}
+  return hatConfig
+    .filter(h => hats.includes(h.key))
+    .map(h => ({ ...h, content: c[h.key] || '' }))
+})
+
 // 判断文件类型
 // 判断文件类型
 const getFileType = (url: string): 'image' | 'video' | 'pdf' | 'office' | 'other' => {
 const getFileType = (url: string): 'image' | 'video' | 'pdf' | 'office' | 'other' => {
   if (!url) return 'other'
   if (!url) return 'other'
@@ -2619,6 +2804,293 @@ ${a.content}\n`
   })
   })
 }
 }
 
 
+// ai应用
+const aiAnalysisRefresh831 = () => {
+
+  let chatMsg = ``
+  console.log('processedWorkArray.value', processedWorkArray.value)
+  processedWorkArray.value.forEach((i) => {
+    if (typeof i.content === 'object') {
+      const c = i.content
+      const studentName = i.name || ''
+      if (c.know && c.know.length) {
+        chatMsg += `\n${studentName} - K|已知:\n${c.know.join(';')}\n`
+      }
+      if (c.want && c.want.length) {
+        chatMsg += `\n${studentName} - W|想知:\n${c.want.join(';')}\n`
+      }
+      if (c.learned && c.learned.length) {
+        chatMsg += `\n${studentName} - L|已学:\n${c.learned.join(';')}\n`
+      }
+      if (c.reflection) {
+        chatMsg += `\n${studentName} - 学习反思:\n${c.reflection}\n`
+      }
+    }
+  })
+
+  const msg = `# CONTEXT #
+课程数据:
+- 课程名称:${props.courseDetail.title}
+- 课程学科:${props.courseDetail.name}
+- 需要提交人数:${props.showData.workArray.length + props.showData.unsubmittedStudents.length}
+- 已提交人数:${props.showData.workArray.length}
+你是一名教学分析助手。请根据全班学生提交的 KWL 表格与学习反思内容,从班级整体视角进行简洁分析,帮助教师在课堂中快速了解学生情况。
+
+请按照以下 4 个维度分析:
+1. K|已知(Know)
+2. W|想知(Want to know)
+3. L|已学(Learned)
+4. 学习反思
+
+分析要求:
+- 每个维度先统计实际有效作答人数及占全班比例。
+- 只分析实际有学生填写的维度;如果某个维度无人填写,则不要输出该维度。
+- 学生未填写某个维度,不代表“不知道”“没学会”或“没有反思”,禁止据此推断。
+- 将意思相近的回答合并归纳,优先呈现班级共性。
+- 如存在明显误解、集中困惑或值得教师关注的问题,可简短指出。
+- 不逐个学生罗列,不评价个人,不排名。
+- 不要为了填满表格而强行生成结论;没有明显发现的内容可以省略。
+- 输出必须简洁,每个单元格尽量控制在 1–2 句话。
+
+请仅使用以下表格格式输出:
+
+| 维度 | 填写情况 | 班级主要情况 | 教师可关注 |
+|---|---|---|---|
+| K|已知 | X人,X% | 概括学生主要已有认知,最多2点 | 如有明显误解或差异则指出,否则写“-” |
+| W|想知 | X人,X% | 概括学生最集中的问题或兴趣,最多2点 | 值得后续回应的问题,最多1点 |
+| L|已学 | X人,X% | 概括学生主要学习收获,最多2点 | 未充分理解或存在混淆的内容,最多1点 |
+| 学习反思 | X人,X% | 概括主要收获、困难或学习感受,最多2点 | 后续教学可调整或跟进的重点,最多1点 |
+
+注意:
+- 无人填写的维度整行删除。
+- 避免空泛表达,例如“学生学习情况较好”“总体表现不错”。
+- 尽量使用具体主题、概念或问题名称。
+
+# 学生提交数据 #
+${chatMsg}`
+
+
+
+
+  console.log('workUrl', props.workUrl)
+  console.log('ai应用提示词', msg)
+  if (!currentAnalysis.value) {
+    aiAnalysisData.value.push({
+      pid: props.workId + (props.cid ? ',' + props.cid : ''),
+      index: props.showData.workIndex,
+      loading: true,
+      json: { text: '', echartsData: '' },
+      noEnd: true,
+      update_at: '',
+      create_at: '',
+    })
+  }
+  else {
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+    }).loading = true
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+    }).json = { text: '', echartsData: '' }
+  }
+
+  chat_stream(msg, 'a7741704-ba56-40b7-a6b8-62a423ef9376', props.userId, lang.lang, (event) => {
+    if (event.type === 'message') {
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).json.text = md.render(event.data)
+
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).loading = false
+    }
+    else if (event.type === 'messageEnd') {
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).json.text = md.render(event.data)
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).noEnd = false
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).update_at = new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).replace(/\//g, '-')
+      saveAnalysis()
+    }
+  }, '', [], 'open-qwen-plus-latest').catch(err => {
+    console.log('err', err)
+  })
+}
+
+// ai应用
+const aiAnalysisRefresh832 = () => {
+
+  let chatMsg = ``
+  console.log('processedWorkArray.value', processedWorkArray.value)
+  const hatNames: Record<string, string> = {
+    white: '白帽|事实与信息',
+    red: '红帽|感受与直觉',
+    black: '黑帽|风险与问题',
+    yellow: '黄帽|价值与机会',
+    green: '绿帽|创意与可能性',
+    blue: '蓝帽|总结与推进',
+  }
+  processedWorkArray.value.forEach((i) => {
+    if (typeof i.content === 'object') {
+      const c = i.content
+      const studentName = i.name || ''
+      const isGroup = c.members && c.members.length > 0
+      const memberNames = isGroup ? c.members.map((m: any) => typeof m === 'object' ? (m.name || '') : m) : []
+      const submitter = isGroup ? `${studentName}(小组成员:${memberNames.join('、')})` : studentName
+      if (c.scenario) {
+        chatMsg += `\n${submitter} - 讨论场景:\n${c.scenario}\n`
+      }
+      const hats = c.hats || []
+      const hatContent = c.hatContent || {}
+      hats.forEach((hat: string) => {
+        const label = hatNames[hat] || hat
+        const content = hatContent[hat] || ''
+        if (content) {
+          chatMsg += `\n${submitter} - ${label}:\n${content}\n`
+        }
+      })
+    }
+  })
+
+  const msg = `# CONTEXT #
+课程数据:
+- 课程名称:${props.courseDetail.title}
+- 课程学科:${props.courseDetail.name}
+- 需要提交人数:${props.showData.workArray.length + props.showData.unsubmittedStudents.length}
+- 已提交人数:${props.showData.workArray.length}
+你是一名教学分析助手。请根据全班学生或各小组提交的「六顶思考帽」讨论内容,从班级整体视角进行简洁分析,帮助教师快速了解学生在不同思考方式下的主要观点、分歧与值得继续讨论的问题。
+本次活动不一定使用完整的六顶思考帽。教师可能只配置其中 3 顶、4 顶或其他组合。
+你必须以本次活动实际配置和学生实际提交的思考帽为准,只分析本次活动中启用的思考帽,不要自行补充未启用的帽子。
+提交内容可能有两种形式:
+个人提交:每名学生分别填写本次活动配置的一个或多个思考帽。
+小组提交:以小组为单位提交,内容中可能包含小组成员姓名、每位成员负责的思考帽,以及对应讨论内容。
+六顶思考帽的含义如下,仅用于识别和分析本次实际启用的帽子:
+白帽|事实与信息
+关注学生提出的事实、数据、已知信息,以及认为仍需补充的信息。
+红帽|感受与直觉
+关注学生表达的感受、直觉、第一反应、喜欢或担忧。
+黑帽|风险与问题
+关注学生发现的问题、限制、风险、困难或可能失败的原因。
+黄帽|价值与机会
+关注学生发现的优点、价值、机会、积极影响或可行之处。
+绿帽|创意与可能性
+关注学生提出的新想法、替代方案、改进方式或不同可能性。
+蓝帽|总结与推进
+关注学生对讨论的总结、观点整合、下一步行动、需要进一步解决的问题。
+分析要求:
+只分析本次活动实际配置的思考帽。
+未配置的思考帽不要输出,也不要视为“缺失”“未作答”或“思考不足”。
+对于已经配置的思考帽,统计实际有效参与情况。
+如果是个人提交,统计有效作答人数及占全班比例,例如“18人,75%”。
+如果是小组提交,优先统计有效参与小组数及占全部提交小组比例,例如“5/6组,83%”;如数据中可以明确判断参与该帽子的学生人数,可补充人数,例如“5/6组,8人参与”。
+如果某顶帽子已配置,但无人或无小组实际提交有效内容,则不要输出该帽子。
+学生或小组未填写某顶已配置的帽子,不代表缺乏这种思维能力,禁止据此推断。
+将意思相近的观点合并归纳,优先呈现班级或多个小组反复出现的共性观点。
+如果不同学生或小组之间存在明显不同观点,可简短呈现主要分歧,不必强行形成统一结论。
+区分“学生明确提出的内容”和你的推断,不要补充学生没有表达过的理由、风险、优势、情绪或创意。
+不逐个学生罗列,不评价个人,不排名。
+如果提交内容包含“小组成员—负责帽子—贡献内容”等信息,只用于判断参与情况和思考分工,不对个人能力进行评价。
+如果不同已配置帽子的参与程度或内容丰富度存在明显差异,可以客观描述,但不要解释为学生“不会”某种思考。
+不要为了让分析看起来完整而强行生成结论;没有明显发现的内容可以省略。
+输出必须简洁,每个单元格尽量控制在 1–2 句话。
+请仅使用以下表格格式输出:
+思考帽
+参与情况
+班级 / 小组主要观点
+教师可关注
+⚪ 白帽|事实与信息
+X人,X% / X组,X%
+概括反复出现的事实、信息或信息缺口,最多2点
+如有事实混淆、证据不足或集中缺失的信息则指出,否则写“-”
+🔴 红帽|感受与直觉
+X人,X% / X组,X%
+概括主要感受、直觉或态度,最多2点
+如存在明显情绪分化或值得进一步了解的感受则指出,否则写“-”
+⚫ 黑帽|风险与问题
+X人,X% / X组,X%
+概括最集中的问题、风险或限制,最多2点
+值得后续讨论或验证的问题,最多1点
+🟡 黄帽|价值与机会
+X人,X% / X组,X%
+概括主要优势、价值或机会,最多2点
+如有值得进一步验证的价值判断则指出,否则写“-”
+🟢 绿帽|创意与可能性
+X人,X% / X组,X%
+概括主要创意、方案或不同可能性,最多2点
+值得继续展开或比较的想法,最多1点
+🔵 蓝帽|总结与推进
+X人,X% / X组,X%
+概括主要结论、共识或下一步行动,最多2点
+尚未解决、需要继续讨论的问题,最多1点
+注意:
+表格只保留“本次活动已配置 + 实际有有效提交”的思考帽。
+例如教师本次只配置白帽、黑帽、绿帽,则最终最多只输出这 3 行,不要出现红帽、黄帽、蓝帽。
+如果已配置的某顶帽子无人有效填写,则该行也删除。
+如果同一学生或小组提交了多个帽子,应分别计入对应帽子的参与统计。
+同一帽子下重复表达相同观点时,应合并统计和概括,不重复罗列。
+如果存在明显的多数观点与少数不同观点,可以表达为“多数小组认为……;另有少数组提出……”,不要逐组列举。
+对小组任务,不要因为某位成员负责某一顶帽子,就推断该成员个人更擅长这种思考方式。
+避免空泛表达,例如“学生思考比较全面”“大家讨论得很好”“学生参与积极”。
+尽量直接使用学生实际讨论中的主题、方案、问题、证据或观点名称。
+
+# 学生提交数据 #
+${chatMsg}`
+
+
+
+
+  console.log('workUrl', props.workUrl)
+  console.log('ai应用提示词', msg)
+  if (!currentAnalysis.value) {
+    aiAnalysisData.value.push({
+      pid: props.workId + (props.cid ? ',' + props.cid : ''),
+      index: props.showData.workIndex,
+      loading: true,
+      json: { text: '', echartsData: '' },
+      noEnd: true,
+      update_at: '',
+      create_at: '',
+    })
+  }
+  else {
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+    }).loading = true
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+    }).json = { text: '', echartsData: '' }
+  }
+
+  chat_stream(msg, 'a7741704-ba56-40b7-a6b8-62a423ef9376', props.userId, lang.lang, (event) => {
+    if (event.type === 'message') {
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).json.text = md.render(event.data)
+
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).loading = false
+    }
+    else if (event.type === 'messageEnd') {
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).json.text = md.render(event.data)
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).noEnd = false
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId + (props.cid ? ',' + props.cid : '') && item.index === props.showData.workIndex
+      }).update_at = new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).replace(/\//g, '-')
+      saveAnalysis()
+    }
+  }, '', [], 'open-qwen-plus-latest').catch(err => {
+    console.log('err', err)
+  })
+}
 
 
 // 当前分析
 // 当前分析
 const currentAnalysis = computed(() => {
 const currentAnalysis = computed(() => {
@@ -2843,6 +3315,11 @@ onUnmounted(() => {
             text-decoration: underline;
             text-decoration: underline;
             cursor: pointer;
             cursor: pointer;
           }
           }
+
+          .c_t45_correct_rate {
+            color: #29AE2B;
+            font-weight: 600;
+          }
         }
         }
       }
       }
 
 
@@ -4019,6 +4496,133 @@ onUnmounted(() => {
   .kwl-grid {
   .kwl-grid {
     grid-template-columns: 1fr;
     grid-template-columns: 1fr;
   }
   }
+
+  .sixhat-grid {
+    grid-template-columns: 1fr;
+  }
+}
+
+/* 六顶思考帽内容 */
+.c_t832_wd_content {
+  margin-top: 16px;
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+}
+
+.sixhat-members {
+  &__header {
+    display: flex;
+    align-items: center;
+    gap: 6px;
+    font-size: 14px;
+    font-weight: 600;
+    color: #374151;
+    margin-bottom: 8px;
+
+    svg {
+      color: #6b7280;
+    }
+  }
+
+  &__list {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 8px;
+  }
+}
+
+.sixhat-member-chip {
+  padding: 4px 12px;
+  background: #f3f4f6;
+  border: 1px solid #e5e7eb;
+  border-radius: 999px;
+  font-size: 12px;
+  color: #4b5563;
+}
+
+.sixhat-scenario {
+  padding: 12px 16px;
+  background: #fffbeb;
+  border: 1px solid #fde68a;
+  border-radius: 10px;
+
+  &__text {
+    font-size: 13px;
+    color: #78350f;
+    line-height: 1.6;
+  }
+}
+
+.sixhat-grid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 12px;
+}
+
+.sixhat-col {
+  border-radius: 12px;
+  overflow: hidden;
+  border: 1px solid #e5e7eb;
+  background: #fff;
+  display: flex;
+  flex-direction: column;
+
+  &__header {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    padding: 10px 14px;
+    font-size: 14px;
+    font-weight: 600;
+    color: #fff;
+  }
+
+  &__dot {
+    width: 12px;
+    height: 12px;
+    border-radius: 50%;
+    flex-shrink: 0;
+  }
+
+  &__body {
+    padding: 12px 14px;
+    flex: 1;
+    min-height: 60px;
+  }
+}
+
+.sixhat-item {
+  font-size: 13px;
+  color: #374151;
+  line-height: 1.7;
+  white-space: pre-wrap;
+}
+
+/* 各帽子主题色 */
+.sixhat-col--white {
+  .sixhat-col__header { background: linear-gradient(135deg, #d1d5db, #9ca3af); }
+  .sixhat-col__dot { background: #fff; border: 1px solid #d1d5db; }
+}
+.sixhat-col--red {
+  .sixhat-col__header { background: linear-gradient(135deg, #ef4444, #dc2626); }
+  .sixhat-col__dot { background: #fca5a5; }
+}
+.sixhat-col--black {
+  .sixhat-col__header { background: linear-gradient(135deg, #374151, #1f2937); }
+  .sixhat-col__dot { background: #9ca3af; }
+}
+.sixhat-col--yellow {
+  .sixhat-col__header { background: linear-gradient(135deg, #f59e0b, #d97706); }
+  .sixhat-col__dot { background: #fde68a; }
+}
+.sixhat-col--green {
+  .sixhat-col__header { background: linear-gradient(135deg, #22c55e, #16a34a); }
+  .sixhat-col__dot { background: #bbf7d0; }
+}
+.sixhat-col--blue {
+  .sixhat-col__header { background: linear-gradient(135deg, #3b82f6, #2563eb); }
+  .sixhat-col__dot { background: #bfdbfe; }
 }
 }
 
 
 /* 文件预览卡片 */
 /* 文件预览卡片 */

+ 496 - 226
src/views/Student/index.vue

@@ -78,7 +78,7 @@
           left: isFullscreen ? '0' : `${(containerWidth - slideWidth * canvasScale) / 2}px`,
           left: isFullscreen ? '0' : `${(containerWidth - slideWidth * canvasScale) / 2}px`,
           top: isFullscreen ? '0' : `${(containerHeight - slideHeight * canvasScale) / 2}px`
           top: isFullscreen ? '0' : `${(containerHeight - slideHeight * canvasScale) / 2}px`
         }" @mousemove="handleLaserMove">
         }" @mousemove="handleLaserMove">
-          <div class="homework-check-box" :class="{ 'fullscreen-mode': isFullscreen, 'fs-expanded': hwBoxExpanded }" v-if="currentSlideHasIframe && !currentSlideHasBilibiliVideo && (props.type == '1' || (props.type == '2' && currentIsResultArray.can && !is_cast_screen))"  v-show="currentSlideHasIframe" :style="{
+          <div class="homework-check-box" :class="{ 'fullscreen-mode': isFullscreen, 'fs-expanded': hwBoxExpanded }" v-if="currentSlideHasIframe && !currentSlideHasBilibiliVideo && (props.type == '1' || (props.type == '2' && currentIsResultArray.can && !is_cast_screen))" :style="{
             top: isFullscreen ? '0' : `0`
             top: isFullscreen ? '0' : `0`
           }" @click="isFullscreen && (hwBoxExpanded = !hwBoxExpanded)">
           }" @click="isFullscreen && (hwBoxExpanded = !hwBoxExpanded)">
             <div class="homework-check-box-item" @click.stop="openChoiceQuestionDetail2(slideIndex); hwBoxExpanded = false" :class="{'active': !choiceQuestionDetailDialogOpenList.includes(slideIndex)}">
             <div class="homework-check-box-item" @click.stop="openChoiceQuestionDetail2(slideIndex); hwBoxExpanded = false" :class="{'active': !choiceQuestionDetailDialogOpenList.includes(slideIndex)}">
@@ -93,7 +93,7 @@
             <IconComment class="aiBtn-icon" />
             <IconComment class="aiBtn-icon" />
             <span>{{ lang.ssAiChat }}</span>
             <span>{{ lang.ssAiChat }}</span>
           </div>
           </div>
-          <aiChat v-show="visibleAIChat" :position="aiBtnPosition" @close="visibleAIChat = false" :userid="props.userid" :workJson="myWork" :visible="visibleAIChat" :cid="props.cid"/>
+          <aiChat v-show="visibleAIChat" :position="aiBtnPosition" @close="visibleAIChat = false" :userid="props.userid" :workJson="myWork" :visible="visibleAIChat" :cid="props.cid" :courseid="props.courseid"/>
          <!--  -->
          <!--  -->
           <div class="viewport" v-if="false">
           <div class="viewport" v-if="false">
             <div class="background" :style="backgroundStyle"></div>
             <div class="background" :style="backgroundStyle"></div>
@@ -169,7 +169,7 @@
                 <IconStopwatchStart v-if="props.type == '1' && courseDetail.userid == props.userid && isFollowModeActive" class="tool-btn" v-tooltip="lang.ssTimer" @click="timerlVisible = !timerlVisible"  />
                 <IconStopwatchStart v-if="props.type == '1' && courseDetail.userid == props.userid && isFollowModeActive" class="tool-btn" v-tooltip="lang.ssTimer" @click="timerlVisible = !timerlVisible"  />
                 <IconWrite v-if="isFollowModeActive && props.type == '1' && courseDetail.userid == props.userid" class="tool-btn" v-tooltip="lang.ssPenTool" @click="writingBoardToolVisible = true"  />
                 <IconWrite v-if="isFollowModeActive && props.type == '1' && courseDetail.userid == props.userid" class="tool-btn" v-tooltip="lang.ssPenTool" @click="writingBoardToolVisible = true"  />
                 <!-- <IconMagic v-if="isFollowModeActive && props.type == '1' && courseDetail.userid == props.userid" class="tool-btn" v-tooltip="lang.ssLaserPen" :class="{ 'active': laserPen }" @click="toggleLaserPen"  /> -->
                 <!-- <IconMagic v-if="isFollowModeActive && props.type == '1' && courseDetail.userid == props.userid" class="tool-btn" v-tooltip="lang.ssLaserPen" :class="{ 'active': laserPen }" @click="toggleLaserPen"  /> -->
-                <IconTips v-if="props.type == '1'" class="tool-btn" v-tooltip="lang.ssAiHelper" :class="{ 'active': !workPanelCollapsed }" @click="workPanelCollapsed = !workPanelCollapsed"  />
+                <IconTips v-if="props.type == '1' && props.userid != 'undefined'" class="tool-btn" v-tooltip="lang.ssAiHelper" :class="{ 'active': !workPanelCollapsed }" @click="workPanelCollapsed = !workPanelCollapsed"  />
                 <IconFullScreenOne class="tool-btn" v-tooltip="lang.ssOpenFull" @click="enterFullscreen" />
                 <IconFullScreenOne class="tool-btn" v-tooltip="lang.ssOpenFull" @click="enterFullscreen" />
               </div>
               </div>
           </div>
           </div>
@@ -240,7 +240,7 @@
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>
-    <div class="layout-content-right" v-show="type == '1'" :class="{ collapsed: workPanelCollapsed }">
+    <div class="layout-content-right" v-show="type == '1' && props.userid != 'undefined'" :class="{ collapsed: workPanelCollapsed }">
       <div class="thumbnails">
       <div class="thumbnails">
         <div class="viewer-header right-panel-header">
         <div class="viewer-header right-panel-header">
           <button class="collapse-btn" @click="workPanelCollapsed = !workPanelCollapsed" :title="workPanelCollapsed ? lang.ssExpand : lang.ssCollapse" v-if="rightPanelMode != ''" style="left: 8px;">
           <button class="collapse-btn" @click="workPanelCollapsed = !workPanelCollapsed" :title="workPanelCollapsed ? lang.ssExpand : lang.ssCollapse" v-if="rightPanelMode != ''" style="left: 8px;">
@@ -350,7 +350,7 @@
         
         
         <!-- 对话区内容 -->
         <!-- 对话区内容 -->
         <div v-show="!workPanelCollapsed && rightPanelMode === 'dialogue'" class="panel-content">
         <div v-show="!workPanelCollapsed && rightPanelMode === 'dialogue'" class="panel-content">
-          <DialoguePanel :userid="props.userid" :courseid="props.courseid"/>
+          <DialoguePanel :userid="props.userid" :courseid="props.courseid" :fileid="pptJsonFileid"/>
         </div>
         </div>
         
         
         <!-- 选择题统计内容 -->
         <!-- 选择题统计内容 -->
@@ -419,7 +419,7 @@
 </template>
 </template>
 
 
 <script lang="ts" setup>
 <script lang="ts" setup>
-import { computed, ref, onMounted, onUnmounted, nextTick, inject, watch, provide } from 'vue'
+import { computed, ref, onMounted, onUnmounted, nextTick, inject, watch, provide, shallowRef } from 'vue'
 import { storeToRefs } from 'pinia'
 import { storeToRefs } from 'pinia'
 import { useSlidesStore } from '@/store'
 import { useSlidesStore } from '@/store'
 import { ElementTypes } from '@/types/slides'
 import { ElementTypes } from '@/types/slides'
@@ -433,7 +433,7 @@ import CountdownTimer from '@/views/Screen/CountdownTimer.vue'
 import useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'
 import useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'
 import useImport from '@/hooks/useImport'
 import useImport from '@/hooks/useImport'
 import message from '@/utils/message'
 import message from '@/utils/message'
-import api, { API_URL, selectSWorks } from '@/services/course'
+import api, { API_URL } from '@/services/course'
 import axios from '@/services/config'
 import axios from '@/services/config'
 import {currentVersion, lang} from '@/main'
 import {currentVersion, lang} from '@/main'
 import ShotWorkModal from './components/ShotWorkModal.vue'
 import ShotWorkModal from './components/ShotWorkModal.vue'
@@ -573,6 +573,8 @@ const timerInterval = ref<number | null>(null)
 
 
 // 作业提交状态
 // 作业提交状态
 const isSubmitting = ref(false)
 const isSubmitting = ref(false)
+// 进入当前幻灯片(作业页)的时间戳,用于计算作业提交耗时(秒)
+const slideEnterTime = ref(0)
 
 
 // 控制组件显示的开关
 // 控制组件显示的开关
 const showSlideList = ref(true)
 const showSlideList = ref(true)
@@ -595,7 +597,7 @@ type WorkItem = {
   [key: string]: any
   [key: string]: any
 }
 }
 const workArray = ref<WorkItem[]>([])
 const workArray = ref<WorkItem[]>([])
-const toolTypeArray = ref<number[]>([45, 15, 73, 72, 78, 79, 831, 84])
+const toolTypeArray = ref<number[]>([45, 15, 73, 72, 78, 79, 831, 832, 84])
 
 
 // 作业弹窗相关
 // 作业弹窗相关
 const selectedWork = ref<any>(null)
 const selectedWork = ref<any>(null)
@@ -716,6 +718,7 @@ const connectionStatus = ref<'disconnected' | 'connecting' | 'connected'>('disco
 // 认证 token 相关变量
 // 认证 token 相关变量
 const authToken = ref<string | null>(null)
 const authToken = ref<string | null>(null)
 const authTokenUpdateTimer = ref<NodeJS.Timeout | null>(null)
 const authTokenUpdateTimer = ref<NodeJS.Timeout | null>(null)
+const heartbeatTimer = ref<NodeJS.Timeout | null>(null)
 const socketCheckTimer = ref<NodeJS.Timeout | null>(null)
 const socketCheckTimer = ref<NodeJS.Timeout | null>(null)
 
 
 // 同步数据最大保留时间(40分钟)
 // 同步数据最大保留时间(40分钟)
@@ -1067,6 +1070,7 @@ onUnmounted(() => {
     aiBtn.removeEventListener('pointerup', handleAiBtnPointerUp)
     aiBtn.removeEventListener('pointerup', handleAiBtnPointerUp)
     aiBtn.removeEventListener('pointercancel', handleAiBtnPointerCancel)
     aiBtn.removeEventListener('pointercancel', handleAiBtnPointerCancel)
   }
   }
+  cleanupWebSocketConnection()
 })
 })
 
 
 const visibleAIChat = ref(false)
 const visibleAIChat = ref(false)
@@ -1110,6 +1114,7 @@ const currentSlideHasEnglishSpeaking = computed(() => {
 
 
 // 检查当前的结果状态
 // 检查当前的结果状态
 const currentIsResultArray = computed(() => {
 const currentIsResultArray = computed(() => {
+  console.log('isResultArray.value[slideIndex.value]', isResultArray.value[slideIndex.value])
   return isResultArray.value[slideIndex.value] || {}
   return isResultArray.value[slideIndex.value] || {}
 })
 })
 
 
@@ -1117,8 +1122,15 @@ const currentIsResultArray = computed(() => {
 // 跳转到指定幻灯片
 // 跳转到指定幻灯片
 const goToSlide = (index: number) => {
 const goToSlide = (index: number) => {
   console.log('goToSlide 被调用,目标索引:', index)
   console.log('goToSlide 被调用,目标索引:', index)
-  console.log('当前索引:', slideIndex.value)
-  
+  console.log('当前索引:', slideIndex.value, 'slides长度:', slides.value.length)
+
+  // slides 还没加载完时,暂存目标索引,等 slides 就绪后再跳转
+  if (slides.value.length === 0) {
+    console.warn('goToSlide: slides 未加载,暂存目标索引:', index)
+    pendingSlideIndex.value = index
+    return
+  }
+
   if (index >= 0 && index < slides.value.length) {
   if (index >= 0 && index < slides.value.length) {
     slidesStore.updateSlideIndex(index)
     slidesStore.updateSlideIndex(index)
     console.log('更新后的索引:', slideIndex.value)
     console.log('更新后的索引:', slideIndex.value)
@@ -1128,6 +1140,20 @@ const goToSlide = (index: number) => {
   }
   }
 }
 }
 
 
+// 暂存的目标幻灯片索引(slides 未就绪时使用)
+const pendingSlideIndex = ref<number | null>(null)
+// slides 加载完成后应用暂存的跳转
+watch(() => slides.value.length, (len) => {
+  if (len > 0 && pendingSlideIndex.value !== null) {
+    const idx = pendingSlideIndex.value
+    pendingSlideIndex.value = null
+    if (idx >= 0 && idx < len) {
+      console.log('🔄 slides 就绪,应用暂存的跳转索引:', idx)
+      slidesStore.updateSlideIndex(idx)
+    }
+  }
+})
+
 // 上一页
 // 上一页
 const previousSlide = () => {
 const previousSlide = () => {
   if (slideIndex.value > 0) {
   if (slideIndex.value > 0) {
@@ -1174,6 +1200,10 @@ watch(() => slideIndex.value, () => {
 
 
 // 监听 currentSlide 变化,确保刷新后能获取到画图状态
 // 监听 currentSlide 变化,确保刷新后能获取到画图状态
 watch(() => currentSlide.value?.id, (newSlideId, oldSlideId) => {
 watch(() => currentSlide.value?.id, (newSlideId, oldSlideId) => {
+  // 记录进入当前幻灯片的时间戳(immediate 保证刷新后 slides 加载完成也能记录)
+  if (newSlideId && newSlideId !== oldSlideId) {
+    slideEnterTime.value = Date.now()
+  }
   // 只在学生端且跟随模式下检查
   // 只在学生端且跟随模式下检查
   if (props.type == '2' && isFollowModeActive.value && yWritingBoardState.value && newSlideId) {
   if (props.type == '2' && isFollowModeActive.value && yWritingBoardState.value && newSlideId) {
     const snap = yWritingBoardState.value.toJSON()
     const snap = yWritingBoardState.value.toJSON()
@@ -1493,12 +1523,8 @@ const clearAllSyncStates = () => {
     if (props.type == '1' && isCreator.value && docSocket.value) {
     if (props.type == '1' && isCreator.value && docSocket.value) {
       console.log('🧹 创建老师退出,清空所有同步状态')
       console.log('🧹 创建老师退出,清空所有同步状态')
       docSocket.value.transact(() => {
       docSocket.value.transact(() => {
-        // 清空普通消息
-        const messageArray = docSocket.value?.getArray?.('message')
-        if (messageArray) {
-          messageArray.delete(0, messageArray.length)
-        }
-        // 清空计时器消息数组
+        // ★ 不删除 latest!delete 会传播给学生导致 get('latest') 返回 undefined
+        // 旧 latest 会被 sendMessage 的 set('latest', message) 自然覆盖
         const timerMessagesArray = docSocket.value?.getArray?.('timerMessages')
         const timerMessagesArray = docSocket.value?.getArray?.('timerMessages')
         if (timerMessagesArray) {
         if (timerMessagesArray) {
           timerMessagesArray.delete(0, timerMessagesArray.length)
           timerMessagesArray.delete(0, timerMessagesArray.length)
@@ -1684,11 +1710,11 @@ const elementDone = async (element: any, slideIndex: number) => {
       let newHash = hashPart
       let newHash = hashPart
       if (newHash.includes('?')) {
       if (newHash.includes('?')) {
         // 如果hash中已经有查询参数,添加&
         // 如果hash中已经有查询参数,添加&
-        newHash += `&courseid=${props.courseid || ''}&userid=${props.userid || ''}&stage=0&task=${slideIndex}&tool=0`
+        newHash += `&courseid=${props.courseid || ''}&userid=${props.userid || ''}&stage=0&task=${slideIndex}&tool=0&cid=${props.cid || ''}`
       } 
       } 
       else {
       else {
         // 如果hash中没有查询参数,添加?
         // 如果hash中没有查询参数,添加?
-        newHash += `?courseid=${props.courseid || ''}&userid=${props.userid || ''}&stage=0&task=${slideIndex}&tool=0`
+        newHash += `?courseid=${props.courseid || ''}&userid=${props.userid || ''}&stage=0&task=${slideIndex}&tool=0&cid=${props.cid || ''}`
       }
       }
 
 
       // 构建新的URL
       // 构建新的URL
@@ -2498,6 +2524,17 @@ const handleHomeworkSubmit = async () => {
     if (!hasSubmitWork) {
     if (!hasSubmitWork) {
       message.info(lang.ssHwNoFunc)
       message.info(lang.ssHwNoFunc)
     }
     }
+    else {
+      api.addPPTOp2({
+        id: props.courseid,
+        userid: props.userid || '',
+        type: '3',
+        index: currentSlide.value.id, // 获取当前ppt页面的id
+        data: String(Math.max(0, Math.round((Date.now() - slideEnterTime.value) / 1000))), // 进入作业页面到提交的耗时(秒)
+      }).then(res => {
+        console.log('res', res)
+      })
+    }
     isSubmitting.value = false
     isSubmitting.value = false
 
 
   }
   }
@@ -2972,6 +3009,7 @@ const getWork = async (isUpdate = false) => {
         // 只有当 ttype == '1' 或 (ttype == '2' 且 classid 包含 props.cid) 时才保留
         // 只有当 ttype == '1' 或 (ttype == '2' 且 classid 包含 props.cid) 时才保留
         // 同时满足 atool === toolType 或 toolType 为空
         // 同时满足 atool === toolType 或 toolType 为空
         // return (work.ttype == '1' || (work.ttype == '2' && work.classid.includes(props.cid))) && (work.atool == toolType.value || !toolType.value)
         // return (work.ttype == '1' || (work.ttype == '2' && work.classid.includes(props.cid))) && (work.atool == toolType.value || !toolType.value)
+        // work.ttype == '1'
         const ttypeMatch = work.ttype == '1' || (work.ttype == '2' && work.classid && work.classid.includes(props.cid))
         const ttypeMatch = work.ttype == '1' || (work.ttype == '2' && work.classid && work.classid.includes(props.cid))
         const toolMatch = toolType ? work.atool == toolType : true
         const toolMatch = toolType ? work.atool == toolType : true
         return ttypeMatch && toolMatch
         return ttypeMatch && toolMatch
@@ -3179,6 +3217,7 @@ const setCan = (Array: any[]) => {
 }
 }
 
 
 const forceLogout = () => {
 const forceLogout = () => {
+  cleanupWebSocketConnection()
   sendMessage({ type: 'logout' })
   sendMessage({ type: 'logout' })
 }
 }
 
 
@@ -3207,167 +3246,157 @@ const checkIsCreator = () => {
  * 初始化消息监听
  * 初始化消息监听
  */
  */
 const messageInit = () => {
 const messageInit = () => {
-  if (!docSocket.value) return
+  const doc = docSocket.value
+  if (!doc) return
+
+  // ★ 关键:判断当前绑定的共享类型是否属于这个 doc
+  // y-websocket 内部重连复用同一个 doc → observe 仍有效,直接返回(避免重复 observe)
+  // 只有 doc 被销毁重建(full reconnect)时才全部重新绑定
+  const boundDoc = (yMessage.value as any)?.doc
+  console.log('🔗 messageInit: doc.guid=', doc.guid, 'boundDoc=', boundDoc?.guid, 'same=', boundDoc === doc)
+  if (boundDoc === doc) {
+    // 同 doc 重连:补发上线消息即可
+    if (props.type === '2') {
+      sendMessage({ type: 'class_begin', courseid: props.courseid })
+    }
+    return
+  }
 
 
-  // 初始化普通消息数组(只保留最后一条)
-  if (!yMessage.value) {
-    console.log('初始化普通消息数组')
-    yMessage.value = docSocket.value.getArray('message')
-    yMessage.value.observe((e: any) => {
-      e.changes.added.forEach((i: any) => {
-        console.log('yMessage', yMessage.value.length)
-        console.log('yMessage', yMessage.value)
-        const message = i.content.getContent()[0]
-        console.log('yMessage', message)
-        if (message.mId !== mId.value) {
-          getMessages(message)
-        }
-      })
-    })
+  console.log('🔗 检测到新 Y.Doc,重新绑定所有共享数据监听')
+
+  // ★ 先把旧 doc 上的引用全部置空,杜绝守卫误判指向旧 doc
+  yMessage.value = null
+  yTimerState.value = null
+  yLaserState.value = null
+  yWritingBoardState.value = null
+  yTimerMessages.value = null
+  yLaserMessages.value = null
+  yWritingBoardMessages.value = null
+  yIsResultArrayMessages.value = null
+
+  // 普通消息(Map,只保留最后一条)
+  // 必须使用 messageV3:服务器上 messageV2 累积了旧的 delete('latest') 标记,
+  // 导致 get('latest') 永远返回 undefined(Yjs 的 typeMapGet 在最后一个 item 被 deleted 时返回 undefined)
+  yMessage.value = doc.getMap('messageV3')
+  yMessage.value.observe((e: any) => {
+    // 同时兼容 keysChanged 和 changes.keys(不同 Yjs 版本/事件结构)
+    const changed = e.keysChanged || e.changes?.keys
+    // ★ 打印每个 key 的 action(add/update/delete)和 oldValue
+    const keysMap = e.keys || e.changes?.keys
+    if (keysMap && keysMap.get) {
+      for (const [key, info] of keysMap.entries()) {
+        console.log(`🔗 observe key="${key}" action=${info.action} oldValue=`, info.oldValue)
+      }
+    }
+    console.log('🔗 yMessage observe 触发, changed keys:', changed ? Array.from(changed) : 'null')
+    if (!changed || !changed.has('latest')) return
+    const message = yMessage.value!.get('latest')
+    console.log('🔗 yMessage latest:', message, '当前 mId:', mId.value)
+    if (message && message.mId !== mId.value) {
+      getMessages(message)
+    }
+  })
+
+  // ★ 追平:连接建立后立即读取当前 latest,
+  // 防止老师在学生 observe 注册之前发的消息丢失(尤其是当前所在幻灯片)
+  const latest = yMessage.value.get('latest')
+  if (latest && latest.mId !== mId.value) {
+    console.log('🔗 追平当前 latest 消息:', latest)
+    getMessages(latest)
   }
   }
 
 
-  // 初始化计时器消息数组
-  if (!yTimerMessages.value) {
-    console.log('初始化计时器消息数组')
-    yTimerMessages.value = docSocket.value.getArray('timerMessages')
-    
-    // 初始化时检查一次是否需要清理
-    if (yTimerMessages.value && yTimerMessages.value.length > 500 && isCreator.value && docSocket.value) {
-      smartCleanupMessages(yTimerMessages.value, 500, 'timer', docSocket.value)
+  // 计时器消息数组
+  yTimerMessages.value = doc.getArray('timerMessages')
+  // 初始化时检查一次是否需要清理
+  if (yTimerMessages.value.length > 500 && isCreator.value) {
+    smartCleanupMessages(yTimerMessages.value, 500, 'timer', doc)
+  }
+  yTimerMessages.value.observe((e: any) => {
+    if (yTimerMessages.value.length > 500 && isCreator.value) {
+      setTimeout(() => {
+        if (yTimerMessages.value && yTimerMessages.value.length > 500) {
+          smartCleanupMessages(yTimerMessages.value, 500, 'timer', doc)
+        }
+      }, 0)
     }
     }
-    
-    yTimerMessages.value.observe((e: any) => {
-      console.log('yTimerMessages', yTimerMessages.value.length)
-      console.log('yTimerMessages', yTimerMessages.value)
-      
-      // 每次有新消息添加后,检查是否需要清理
-      if (yTimerMessages.value && yTimerMessages.value.length > 500 && isCreator.value && docSocket.value) {
-        // 使用 setTimeout 确保在 observe 回调执行完成后再清理
-        setTimeout(() => {
-          if (docSocket.value && yTimerMessages.value && yTimerMessages.value.length > 500) {
-            smartCleanupMessages(yTimerMessages.value, 500, 'timer', docSocket.value)
-          }
-        }, 0)
+    e.changes.added.forEach((i: any) => {
+      const message = i.content.getContent()[0]
+      if (message.mId !== mId.value) {
+        getMessages(message)
       }
       }
-      
-      e.changes.added.forEach((i: any) => {
-        const message = i.content.getContent()[0]
-        if (message.mId !== mId.value) {
-          getMessages(message)
-        }
-      })
     })
     })
-  }
+  })
 
 
-  // 初始化激光笔消息数组
-  if (!yLaserMessages.value) {
-    console.log('初始化激光笔消息数组')
-    yLaserMessages.value = docSocket.value.getArray('laserMessages')
-    
-    // 初始化时检查一次是否需要清理
-    if (yLaserMessages.value && yLaserMessages.value.length > 500 && isCreator.value && docSocket.value) {
-      smartCleanupMessages(yLaserMessages.value, 500, 'laser', docSocket.value)
+  // 激光笔消息数组
+  yLaserMessages.value = doc.getArray('laserMessages')
+  if (yLaserMessages.value.length > 500 && isCreator.value) {
+    smartCleanupMessages(yLaserMessages.value, 500, 'laser', doc)
+  }
+  yLaserMessages.value.observe((e: any) => {
+    if (yLaserMessages.value.length > 500 && isCreator.value) {
+      setTimeout(() => {
+        if (yLaserMessages.value && yLaserMessages.value.length > 500) {
+          smartCleanupMessages(yLaserMessages.value, 500, 'laser', doc)
+        }
+      }, 0)
     }
     }
-    
-    yLaserMessages.value.observe((e: any) => {
-      console.log('yLaserMessages', yLaserMessages.value.length)
-      console.log('yLaserMessages', yLaserMessages.value)
-      
-      // 每次有新消息添加后,检查是否需要清理
-      if (yLaserMessages.value && yLaserMessages.value.length > 500 && isCreator.value && docSocket.value) {
-        // 使用 setTimeout 确保在 observe 回调执行完成后再清理
-        setTimeout(() => {
-          if (docSocket.value && yLaserMessages.value && yLaserMessages.value.length > 500) {
-            smartCleanupMessages(yLaserMessages.value, 500, 'laser', docSocket.value)
-          }
-        }, 0)
+    e.changes.added.forEach((i: any) => {
+      const message = i.content.getContent()[0]
+      // 只处理开关消息,位置消息直接通过 Map 同步
+      if (message.type === 'laser_toggle' && message.mId !== mId.value) {
+        getMessages(message)
       }
       }
-      
-      e.changes.added.forEach((i: any) => {
-        const message = i.content.getContent()[0]
-        // 只处理开关消息,位置消息直接通过 Map 同步
-        if (message.type === 'laser_toggle' && message.mId !== mId.value) {
-          getMessages(message)
-        }
-      })
     })
     })
-  }
+  })
 
 
-  // 初始化画图消息数组
-  if (!yWritingBoardMessages.value) {
-    console.log('初始化画图消息数组')
-    yWritingBoardMessages.value = docSocket.value.getArray('writingBoardMessages')
-    
-    // 初始化时检查一次是否需要清理
-    if (yWritingBoardMessages.value && yWritingBoardMessages.value.length > 500 && isCreator.value && docSocket.value) {
-      smartCleanupMessages(yWritingBoardMessages.value, 500, 'writingBoard', docSocket.value)
+  // 画图消息数组
+  yWritingBoardMessages.value = doc.getArray('writingBoardMessages')
+  if (yWritingBoardMessages.value.length > 500 && isCreator.value) {
+    smartCleanupMessages(yWritingBoardMessages.value, 500, 'writingBoard', doc)
+  }
+  yWritingBoardMessages.value.observe((e: any) => {
+    if (yWritingBoardMessages.value.length > 500 && isCreator.value) {
+      setTimeout(() => {
+        if (yWritingBoardMessages.value && yWritingBoardMessages.value.length > 500) {
+          smartCleanupMessages(yWritingBoardMessages.value, 500, 'writingBoard', doc)
+        }
+      }, 0)
     }
     }
-    
-    yWritingBoardMessages.value.observe((e: any) => {
-      console.log('yWritingBoardMessages', yWritingBoardMessages.value.length)
-      console.log('yWritingBoardMessages', yWritingBoardMessages.value)
-      
-      // 每次有新消息添加后,检查是否需要清理
-      if (yWritingBoardMessages.value && yWritingBoardMessages.value.length > 500 && isCreator.value && docSocket.value) {
-        // 使用 setTimeout 确保在 observe 回调执行完成后再清理
-        setTimeout(() => {
-          if (docSocket.value && yWritingBoardMessages.value && yWritingBoardMessages.value.length > 500) {
-            smartCleanupMessages(yWritingBoardMessages.value, 500, 'writingBoard', docSocket.value)
-          }
-        }, 0)
+    e.changes.added.forEach((i: any) => {
+      const message = i.content.getContent()[0]
+      if (message.mId !== mId.value) {
+        getMessages(message)
       }
       }
-      
-      e.changes.added.forEach((i: any) => {
-        const message = i.content.getContent()[0]
-        if (message.mId !== mId.value) {
-          getMessages(message)
-        }
-      })
     })
     })
-  }
-
-  if (!yIsResultArrayMessages.value) {
-    console.log('初始化isResultArray消息数组')
-    yIsResultArrayMessages.value = docSocket.value.getArray('isResultArrayMessages')
+  })
 
 
-    // 初始化时检查一次是否需要清理
-    if (yIsResultArrayMessages.value && yIsResultArrayMessages.value.length > 1 && isCreator.value && docSocket.value) {
-      smartCleanupMessages(yIsResultArrayMessages.value, 1, 'isResultArray', docSocket.value)
+  // isResultArray 消息数组
+  yIsResultArrayMessages.value = doc.getArray('isResultArrayMessages')
+  if (yIsResultArrayMessages.value.length > 1 && isCreator.value) {
+    smartCleanupMessages(yIsResultArrayMessages.value, 1, 'isResultArray', doc)
+  }
+  yIsResultArrayMessages.value.observe((e: any) => {
+    if (yIsResultArrayMessages.value.length > 1 && isCreator.value) {
+      setTimeout(() => {
+        if (yIsResultArrayMessages.value && yIsResultArrayMessages.value.length > 1) {
+          smartCleanupMessages(yIsResultArrayMessages.value, 1, 'isResultArray', doc)
+        }
+      }, 0)
     }
     }
-
-    yIsResultArrayMessages.value.observe((e: any) => {
-      console.log('yIsResultArrayMessages', yIsResultArrayMessages.value.length)
-      console.log('yIsResultArrayMessages', yIsResultArrayMessages.value)
-      
-      // 每次有新消息添加后,检查是否需要清理
-      if (yIsResultArrayMessages.value && yIsResultArrayMessages.value.length > 1 && isCreator.value && docSocket.value) {  
-        // 使用 setTimeout 确保在 observe 回调执行完成后再清理
-        setTimeout(() => {
-          if (docSocket.value && yIsResultArrayMessages.value && yIsResultArrayMessages.value.length > 1) {
-            smartCleanupMessages(yIsResultArrayMessages.value, 1, 'isResultArray', docSocket.value)
-          }
-        }, 0)
+    e.changes.added.forEach((i: any) => {
+      const message = i.content.getContent()[0]
+      if (message.mId !== mId.value) {
+        getMessages(message)
       }
       }
-      
-      e.changes.added.forEach((i: any) => {
-        const message = i.content.getContent()[0]
-        if (message.mId !== mId.value) {
-          getMessages(message)
-        }
-      })
     })
     })
-    
-  }
+  })
 
 
   // 如果是首次进入且是创建者,清空所有同步状态
   // 如果是首次进入且是创建者,清空所有同步状态
   if (isFirstEnter.value && isCreator.value && docSocket.value) {
   if (isFirstEnter.value && isCreator.value && docSocket.value) {
     console.log('🧹 首次进入且为创建者,清空所有同步状态')
     console.log('🧹 首次进入且为创建者,清空所有同步状态')
     docSocket.value.transact(() => {
     docSocket.value.transact(() => {
-      // 清空普通消息(只保留最后一条的逻辑在 sendMessage 中处理)
-      const messageArray = docSocket.value?.getArray?.('message')
-      if (messageArray) {
-        messageArray.delete(0, messageArray.length)
-      }
+      // ★ 不删除 latest!delete 会传播给学生导致 get('latest') 返回 undefined
+      // 旧 latest 会被 sendMessage 的 set('latest', message) 自然覆盖
       // 清空计时器消息数组
       // 清空计时器消息数组
       const timerMessagesArray = docSocket.value?.getArray?.('timerMessages')
       const timerMessagesArray = docSocket.value?.getArray?.('timerMessages')
       if (timerMessagesArray) {
       if (timerMessagesArray) {
@@ -3402,66 +3431,54 @@ const messageInit = () => {
     // 标记已不再是首次进入
     // 标记已不再是首次进入
     isFirstEnter.value = false
     isFirstEnter.value = false
   }
   }
-  // 初始化计时器状态 Map 并监听
-  if (docSocket.value && !yTimerState.value) {
-    yTimerState.value = docSocket.value.getMap('timerState')
-    // 初始状态同步(后加入用户会立即拿到当前 map 值)
-    const snapshot = yTimerState.value.toJSON()
-    applyTimerStateSnapshot(snapshot)
-    // 监听变化
-    yTimerState.value.observe((event: any) => {
-      const snap = yTimerState.value.toJSON()
-      applyTimerStateSnapshot(snap)
-    })
-  }
-  // 初始化激光笔状态 Map 并监听
-  if (docSocket.value && !yLaserState.value) {
-    yLaserState.value = docSocket.value.getMap('laserState')
-    const lsnap = yLaserState.value.toJSON()
-    applyLaserStateSnapshot(lsnap)
-    yLaserState.value.observe(() => {
-      const s = yLaserState.value.toJSON()
-      applyLaserStateSnapshot(s)
-    })
-  }
-  // 初始化画图状态 Map 并监听
-  if (docSocket.value && !yWritingBoardState.value) {
-    yWritingBoardState.value = docSocket.value.getMap('writingBoardState')
-    const wsnap = yWritingBoardState.value.toJSON()
-    console.log('📝 初始化画图状态Map,快照:', wsnap, '当前幻灯片:', currentSlide.value?.id)
-    // 延迟应用,确保 currentSlide 已初始化
-    nextTick(() => {
-      // 如果 currentSlide 还没准备好,再等一帧
-      if (currentSlide.value && currentSlide.value.id) {
-        applyWritingBoardStateSnapshot(wsnap)
-      }
-      else {
-        // 如果还没准备好,等待 currentSlide 变化(最多等待3秒)
-        let timeoutId: any = null
-        const unwatch = watch(() => currentSlide.value?.id, (slideId) => {
-          if (slideId) {
-            applyWritingBoardStateSnapshot(wsnap)
-            unwatch()
-            if (timeoutId) clearTimeout(timeoutId)
-          }
-        }, { immediate: true })
-        // 3秒后如果还没准备好,强制应用一次
-        timeoutId = setTimeout(() => {
-          if (currentSlide.value && currentSlide.value.id) {
-            applyWritingBoardStateSnapshot(wsnap)
-          }
+  // 计时器状态 Map 并监听
+  yTimerState.value = doc.getMap('timerState')
+  // 初始状态同步(后加入用户会立即拿到当前 map 值)
+  applyTimerStateSnapshot(yTimerState.value.toJSON())
+  yTimerState.value.observe(() => {
+    applyTimerStateSnapshot(yTimerState.value!.toJSON())
+  })
+
+  // 激光笔状态 Map 并监听
+  yLaserState.value = doc.getMap('laserState')
+  applyLaserStateSnapshot(yLaserState.value.toJSON())
+  yLaserState.value.observe(() => {
+    applyLaserStateSnapshot(yLaserState.value!.toJSON())
+  })
+
+  // 画图状态 Map 并监听
+  yWritingBoardState.value = doc.getMap('writingBoardState')
+  const wsnap = yWritingBoardState.value.toJSON()
+  console.log('📝 初始化画图状态Map,快照:', wsnap, '当前幻灯片:', currentSlide.value?.id)
+  nextTick(() => {
+    if (currentSlide.value && currentSlide.value.id) {
+      applyWritingBoardStateSnapshot(wsnap)
+    }
+    else {
+      let timeoutId: any = null
+      const unwatch = watch(() => currentSlide.value?.id, (slideId) => {
+        if (slideId) {
+          applyWritingBoardStateSnapshot(wsnap)
           unwatch()
           unwatch()
-        }, 3000)
-      }
-    })
-    yWritingBoardState.value.observe(() => {
-      const s = yWritingBoardState.value.toJSON()
-      if (currentSlide.value && currentSlide.value.id) {
-        applyWritingBoardStateSnapshot(s)
-      }
-    })
-  }
+          if (timeoutId) clearTimeout(timeoutId)
+        }
+      }, { immediate: true })
+      timeoutId = setTimeout(() => {
+        if (currentSlide.value && currentSlide.value.id) {
+          applyWritingBoardStateSnapshot(wsnap)
+        }
+        unwatch()
+      }, 3000)
+    }
+  })
+  yWritingBoardState.value.observe(() => {
+    const s = yWritingBoardState.value!.toJSON()
+    if (currentSlide.value && currentSlide.value.id) {
+      applyWritingBoardStateSnapshot(s)
+    }
+  })
 
 
+  // 新 doc 绑定完成,补发上线消息
   if (props.type === '2') {
   if (props.type === '2') {
     sendMessage({ type: 'class_begin', courseid: props.courseid })
     sendMessage({ type: 'class_begin', courseid: props.courseid })
   }
   }
@@ -3605,15 +3622,22 @@ const sendMessage = (obj: any) => {
       // 特殊类型消息:存储到对应的独立数组
       // 特殊类型消息:存储到对应的独立数组
       const targetArray = getMessageArrayByType(messageType)
       const targetArray = getMessageArrayByType(messageType)
       if (targetArray) {
       if (targetArray) {
+        // 限制特殊消息数组最多 200 条,超出时删除最早的
+        const MAX_SPECIAL = 200
+        if (targetArray.length >= MAX_SPECIAL) {
+          targetArray.delete(0, targetArray.length - MAX_SPECIAL + 1)
+        }
         targetArray.push([message])
         targetArray.push([message])
       }
       }
     }
     }
     else {
     else {
       // 普通消息:只保留最后一条
       // 普通消息:只保留最后一条
       if (yMessage.value) {
       if (yMessage.value) {
-        // 清空数组,只保留新消息
-        yMessage.value.delete(0, yMessage.value.length)
-        yMessage.value.push([message])
+        // 用 Map.set 代替 Array.delete+push,只产生 1 条 update
+        yMessage.value.set('latest', message)
+      }
+      else {
+        console.warn('⚠️ sendMessage: yMessage.value 为 null,消息未写入! type:', messageType, 'docSocket:', !!docSocket.value)
       }
       }
     }
     }
   })
   })
@@ -3763,7 +3787,11 @@ const getMessages = (msgObj: any) => {
   // 获取是否展开结果数组
   // 获取是否展开结果数组
   if (props.type == '2' && msgObj.type === 'isResultArray' && msgObj.courseid === props.courseid) {
   if (props.type == '2' && msgObj.type === 'isResultArray' && msgObj.courseid === props.courseid) {
     try {
     try {
-      isResultArray.value = JSON.parse(msgObj.isResultArray || '[]')
+      console.error('是否展开结果数组:', msgObj.isResultArray || '[]')
+      const newResultArray = JSON.parse(msgObj.isResultArray || '[]')
+      // 值未变化时跳过下游逻辑
+      if (JSON.stringify(newResultArray) === JSON.stringify(isResultArray.value)) return
+      isResultArray.value = newResultArray
     }
     }
     catch (error) {
     catch (error) {
       console.error('解析是否展开结果数组失败:', error)
       console.error('解析是否展开结果数组失败:', error)
@@ -3820,6 +3848,13 @@ const getMessages = (msgObj: any) => {
       })
       })
     })
     })
   }
   }
+
+  // ★ 老师收到学生 class_begin 后,回发当前幻灯片,确保学生有 latest 可跟随
+  if (msgObj.type === 'class_begin' && isCreator.value) {
+    const curIndex = slidesStore.slideIndex ?? 0
+    sendMessage({ slideIndex: curIndex, courseid: props.courseid, type: 'slideIndex' })
+    console.log('🔗 老师响应 class_begin,回发 slideIndex:', curIndex)
+  }
 }
 }
 
 
 
 
@@ -3912,9 +3947,13 @@ const addOp3 = async (userTime: any, loadTime: any, object: any, status: any) =>
 
 
   try {
   try {
     if (!userJson.value || !userJson.value.accountNumber) {
     if (!userJson.value || !userJson.value.accountNumber) {
-      const res = await axios.get('https://pbl.cocorobo.cn/api/pbl/selectUser', {
+      const res = await axios.get('https://pbl.cocorobo.cn/api/pbl/selectUser2', {
         params: { userid: props.userid }
         params: { userid: props.userid }
       })
       })
+      if (res == 201 || res.length == 0) {
+        // message.error('登录已过期,请重新登录')
+        return
+      }
       userJson.value = res[0][0]
       userJson.value = res[0][0]
       console.log(userJson.value)
       console.log(userJson.value)
       console.log(res[0][0])
       console.log(res[0][0])
@@ -3922,7 +3961,13 @@ const addOp3 = async (userTime: any, loadTime: any, object: any, status: any) =>
   }
   }
   catch (e) {
   catch (e) {
     console.log(e)
     console.log(e)
-    return addOp3(userTime, loadTime, object, status)
+    if (e === 123) {
+      return
+    }
+    setTimeout(() => {
+      addOp3(userTime, loadTime, object, status)
+    }, 10000)
+    return
   }
   }
 
 
   const _time = new Date()
   const _time = new Date()
@@ -4032,6 +4077,35 @@ onMounted(() => {
     forceLogout,
     forceLogout,
     forceLogout2,
     forceLogout2,
     setCan,
     setCan,
+    // Yjs 诊断函数:控制台调用 PPTistStudent.diagnoseYjs()
+    diagnoseYjs: () => {
+      const doc = docSocket.value
+      if (!doc) {
+        console.log('════════ Yjs 诊断 ════════\ndocSocket.value 为 null')
+        return null
+      }
+      const msgV3Type = doc.share.get('messageV3')
+      const oldMsgType = doc.share.get('message')
+      const report = {
+        '1. doc.guid': doc.guid,
+        '2. yMessage.value === doc.share.get("messageV3")': yMessage.value === msgV3Type,
+        '3. yMessage.value?.doc?.guid': yMessage.value?.doc?.guid,
+        '4. doc.store.clients.size': doc.store.clients.size,
+        '5a. share.get("messageV3") 类型': msgV3Type?.constructor?.name,
+        '5b. share.get("message") 类型': oldMsgType?.constructor?.name,
+        '6. messageV3.size': msgV3Type?.size,
+        '7. messageV3?.get("latest")': msgV3Type?.get?.('latest'),
+        '8. yMessage.value?.get("latest")': yMessage.value?.get?.('latest'),
+        '9. doc 里所有顶层 key': Array.from(doc.share.entries()).map(([k, v]: [string, any]) => k + ':' + v.constructor.name),
+        '10. provider synced': providerSocket.value?.synced,
+        '11. ws.readyState': providerSocket.value?.ws?.readyState,
+      }
+      console.log('════════ Yjs 诊断 ════════')
+      for (const [k, v] of Object.entries(report)) {
+        console.log(k + ':', typeof v === 'object' ? JSON.stringify(v) : v)
+      }
+      return report
+    },
   }
   }
 
 
   console.log('PPTist Student View 已加载,可通过 window.PPTistStudent 访问功能')
   console.log('PPTist Student View 已加载,可通过 window.PPTistStudent 访问功能')
@@ -4061,7 +4135,10 @@ onMounted(() => {
   document.addEventListener('visibilitychange', handleVisibilityChange)
   document.addEventListener('visibilitychange', handleVisibilityChange)
   
   
   // pagehide 事件(作为补充,某些浏览器中比 beforeunload 更可靠)
   // pagehide 事件(作为补充,某些浏览器中比 beforeunload 更可靠)
-  window.addEventListener('pagehide', handlePageUnload)
+  window.addEventListener('pagehide', () => {
+    console.log('pagehide')
+    handlePageUnload()
+  })
   
   
   // 存储清理函数,方便在 onUnmounted 中移除
   // 存储清理函数,方便在 onUnmounted 中移除
   ;(window as any).__pptistStudentUnloadHandlers = {
   ;(window as any).__pptistStudentUnloadHandlers = {
@@ -4095,6 +4172,12 @@ onUnmounted(() => {
     authTokenUpdateTimer.value = null
     authTokenUpdateTimer.value = null
   }
   }
 
 
+  // 清理心跳定时器
+  if (heartbeatTimer.value) {
+    clearInterval(heartbeatTimer.value)
+    heartbeatTimer.value = null
+  }
+
   // 清理 socket 连接检查定时器
   // 清理 socket 连接检查定时器
   if (socketCheckTimer.value) {
   if (socketCheckTimer.value) {
     clearInterval(socketCheckTimer.value)
     clearInterval(socketCheckTimer.value)
@@ -4226,12 +4309,25 @@ const cleanupWebSocketConnection = () => {
     providerSocket.value.destroy()
     providerSocket.value.destroy()
     providerSocket.value = null
     providerSocket.value = null
   }
   }
-  
+
   if (docSocket.value) {
   if (docSocket.value) {
     // 注意:doc 会被 provider.destroy() 自动销毁,不需要手动 destroy
     // 注意:doc 会被 provider.destroy() 自动销毁,不需要手动 destroy
     // 但如果 provider 已经被销毁,这里置空即可
     // 但如果 provider 已经被销毁,这里置空即可
+    docSocket.value.destroy()
     docSocket.value = null
     docSocket.value = null
   }
   }
+
+  // ★ 关键:doc 已销毁,必须把绑定在旧 doc 上的共享类型引用全部置空,
+  // 否则重连后 messadocSocket.value.guid === yMessazeInit() 的 if (!yXxx.value) 守卫会跳过绑定,
+  // 新 doc 收到更新时 observe 回调不会触发(表现为突然收不到消息)
+  yMessage.value = null
+  yTimerState.value = null
+  yLaserState.value = null
+  yWritingBoardState.value = null
+  yTimerMessages.value = null
+  yLaserMessages.value = null
+  yWritingBoardMessages.value = null
+  yIsResultArrayMessages.value = null
 }
 }
 
 
 // 创建WebSocket连接
 // 创建WebSocket连接
@@ -4240,7 +4336,6 @@ const createWebSocketConnection = async (type = 1) => {
   
   
   isConnecting.value = true
   isConnecting.value = true
   connectionStatus.value = 'connecting'
   connectionStatus.value = 'connecting'
-  
   try {
   try {
     // 清理之前的连接
     // 清理之前的连接
     // if (providerSocket.value && type == 1) {
     // if (providerSocket.value && type == 1) {
@@ -4274,9 +4369,111 @@ const createWebSocketConnection = async (type = 1) => {
       api.yweb_socket,
       api.yweb_socket,
       'PPT' + props.courseid,
       'PPT' + props.courseid,
       docSocket.value,
       docSocket.value,
-      { params: { yauth: authToken.value } }
+      {
+        params: { yauth: authToken.value },
+        resyncInterval: 5000, // 每 5 秒用标准协议请求服务器状态(代替畸形心跳)
+        maxBackoffTime: 5000, // 重连最长退避 5 秒
+      }
     )
     )
-    
+    providerSocket.value.awareness.setLocalState(null)
+    providerSocket.value.awareness.destroy() // 完全禁用 awareness
+
+    // ★ 三层日志之一:raw websocket 消息(确认数据到达浏览器)
+    const _ws = (providerSocket.value as any).ws
+    if (_ws && !_ws.__logged) {
+      _ws.__logged = true // 防止重复绑定
+      // 包一层 onmessage,抓 provider 处理异常
+      const _origOnMsg = _ws.onmessage
+      if (typeof _origOnMsg === 'function') {
+        _ws.onmessage = function(ev: MessageEvent) {
+          try {
+            _origOnMsg.call(_ws, ev)
+          }
+          catch (e: any) {
+            console.error('❌ provider onmessage 异常:', e?.message || e, e?.stack || '')
+          }
+        }
+      }
+      _ws.addEventListener('message', (ev: MessageEvent) => {
+        try {
+          const data = new Uint8Array(ev.data)
+          const msgType = data[0]
+          const typeNames: any = { 0: 'sync', 1: 'awareness', 2: 'queryAwareness' }
+          let detail = ''
+          if (msgType === 0) {
+            const sub = data[1]
+            detail = ({ 0: 'step1(请求缺失)', 1: 'step2(服务器推送)', 2: 'update' } as any)[sub] || 'unknown'
+          }
+          console.log(`📥 ws raw: ${typeNames[msgType] || msgType} ${detail} (${data.length} bytes)`)
+
+          // ★ 诊断:sync update 到达时手动解码 + applyUpdate,看是不是重复数据
+          if (msgType === 0 && data[1] === 2) {
+            const doc = docSocket.value
+            if (doc) {
+              // 解码 varint 提取 update bytes
+              let pos = 2 // 跳过 msgType + subType
+              let updateLen = 0
+              let shift = 0
+              while (pos < data.length) {
+                const b = data[pos++]
+                updateLen |= (b & 0x7f) << shift
+                if (b < 0x80) break
+                shift += 7
+              }
+              const updateBytes = data.slice(pos, pos + updateLen)
+
+              // ★ 用 Y.decodeUpdate 解码 update(不创建 temp doc,不触发 applyUpdate 的 DELETE)
+              try {
+                const { structs } = Y.decodeUpdate(updateBytes)
+                console.log(`📦 解码: updateBytes=${updateBytes.length}, structs=${structs.length}`)
+                for (const struct of structs) {
+                  const arr = struct?.content?.arr
+                  console.log(`📦 struct: type=${struct?.content?.constructor?.name}, parentSub=${struct?.parentSub}, arr=${arr ? JSON.stringify(arr)?.slice(0, 150) : '无'}`)
+                  if (arr && Array.isArray(arr)) {
+                    for (const val of arr) {
+                      if (val && typeof val === 'object' && val.type && val.mId) {
+                        console.log(`📦 ✅ 从 update 提取消息: type=${val.type}, mId=${val.mId}, 当前 mId=${mId.value}`)
+                        if (val.mId !== mId.value) {
+                          getMessages(val)
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+              catch (e) {
+                console.log('📦 update 解码失败:', e)
+              }
+            }
+          }
+        }
+        catch (e) {
+          console.log('📥 ws raw: parse error', e)
+        }
+      })
+    }
+
+    // ★ 三层日志之二:Y.Doc update 事件 — 列出所有根类型的 size,看更新到底改了哪个
+    docSocket.value.on('update', (update: Uint8Array, origin: any) => {
+      const originName = origin?.constructor?.name || (origin === providerSocket.value ? 'ws-provider' : typeof origin)
+      const share = (docSocket.value as any)?.share
+      const sizes: string[] = []
+      if (share) {
+        for (const [name, type] of share.entries()) {
+          const sz = type.size ?? type.length ?? '?'
+          const latest = type.get?.('latest')
+          sizes.push(`${name}=${sz}${latest ? '(' + latest.type + ')' : ''}`)
+        }
+      }
+      console.log(`📥 Y.Doc update: ${update.length} bytes, origin: ${originName}, types: [${sizes.join(', ')}]`)
+    })
+
+    // 清理可能残留的旧心跳定时器
+    if (heartbeatTimer.value) {
+      clearInterval(heartbeatTimer.value)
+      heartbeatTimer.value = null
+    }
+
     // 启动定期更新 token
     // 启动定期更新 token
     // 30分钟后再次更新
     // 30分钟后再次更新
     if (authTokenUpdateTimer.value) {
     if (authTokenUpdateTimer.value) {
@@ -4302,10 +4499,16 @@ const createWebSocketConnection = async (type = 1) => {
         
         
         mId.value = Math.random().toString(36).substr(2, 9)
         mId.value = Math.random().toString(36).substr(2, 9)
         messageInit()
         messageInit()
+        console.log('🔗 connected 后: yMessage.value =', yMessage.value ? '已绑定' : 'null', 'doc.guid=', docSocket.value?.guid)
         // 连接成功后,读取当前计时器状态(Map)
         // 连接成功后,读取当前计时器状态(Map)
         if (docSocket.value) {
         if (docSocket.value) {
           initializeYjsData()
           initializeYjsData()
         }
         }
+        if (type == 1) {
+          setTimeout(() => {
+            createWebSocketConnection(2)
+          }, 1000)
+        }
       }
       }
       else if (event.status === 'disconnected') {
       else if (event.status === 'disconnected') {
         console.log('👉 连接断开,等待自动重连...')
         console.log('👉 连接断开,等待自动重连...')
@@ -4331,10 +4534,77 @@ const createWebSocketConnection = async (type = 1) => {
     providerSocket.value.on('connection-error', (error: any) => {
     providerSocket.value.on('connection-error', (error: any) => {
       console.error('👉 WebSocket 连接错误(将自动重连):', error)
       console.error('👉 WebSocket 连接错误(将自动重连):', error)
     })
     })
-    
+
     providerSocket.value.on('connection-close', (event: any) => {
     providerSocket.value.on('connection-close', (event: any) => {
       console.log('👉 WebSocket 连接关闭(将自动重连):', event)
       console.log('👉 WebSocket 连接关闭(将自动重连):', event)
     })
     })
+
+    // ★ synced 事件:在服务器状态同步完成(sync step 2 已应用到 Y.Doc)后触发
+    // 'connected' 在 onopen 时就触发,此时 sync 尚未完成,messageInit 的 catch-up 读不到数据
+    // 'synced' 才是做 catch-up 的正确时机——确保服务器上的 latest 已写入本地 Y.Doc
+    providerSocket.value.on('sync', (isSynced: boolean) => {
+      if (!isSynced) return
+      console.log('🔗 Yjs sync 完成,开始 catch-up')
+
+      // ★ 诊断:枚举 doc.share 里所有根类型,给每个都加 observe
+      const share = (docSocket.value as any).share
+      if (share) {
+        console.log('🔗 根类型列表:')
+        for (const [name, type] of share.entries()) {
+          console.log(`  ${name}: ${type.constructor.name}, size: ${type.size ?? type.length ?? '?'}`)
+          // 给每个根类型加 observe,看哪个在动
+          if (type.observe && !type.__diagObserved) {
+            type.__diagObserved = true
+            type.observe((e: any) => {
+              const changed = e.keysChanged || e.changes?.keys
+              console.log(`🔗 [${name}] observe 触发! changed:`, changed ? Array.from(changed) : e)
+            })
+          }
+        }
+      }
+
+      // catch-up:读取服务器同步过来的 latest 消息
+      if (yMessage.value) {
+        const latest = yMessage.value.get('latest')
+        console.log('🔗 synced catch-up latest:', latest)
+        if (latest && latest.mId !== mId.value) {
+          console.log('🔗 synced catch-up: 处理 latest 消息', latest.type)
+          getMessages(latest)
+        }
+      }
+
+      // catch-up:读取计时器、激光笔、画图状态
+      if (yTimerState.value) {
+        const snapshot = yTimerState.value.toJSON()
+        applyTimerStateSnapshot(snapshot)
+      }
+      if (yLaserState.value) {
+        const laserSnap = yLaserState.value.toJSON()
+        if (laserSnap.visible !== undefined) {
+          laserPenOverlay.value.visible = !!laserSnap.visible
+        }
+      }
+
+      // 学生端补发上线消息,让老师知道学生已就绪
+      if (props.type === '2') {
+        console.log('🔗 sync handler: yMessage.value =', yMessage.value ? '已绑定' : 'null', 'doc.guid=', docSocket.value?.guid)
+        sendMessage({ type: 'class_begin', courseid: props.courseid })
+        // ★ 确认 class_begin 是否真的写入了 messageV3
+        const msgV3 = (docSocket.value as any)?.share?.get?.('messageV3')
+        console.log('🔗 学生发送 class_begin 后, messageV3.size:', msgV3?.size, 'latest:', msgV3?.get?.('latest')?.type)
+      }
+
+      // ★ 老师端:sync 完成后补发当前幻灯片,确保 messageV3 的 latest 有值
+      // 解决:服务器上 latest 被 clearAllSyncStates 删除后,新连入学生拿到空 Map 无法跟随
+      if (props.type === '1') {
+        const curIndex = slidesStore.slideIndex ?? 0
+        sendMessage({ slideIndex: curIndex, courseid: props.courseid, type: 'slideIndex' })
+        console.log('🔗 老师补发当前幻灯片 slideIndex:', curIndex)
+      }
+
+      // 自动运行 Yjs 诊断
+      (window as any).PPTistStudent?.diagnoseYjs?.()
+    })
     // 监听连接错误
     // 监听连接错误
     // providerSocket.value.on('connection-error', (error: any) => {
     // providerSocket.value.on('connection-error', (error: any) => {
     //   console.error('👉 WebSocket连接错误:', error)
     //   console.error('👉 WebSocket连接错误:', error)

File diff suppressed because it is too large
+ 577 - 262
src/views/Student/index2.vue


+ 84 - 1
src/views/components/element/FrameElement/BaseFrameElement.vue

@@ -64,7 +64,7 @@
         <!-- 延迟加载iframe:只有在可见且不是缩略图时才加载 -->
         <!-- 延迟加载iframe:只有在可见且不是缩略图时才加载 -->
         <iframe
         <iframe
           :key="`html-${iframeKey}`"
           :key="`html-${iframeKey}`"
-          :srcdoc="elementInfo.url"
+          :srcdoc="processedSrcDoc"
           v-else-if="elementInfo.isHTML && !isThumbnail && isVisible"
           v-else-if="elementInfo.isHTML && !isThumbnail && isVisible"
           :width="width"
           :width="width"
           :height="height"
           :height="height"
@@ -161,6 +161,88 @@ const width = computed(() => {
   return props.elementInfo.width * props.scale
   return props.elementInfo.width * props.scale
 })
 })
 
 
+// srcdoc 外链 CDN 镜像替换
+const CDN_RULES: [RegExp, string][] = [
+  // ===== 1. lucide 特殊处理(必须放在最前,且指向 UMD)=====
+  [/unpkg\.com\/lucide@latest/g,
+    'cdn.jsdmirror.com/npm/lucide@1.47.0/dist/umd/lucide.min.js'],
+  [/unpkg\.com\/lucide@([\d.]+)/g,
+    'cdn.jsdmirror.com/npm/lucide@$1/dist/umd/lucide.min.js'],
+  [/cdn\.jsdelivr\.net\/npm\/lucide@([\d.]+)(?!\/dist\/umd)/g,
+    'cdn.jsdmirror.com/npm/lucide@$1/dist/umd/lucide.min.js'],
+
+  // ===== 2. unpkg → JSDMirror(一步到位,避免链式替换)=====
+  [/unpkg\.com/g, 'cdn.jsdmirror.com/npm'],
+
+  // ===== 3. jsDelivr 全系列 → JSDMirror =====
+  [/fastly\.jsdelivr\.net/g, 'cdn.jsdmirror.com'],
+  [/gcore\.jsdelivr\.net/g, 'cdn.jsdmirror.com'],
+  [/cdn\.jsdelivr\.net/g, 'cdn.jsdmirror.com'],
+
+  // ===== 4. Google Hosted Libraries → JSDMirror(按路径精确映射)=====
+  [/ajax\.googleapis\.com\/ajax\/libs\/jquery\/([\d.]+)\/jquery(\.min)?\.js/g,
+    'cdn.jsdmirror.com/npm/jquery@$1/dist/jquery$2.js'],
+  [/ajax\.googleapis\.com\/ajax\/libs\/([^\/]+)\/([\d.]+)\/(.+)/g,
+    'cdn.jsdmirror.com/npm/$1@$2/$3'],
+  [/ajax\.googleapis\.com\/ajax\/libs\/([^\/]+)\/([\d.]+)/g,
+    'cdn.jsdmirror.com/npm/$1@$2'],
+
+  // ===== 5. Google Fonts =====
+  [/fonts\.googleapis\.com/g, 'fonts.loli.net'],
+  [/fonts\.gstatic\.com/g, 'gstatic.loli.net'],
+  [/themes\.googleusercontent\.com/g, 'gstatic.loli.net'],
+
+  // ===== 6. cdnjs =====
+  [/cdnjs\.cloudflare\.com/g, 'cdnjs.loli.net'],
+  [/cdnjs\.loli\.net/g, 'cdnjs.loli.net'], // 幂等,防止重复替换
+
+  // ===== 7. Font Awesome =====
+  [/kit\.fontawesome\.com/g, 'cdn.jsdmirror.com/npm/@fortawesome/fontawesome-free@6/js/all.min.js'],
+  [/use\.fontawesome\.com\/releases\/([^\/]+)\/css\/all\.min\.css/g,
+    'cdn.jsdmirror.com/npm/@fortawesome/fontawesome-free@$1/css/all.min.css'],
+
+  // ===== 8. Bootstrap CDN =====
+  [/stackpath\.bootstrapcdn\.com\/bootstrap\/([\d.]+)\/css\/bootstrap(\.min)?\.css/g,
+    'cdn.jsdmirror.com/npm/bootstrap@$1/dist/css/bootstrap$2.css'],
+  [/stackpath\.bootstrapcdn\.com\/bootstrap\/([\d.]+)\/js\/bootstrap(\.min)?\.js/g,
+    'cdn.jsdmirror.com/npm/bootstrap@$1/dist/js/bootstrap$2.js'],
+  [/maxcdn\.bootstrapcdn\.com\/bootstrap\/([\d.]+)\/css\/bootstrap(\.min)?\.css/g,
+    'cdn.jsdmirror.com/npm/bootstrap@$1/dist/css/bootstrap$2.css'],
+  [/maxcdn\.bootstrapcdn\.com\/bootstrap\/([\d.]+)\/js\/bootstrap(\.min)?\.js/g,
+    'cdn.jsdmirror.com/npm/bootstrap@$1/dist/js/bootstrap$2.js'],
+
+  // ===== 9. polyfill =====
+  [/polyfill\.io/g, 'cdn.jsdmirror.com/npm/polyfill-library@3/polyfill.min.js'],
+  [/polyfill-fastly\.io/g, 'cdn.jsdmirror.com/npm/polyfill-library@3/polyfill.min.js'],
+
+  // ===== 10. Tailwind Play CDN =====
+  [/https?:\/\/cdn\.tailwindcss\.com[\d.\/]*/g,
+    'https://cdn.jsdmirror.com/npm/@tailwindcss/browser@4.3.3'],
+
+  // ===== 11. jQuery 官方 CDN =====
+  [/code\.jquery\.com\/jquery-([\d.]+)(\.min)?\.js/g,
+    'cdn.jsdmirror.com/npm/jquery@$1/dist/jquery$2.js'],
+
+  // ===== 12. GitHub Raw =====
+  [/raw\.githubusercontent\.com\/([^\/]+)\/([^\/]+)\/([^\/]+)\/(.+)/g,
+    'cdn.jsdmirror.com/gh/$1/$2@$3/$4'],
+  [/raw\.githack\.com\/([^\/]+)\/([^\/]+)\/([^\/]+)\/(.+)/g,
+    'cdn.jsdmirror.com/gh/$1/$2@$3/$4'],
+
+  // ===== 13. Gravatar(这个真没有靠谱国内镜像,建议保留原样)=====
+  // 如果必须替换,用下面这条,但不保证可用
+  // [/www\.gravatar\.com\/avatar/g, 'sdn.geekzu.org/avatar'],
+]
+
+const processedSrcDoc = computed(() => {
+  let html = props.elementInfo.url || ''
+  if (!html || typeof html !== 'string') return html
+  for (const [pattern, replacement] of CDN_RULES) {
+    html = html.replace(pattern, replacement)
+  }
+  return html
+})
+
 const height = computed(() => {
 const height = computed(() => {
   return props.elementInfo.height * props.scale
   return props.elementInfo.height * props.scale
 })
 })
@@ -191,6 +273,7 @@ const getTypeLabel = (type: number): string => {
     84: 'ssFile',
     84: 'ssFile',
     [ARTICLE_READING_TOOL_TYPE]: 'ssArticleReadingTool',
     [ARTICLE_READING_TOOL_TYPE]: 'ssArticleReadingTool',
     831: 'ssKwlTitle',
     831: 'ssKwlTitle',
+    832: 'ssSixHatTitle',
   }
   }
   const key = typeMap[type]
   const key = typeMap[type]
   return (key ? lang[key] : lang.ssUnknown) as string
   return (key ? lang[key] : lang.ssUnknown) as string

+ 33 - 1
src/views/lang/cn.json

@@ -502,6 +502,7 @@
   "ssResetPoster": "重置封面",
   "ssResetPoster": "重置封面",
   "ssBgFillTit": "背景填充",
   "ssBgFillTit": "背景填充",
   "ssBgContain": "缩放",
   "ssBgContain": "缩放",
+  "ssFontScale": "缩放",
   "ssBgRepeat": "拼贴",
   "ssBgRepeat": "拼贴",
   "ssBgCover": "缩放铺满",
   "ssBgCover": "缩放铺满",
   "ssApplyBgAll": "应用背景到全部",
   "ssApplyBgAll": "应用背景到全部",
@@ -746,6 +747,8 @@
   "ssAiChatQuickAction2": "为当前页面内容生成1道问答题",
   "ssAiChatQuickAction2": "为当前页面内容生成1道问答题",
   "ssAiChatQuickAction6": "为当前页面生成投票",
   "ssAiChatQuickAction6": "为当前页面生成投票",
   "ssAiChatQuickAction7": "为当前页面生成拍照题",
   "ssAiChatQuickAction7": "为当前页面生成拍照题",
+  "ssAiChatQuickAction8": "当前页面生成配图",
+  "ssAiChatQuickAction9": "为当前页面内容生成文件上传",
   "ssAiChatParsing": "解析中...",
   "ssAiChatParsing": "解析中...",
   "ssAiChatWaitUpload": "请等待文件上传完成后再发送消息",
   "ssAiChatWaitUpload": "请等待文件上传完成后再发送消息",
   "ssAiChatFileSizeLimit": "文件大小不能超过10MB",
   "ssAiChatFileSizeLimit": "文件大小不能超过10MB",
@@ -1090,7 +1093,36 @@
   "ssKwlWant": "W-想知",
   "ssKwlWant": "W-想知",
   "ssKwlLearned": "L-已学",
   "ssKwlLearned": "L-已学",
   "ssKwlReflection": "学习反思",
   "ssKwlReflection": "学习反思",
+  "ssSixHatTitle": "六顶思考帽",
+  "ssSixHatDesc": "通过六种不同思维角色(白帽-事实、红帽-情感、黑帽-风险、黄帽-优点、绿帽-创意、蓝帽-控制)进行全面思考",
+  "ssSixHatGradeRange": "初中-高中",
+  "ssSixHatUsageScenario": "使用场景",
+  "ssSixHatScenarioText": "学生独立使用六顶思考帽从多角度分析问题",
+  "ssSixHatSteps": "操作步骤",
+  "ssSixHatStep1": "白帽思考:收集客观事实和数据",
+  "ssSixHatStep2": "红帽思考:表达直觉和情感反应",
+  "ssSixHatStep3": "黑帽思考:识别风险和潜在问题",
+  "ssSixHatStep4": "黄帽思考:寻找优点和积极面",
+  "ssSixHatStep5": "绿帽思考:提出创新想法和方案",
+  "ssSixHatStep6": "蓝帽思考:总结思考过程和结论",
+  "ssSixHatSource": "来源:爱德华·德博诺(Edward de Bono)1985年提出的平行思维训练法",
+  "ssSixHatPurpose": "目的:让学生轮流从六种思维角色出发看待同一个问题,避免争论式思维,进行更全面的分析",
+  "ssSixHatUserConfig": "工具内容由使用者配置",
+  "ssSixHatUserConfigDesc": "学生打开时会先自己设置,下方相关配置项由学生决定",
+  "ssSixHatGroupWork": "小组合作",
+  "ssSixHatGroupWorkDesc": "关闭则不显示小组成员和负责人功能",
+  "ssSixHatShowTimer": "显示计时器",
+  "ssSixHatTimerDuration": "计时时长",
+  "ssSixHatTimerSeconds": "秒",
+  "ssSixHatSelectHats": "思考帽选择",
+  "ssSixHatWhite": "白帽·事实",
+  "ssSixHatRed": "红帽·情感",
+  "ssSixHatBlack": "黑帽·风险",
+  "ssSixHatYellow": "黄帽·优点",
+  "ssSixHatGreen": "绿帽·创意",
+  "ssSixHatBlue": "蓝帽·控制",
   "ssFile": "文件上传",
   "ssFile": "文件上传",
   "ssClickToPreview": "点击预览",
   "ssClickToPreview": "点击预览",
-  "ssClickToOpen": "点击打开"
+  "ssClickToOpen": "点击打开",
+  "ssAccuracy2": "正确率"
 }
 }

+ 33 - 1
src/views/lang/en.json

@@ -503,6 +503,7 @@
   "ssResetPoster": "Reset poster",
   "ssResetPoster": "Reset poster",
   "ssBgFillTit": "Background fill",
   "ssBgFillTit": "Background fill",
   "ssBgContain": "Contain",
   "ssBgContain": "Contain",
+  "ssFontScale": "Scale",
   "ssBgRepeat": "Tile",
   "ssBgRepeat": "Tile",
   "ssBgCover": "Cover",
   "ssBgCover": "Cover",
   "ssApplyBgAll": "Apply background to all",
   "ssApplyBgAll": "Apply background to all",
@@ -747,6 +748,8 @@
   "ssAiChatQuickAction2": "Generate 1 essay question for the current page content",
   "ssAiChatQuickAction2": "Generate 1 essay question for the current page content",
   "ssAiChatQuickAction6": "Generate a poll for the current page",
   "ssAiChatQuickAction6": "Generate a poll for the current page",
   "ssAiChatQuickAction7": "Generate a photo question for the current page",
   "ssAiChatQuickAction7": "Generate a photo question for the current page",
+  "ssAiChatQuickAction8": "Generate a photo for the current page",
+  "ssAiChatQuickAction9": "Generate a file upload for the current page content",
   "ssAiChatParsing": "Parsing...",
   "ssAiChatParsing": "Parsing...",
   "ssAiChatWaitUpload": "Please wait for the file upload to complete before sending a message",
   "ssAiChatWaitUpload": "Please wait for the file upload to complete before sending a message",
   "ssAiChatFileSizeLimit": "File size cannot exceed 10MB",
   "ssAiChatFileSizeLimit": "File size cannot exceed 10MB",
@@ -1090,7 +1093,36 @@
   "ssKwlWant": "W-Want to know",
   "ssKwlWant": "W-Want to know",
   "ssKwlLearned": "L-Learned",
   "ssKwlLearned": "L-Learned",
   "ssKwlReflection": "Learning Reflection",
   "ssKwlReflection": "Learning Reflection",
+  "ssSixHatTitle": "Six Thinking Hats",
+  "ssSixHatDesc": "Think comprehensively through six different thinking roles (White-Facts, Red-Emotions, Black-Risks, Yellow-Benefits, Green-Creativity, Blue-Control)",
+  "ssSixHatGradeRange": "Middle-High School",
+  "ssSixHatUsageScenario": "Usage Scenario",
+  "ssSixHatScenarioText": "Students independently use the Six Thinking Hats to analyze problems from multiple perspectives",
+  "ssSixHatSteps": "Steps",
+  "ssSixHatStep1": "White Hat: Gather objective facts and data",
+  "ssSixHatStep2": "Red Hat: Express intuition and emotional reactions",
+  "ssSixHatStep3": "Black Hat: Identify risks and potential problems",
+  "ssSixHatStep4": "Yellow Hat: Find strengths and positive aspects",
+  "ssSixHatStep5": "Green Hat: Propose innovative ideas and solutions",
+  "ssSixHatStep6": "Blue Hat: Summarize the thinking process and conclusions",
+  "ssSixHatSource": "Source: The parallel thinking training method proposed by Edward de Bono in 1985",
+  "ssSixHatPurpose": "Purpose: Let students take turns viewing the same problem from six thinking roles, avoiding argumentative thinking for more comprehensive analysis",
+  "ssSixHatUserConfig": "Tool content configured by users",
+  "ssSixHatUserConfigDesc": "Students configure it themselves when opening; related options below are decided by students",
+  "ssSixHatGroupWork": "Group Collaboration",
+  "ssSixHatGroupWorkDesc": "When off, group members and leader features are hidden",
+  "ssSixHatShowTimer": "Show Timer",
+  "ssSixHatTimerDuration": "Timer Duration",
+  "ssSixHatTimerSeconds": "sec",
+  "ssSixHatSelectHats": "Select Hats",
+  "ssSixHatWhite": "White·Facts",
+  "ssSixHatRed": "Red·Emotion",
+  "ssSixHatBlack": "Black·Risks",
+  "ssSixHatYellow": "Yellow·Benefits",
+  "ssSixHatGreen": "Green·Creativity",
+  "ssSixHatBlue": "Blue·Control",
   "ssFile": "File Upload",
   "ssFile": "File Upload",
   "ssClickToPreview": "Click to Preview",
   "ssClickToPreview": "Click to Preview",
-  "ssClickToOpen": "Click to Open"
+  "ssClickToOpen": "Click to Open",
+  "ssAccuracy2": "accuracy rate"
 }
 }

+ 33 - 1
src/views/lang/hk.json

@@ -503,6 +503,7 @@
   "ssResetPoster": "重置封面",
   "ssResetPoster": "重置封面",
   "ssBgFillTit": "背景填充",
   "ssBgFillTit": "背景填充",
   "ssBgContain": "縮放",
   "ssBgContain": "縮放",
+  "ssFontScale": "縮放",
   "ssBgRepeat": "拼貼",
   "ssBgRepeat": "拼貼",
   "ssBgCover": "縮放鋪滿",
   "ssBgCover": "縮放鋪滿",
   "ssApplyBgAll": "應用背景到全部",
   "ssApplyBgAll": "應用背景到全部",
@@ -747,6 +748,8 @@
   "ssAiChatQuickAction2": "為當前頁面內容生成1道問答題",
   "ssAiChatQuickAction2": "為當前頁面內容生成1道問答題",
   "ssAiChatQuickAction6": "為當前頁面生成投票",
   "ssAiChatQuickAction6": "為當前頁面生成投票",
   "ssAiChatQuickAction7": "為當前頁面生成拍照題",
   "ssAiChatQuickAction7": "為當前頁面生成拍照題",
+  "ssAiChatQuickAction8": "當前頁面生成配圖",
+  "ssAiChatQuickAction9": "為當前頁面內容生成文件上傳",
   "ssAiChatParsing": "解析中...",
   "ssAiChatParsing": "解析中...",
   "ssAiChatWaitUpload": "請等待文件上傳完成後再發送消息",
   "ssAiChatWaitUpload": "請等待文件上傳完成後再發送消息",
   "ssAiChatFileSizeLimit": "文件大小不能超過10MB",
   "ssAiChatFileSizeLimit": "文件大小不能超過10MB",
@@ -1090,7 +1093,36 @@
   "ssKwlWant": "W-想知",
   "ssKwlWant": "W-想知",
   "ssKwlLearned": "L-已學",
   "ssKwlLearned": "L-已學",
   "ssKwlReflection": "學習反思",
   "ssKwlReflection": "學習反思",
+  "ssSixHatTitle": "六頂思考帽",
+  "ssSixHatDesc": "透過六種不同思維角色(白帽-事實、紅帽-情感、黑帽-風險、黃帽-優點、綠帽-創意、藍帽-控制)進行全面思考",
+  "ssSixHatGradeRange": "初中-高中",
+  "ssSixHatUsageScenario": "使用場景",
+  "ssSixHatScenarioText": "學生獨立使用六頂思考帽從多角度分析問題",
+  "ssSixHatSteps": "操作步驟",
+  "ssSixHatStep1": "白帽思考:收集客觀事實和數據",
+  "ssSixHatStep2": "紅帽思考:表達直覺和情感反應",
+  "ssSixHatStep3": "黑帽思考:識別風險和潛在問題",
+  "ssSixHatStep4": "黃帽思考:尋找優點和積極面",
+  "ssSixHatStep5": "綠帽思考:提出創新想法和方案",
+  "ssSixHatStep6": "藍帽思考:總結思考過程和結論",
+  "ssSixHatSource": "來源:愛德華·德博諾(Edward de Bono)1985年提出的平行思維訓練法",
+  "ssSixHatPurpose": "目的:讓學生輪流從六種思維角色出發看待同一個問題,避免爭論式思維,進行更全面的分析",
+  "ssSixHatUserConfig": "工具內容由使用者配置",
+  "ssSixHatUserConfigDesc": "學生打開時會先自己設置,下方相關配置項由學生決定",
+  "ssSixHatGroupWork": "小組合作",
+  "ssSixHatGroupWorkDesc": "關閉則不顯示小組成員和負責人功能",
+  "ssSixHatShowTimer": "顯示計時器",
+  "ssSixHatTimerDuration": "計時時長",
+  "ssSixHatTimerSeconds": "秒",
+  "ssSixHatSelectHats": "思考帽選擇",
+  "ssSixHatWhite": "白帽·事實",
+  "ssSixHatRed": "紅帽·情感",
+  "ssSixHatBlack": "黑帽·風險",
+  "ssSixHatYellow": "黃帽·優點",
+  "ssSixHatGreen": "綠帽·創意",
+  "ssSixHatBlue": "藍帽·控制",
   "ssFile": "文件上傳",
   "ssFile": "文件上傳",
   "ssClickToPreview": "點擊預覽",
   "ssClickToPreview": "點擊預覽",
-  "ssClickToOpen": "點擊打開"
+  "ssClickToOpen": "點擊打開",
+  "ssAccuracy2": "正確率"
 }
 }

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