Kaynağa Gözat

vue初始化

[plg137200.] 1 yıl önce
ebeveyn
işleme
47d650ecf6

+ 2 - 0
vue/.env.development

@@ -0,0 +1,2 @@
+# mode development
+BASE_API = 'http://10.113.248.3:8666/'

+ 2 - 0
vue/.env.production

@@ -0,0 +1,2 @@
+# mode development
+BASE_API = 'https://dcbt.jue-ming.com:8666'

+ 29 - 0
vue/README.md

@@ -0,0 +1,29 @@
+# ctdweb
+
+This template should help get you started developing with Vue 3 in Vite.
+
+## Recommended IDE Setup
+
+[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
+
+## Customize configuration
+
+See [Vite Configuration Reference](https://vitejs.dev/config/).
+
+## Project Setup
+
+```sh
+npm install
+```
+
+### Compile and Hot-Reload for Development
+
+```sh
+npm run dev
+```
+
+### Compile and Minify for Production
+
+```sh
+npm run build
+```

+ 18 - 0
vue/index.html

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" href="/favicon_bak.ico" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>后台管理系统</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.js"></script>
+  </body>
+</html>
+<style>
+  body{
+    margin:0px;
+  }
+</style>

+ 2822 - 0
vue/package-lock.json

@@ -0,0 +1,2822 @@
+{
+  "name": "ctdweb",
+  "version": "0.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "ctdweb",
+      "version": "0.0.0",
+      "dependencies": {
+        "@element-plus/icons-vue": "^2.1.0",
+        "@wangeditor/editor": "^5.1.21",
+        "@wangeditor/editor-for-vue": "^5.1.12",
+        "axios": "^0.27.2",
+        "crypto-js": "^4.1.1",
+        "element-plus": "^2.2.16",
+        "jwchat": "^1.0.10",
+        "vue": "^3.2.38",
+        "vue-axios": "^3.4.1",
+        "vue-router": "^4.1.5"
+      },
+      "devDependencies": {
+        "@vitejs/plugin-vue": "^3.0.3",
+        "unplugin-auto-import": "^0.11.2",
+        "unplugin-vue-components": "^0.22.4",
+        "vite": "^3.0.9"
+      }
+    },
+    "node_modules/@ampproject/remapping": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.2.1.tgz",
+      "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@antfu/utils": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.2.tgz",
+      "integrity": "sha512-vy9fM3pIxZmX07dL+VX1aZe7ynZ+YyB0jY+jE6r3hOK6GNY2t6W8rzpFC4tgpbXUYABkFQwgJq2XYXlxbXAI0g==",
+      "dev": true
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.22.5.tgz",
+      "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
+      "peer": true,
+      "dependencies": {
+        "@babel/highlight": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.22.6",
+      "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.22.6.tgz",
+      "integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.22.8",
+      "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.22.8.tgz",
+      "integrity": "sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==",
+      "peer": true,
+      "dependencies": {
+        "@ampproject/remapping": "^2.2.0",
+        "@babel/code-frame": "^7.22.5",
+        "@babel/generator": "^7.22.7",
+        "@babel/helper-compilation-targets": "^7.22.6",
+        "@babel/helper-module-transforms": "^7.22.5",
+        "@babel/helpers": "^7.22.6",
+        "@babel/parser": "^7.22.7",
+        "@babel/template": "^7.22.5",
+        "@babel/traverse": "^7.22.8",
+        "@babel/types": "^7.22.5",
+        "@nicolo-ribaudo/semver-v6": "^6.3.3",
+        "convert-source-map": "^1.7.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.22.7",
+      "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.22.7.tgz",
+      "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==",
+      "peer": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5",
+        "@jridgewell/gen-mapping": "^0.3.2",
+        "@jridgewell/trace-mapping": "^0.3.17",
+        "jsesc": "^2.5.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.22.6",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz",
+      "integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/compat-data": "^7.22.6",
+        "@babel/helper-validator-option": "^7.22.5",
+        "@nicolo-ribaudo/semver-v6": "^6.3.3",
+        "browserslist": "^4.21.9",
+        "lru-cache": "^5.1.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-environment-visitor": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+      "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-function-name": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+      "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+      "peer": true,
+      "dependencies": {
+        "@babel/template": "^7.22.5",
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-hoist-variables": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+      "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
+      "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz",
+      "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-environment-visitor": "^7.22.5",
+        "@babel/helper-module-imports": "^7.22.5",
+        "@babel/helper-simple-access": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.5",
+        "@babel/helper-validator-identifier": "^7.22.5",
+        "@babel/template": "^7.22.5",
+        "@babel/traverse": "^7.22.5",
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-simple-access": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+      "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+      "peer": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-split-export-declaration": {
+      "version": "7.22.6",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+      "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+      "peer": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+      "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
+      "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
+      "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.22.6",
+      "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.22.6.tgz",
+      "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/template": "^7.22.5",
+        "@babel/traverse": "^7.22.6",
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/highlight": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.22.5.tgz",
+      "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.22.5",
+        "chalk": "^2.0.0",
+        "js-tokens": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.22.7",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.22.7.tgz",
+      "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/runtime": {
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
+      "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
+      "dependencies": {
+        "regenerator-runtime": "^0.13.11"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.22.5.tgz",
+      "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.22.5",
+        "@babel/parser": "^7.22.5",
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.22.8",
+      "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.22.8.tgz",
+      "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.22.5",
+        "@babel/generator": "^7.22.7",
+        "@babel/helper-environment-visitor": "^7.22.5",
+        "@babel/helper-function-name": "^7.22.5",
+        "@babel/helper-hoist-variables": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.6",
+        "@babel/parser": "^7.22.7",
+        "@babel/types": "^7.22.5",
+        "debug": "^4.1.0",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.22.5.tgz",
+      "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.22.5",
+        "@babel/helper-validator-identifier": "^7.22.5",
+        "to-fast-properties": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@better-scroll/core": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/@better-scroll/core/-/core-2.5.1.tgz",
+      "integrity": "sha512-koKOuYA55dQ04FJRIVUpMGDr1hbCfWmfX0MGp1hKagkQSWSRpwblqACiwtggVauoj9aaJRJZ9hDsTM4weaavlg==",
+      "dependencies": {
+        "@better-scroll/shared-utils": "^2.5.1"
+      }
+    },
+    "node_modules/@better-scroll/mouse-wheel": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/@better-scroll/mouse-wheel/-/mouse-wheel-2.5.1.tgz",
+      "integrity": "sha512-DGnrirRMY6zMM7xwgx09D/cA9A//3J1/uDkq8iBVEyE5p0sEr/keQpjEfFHGkBRa505BnbBwdbN6f5lugEDSPw==",
+      "dependencies": {
+        "@better-scroll/core": "^2.5.1"
+      }
+    },
+    "node_modules/@better-scroll/observe-dom": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/@better-scroll/observe-dom/-/observe-dom-2.5.1.tgz",
+      "integrity": "sha512-TCMGFLRfpXBPIwtUV/efliUmfmrhSNI7NXdSyjdWjsLOS7dh3eFkmcom5ERVWMaXVELSmujGXLqobT+dT0C/jg==",
+      "dependencies": {
+        "@better-scroll/core": "^2.5.1"
+      }
+    },
+    "node_modules/@better-scroll/observe-image": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/@better-scroll/observe-image/-/observe-image-2.5.1.tgz",
+      "integrity": "sha512-0Lhfj83o8EESwOxr8bfStCzNOokTm3KB7JeyMS8u/xl+3tyTuls9889cyAukYk4Yly1cS49pCGfj2P8YOiwtUg==",
+      "dependencies": {
+        "@better-scroll/core": "^2.5.1"
+      }
+    },
+    "node_modules/@better-scroll/pull-down": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/@better-scroll/pull-down/-/pull-down-2.5.1.tgz",
+      "integrity": "sha512-Y6XcGu2NlevPg3k9VBRRFvpmfoTA+rO96JGdog2qKHclIPNXnsVwsIHtZfAm9weE/f9UuC4BnB+VUFRlucfupg==",
+      "dependencies": {
+        "@better-scroll/core": "^2.5.1"
+      }
+    },
+    "node_modules/@better-scroll/scroll-bar": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/@better-scroll/scroll-bar/-/scroll-bar-2.5.1.tgz",
+      "integrity": "sha512-i6r60pWG/ztkFK2j5Gj54I0LJb2jGh5TWJNQBoW0gUkp28B+0JvBFTwZn9tF7beZCBorKR7Hvvu4O9A1TJy94Q==",
+      "dependencies": {
+        "@better-scroll/core": "^2.5.1"
+      }
+    },
+    "node_modules/@better-scroll/shared-utils": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/@better-scroll/shared-utils/-/shared-utils-2.5.1.tgz",
+      "integrity": "sha512-AplkfSjXVYP9LZiD6JsKgmgQJ/mG4uuLmBuwLz8W5OsYc7AYTfN8kw6GqZ5OwCGoXkVhBGyd8NeC4xwYItp0aw=="
+    },
+    "node_modules/@ctrl/tinycolor": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz",
+      "integrity": "sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@element-plus/icons-vue": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz",
+      "integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==",
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
+      "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
+      "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@floating-ui/core": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.6.tgz",
+      "integrity": "sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg=="
+    },
+    "node_modules/@floating-ui/dom": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.6.tgz",
+      "integrity": "sha512-02vxFDuvuVPs22iJICacezYJyf7zwwOCWkPNkWNBr1U0Qt1cKFYzWvxts0AmqcOQGwt/3KJWcWIgtbUU38keyw==",
+      "dependencies": {
+        "@floating-ui/core": "^1.2.6"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+      "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.15",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.18",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+      "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/resolve-uri": "3.1.0",
+        "@jridgewell/sourcemap-codec": "1.4.14"
+      }
+    },
+    "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.14",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+      "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+      "peer": true
+    },
+    "node_modules/@nicolo-ribaudo/semver-v6": {
+      "version": "6.3.3",
+      "resolved": "https://registry.npmmirror.com/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
+      "integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
+      "peer": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/@nodelib/fs.scandir": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.stat": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.walk": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@popperjs/core": {
+      "name": "@sxzz/popperjs-es",
+      "version": "2.11.7",
+      "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
+      "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
+    },
+    "node_modules/@rollup/pluginutils": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
+      "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "^1.0.0",
+        "estree-walker": "^2.0.2",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "peerDependencies": {
+        "rollup": "^1.20.0||^2.0.0||^3.0.0"
+      },
+      "peerDependenciesMeta": {
+        "rollup": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@transloadit/prettier-bytes": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz",
+      "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA=="
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
+      "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
+      "dev": true
+    },
+    "node_modules/@types/event-emitter": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.3.tgz",
+      "integrity": "sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q=="
+    },
+    "node_modules/@types/lodash": {
+      "version": "4.14.192",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.192.tgz",
+      "integrity": "sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A=="
+    },
+    "node_modules/@types/lodash-es": {
+      "version": "4.17.7",
+      "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.7.tgz",
+      "integrity": "sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==",
+      "dependencies": {
+        "@types/lodash": "*"
+      }
+    },
+    "node_modules/@types/web-bluetooth": {
+      "version": "0.0.16",
+      "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
+      "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
+    },
+    "node_modules/@uppy/companion-client": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.2.2.tgz",
+      "integrity": "sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==",
+      "dependencies": {
+        "@uppy/utils": "^4.1.2",
+        "namespace-emitter": "^2.0.1"
+      }
+    },
+    "node_modules/@uppy/core": {
+      "version": "2.3.4",
+      "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.3.4.tgz",
+      "integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==",
+      "dependencies": {
+        "@transloadit/prettier-bytes": "0.0.7",
+        "@uppy/store-default": "^2.1.1",
+        "@uppy/utils": "^4.1.3",
+        "lodash.throttle": "^4.1.1",
+        "mime-match": "^1.0.2",
+        "namespace-emitter": "^2.0.1",
+        "nanoid": "^3.1.25",
+        "preact": "^10.5.13"
+      }
+    },
+    "node_modules/@uppy/store-default": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.1.tgz",
+      "integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ=="
+    },
+    "node_modules/@uppy/utils": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.3.tgz",
+      "integrity": "sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==",
+      "dependencies": {
+        "lodash.throttle": "^4.1.1"
+      }
+    },
+    "node_modules/@uppy/xhr-upload": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz",
+      "integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==",
+      "dependencies": {
+        "@uppy/companion-client": "^2.2.2",
+        "@uppy/utils": "^4.1.2",
+        "nanoid": "^3.1.25"
+      },
+      "peerDependencies": {
+        "@uppy/core": "^2.3.3"
+      }
+    },
+    "node_modules/@vitejs/plugin-vue": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-3.2.0.tgz",
+      "integrity": "sha512-E0tnaL4fr+qkdCNxJ+Xd0yM31UwMkQje76fsDVBBUCoGOUPexu2VDUYHL8P4CwV+zMvWw6nlRw19OnRKmYAJpw==",
+      "dev": true,
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "vite": "^3.0.0",
+        "vue": "^3.2.25"
+      }
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz",
+      "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==",
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/shared": "3.2.47",
+        "estree-walker": "^2.0.2",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz",
+      "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==",
+      "dependencies": {
+        "@vue/compiler-core": "3.2.47",
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "2.7.14",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.14.tgz",
+      "integrity": "sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==",
+      "dependencies": {
+        "@babel/parser": "^7.18.4",
+        "postcss": "^8.4.14",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz",
+      "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==",
+      "dependencies": {
+        "@vue/compiler-dom": "3.2.47",
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "node_modules/@vue/devtools-api": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz",
+      "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.47.tgz",
+      "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==",
+      "dependencies": {
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "node_modules/@vue/reactivity-transform": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz",
+      "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==",
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.47",
+        "@vue/shared": "3.2.47",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.47.tgz",
+      "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==",
+      "dependencies": {
+        "@vue/reactivity": "3.2.47",
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz",
+      "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==",
+      "dependencies": {
+        "@vue/runtime-core": "3.2.47",
+        "@vue/shared": "3.2.47",
+        "csstype": "^2.6.8"
+      }
+    },
+    "node_modules/@vue/runtime-dom/node_modules/csstype": {
+      "version": "2.6.21",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
+      "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.47.tgz",
+      "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.2.47",
+        "@vue/shared": "3.2.47"
+      },
+      "peerDependencies": {
+        "vue": "3.2.47"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz",
+      "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ=="
+    },
+    "node_modules/@vueuse/core": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz",
+      "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
+      "dependencies": {
+        "@types/web-bluetooth": "^0.0.16",
+        "@vueuse/metadata": "9.13.0",
+        "@vueuse/shared": "9.13.0",
+        "vue-demi": "*"
+      }
+    },
+    "node_modules/@vueuse/metadata": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz",
+      "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ=="
+    },
+    "node_modules/@vueuse/shared": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz",
+      "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
+      "dependencies": {
+        "vue-demi": "*"
+      }
+    },
+    "node_modules/@wangeditor/basic-modules": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz",
+      "integrity": "sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==",
+      "dependencies": {
+        "is-url": "^1.2.4"
+      },
+      "peerDependencies": {
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "lodash.throttle": "^4.1.1",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/code-highlight": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz",
+      "integrity": "sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==",
+      "dependencies": {
+        "prismjs": "^1.23.0"
+      },
+      "peerDependencies": {
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/core": {
+      "version": "1.1.19",
+      "resolved": "https://registry.npmjs.org/@wangeditor/core/-/core-1.1.19.tgz",
+      "integrity": "sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==",
+      "dependencies": {
+        "@types/event-emitter": "^0.3.3",
+        "event-emitter": "^0.3.5",
+        "html-void-elements": "^2.0.0",
+        "i18next": "^20.4.0",
+        "scroll-into-view-if-needed": "^2.2.28",
+        "slate-history": "^0.66.0"
+      },
+      "peerDependencies": {
+        "@uppy/core": "^2.1.1",
+        "@uppy/xhr-upload": "^2.0.3",
+        "dom7": "^3.0.0",
+        "is-hotkey": "^0.2.0",
+        "lodash.camelcase": "^4.3.0",
+        "lodash.clonedeep": "^4.5.0",
+        "lodash.debounce": "^4.0.8",
+        "lodash.foreach": "^4.5.0",
+        "lodash.isequal": "^4.5.0",
+        "lodash.throttle": "^4.1.1",
+        "lodash.toarray": "^4.4.0",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/editor": {
+      "version": "5.1.23",
+      "resolved": "https://registry.npmjs.org/@wangeditor/editor/-/editor-5.1.23.tgz",
+      "integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==",
+      "dependencies": {
+        "@uppy/core": "^2.1.1",
+        "@uppy/xhr-upload": "^2.0.3",
+        "@wangeditor/basic-modules": "^1.1.7",
+        "@wangeditor/code-highlight": "^1.0.3",
+        "@wangeditor/core": "^1.1.19",
+        "@wangeditor/list-module": "^1.0.5",
+        "@wangeditor/table-module": "^1.1.4",
+        "@wangeditor/upload-image-module": "^1.0.2",
+        "@wangeditor/video-module": "^1.1.4",
+        "dom7": "^3.0.0",
+        "is-hotkey": "^0.2.0",
+        "lodash.camelcase": "^4.3.0",
+        "lodash.clonedeep": "^4.5.0",
+        "lodash.debounce": "^4.0.8",
+        "lodash.foreach": "^4.5.0",
+        "lodash.isequal": "^4.5.0",
+        "lodash.throttle": "^4.1.1",
+        "lodash.toarray": "^4.4.0",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/editor-for-vue": {
+      "version": "5.1.12",
+      "resolved": "https://registry.npmjs.org/@wangeditor/editor-for-vue/-/editor-for-vue-5.1.12.tgz",
+      "integrity": "sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==",
+      "peerDependencies": {
+        "@wangeditor/editor": ">=5.1.0",
+        "vue": "^3.0.5"
+      }
+    },
+    "node_modules/@wangeditor/list-module": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.5.tgz",
+      "integrity": "sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==",
+      "peerDependencies": {
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/table-module": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@wangeditor/table-module/-/table-module-1.1.4.tgz",
+      "integrity": "sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==",
+      "peerDependencies": {
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "lodash.isequal": "^4.5.0",
+        "lodash.throttle": "^4.1.1",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/upload-image-module": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz",
+      "integrity": "sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==",
+      "peerDependencies": {
+        "@uppy/core": "^2.0.3",
+        "@uppy/xhr-upload": "^2.0.3",
+        "@wangeditor/basic-modules": "1.x",
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "lodash.foreach": "^4.5.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/video-module": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@wangeditor/video-module/-/video-module-1.1.4.tgz",
+      "integrity": "sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==",
+      "peerDependencies": {
+        "@uppy/core": "^2.1.4",
+        "@uppy/xhr-upload": "^2.0.7",
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.8.2",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
+      "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+      "dev": true,
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "peer": true,
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "dev": true,
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/async-validator": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
+      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+    },
+    "node_modules/axios": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+      "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+      "dependencies": {
+        "follow-redirects": "^1.14.9",
+        "form-data": "^4.0.0"
+      }
+    },
+    "node_modules/babel-core": {
+      "version": "7.0.0-bridge.0",
+      "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
+      "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==",
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/babel-helper-vue-jsx-merge-props": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+      "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
+    },
+    "node_modules/babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+      "dependencies": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      }
+    },
+    "node_modules/babel-runtime/node_modules/regenerator-runtime": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "node_modules/binary-extensions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dev": true,
+      "dependencies": {
+        "fill-range": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.21.9",
+      "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.9.tgz",
+      "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
+      "peer": true,
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001503",
+        "electron-to-chromium": "^1.4.431",
+        "node-releases": "^2.0.12",
+        "update-browserslist-db": "^1.0.11"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001515",
+      "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001515.tgz",
+      "integrity": "sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==",
+      "peer": true
+    },
+    "node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "peer": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/chalk/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "3.5.3",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+      "dev": true,
+      "dependencies": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.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"
+      },
+      "engines": {
+        "node": ">= 8.10.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "peer": true,
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "peer": true
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/compute-scroll-into-view": {
+      "version": "1.0.20",
+      "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz",
+      "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg=="
+    },
+    "node_modules/convert-source-map": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.9.0.tgz",
+      "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+      "peer": true
+    },
+    "node_modules/core-js": {
+      "version": "2.6.12",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+      "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+      "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+      "hasInstallScript": true
+    },
+    "node_modules/crypto-js": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
+      "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
+    },
+    "node_modules/csstype": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+      "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+    },
+    "node_modules/d": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+      "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+      "dependencies": {
+        "es5-ext": "^0.10.50",
+        "type": "^1.0.1"
+      }
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.7",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
+      "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ=="
+    },
+    "node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/deepmerge": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz",
+      "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/dom7": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz",
+      "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==",
+      "dependencies": {
+        "ssr-window": "^3.0.0-alpha.1"
+      }
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.4.457",
+      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.457.tgz",
+      "integrity": "sha512-/g3UyNDmDd6ebeWapmAoiyy+Sy2HyJ+/X8KyvNeHfKRFfHaA2W8oF5fxD5F3tjBDcjpwo0iek6YNgxNXDBoEtA==",
+      "peer": true
+    },
+    "node_modules/element-plus": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.3.3.tgz",
+      "integrity": "sha512-Zy61OXrG6b4FF3h29A9ZOUkaEQXjCuFwNa7DlpB3Vo+42Tw5zBbHe5a4BY7i56TVJG5xTbS9UQyA726J91pDqg==",
+      "dependencies": {
+        "@ctrl/tinycolor": "^3.4.1",
+        "@element-plus/icons-vue": "^2.0.6",
+        "@floating-ui/dom": "^1.0.1",
+        "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
+        "@types/lodash": "^4.14.182",
+        "@types/lodash-es": "^4.17.6",
+        "@vueuse/core": "^9.1.0",
+        "async-validator": "^4.2.5",
+        "dayjs": "^1.11.3",
+        "escape-html": "^1.0.3",
+        "lodash": "^4.17.21",
+        "lodash-es": "^4.17.21",
+        "lodash-unified": "^1.0.2",
+        "memoize-one": "^6.0.0",
+        "normalize-wheel-es": "^1.2.0"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/element-ui": {
+      "version": "2.15.13",
+      "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.13.tgz",
+      "integrity": "sha512-LJoatEYX6WV74FqXBss8Xfho9fh9rjDSzrDrTyREdGb1h1R3uRvmLh5jqp2JU137aj4/BgqA3K06RQpQBX33Bg==",
+      "dependencies": {
+        "async-validator": "~1.8.1",
+        "babel-helper-vue-jsx-merge-props": "^2.0.0",
+        "deepmerge": "^1.2.0",
+        "normalize-wheel": "^1.0.1",
+        "resize-observer-polyfill": "^1.5.0",
+        "throttle-debounce": "^1.0.1"
+      },
+      "peerDependencies": {
+        "vue": "^2.5.17"
+      }
+    },
+    "node_modules/element-ui/node_modules/async-validator": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz",
+      "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
+      "dependencies": {
+        "babel-runtime": "6.x"
+      }
+    },
+    "node_modules/es5-ext": {
+      "version": "0.10.62",
+      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
+      "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
+      "hasInstallScript": true,
+      "dependencies": {
+        "es6-iterator": "^2.0.3",
+        "es6-symbol": "^3.1.3",
+        "next-tick": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/es6-iterator": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+      "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+      "dependencies": {
+        "d": "1",
+        "es5-ext": "^0.10.35",
+        "es6-symbol": "^3.1.1"
+      }
+    },
+    "node_modules/es6-symbol": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
+      "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
+      "dependencies": {
+        "d": "^1.0.1",
+        "ext": "^1.1.2"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
+      "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
+      "dev": true,
+      "hasInstallScript": true,
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/android-arm": "0.15.18",
+        "@esbuild/linux-loong64": "0.15.18",
+        "esbuild-android-64": "0.15.18",
+        "esbuild-android-arm64": "0.15.18",
+        "esbuild-darwin-64": "0.15.18",
+        "esbuild-darwin-arm64": "0.15.18",
+        "esbuild-freebsd-64": "0.15.18",
+        "esbuild-freebsd-arm64": "0.15.18",
+        "esbuild-linux-32": "0.15.18",
+        "esbuild-linux-64": "0.15.18",
+        "esbuild-linux-arm": "0.15.18",
+        "esbuild-linux-arm64": "0.15.18",
+        "esbuild-linux-mips64le": "0.15.18",
+        "esbuild-linux-ppc64le": "0.15.18",
+        "esbuild-linux-riscv64": "0.15.18",
+        "esbuild-linux-s390x": "0.15.18",
+        "esbuild-netbsd-64": "0.15.18",
+        "esbuild-openbsd-64": "0.15.18",
+        "esbuild-sunos-64": "0.15.18",
+        "esbuild-windows-32": "0.15.18",
+        "esbuild-windows-64": "0.15.18",
+        "esbuild-windows-arm64": "0.15.18"
+      }
+    },
+    "node_modules/esbuild-android-64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
+      "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-android-arm64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
+      "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-darwin-64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
+      "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-darwin-arm64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
+      "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-freebsd-64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
+      "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-freebsd-arm64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
+      "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-linux-32": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
+      "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-linux-64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
+      "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-linux-arm": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
+      "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-linux-arm64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
+      "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-linux-mips64le": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
+      "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-linux-ppc64le": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
+      "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-linux-riscv64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
+      "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-linux-s390x": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
+      "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-netbsd-64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
+      "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-openbsd-64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
+      "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-sunos-64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
+      "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-windows-32": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
+      "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-windows-64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
+      "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/esbuild-windows-arm64": {
+      "version": "0.15.18",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
+      "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/escalade": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz",
+      "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+      "peer": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+      "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+    },
+    "node_modules/event-emitter": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+      "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
+      "dependencies": {
+        "d": "1",
+        "es5-ext": "~0.10.14"
+      }
+    },
+    "node_modules/ext": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
+      "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
+      "dependencies": {
+        "type": "^2.7.2"
+      }
+    },
+    "node_modules/ext/node_modules/type": {
+      "version": "2.7.2",
+      "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
+      "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
+    },
+    "node_modules/fast-glob": {
+      "version": "3.2.12",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+      "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+      "dev": true,
+      "dependencies": {
+        "@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"
+      },
+      "engines": {
+        "node": ">=8.6.0"
+      }
+    },
+    "node_modules/fastq": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+      "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+      "dev": true,
+      "dependencies": {
+        "reusify": "^1.0.4"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "dev": true,
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/follow-redirects": {
+      "version": "1.15.2",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+      "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dev": true,
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/globals": {
+      "version": "11.12.0",
+      "resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "peer": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "peer": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/html-void-elements": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
+      "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A=="
+    },
+    "node_modules/i18next": {
+      "version": "20.6.1",
+      "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz",
+      "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==",
+      "dependencies": {
+        "@babel/runtime": "^7.12.0"
+      }
+    },
+    "node_modules/immer": {
+      "version": "9.0.21",
+      "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
+      "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA=="
+    },
+    "node_modules/is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "dev": true,
+      "dependencies": {
+        "binary-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.12.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz",
+      "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==",
+      "dev": true,
+      "dependencies": {
+        "has": "^1.0.3"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-hotkey": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz",
+      "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw=="
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/is-plain-object": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
+      "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-url": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
+      "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "peer": true
+    },
+    "node_modules/jsesc": {
+      "version": "2.5.2",
+      "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz",
+      "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+      "peer": true,
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "peer": true,
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsonc-parser": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
+      "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
+      "dev": true
+    },
+    "node_modules/jwchat": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/jwchat/-/jwchat-1.0.12.tgz",
+      "integrity": "sha512-PqdzjqaARD01u9RjkjUVb/q4gSV2teKNbAYHiBJ93gfo14q2R/7qJCkldzw6qK+hUmmNNpjwCQFl2Dyjbjkhug==",
+      "dependencies": {
+        "@better-scroll/core": "^2.4.2",
+        "@better-scroll/mouse-wheel": "^2.4.2",
+        "@better-scroll/observe-dom": "^2.4.2",
+        "@better-scroll/observe-image": "^2.4.2",
+        "@better-scroll/pull-down": "^2.4.2",
+        "@better-scroll/scroll-bar": "^2.4.2",
+        "async-validator": "1.11.5",
+        "babel-core": "7.0.0-bridge.0",
+        "element-ui": "^2.13.1",
+        "vue": "^2.6.11",
+        "wechat-emoji-parser": "^1.1.0"
+      }
+    },
+    "node_modules/jwchat/node_modules/async-validator": {
+      "version": "1.11.5",
+      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.11.5.tgz",
+      "integrity": "sha512-XNtCsMAeAH1pdLMEg1z8/Bb3a8cdCbui9QbJATRFHHHW5kT6+NPI3zSVQUXgikTFITzsg+kYY5NTWhM2Orwt9w=="
+    },
+    "node_modules/jwchat/node_modules/vue": {
+      "version": "2.7.14",
+      "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.14.tgz",
+      "integrity": "sha512-b2qkFyOM0kwqWFuQmgd4o+uHGU7T+2z3T+WQp8UBjADfEv2n4FEMffzBmCKNP0IGzOEEfYjvtcC62xaSKeQDrQ==",
+      "dependencies": {
+        "@vue/compiler-sfc": "2.7.14",
+        "csstype": "^3.1.0"
+      }
+    },
+    "node_modules/local-pkg": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz",
+      "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
+      "dev": true,
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
+    "node_modules/lodash-es": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+    },
+    "node_modules/lodash-unified": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz",
+      "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
+      "peerDependencies": {
+        "@types/lodash-es": "*",
+        "lodash": "*",
+        "lodash-es": "*"
+      }
+    },
+    "node_modules/lodash.camelcase": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+      "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
+    },
+    "node_modules/lodash.clonedeep": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+      "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
+    },
+    "node_modules/lodash.debounce": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
+    },
+    "node_modules/lodash.foreach": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
+      "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ=="
+    },
+    "node_modules/lodash.isequal": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+      "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
+    },
+    "node_modules/lodash.throttle": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+      "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
+    },
+    "node_modules/lodash.toarray": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
+      "integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw=="
+    },
+    "node_modules/lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "peer": true,
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
+      "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
+      "dependencies": {
+        "sourcemap-codec": "^1.4.8"
+      }
+    },
+    "node_modules/memoize-one": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
+      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
+    },
+    "node_modules/merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+      "dev": true,
+      "dependencies": {
+        "braces": "^3.0.2",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz",
+      "integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==",
+      "dependencies": {
+        "wildcard": "^1.1.0"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "5.1.6",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+      "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/mlly": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.2.0.tgz",
+      "integrity": "sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==",
+      "dev": true,
+      "dependencies": {
+        "acorn": "^8.8.2",
+        "pathe": "^1.1.0",
+        "pkg-types": "^1.0.2",
+        "ufo": "^1.1.1"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+    },
+    "node_modules/namespace-emitter": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz",
+      "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g=="
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+      "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/next-tick": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
+      "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.13",
+      "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.13.tgz",
+      "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
+      "peer": true
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/normalize-wheel": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
+      "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA=="
+    },
+    "node_modules/normalize-wheel-es": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
+      "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "node_modules/pathe": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz",
+      "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==",
+      "dev": true
+    },
+    "node_modules/picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/pkg-types": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.2.tgz",
+      "integrity": "sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==",
+      "dev": true,
+      "dependencies": {
+        "jsonc-parser": "^3.2.0",
+        "mlly": "^1.1.1",
+        "pathe": "^1.1.0"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.4.21",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
+      "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
+      "dependencies": {
+        "nanoid": "^3.3.4",
+        "picocolors": "^1.0.0",
+        "source-map-js": "^1.0.2"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/preact": {
+      "version": "10.13.2",
+      "resolved": "https://registry.npmjs.org/preact/-/preact-10.13.2.tgz",
+      "integrity": "sha512-q44QFLhOhty2Bd0Y46fnYW0gD/cbVM9dUVtNTDKPcdXSMA7jfY+Jpd6rk3GB0lcQss0z5s/6CmVP0Z/hV+g6pw=="
+    },
+    "node_modules/prismjs": {
+      "version": "1.29.0",
+      "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
+      "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true
+    },
+    "node_modules/readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "dev": true,
+      "dependencies": {
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/regenerator-runtime": {
+      "version": "0.13.11",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+      "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+    },
+    "node_modules/resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+    },
+    "node_modules/resolve": {
+      "version": "1.22.2",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
+      "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.11.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      }
+    },
+    "node_modules/reusify": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+      "dev": true,
+      "engines": {
+        "iojs": ">=1.0.0",
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/rollup": {
+      "version": "2.79.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+      "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+      "dev": true,
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "dev": true,
+      "dependencies": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
+    "node_modules/scroll-into-view-if-needed": {
+      "version": "2.2.31",
+      "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
+      "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==",
+      "dependencies": {
+        "compute-scroll-into-view": "^1.0.20"
+      }
+    },
+    "node_modules/scule": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/scule/-/scule-1.0.0.tgz",
+      "integrity": "sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==",
+      "dev": true
+    },
+    "node_modules/slate": {
+      "version": "0.72.8",
+      "resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz",
+      "integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==",
+      "dependencies": {
+        "immer": "^9.0.6",
+        "is-plain-object": "^5.0.0",
+        "tiny-warning": "^1.0.3"
+      }
+    },
+    "node_modules/slate-history": {
+      "version": "0.66.0",
+      "resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz",
+      "integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==",
+      "dependencies": {
+        "is-plain-object": "^5.0.0"
+      },
+      "peerDependencies": {
+        "slate": ">=0.65.3"
+      }
+    },
+    "node_modules/snabbdom": {
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.1.tgz",
+      "integrity": "sha512-wHMNIOjkm/YNE5EM3RCbr/+DVgPg6AqQAX1eOxO46zYNvCXjKP5Y865tqQj3EXnaMBjkxmQA5jFuDpDK/dbfiA==",
+      "engines": {
+        "node": ">=8.3.0"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/sourcemap-codec": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+      "deprecated": "Please use @jridgewell/sourcemap-codec instead"
+    },
+    "node_modules/ssr-window": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz",
+      "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA=="
+    },
+    "node_modules/strip-literal": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz",
+      "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==",
+      "dev": true,
+      "dependencies": {
+        "acorn": "^8.8.2"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "peer": true,
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/throttle-debounce": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
+      "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tiny-warning": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+      "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+    },
+    "node_modules/to-fast-properties": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+      "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+      "peer": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/type": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+      "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
+    },
+    "node_modules/ufo": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.1.tgz",
+      "integrity": "sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==",
+      "dev": true
+    },
+    "node_modules/unimport": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/unimport/-/unimport-1.3.0.tgz",
+      "integrity": "sha512-fOkrdxglsHd428yegH0wPH/6IfaSdDeMXtdRGn6en/ccyzc2aaoxiUTMrJyc6Bu+xoa18RJRPMfLUHEzjz8atw==",
+      "dev": true,
+      "dependencies": {
+        "@rollup/pluginutils": "^5.0.2",
+        "escape-string-regexp": "^5.0.0",
+        "fast-glob": "^3.2.12",
+        "local-pkg": "^0.4.3",
+        "magic-string": "^0.27.0",
+        "mlly": "^1.1.0",
+        "pathe": "^1.0.0",
+        "pkg-types": "^1.0.1",
+        "scule": "^1.0.0",
+        "strip-literal": "^1.0.0",
+        "unplugin": "^1.0.1"
+      }
+    },
+    "node_modules/unimport/node_modules/magic-string": {
+      "version": "0.27.0",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz",
+      "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.4.13"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/unplugin": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.3.1.tgz",
+      "integrity": "sha512-h4uUTIvFBQRxUKS2Wjys6ivoeofGhxzTe2sRWlooyjHXVttcVfV/JiavNd3d4+jty0SVV0dxGw9AkY9MwiaCEw==",
+      "dev": true,
+      "dependencies": {
+        "acorn": "^8.8.2",
+        "chokidar": "^3.5.3",
+        "webpack-sources": "^3.2.3",
+        "webpack-virtual-modules": "^0.5.0"
+      }
+    },
+    "node_modules/unplugin-auto-import": {
+      "version": "0.11.5",
+      "resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.11.5.tgz",
+      "integrity": "sha512-nvbL2AQwLRR8wbHpJ6L1EBVNmjN045RSedTa4NtsGRkSQFXkI1iKHs4dTqJwcKZsnFrZOAKtLPiN1/oQTObLZw==",
+      "dev": true,
+      "dependencies": {
+        "@antfu/utils": "^0.7.0",
+        "@rollup/pluginutils": "^5.0.2",
+        "local-pkg": "^0.4.2",
+        "magic-string": "^0.26.7",
+        "unimport": "^1.0.1",
+        "unplugin": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "peerDependencies": {
+        "@vueuse/core": "*"
+      },
+      "peerDependenciesMeta": {
+        "@vueuse/core": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/unplugin-auto-import/node_modules/magic-string": {
+      "version": "0.26.7",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz",
+      "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==",
+      "dev": true,
+      "dependencies": {
+        "sourcemap-codec": "^1.4.8"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/unplugin-vue-components": {
+      "version": "0.22.12",
+      "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.22.12.tgz",
+      "integrity": "sha512-FxyzsuBvMCYPIk+8cgscGBQ345tvwVu+qY5IhE++eorkyvA4Z1TiD/HCiim+Kbqozl10i4K+z+NCa2WO2jexRA==",
+      "dev": true,
+      "dependencies": {
+        "@antfu/utils": "^0.7.2",
+        "@rollup/pluginutils": "^5.0.2",
+        "chokidar": "^3.5.3",
+        "debug": "^4.3.4",
+        "fast-glob": "^3.2.12",
+        "local-pkg": "^0.4.2",
+        "magic-string": "^0.27.0",
+        "minimatch": "^5.1.1",
+        "resolve": "^1.22.1",
+        "unplugin": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "peerDependencies": {
+        "@babel/parser": "^7.15.8",
+        "vue": "2 || 3"
+      },
+      "peerDependenciesMeta": {
+        "@babel/parser": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/unplugin-vue-components/node_modules/magic-string": {
+      "version": "0.27.0",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz",
+      "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.4.13"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
+      "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
+      "peer": true,
+      "dependencies": {
+        "escalade": "^3.1.1",
+        "picocolors": "^1.0.0"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/vite": {
+      "version": "3.2.5",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz",
+      "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==",
+      "dev": true,
+      "dependencies": {
+        "esbuild": "^0.15.9",
+        "postcss": "^8.4.18",
+        "resolve": "^1.22.1",
+        "rollup": "^2.79.1"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      },
+      "peerDependencies": {
+        "@types/node": ">= 14",
+        "less": "*",
+        "sass": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.4.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.47.tgz",
+      "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==",
+      "dependencies": {
+        "@vue/compiler-dom": "3.2.47",
+        "@vue/compiler-sfc": "3.2.47",
+        "@vue/runtime-dom": "3.2.47",
+        "@vue/server-renderer": "3.2.47",
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "node_modules/vue-axios": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/vue-axios/-/vue-axios-3.5.2.tgz",
+      "integrity": "sha512-GP+dct7UlAWkl1qoP3ppw0z6jcSua5/IrMpjB5O8bh089iIiJ+hdxPYH2NPEpajlYgkW5EVMP95ttXWdas1O0g==",
+      "peerDependencies": {
+        "axios": "*",
+        "vue": "^3.0.0 || ^2.0.0"
+      }
+    },
+    "node_modules/vue-demi": {
+      "version": "0.13.11",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
+      "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
+      "hasInstallScript": true,
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-router": {
+      "version": "4.1.6",
+      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz",
+      "integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==",
+      "dependencies": {
+        "@vue/devtools-api": "^6.4.5"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/vue/node_modules/@vue/compiler-sfc": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz",
+      "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==",
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.47",
+        "@vue/compiler-dom": "3.2.47",
+        "@vue/compiler-ssr": "3.2.47",
+        "@vue/reactivity-transform": "3.2.47",
+        "@vue/shared": "3.2.47",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7",
+        "postcss": "^8.1.10",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/webpack-sources": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
+      "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+      "dev": true,
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/webpack-virtual-modules": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz",
+      "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==",
+      "dev": true
+    },
+    "node_modules/wechat-emoji-parser": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/wechat-emoji-parser/-/wechat-emoji-parser-1.1.1.tgz",
+      "integrity": "sha512-FOB3KIhyEYmYledm/gnyHitL+sq1SGvDPpUE1AYxougmcd1/ibGHld/J+GDC+8DtgxsmGpY5f30gTFX0zwtTJQ=="
+    },
+    "node_modules/wildcard": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz",
+      "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng=="
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "peer": true
+    }
+  }
+}

+ 27 - 0
vue/package.json

@@ -0,0 +1,27 @@
+{
+  "name": "ctdweb",
+  "version": "0.0.0",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build",
+    "preview": "vite preview --port 4173"
+  },
+  "dependencies": {
+    "@element-plus/icons-vue": "^2.1.0",
+    "@wangeditor/editor": "^5.1.21",
+    "@wangeditor/editor-for-vue": "^5.1.12",
+    "axios": "^0.27.2",
+    "crypto-js": "^4.1.1",
+    "element-plus": "^2.2.16",
+    "jwchat": "^1.0.10",
+    "vue": "^3.2.38",
+    "vue-axios": "^3.4.1",
+    "vue-router": "^4.1.5"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^3.0.3",
+    "unplugin-auto-import": "^0.11.2",
+    "unplugin-vue-components": "^0.22.4",
+    "vite": "^3.0.9"
+  }
+}

BIN
vue/public/favicon_bak.ico


+ 10 - 0
vue/src/App.vue

@@ -0,0 +1,10 @@
+<script setup>
+</script>
+
+<template>
+    <div>
+        <router-view></router-view>
+    </div>
+</template>
+
+<style scoped></style>

BIN
vue/src/assets/back.png


+ 74 - 0
vue/src/assets/base.css

@@ -0,0 +1,74 @@
+/* color palette from <https://github.com/vuejs/theme> */
+:root {
+  --vt-c-white: #ffffff;
+  --vt-c-white-soft: #f8f8f8;
+  --vt-c-white-mute: #f2f2f2;
+
+  --vt-c-black: #181818;
+  --vt-c-black-soft: #222222;
+  --vt-c-black-mute: #282828;
+
+  --vt-c-indigo: #2c3e50;
+
+  --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
+  --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
+  --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
+  --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
+
+  --vt-c-text-light-1: var(--vt-c-indigo);
+  --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
+  --vt-c-text-dark-1: var(--vt-c-white);
+  --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
+}
+
+/* semantic color variables for this project */
+:root {
+  --color-background: var(--vt-c-white);
+  --color-background-soft: var(--vt-c-white-soft);
+  --color-background-mute: var(--vt-c-white-mute);
+
+  --color-border: var(--vt-c-divider-light-2);
+  --color-border-hover: var(--vt-c-divider-light-1);
+
+  --color-heading: var(--vt-c-text-light-1);
+  --color-text: var(--vt-c-text-light-1);
+
+  --section-gap: 160px;
+}
+
+@media (prefers-color-scheme: dark) {
+  :root {
+    --color-background: var(--vt-c-black);
+    --color-background-soft: var(--vt-c-black-soft);
+    --color-background-mute: var(--vt-c-black-mute);
+
+    --color-border: var(--vt-c-divider-dark-2);
+    --color-border-hover: var(--vt-c-divider-dark-1);
+
+    --color-heading: var(--vt-c-text-dark-1);
+    --color-text: var(--vt-c-text-dark-2);
+  }
+}
+
+*,
+*::before,
+*::after {
+  box-sizing: border-box;
+  margin: 0;
+  position: relative;
+  font-weight: normal;
+}
+
+body {
+  min-height: 100vh;
+  color: var(--color-text);
+  background: var(--color-background);
+  transition: color 0.5s, background-color 0.5s;
+  line-height: 1.6;
+  font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
+    Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+  font-size: 15px;
+  text-rendering: optimizeLegibility;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}

BIN
vue/src/assets/beian.png


BIN
vue/src/assets/login/login_banner.png


+ 1 - 0
vue/src/assets/logo.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"  xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

+ 35 - 0
vue/src/assets/main.css

@@ -0,0 +1,35 @@
+@import "./base.css";
+
+#app {
+  max-width: 1280px;
+  margin: 0 auto;
+  padding: 2rem;
+
+  font-weight: normal;
+}
+
+a,
+.green {
+  text-decoration: none;
+  color: hsla(160, 100%, 37%, 1);
+  transition: 0.4s;
+}
+
+@media (hover: hover) {
+  a:hover {
+    background-color: hsla(160, 100%, 37%, 0.2);
+  }
+}
+
+@media (min-width: 1024px) {
+  body {
+    display: flex;
+    place-items: center;
+  }
+
+  #app {
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+    padding: 0 2rem;
+  }
+}

BIN
vue/src/assets/wifi.png


+ 7 - 0
vue/src/components/icons/IconCommunity.vue

@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
+    <path
+      d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
+    />
+  </svg>
+</template>

+ 7 - 0
vue/src/components/icons/IconDocumentation.vue

@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
+    <path
+      d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
+    />
+  </svg>
+</template>

+ 7 - 0
vue/src/components/icons/IconEcosystem.vue

@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
+    <path
+      d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
+    />
+  </svg>
+</template>

+ 7 - 0
vue/src/components/icons/IconSupport.vue

@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
+    <path
+      d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
+    />
+  </svg>
+</template>

+ 19 - 0
vue/src/components/icons/IconTooling.vue

@@ -0,0 +1,19 @@
+<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
+<template>
+  <svg
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    aria-hidden="true"
+    role="img"
+    class="iconify iconify--mdi"
+    width="24"
+    height="24"
+    preserveAspectRatio="xMidYMid meet"
+    viewBox="0 0 24 24"
+  >
+    <path
+      d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
+      fill="currentColor"
+    ></path>
+  </svg>
+</template>

+ 22 - 0
vue/src/main.js

@@ -0,0 +1,22 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+
+import ElementPlus from 'element-plus'
+
+
+// import './assets/main.css'
+import 'element-plus/dist/index.css'
+import './style/public.css'
+import router from "./router";
+import JwChat from 'jwchat';
+import zhCn from 'element-plus/lib/locale/lang/zh-cn'
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
+const app = createApp(App)
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+    app.component(key, component)
+}
+app.use(ElementPlus, { locale: zhCn })
+app.use(router)
+app.use(JwChat)
+app.mount('#app')
+// createApp(App).use(ElementPlus).mount('#app')

+ 56 - 0
vue/src/router/index.js

@@ -0,0 +1,56 @@
+import { createRouter, createWebHistory } from "vue-router";
+const router = createRouter({
+    history: createWebHistory(),
+    routes: [
+        {
+            path: '/',
+            redirect: '/login'
+        },
+        {
+            path: '/main',
+            component: () => import('../views/HelloWorld.vue'),
+            children: [
+                {
+                    path: 'TreeHoleManage',
+                    component:() => import('../views/TreeHoleManage.vue')
+                },
+                {
+                    path: 'PsychologicalConsultation',
+                    component: () => import('../views/PsychologicalConsultation.vue')
+                },
+                {
+                    path: 'WangEditor',
+                    component: () => import('../views/WangEditor.vue')
+                },
+                {
+                    path: 'RecordList',
+                    component: () => import('../views/RecordList.vue')
+                },
+                {
+                    path: 'Audit',
+                    component: () => import('../views/Audit.vue')
+                },
+                {
+                    path: 'institutionManage',
+                    component: () => import('../views/institutionManage/index.vue')
+                },
+                {
+                    path: 'fileUpload',
+                    component: () => import('../views/FileUpload.vue')
+                },
+                {
+                    path: 'recordList',
+                    component: () => import('../views/RecordList.vue')
+                },
+            ]
+        },
+
+        {
+            path: '/login',
+            name: 'Login',
+            component: () => import('../views/user/login.vue'),
+        }
+
+    ]
+})
+export default router;

+ 36 - 0
vue/src/style/public.css

@@ -0,0 +1,36 @@
+a {
+    text-decoration: none;
+}
+
+li {
+    list-style: none;
+}
+
+.el-table th {
+    font-family: PingFang SC;
+    color: #101010;
+    background: #ecf7f9;
+}
+
+
+.el-table .el-table__cell {
+    padding: 12px 0;
+}
+
+:root {
+    --el-color-primary: #57acbb;
+    --el-color-primary-light-3: rgb(137, 197, 207);
+    --el-color-primary-dark-2: rgb(74, 142, 154);
+}
+
+.search-form {
+    margin-bottom: 16px;
+}
+
+.pagination-box {
+    width: 100%;
+    margin-top: 20px;
+    text-align: right;
+    display: flex;
+    justify-content: right;
+}

+ 6 - 0
vue/src/utils/config.js

@@ -0,0 +1,6 @@
+export default {
+    baseUrl: {
+        dev: '/api', //生产环境
+        pro: 'http://production.com' //生产环境
+    }
+}

+ 98 - 0
vue/src/utils/http.js

@@ -0,0 +1,98 @@
+import axios from 'axios'
+import config from '@/utils/config'
+import { ElMessage } from "element-plus";
+import router from '@/router'
+//使用到代理
+const _baseUrl = config.baseUrl.dev
+const apiUrl = _baseUrl
+
+//axios配置
+// 设置接口响应时间
+axios.defaults.timeout = 120000
+axios.defaults.baseURL = 'http://localhost:8000' //
+
+// axios.defaults.baseURL = 'http://10.113.248.3:8000' //
+// axios.defaults.baseURL = 'https://dcbt.jue-ming.com:8666' //
+// axios.defaults.baseURL = 'http://120.55.54.207:8666' //
+// axios.defaults.baseURL = '/api'
+axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
+
+axios.interceptors.request.use(function (config) {
+  config.headers.token = sessionStorage.getItem('token') ? `${sessionStorage.getItem('token')}` : '';
+  return config;
+}, function (error) {
+  // 对请求错误做些什么
+  return Promise.reject(error);
+});
+
+// 添加响应拦截器
+axios.interceptors.response.use(function (response) {
+
+  if (response.data.code == '401') {
+    ElMessage({
+      message: "登录信息已过期,请重新登录",
+      type: "warning",
+    });
+    setTimeout(() => {
+      router.push("/login")
+  }, 500)
+  } else {
+    return response;
+  }
+}, function (error) {
+  return Promise.reject(error);
+});
+
+export default {
+  post(url, data) {
+    return new Promise((resolve, reject) => {
+      axios({
+        method: 'post',
+        url,
+        data: data,
+      })
+        .then(res => {
+          if(res.data.code == 200|| res.data.code==400) {
+            resolve(res.data)
+          } else {
+            reject(res.data)
+          }
+        })
+        .catch(err => {
+          reject(err)
+        });
+    })
+  },
+  get(url, data) {
+    return new Promise((resolve, reject) => {
+      axios({
+        method: 'get',
+        url,
+        params: data,
+      })
+        .then(res => {
+          resolve(res.data)
+        })
+        .catch(err => {
+          reject(err)
+        })
+    })
+  },
+  delete(url, data) {
+    return new Promise((resolve, reject) => {
+      axios({
+        method: 'delete',
+        url,
+        params: data,
+      })
+        .then(res => {
+          resolve(res.data)
+        })
+        .catch(err => {
+          reject(err)
+        })
+    })
+  }
+
+}
+

+ 171 - 0
vue/src/views/Audit.vue

@@ -0,0 +1,171 @@
+<template>
+  <el-table :data="tableData" border style="width: 100%">
+    <el-table-column prop="phone" label="电话" align="" />
+    <el-table-column prop="name" label="姓名" align="" />
+    <el-table-column prop="authority" label="状态" align="" :formatter="statusFun" />
+    <el-table-column fixed="right" label="操作" width="220">
+      <template #default="scope">
+        <el-button link type="primary" size="small" @click="detailPage(scope.row, 1)">通过审核</el-button>
+        <el-button link type="primary" size="small" @click="detailPage(scope.row, 2)">不通过审核</el-button>
+      </template>
+    </el-table-column>
+  </el-table>
+  <div class="demo-pagination-block">
+    <el-pagination style="justify-content: center" v-model:currentPage="currentPage" v-model:page-size="pageSize"
+      :page-sizes="[10, 20, 50, 100]" :small="small" :disabled="disabled" :background="background"
+      layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange"
+      @current-change="handleCurrentChange" />
+  </div>
+  <el-dialog v-model="centerDialogVisible" title="详细信息" width="60%" align-center>
+    <el-descriptions class="margin-top" title="" :column="2" :size="size" border>
+      <el-descriptions-item>
+        <template #label>
+          <div class="cell-item">
+            <el-icon :style="iconStyle">
+              <user />
+            </el-icon>
+            发作时间
+          </div>
+        </template>
+        {{ dataObj.doDate }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template #label>
+          <div class="cell-item">
+            <el-icon :style="iconStyle">
+              <iphone />
+            </el-icon>
+            发作类型
+          </div>
+        </template>
+        {{ dataObj.type }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template #label>
+          <div class="cell-item">
+            <el-icon :style="iconStyle">
+              <tickets />
+            </el-icon>
+            使用药物
+          </div>
+        </template>
+        {{ dataObj.drugs }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template #label>
+          <div class="cell-item">
+            <el-icon :style="iconStyle">
+              <tickets />
+            </el-icon>
+            发作诱因
+          </div>
+        </template>
+        {{ dataObj.incentive }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template #label>
+          <div class="cell-item">
+            <el-icon :style="iconStyle">
+              <tickets />
+            </el-icon>
+            联系电话
+          </div>
+        </template>
+        {{ dataObj.phone }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template #label>
+          <div class="cell-item">
+            <el-icon :style="iconStyle">
+              <tickets />
+            </el-icon>
+            备注
+          </div>
+        </template>
+        {{ dataObj.note }}
+      </el-descriptions-item>
+    </el-descriptions>
+    <video v-show="dataObj.media" width="320" height="240" id="mp4" controls>
+      <source src="" type="video/mp4" />
+    </video>
+    <template #footer>
+      <span class="dialog-footer">
+        <!-- <el-button @click="centerDialogVisible = false">Cancel</el-button> -->
+        <el-button type="primary" @click="centerDialogVisible = false">关闭</el-button>
+      </span>
+    </template>
+  </el-dialog>
+</template>
+<script lang="ts" setup>
+import { ref, onMounted, computed } from "vue";
+import { ElMessage } from "element-plus";
+import axios from "../utils/http";
+let currentPage = ref(1);
+let pageSize = ref(10);
+let tableData = ref([]);
+let totalSize = ref(0);
+let centerDialogVisible = ref(false);
+let dataObj = ref({});
+let media = ref("");
+
+onMounted(() => {
+  datalist();
+});
+const detailPage = (row: any, a: number) => {
+  //调用接口 /user/verify/
+  axios
+    .get(`/user/verify/${row.phone}/${a}`)
+    .then((res) => {
+      console.log("审核通过");
+      ElMessage({
+        message: "操作成功",
+        type: "success",
+      });
+      datalist();
+    })
+    .catch((err) => {
+      console.log(err);
+    });
+};
+//状态管理
+const statusFun = (row: any) => {
+
+  console.log(row.authority);
+  if (row.authority == -1) {
+    return "未申请审核";
+  }
+  if (row.authority == 0) {
+    return "审核中";
+  }
+  if (row.authority == 1) {
+    return "审核通过";
+  }
+  if (row.authority == 2) {
+    return "审核未通过";
+  }
+};
+const datalist = () => {
+  let tempStr = sessionStorage.getItem('userInfo') ?? '{}'
+  let userInfo = JSON.parse(tempStr)
+  let organId = userInfo.type == '1' ? userInfo.id : '';
+  axios
+    .get(`/user/find/apply/${currentPage.value}/${pageSize.value}/${organId}`)
+    .then((res) => {
+      console.log(res);
+      tableData.value = res.data.content;
+      console.log(tableData.value);
+      totalSize.value = res.data.totalElements;
+    })
+    .catch((err) => {
+      console.log(err);
+    });
+};
+const handleSizeChange = (val: number) => {
+  pageSize.value = val;
+  datalist();
+};
+const handleCurrentChange = (val: number) => {
+  currentPage.value = val;
+  datalist();
+};
+</script>

+ 424 - 0
vue/src/views/FileUpload.vue

@@ -0,0 +1,424 @@
+<template>
+  <!-- <div>
+    <el-upload
+      ref="upload"
+      class="upload-demo"
+      action="http://10.113.248.3:8000/v1/file/upload"
+      method="post"
+      :data="params"
+      :limit="1"
+      :on-exceed="handleExceed"
+      :auto-upload="false"
+      :on-success="uploadSucess"
+      :on-change="fileChange"
+      accept=".json,.txt,.wav,.npy,.xls,.xlsx" 
+    >
+      <template #trigger>
+        <el-button>选择文件</el-button>    
+      </template>
+      <el-button @click="submitUpload">上传文件</el-button>
+      <template #tip>
+        <div class="el-upload__tip text-red"></div>
+      </template>
+    </el-upload>
+  </div> -->
+
+  <!-- <div style='font-size:10px;color:#aeaeae'>支持json,txt,wav,npy,xls,xlsx文件格式</div>
+  <div>解析结果:</div> -->
+  <div><input ref="fileId" @change="fileFun" type="file" v-show="false" /></div>
+  <div class="connentClass" ref="contentBu">
+    <div v-for="(item, index) in chartList" :key="index" class="contentChart">
+      <div v-show="item.direction == 'r'" class="contRight">
+        <div class="rightDes">
+          <div class="speack_right">{{ item.chartContent }}</div>
+          <div class="rightImage">
+            <img
+              style="
+                width: 50px;
+                height: 50px;
+                border-radius: 10px;
+                margin: 1px;
+              "
+              src="../assets/back.png"
+            />
+          </div>
+        </div>
+      </div>
+      <div v-show="item.direction == 'l'" class="contLeft">
+        <div class="leftDes">
+          <div class="rightImage">
+            <img
+              style="
+                width: 50px;
+                height: 50px;
+                border-radius: 10px;
+                margin: 1px;
+              "
+              src="../assets/back.png"
+            />
+          </div>
+          <div class="speack_left">{{ item.chartContent }}</div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="sendMsg">
+    <div>
+      <el-icon @click="selectFile" class="sendFileIcon"
+        ><FolderOpened
+      /></el-icon>
+    </div>
+    <div class="sendArea">
+      <span class="leftSend">{{ fileName }}</span
+      ><button @click="sendMessge" :disabled="!disableFlag" class="sendBu">
+        <el-icon><Promotion /></el-icon>发送文件
+      </button>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+import { ref, reactive, onMounted, onUnmounted } from "vue";
+import { genFileId, ElMessage } from "element-plus";
+
+import type {
+  UploadInstance,
+  UploadProps,
+  UploadRawFile,
+  UploadFile,
+  UploadFiles,
+} from "element-plus";
+import axios from "axios";
+
+var timeFalg: any = reactive(null);
+
+let fileId = ref<HTMLElement>();
+
+const upload = ref<UploadInstance>();
+const params = reactive({
+  name: "",
+  num: "",
+  fileName: "",
+});
+const disableFlag = ref<boolean>(false);
+
+var chartList = reactive([]);
+
+const handleExceed: UploadProps["onExceed"] = (files) => {
+  upload.value!.clearFiles();
+  const file = files[0] as UploadRawFile;
+  file.uid = genFileId();
+  upload.value!.handleStart(file);
+};
+onUnmounted(() => {
+  clearInterval(timeFalg);
+});
+onMounted(() => {
+  console.log(fileId);
+  params.name = JSON.parse(
+    sessionStorage.getItem("userInfo") ?? "{}"
+  )?.organName;
+  getOrginizeList();
+
+  // window.addEventListener("scroll", scrollSlide, true);
+  contentBu.value.addEventListener("scroll", (e: any) => {
+    scrollSlide(contentBu.value.scrollTop);
+  });
+  setTimeout(() => {
+    scrollFun();
+  }, 300);
+});
+//闪上传的文件名称
+const fileName = ref("");
+const fileForma = ref("");
+var file = ref("");
+
+var pageNum = ref(1);
+var pageSize = ref(10);
+var slideFlag = ref(true);
+//查询测试及记录
+const getOrginizeList = () => {
+  slideFlag.value = false;
+  let name = JSON.parse(sessionStorage.getItem("userInfo")).organName;
+
+  let role = JSON.parse(sessionStorage.getItem("userInfo")).type;
+  axios
+    .post(`/v1/record/find`, {
+      pageNum: pageNum.value,
+      pageSize: pageSize.value,
+      userName: name,
+      role: role,
+    })
+    .then((res: any) => {
+      //请求接口中禁止再次请求
+      slideFlag.value = true;
+      if (res.data.code == 200) {
+        //循环data显示
+        let list = res.data.data.data;
+        if (list.length == 0) {
+          slideFlag.value = false;
+        }
+        for (let i = 0; i < list.length; i++) {
+          chartList.push({
+            direction: "r",
+            url: "",
+            icon: "",
+            chartContent: list[i].FileName,
+            perpleImage: "",
+          });
+          chartList.push({
+            direction: "l",
+            url: "",
+            icon: "",
+            chartContent: list[i].Result,
+            perpleImage: "",
+          });
+        }
+        console.log(chartList);
+        //设置显示记录结果
+        //将所有记录显示道
+      }
+    })
+    .catch((err) => {});
+};
+//滚动条上滑操作
+const scrollSlide = (num: number) => {
+  if (num == 0) {
+    //将页数增加1
+    if (slideFlag.value) {
+      pageNum.value++;
+      getOrginizeList();
+    }
+  }
+  // let scrollTop=ref.Box.getBoundingClientRect().top * -1;
+  //滚动条距离顶部的距离(因为是负的所以*-1)
+  //       let scrollTop = $refs.Box.getBoundingClientRect().top * -1;
+  // //页面可是高度
+  //       let windowHeight =
+  //         document.documentElement.clientHeight || document.body.clientHeight;
+  // //盒子的高度
+  //       let scrollHeight = this.$refs.Box.scrollHeight;
+  // //当滚动条距离顶部的距离加上页面可视高度和盒子的高度相等的情况下说明已经到底了
+  //       if (scrollTop + windowHeight == scrollHeight ) {
+  // //可以操作加载更多了。
+  //         this.PageIndex++;
+  //         this.loading=true
+  //         this.getList();
+  //       }
+};
+
+//上传文件的方法
+const fileFun = (e: any, opt: any, size: any) => {
+  file.value = e.target.files[0];
+  fileName.value = e.target.files[0].name;
+  //切割字符串得到类型
+
+  let index = fileName.value.lastIndexOf(".");
+  //获取后缀
+  fileForma.value = fileName.value.substr(index + 1);
+  if (!reType(fileForma.value)) {
+    ElMessage({
+      message: "请选择正确的文件格式",
+      type: "error",
+    });
+    fileName.value = "";
+    return;
+  }
+  disableFlag.value = true;
+  //获取到文件的名字
+  e.target.value = "";
+  //调用调用上传文件的接口
+  //返回结果后
+};
+
+//算法id
+var resultId = ref<string>("");
+//根据id查询算法结果的方法
+const selectResultById = () => {
+  //根据id查询算法结果
+  axios.get(`/v1/record/${resultId.value}/find`, {}).then((res) => {
+    console.log(res.data.data.Result !== "");
+
+    if (res.data.data.Result == "") {
+      setIntervalFun();
+    } else {
+      chartList.push({
+        direction: "l",
+        url: "",
+        icon: "",
+        chartContent: res.data.data.Result,
+        perpleImage: "",
+      });
+      console.log(chartList);
+      clearInterval(timeFalg);
+      scrollFun();
+    }
+  });
+};
+
+//发送文件的方法
+const sendMessge = () => {
+  if (!disableFlag.value) {
+    return;
+  }
+  const formData = new FormData();
+  formData.append("file", file.value);
+  formData.append("userName", params.name);
+  formData.append("fileType", fileForma.value);
+  axios.post(`/v1/record/create`, formData).then((res) => {
+    console.log(res);
+    //如果结果是返回的是正确的
+    if (res?.data?.code == 200) {
+      disableFlag.value = false;
+      chartList.push({
+        direction: "r",
+        url: "",
+        icon: "",
+        chartContent: fileName.value,
+        perpleImage: "",
+      });
+      //   chartList = arr2;
+      console.log(chartList);
+      fileName.value = "";
+      resultId.value = res.data.data;
+      scrollFun();
+      setIntervalFun();
+      //发送以后得到返回的id,然后一直启动轮询一直调接口
+    }
+  });
+};
+//滚动条滚动到最底部
+const contentBu = ref<HTMLElement>();
+const scrollFun = () => {
+  setTimeout(() => {
+    contentBu.value.scrollTo({
+      // 保持最底部
+      top: contentBu.value.scrollHeight,
+      behavior: "smooth", // 缓慢滚动
+    });
+  }, 0);
+};
+//轮询方法
+const setIntervalFun = () => {
+  clearInterval(timeFalg);
+  timeFalg = setInterval(() => {
+    selectResultById();
+  }, 2000);
+};
+const reType = (val: string): boolean => {
+  if (
+    val == "json" ||
+    val == "txt" ||
+    val == "wav" ||
+    val == "npy" ||
+    val == "xls" ||
+    val == "xlsx"
+  ) {
+    return true;
+  } else {
+    return false;
+  }
+};
+const fileChange = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
+  params.fileName = uploadFile.name;
+  console.log(uploadFile);
+  console.log(uploadFiles);
+};
+const selectFile = () => {
+  fileId.value.click();
+  //调用文件选择器
+  //获取到文件选择器,调用文件选择器的open函数,打开文件弹出框
+};
+const submitUpload = () => {
+  upload.value!.submit();
+};
+</script>
+<style scoped>
+.connentClass {
+  overflow-y: auto;
+  border-bottom: solid 2px #e9e6e6;
+  border-right: solid 2px #e9e6e6;
+  border-left: solid 2px #e9e6e6;
+  border-top: solid 2px #e9e6e6;
+  height: 60vh;
+}
+
+.sendMsg {
+  border-bottom: solid 2px #e9e6e6;
+  border-right: solid 2px #e9e6e6;
+  border-left: solid 2px #e9e6e6;
+  border-top: solid 0px #dddada;
+  position: relative;
+  height: 15vh;
+}
+.sendFileIcon {
+  margin-left: 10px;
+  margin-top: 5px;
+}
+.sendArea {
+  position: absolute;
+  bottom: 2px;
+  display: block;
+  display: flex;
+  width: 100%;
+}
+.leftSend {
+  flex: 1;
+  justify-content: flex-start;
+  display: flex;
+  align-items: center;
+  width: 100px;
+  margin-left: 2px;
+}
+.sendBu {
+  justify-content: flex-end;
+  display: flex;
+  align-items: center;
+  color: white;
+  background-color: #57acbb;
+  border: 0px;
+  text-align: center;
+  line-height: 30px;
+  margin-right: 2px;
+}
+.contentChart {
+  /* position: relative; */
+  margin-bottom: 10px;
+}
+.contRight {
+  margin-left: auto;
+  /* position: relative; */
+  width: 200px;
+  /* border:solid 3px #cbc7c7; */
+  display: flex;
+}
+.contLeft {
+  /* position: relative; */
+  width: 200px;
+
+  left: 0;
+}
+
+.rightDes {
+  margin-left: auto;
+  display: flex;
+  justify-content: flex-end;
+}
+.leftDes {
+  display: flex;
+  justify-content: flex-start;
+}
+.speack_right {
+  padding: 10px;
+  background-color: #c5c3c3;
+  border-top-left-radius: 8px;
+  border-bottom-left-radius: 8px;
+  border-bottom-right-radius: 8px;
+}
+.speack_left {
+  padding: 10px;
+  background-color: #c5c3c3;
+  border-top-right-radius: 8px;
+  border-bottom-left-radius: 8px;
+  border-bottom-right-radius: 8px;
+}
+</style>

+ 440 - 0
vue/src/views/HelloWorld.vue

@@ -0,0 +1,440 @@
+<template>
+  <div class="common-layout">
+    <el-container style="height: 100vh">
+      <el-header>
+        <el-row :gutter="24">
+          <!-- <el-col :span="6" style="text-align: left">
+            抑郁认知行为治疗系统管理端
+          </el-col> -->
+          <el-col :span="6" style="text-align: left"> 管理端 </el-col>
+          <el-col :span="6"> </el-col>
+          <el-col :span="6"> </el-col>
+          <el-col :span="6" class="user_operate">
+            <el-dropdown @command="handleCommand">
+              <span class="el-dropdown-link">
+                {{ userInfo.organName }}
+                <el-icon class="el-icon--right">
+                  <arrow-down />
+                </el-icon>
+              </span>
+              <template #dropdown>
+                <el-dropdown-menu>
+                  <el-dropdown-item command="logout">退出登录</el-dropdown-item>
+                  <el-dropdown-item command="editPassword"
+                    >修改密码</el-dropdown-item
+                  >
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown>
+          </el-col>
+        </el-row>
+      </el-header>
+      <el-container>
+        <el-container>
+          <el-aside width="auto" height="100%">
+            <el-menu
+              default-active="/TreeHoleManage"
+              class="el-menu-vertical-demo"
+              :collapse="isCollapse"
+              router
+              @open="handleOpen"
+              @close="handleClose"
+            >
+              <!-- <el-menu-item index="/main/TreeHoleManage">
+                <el-icon><icon-menu /></el-icon>
+                <template #title>树洞管理</template>
+              </el-menu-item> -->
+              <!-- <el-menu-item index="/main/PsychologicalConsultation">
+                <el-icon>
+                  <el-icon>
+                    <ChatLineSquare />
+                  </el-icon>
+                </el-icon>
+                <template #title>心理咨询</template>
+              </el-menu-item> -->
+              <!-- <el-menu-item
+                v-if="userInfo.type === '0'"
+                index="/main/WangEditor"
+              >
+                <el-icon>
+                  <document />
+                </el-icon>
+                <template #title>文章编辑</template>
+              </el-menu-item>
+              <el-menu-item index="/main/RecordList">
+                <el-icon>
+                  <Notebook />
+                </el-icon>
+                <template #title>发作记录</template>
+              </el-menu-item> -->
+              <!-- <el-menu-item index="/main/WuRen">
+                <el-icon><document /></el-icon>
+                <template #title>无人机</template>
+              </el-menu-item> -->
+              <!-- <el-menu-item v-if="userInfo.type === '1'" index="/main/Audit">
+                <el-icon>
+                  <document />
+                </el-icon>
+                <template #title>审核页面</template>
+              </el-menu-item> -->
+              <el-menu-item index="/main/institutionManage">
+                <el-icon>
+                  <document />
+                </el-icon>
+                <template #title>用户管理</template>
+              </el-menu-item>
+
+              <el-menu-item index="/main/fileUpload">
+                <el-icon>
+                  <document />
+                </el-icon>
+                <template #title>文件上传</template>
+              </el-menu-item>
+              <el-menu-item index="/main/recordList">
+                <el-icon>
+                  <document />
+                </el-icon>
+                <template #title>上传记录</template>
+              </el-menu-item>
+              <!-- <el-menu-item
+                v-if="userInfo.type === '0'"
+                index="/main/institutionManage"
+              >
+                <el-icon>
+                  <User />
+                </el-icon>
+                <template #title>机构管理</template>
+              </el-menu-item> -->
+            </el-menu></el-aside
+          >
+          <el-main>
+            <p class="main_p">
+              <Expand
+                @click="isCollapse = !isCollapse"
+                style="width: 1em; height: 1em; margin-right: 8px"
+              />
+            </p>
+            <div class="main">
+              <router-view></router-view>
+            </div>
+          </el-main>
+        </el-container>
+      </el-container>
+
+      <el-footer>
+        <div class="footer">
+          <div class="wrap" style="overflow: hidden">
+            <ul class="record">
+              <!-- <li>
+                <a
+                  target="_blank"
+                  href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11011402011379"
+                  ><img src="../assets/beian.png" /><span class="ml10"
+                    >京公网安备 11011402011379号</span
+                  ></a
+                >
+              </li>
+              <li>
+                <a href="javascript:;">京ICP备20000146号-2</a>
+              </li> -->
+              <!-- <li>
+                <a href="javascript:;">Copyright© 北京决明科技有限公司</a>
+              </li> -->
+              <li>
+                <a href="javascript:;">Copyright©2023</a>
+              </li>
+            </ul>
+          </div>
+        </div>
+      </el-footer>
+    </el-container>
+    <el-dialog
+      v-model="dialogFormVisible"
+      title="修改密码"
+      width="480"
+      @close="cancelHandle"
+    >
+      <el-form ref="ruleFormRef" :model="orginizeInfo" :rules="rules">
+        <el-form-item label="密码" :label-width="120" prop="oldPassword">
+          <el-input
+            v-model="orginizeInfo.oldPassword"
+            type="password"
+            placeholder="请输入密码"
+            autocomplete="off"
+          />
+        </el-form-item>
+        <el-form-item label="新密码" :label-width="120" prop="newPassword">
+          <el-input
+            v-model="orginizeInfo.newPassword"
+            type="password"
+            placeholder="请输入新密码"
+            autocomplete="off"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="cancelHandle">取消</el-button>
+          <el-button type="primary" @click="updataPassword(ruleFormRef)">
+            保存
+          </el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script lang="ts" setup>
+import { ref, reactive, onBeforeMount } from "vue";
+import { ArrowDown } from "@element-plus/icons-vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import CryptoJS from "crypto-js";
+import axios from "../utils/http";
+import { useRouter } from "vue-router";
+const router = useRouter();
+const userInfo = ref({
+  organName: "",
+  type: "",
+});
+
+defineProps({
+  // msg: {
+  //   type: String,
+  //   required: true,
+  // },
+});
+
+let dialogFormVisible = ref(false);
+let orginizeInfo = reactive({
+  organNumber: "",
+  oldPassword: "",
+  newPassword: "",
+});
+
+const ruleFormRef = ref();
+
+const validatePass = (rule, value, callback) => {
+  if (value === "") {
+    callback(new Error("请输入密码"));
+  } else {
+    const reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[a-zA-Z0-9]{6,12}$/;
+    if (!reg.test(value)) {
+      callback(new Error("密码需为6~12位的字母数字组合"));
+      return;
+    }
+    callback();
+  }
+};
+
+const rules = reactive({
+  oldPassword: [
+    {
+      required: true,
+      validator: validatePass,
+      trigger: "blur",
+    },
+  ],
+  newPassword: [
+    {
+      required: true,
+      validator: validatePass,
+      trigger: "blur",
+    },
+  ],
+});
+
+import {
+  ChatLineSquare,
+  Document,
+  Menu as IconMenu,
+  Location,
+  Setting,
+  Expand,
+  User,
+  Notebook,
+} from "@element-plus/icons-vue";
+const isCollapse = ref(false);
+
+onBeforeMount(() => {
+  let tempStr = sessionStorage.getItem("userInfo") ?? "{}";
+  if (tempStr) userInfo.value = JSON.parse(tempStr);
+});
+
+const handleOpen = (key: string, keyPath: string[]) => {
+  console.log(key, keyPath);
+};
+const handleClose = (key: string, keyPath: string[]) => {
+  console.log(key, keyPath);
+};
+
+const handleCommand = (command: string | number | object) => {
+  if (command === "logout") {
+    sessionStorage.clear();
+    router.push("/login");
+  } else if (command === "editPassword") {
+    dialogFormVisible.value = true;
+  }
+};
+
+const cancelHandle = () => {
+  ruleFormRef.value.resetFields();
+  dialogFormVisible.value = false;
+  ruleFormRef.value.clearValidate();
+};
+
+const updataPassword = async (formEl) => {
+  if (!formEl) return;
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+    let username  = JSON.parse(
+        sessionStorage.getItem("userInfo") ?? "{}"
+      )?.organName;
+   let password1 = CryptoJS.MD5(
+        orginizeInfo.oldPassword
+      ).toString();
+  let password2=    CryptoJS.MD5(
+        orginizeInfo.newPassword
+      ).toString();
+      axios
+        .post(`/v1/user/change/password`, {
+          username: username,
+          password: password1,
+          newPassword: password2,
+        })
+        .then((res) => {
+          if (res.code == 200) {
+            ElMessage({
+              message: "密码修改成功",
+              type: "success",
+            });
+            dialogFormVisible.value = false;
+          }else{
+              ElMessage({
+              message: res.message,
+              type: "error",
+            });
+          }
+        })
+        .catch((err) => {
+          ElMessage({
+            message: err.msg,
+            type: "error",
+          });
+        });
+    } else {
+      ElMessage({
+        message: "请将信息填写完整",
+        type: "error",
+      });
+    }
+  });
+};
+</script>
+
+
+<style >
+.el-aside {
+  background-color: #ffffff !important;
+}
+</style>
+<style scoped>
+.el-header,
+.el-footer {
+  background-color: #57acbb;
+  color: #ffffff;
+  text-align: center;
+  line-height: 60px;
+}
+
+.el-aside {
+  background-color: #d3dce6;
+  color: var(--el-text-color-primary);
+  text-align: center;
+  line-height: 200px;
+}
+
+.el-main {
+  background-color: #e9eef3;
+  color: var(--el-text-color-primary);
+  /* text-align: center;
+  line-height: 160px; */
+}
+
+body > .el-container {
+  margin-bottom: 40px;
+}
+
+.el-container:nth-child(5) .el-aside,
+.el-container:nth-child(6) .el-aside {
+  line-height: 260px;
+}
+
+.el-container:nth-child(7) .el-aside {
+  line-height: 320px;
+}
+
+.el-menu-vertical-demo:not(.el-menu--collapse) {
+  width: 200px;
+  min-height: 400px;
+}
+
+.el-main {
+  --el-main-padding: 0px;
+}
+
+.main_p {
+  line-height: 15px;
+  text-align: left;
+  margin-top: 2px;
+}
+
+.el-dropdown-link {
+  cursor: pointer;
+  color: #ffffff;
+  display: flex;
+  align-items: center;
+}
+
+.user_operate {
+  display: flex !important;
+  justify-content: end;
+  align-items: center;
+}
+
+.main {
+  padding: 20px;
+  margin: 8px;
+  background: #ffffff;
+  border-radius: 5px;
+  box-shadow: 0px 3px 10px 0px rgba(49, 131, 207, 0.38);
+}
+
+.el-footer {
+  height: auto;
+}
+
+.footer {
+  width: 100%;
+  background: #57acbb;
+  overflow: hidden;
+}
+
+.footer .record {
+  display: flex;
+  justify-content: center;
+  margin: 0;
+}
+
+.footer .record li {
+  line-height: 60px;
+  margin: 0 35px;
+}
+
+.footer .record li a {
+  color: #ffffff;
+}
+
+.footer .record img,
+.footer .record span {
+  vertical-align: middle;
+}
+</style>

+ 262 - 0
vue/src/views/PsychologicalConsultation.vue

@@ -0,0 +1,262 @@
+
+<template>
+  <div>
+    <div class="search-form">
+      <el-form :inline="true" :model="formInline">
+        <el-form-item label="姓名">
+          <el-input v-model="formInline.name" placeholder="请输入姓名" />
+        </el-form-item>
+        <el-form-item label="电话">
+          <el-input v-model="formInline.phone" placeholder="请输入电话号" />
+        </el-form-item>
+        <el-form-item label="性别">
+          <el-select v-model="formInline.sex" placeholder="请选择性别">
+            <el-option label="男" value="男" />
+            <el-option label="女" value="女" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="学历">
+          <el-select v-model="formInline.education" placeholder="请选择学历">
+            <el-option label="博士研究生" value="博士研究生" />
+            <el-option label="硕士研究生" value="硕士研究生" />
+            <el-option label="本科" value="本科" />
+            <el-option label="专科" value="专科" />
+            <el-option label="高中" value="高中" />
+            <el-option label="初中" value="初中" />
+            <el-option label="小学" value="小学" />
+            <el-option label="无" value="无" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="datalist">查询</el-button>
+          <el-button type="default" plain @click="resetSearch">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <el-table :data="tableData" style="width: 100%" border :highlight-current-row="true"
+      :header-cell-style="{ background: '#ecf7f9' }">
+      <el-table-column label="姓名" prop="name" width="160"> </el-table-column>
+      <el-table-column label="性别" prop="sex" width="100" align="center"> </el-table-column>
+      <el-table-column prop="age" label="年龄" width="100" align="center" />
+      <el-table-column prop="phone" label="电话" width="160" align="center" />
+      <el-table-column prop="education" label="学历" width="160" />
+      <el-table-column :show-overflow-tooltip="true" prop="problem" label="咨询的问题" />
+      <el-table-column :show-overflow-tooltip="true" prop="effect" label="影响" />
+      <el-table-column fixed="right" label="操作" width="120" align="center">
+        <template #default="scope">
+          <el-button plain type="primary" size="small" @click="detailPage(scope.row)">查看详情</el-button>
+        </template>
+      </el-table-column>
+      <!-- <el-table-column label="Operations">
+        <template #default="scope">
+          <el-button size="small" @click="handleEdit(scope.$index, scope.row)"
+            >Edit</el-button
+          >
+        </template>
+      </el-table-column> -->
+    </el-table>
+    <div class="pagination-box">
+      <el-pagination v-model:currentPage="formInline.beginNum" v-model:page-size="formInline.pageSize"
+        :page-sizes="[10, 20, 50, 100]" small background layout="total, sizes, prev, pager, next, jumper"
+        :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+    </div>
+    <el-dialog v-model="centerDialogVisible" title="详细信息" width="60%" align-center>
+      <el-descriptions class="margin-top" title="" :column="2" :size="size" border>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <el-icon :style="iconStyle">
+                <user />
+              </el-icon>
+              姓名
+            </div>
+          </template>
+          {{ userDetail.name }}
+
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <el-icon :style="iconStyle">
+                <iphone />
+              </el-icon>
+              性别
+            </div>
+          </template>
+          {{ userDetail.sex }}
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <el-icon :style="iconStyle">
+                <tickets />
+              </el-icon>
+              年龄
+            </div>
+          </template>
+          {{ userDetail.age }}
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <el-icon :style="iconStyle">
+                <tickets />
+              </el-icon>
+              电话
+            </div>
+          </template>
+          {{ userDetail.phone }}
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <el-icon :style="iconStyle">
+                <tickets />
+              </el-icon>
+              学历
+            </div>
+          </template>
+          {{ userDetail.education }}
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions class="margin-top" title="" :column="1" :size="size" border>
+        <el-descriptions-item width='100px'>
+          <template #label>
+            <div class="cell-item">
+              <el-icon :style="iconStyle">
+                <user />
+              </el-icon>
+              咨询的问题
+            </div>
+          </template>
+          {{ userDetail.problem }}
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <el-icon :style="iconStyle">
+                <iphone />
+              </el-icon>
+              影响
+            </div>
+          </template>
+          {{ userDetail.effect }}
+        </el-descriptions-item>
+      </el-descriptions>
+
+      <template #footer>
+        <span class="dialog-footer">
+          <!-- <el-button @click="centerDialogVisible = false">Cancel</el-button> -->
+          <el-button type="primary" @click="centerDialogVisible = false">关闭</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script lang="ts" setup>
+import { ref, onMounted, ssrContextKey } from "vue";
+import axios from "../utils/http";
+import { Timer } from "@element-plus/icons-vue";
+const path = ref("/psyCounseling/getCounseling");
+let totalSize = ref(0);
+let centerDialogVisible = ref(false);
+let userDetail = ref({})
+let formInline = ref({
+  name: '',
+  sex: '',
+  phone: '',
+  education: '',
+  pageSize: 10,
+  beginNum: 1,
+  organId: "",
+  status: "",
+})
+interface User {
+  date: string;
+  name: string;
+  address: string;
+}
+const handleEdit = (index: number, row: User) => {
+  console.log(index, row);
+};
+const handleDelete = (index: number, row: User) => {
+  console.log(index, row);
+};
+
+const tableData = ref([]);
+
+onMounted(() => {
+  datalist();
+});
+const datalist = () => {
+  let tempStr = sessionStorage.getItem('userInfo') ?? '{}'
+  let userInfo = JSON.parse(tempStr)
+  formInline.value.organId = userInfo.type == '1' ? userInfo.id : '';
+  axios
+    .get("/psyCounseling/getCounseling", formInline.value)
+    .then((res) => {
+      tableData.value = res.data.counselingInfos;
+      totalSize.value = res.data.num;
+    })
+    .catch((err) => {
+      console.log(err);
+    });
+};
+
+//当前页
+
+const small = ref(false);
+const background = ref(false);
+const disabled = ref(false);
+
+const handleSizeChange = (val: number) => {
+  formInline.value.pageSize = val;
+  datalist();
+};
+const handleCurrentChange = (val: number) => {
+  formInline.value.beginNum = val;
+  datalist();
+};
+
+// 搜索
+const searchHandle = () => {
+  formInline.value.beginNum = 1;
+  datalist()
+}
+
+// 重置
+const resetSearch = () => {
+  formInline.value = {
+    name: '',
+    sex: '',
+    phone: '',
+    education: '',
+    pageSize: 10,
+    beginNum: 1,
+    organId: "",
+    status: "",
+  }
+  datalist()
+}
+
+const detailPage = (row: any) => {
+  userDetail.value = row;
+  console.log(row)
+  centerDialogVisible.value = true;
+};
+</script>
+<style>
+.el-descriptions__body .el-descriptions__table {
+  border-collapse: inherit !important;
+  width: 100%;
+}
+</style>
+<style scoped>
+.demo-pagination-block+.demo-pagination-block {
+  margin-top: 10px;
+}
+
+.demo-pagination-block .demonstration {
+  margin-bottom: 16px;
+}
+</style>

+ 318 - 0
vue/src/views/RecordList.vue

@@ -0,0 +1,318 @@
+<template>
+  <div class="search-form">
+    <!-- <el-form :inline="true" :model="formInline" class="demo-form-inline">
+      <el-form-item label="用户姓名">
+        <el-input v-model="organName" placeholder="请输入用户姓名" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="getOrginizeList">查询</el-button>
+        <el-button type="primary" @click="dialogFormVisible = true">新增</el-button>
+      </el-form-item>
+    </el-form> -->
+  </div>
+  <el-table
+    :data="orginizeList"
+    border
+    style="width: 100%"
+    :highlight-current-row="true"
+    :header-cell-style="{ background: '#ecf7f9' }"
+  >
+    <el-table-column prop="FileName" label="文件名称" />
+    <el-table-column prop="FileType" label="文件类型" />
+    <el-table-column prop="CreateTime" label="创建时间" />
+    <el-table-column prop="UserName" label="用户名" />
+    <el-table-column prop="Result" label="解析结果" />
+    <!-- <el-table-column fixed="right" label="操作" width="200" align="center">
+      <template #default="scope">
+        <el-button type="primary" :icon="Edit" size="small" plain @click="editHandle(scope.row)">编辑</el-button>
+        <el-button type="danger" :icon="Delete" size="small" @click="delHandle(scope.row.id)">删除</el-button>
+      </template>
+    </el-table-column> -->
+  </el-table>
+  <div class="pagination-box">
+    <el-pagination
+      v-model:currentPage="pageNum"
+      v-model:page-size="pageSize"
+      small
+      background
+      :page-sizes="[10, 20, 50, 100]"
+      layout="total, sizes, prev, pager, next, jumper"
+      :total="totalSize"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+    />
+  </div>
+  <el-dialog
+    v-model="dialogFormVisible"
+    title="用户信息"
+    width="480"
+    @close="cancelHandle"
+  >
+    <el-form ref="ruleFormRef" :model="orginizeInfo" :rules="rules">
+      <el-form-item label="姓名" :label-width="120" prop="organName">
+        <el-input v-model="orginizeInfo.organName" autocomplete="off" />
+      </el-form-item>
+      <el-form-item label="编号" :label-width="120" prop="organNumber">
+        <el-input
+          v-model.number="orginizeInfo.organNumber"
+          autocomplete="off"
+        />
+      </el-form-item>
+      <el-form-item label="联系电话" :label-width="120" prop="contactNumber">
+        <el-input
+          v-model="orginizeInfo.contactNumber"
+          maxlength="11"
+          type="tel"
+          autocomplete="off"
+        />
+      </el-form-item>
+      <el-form-item label="登录密码" :label-width="120" prop="password">
+        <el-input
+          v-model="orginizeInfo.password"
+          type="password"
+          autocomplete="off"
+        />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="cancelHandle">取消</el-button>
+        <el-button type="primary" @click="saveOriginize(ruleFormRef)">
+          保存
+        </el-button>
+      </span>
+    </template>
+  </el-dialog>
+</template>
+  
+<script lang="ts" setup>
+import { Delete, Edit } from "@element-plus/icons-vue";
+import { reactive, ref, onMounted } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import axios from "../utils/http";
+import CryptoJS from "crypto-js";
+
+let pageNum = ref(1);
+let pageSize = ref(10);
+let totalSize = ref(0);
+let organName = ref("");
+let dialogFormVisible = ref(false);
+let orginizeList = ref([]);
+let orginizeInfo = reactive({
+  id: "",
+  organName: "",
+  contactNumber: "",
+  contactName: "",
+  organNumber: "",
+  type: 1,
+  password: "",
+});
+
+const ruleFormRef = ref();
+
+const validateTel = (rule, value, callback) => {
+  if (value === "") {
+    callback(new Error("请输入联系电话"));
+  } else {
+    if (!/^1[3456789]\d{9}$/.test(value)) {
+      callback(new Error("请输入正确的手机号码"));
+      return;
+    }
+    callback();
+  }
+};
+const validatePass = (rule, value, callback) => {
+  if (value === "") {
+    callback(new Error("请输入密码"));
+  } else {
+    const reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[a-zA-Z0-9]{6,12}$/;
+    if (!reg.test(value)) {
+      callback(new Error("密码需为6~12位的字母数字组合"));
+      return;
+    }
+    callback();
+  }
+};
+
+const rules = reactive({
+  organName: [{ required: true, message: "请输入机构名称", trigger: "blur" }],
+  organNumber: [
+    {
+      required: true,
+      message: "请输入机构编号",
+      trigger: "blur",
+    },
+    { type: "number", message: "机构编号需为数字", trigger: "blur" },
+  ],
+  contactNumber: [
+    {
+      required: true,
+      validator: validateTel,
+      trigger: "blur",
+    },
+  ],
+  contactName: [
+    {
+      required: true,
+      message: "请输输入联系人名称",
+      trigger: "blur",
+    },
+  ],
+  password: [
+    {
+      required: true,
+      validator: validatePass,
+      trigger: "blur",
+    },
+  ],
+});
+
+onMounted(() => {
+  getOrginizeList();
+});
+
+// 查询机构列表
+const getOrginizeList = () => {
+  // sessionStorage.setItem("userInfo", JSON.stringify({organName:form.userName,type:type.value}));
+  let name = JSON.parse(sessionStorage.getItem("userInfo")).organName;
+
+  let role = JSON.parse(sessionStorage.getItem("userInfo")).type;
+  axios
+    .post(`/v1/record/find`, {
+      pageNum: pageNum.value,
+      pageSize: pageSize.value,
+      userName: name,
+      role: role,
+    })
+    .then((res) => {
+      if (res.code == 200) {
+        orginizeList.value = res.data.data;
+        totalSize.value = res.data.total;
+        dialogFormVisible.value = false;
+      }
+    })
+    .catch((err) => {});
+};
+
+// 保存机构信息
+const saveOriginize = async (formEl) => {
+  if (!formEl) return;
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      orginizeInfo.password = CryptoJS.MD5(orginizeInfo.password).toString();
+      axios
+        .post(`/organ/saveInfo`, orginizeInfo)
+        .then((res) => {
+          if (res.code == 200) {
+            ElMessage({
+              message: "保存成功",
+              type: "success",
+            });
+            orginizeInfo = {
+              id: "",
+              organName: "",
+              contactNumber: "",
+              contactName: "",
+              organNumber: "",
+              type: 1,
+              password: "",
+            };
+            getOrginizeList();
+            dialogFormVisible.value = false;
+          }
+        })
+        .catch((err) => {
+          ElMessage({
+            message: err.msg,
+            type: "error",
+          });
+        });
+    } else {
+      ElMessage({
+        message: "请将信息填写完整",
+        type: "error",
+      });
+    }
+  });
+};
+
+const cancelHandle = () => {
+  ruleFormRef.value.resetFields();
+  dialogFormVisible.value = false;
+  ruleFormRef.value.clearValidate();
+};
+
+// 删除
+const delHandle = (id) => {
+  ElMessageBox.alert("确定要删除该条数据", {
+    confirmButtonText: "确定",
+    callback: (action) => {
+      if ("confirm" === action) delOriginize(id);
+    },
+  });
+};
+
+const editHandle = (info) => {
+  orginizeInfo = info;
+  dialogFormVisible.value = true;
+};
+
+// 删除机构信息
+const delOriginize = (id) => {
+  axios
+    .delete(`/organ/delete/${id}`)
+    .then((res) => {
+      if (res.code == 200) {
+        ElMessage({
+          message: "删除成功",
+          type: "success",
+        });
+        getOrginizeList();
+      }
+    })
+    .catch((err) => {});
+};
+
+const handleSizeChange = (val: number) => {
+  pageSize.value = val;
+  getOrginizeList();
+};
+const handleCurrentChange = (val: number) => {
+  pageNum.value = val;
+  getOrginizeList();
+};
+
+const tableData = [
+  {
+    date: "2016-05-03",
+    name: "Tom",
+    address: "No. 189, Grove St, Los Angeles",
+  },
+  {
+    date: "2016-05-02",
+    name: "Tom",
+    address: "No. 189, Grove St, Los Angeles",
+  },
+  {
+    date: "2016-05-04",
+    name: "Tom",
+    address: "No. 189, Grove St, Los Angeles",
+  },
+  {
+    date: "2016-05-01",
+    name: "Tom",
+    address: "No. 189, Grove St, Los Angeles",
+  },
+];
+
+const formInline = reactive({
+  user: "",
+  region: "",
+});
+
+const onSubmit = () => {
+  console.log("submit!");
+};
+</script>
+  
+<style></style>

+ 0 - 0
vue/src/views/RecordTest.vue


+ 372 - 0
vue/src/views/TreeHoleManage.vue

@@ -0,0 +1,372 @@
+
+<template>
+  <div style="display: flex; width: 100%; position: relative">
+    <ul
+      v-infinite-scroll="load"
+      infinite-scroll-distance="1"
+      class="infinite-list"
+      infinite-scroll-delay="500"
+      :infinite-scroll-disabled="disabled"
+      style="overflow-x: hidden; overflow-y: auto"
+    >
+      <li
+        v-for="(item, index) in dataList"
+        :key="index"
+        class="infinite-list-item"
+        @click="userSingle(item, index)"
+        :style="{ background: userBgFlag === index ? '#dde0e4' : '#ffffff' }"
+      >
+        <el-badge :is-dot="true" style='margin-top:5px' class="item">
+          <el-avatar
+            shape="square"
+            style="margin-left: 5px"
+            :size="40"
+            :src="getAvatar(item.photoPath)"
+          />
+        </el-badge>
+          <!-- src="https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png" -->
+<!-- https://static.turbosquid.com/Preview/001236/836/UV/Z-1.jpg -->
+        <div style="line-height:70px; margin-left: 20px" :tabindex="1">
+          <span style="display: block; line-height: 38px">{{
+            item.userName
+          }}</span>
+          <!-- <span style="display: block; line-height: 38px">点击查看...</span> -->
+        </div>
+      </li>
+      <p align="center" v-if="loading">Loading...</p>
+      <p align="center" v-if="noMore">No more</p>
+    </ul>
+    <div class="infinite-list-main">
+      <div
+        ref="innerRef"
+        class="mainScroll"
+        style="display: block; height: 50vh; overflow-y: hidden"
+        id="contant1"
+      >
+        <el-scrollbar height="50vh" ref="mainChartContent">
+          <div
+            class="chat-msg-content"
+            id="rongqi"
+            v-for="content in chatContents"
+            :key="content.index"
+          >
+            <div
+              v-if="content.from == 1"
+              :key="content.id"
+              class="main_answer_right"
+              style="margin-top: 10px"
+            >
+              <div class="img-wrapper">
+                <el-avatar
+                  shape="square"
+                  style="margin-left: 5px"
+                  :size="40"
+                  :src="currentAvatar"
+                />
+                <div class="message-wrapper message-wrapper-left">
+                  <div class="message">{{ content.question }}</div>
+                </div>
+              </div>
+            </div>
+
+            <el-row v-else style="margin-top: 10px">
+              <el-col :span="10"> &nbsp; </el-col>
+              <el-col :span="14">
+                <div class="main_answer_left" style="float: right">
+                  <div class="message-wrapper message-wrapper-right">
+                    <div class="message_answer">{{ content.answer }}</div>
+                  </div>
+                  <div class="img-wrapper">
+                    <el-avatar
+                      shape="square"
+                      style="margin-left: 5px"
+                      :size="40"
+                      src="https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png"
+                    />
+                  </div>
+                </div>
+              </el-col>
+            </el-row>
+          </div>
+        </el-scrollbar>
+      </div>
+      <el-divider />
+      <div style="display: block; height: 20vh; position: relative">
+        <el-input
+          v-model="textarea"
+          resize="none"
+          :autosize="{ minRows: 2, maxRows: 6 }"
+          maxlength="600"
+          type="textarea"
+          style="border: 0px solid #ffffff"
+          placeholder="请输入内容"
+        >
+        </el-input>
+      </div>
+      <el-button
+        @click="sendMsg"
+        text
+        type="success"
+        bg
+        style="bottom: 0px; position: absolate; float: right"
+      >
+        发送
+      </el-button>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+import { ref, onMounted, computed } from "vue";
+import axios from "../utils/http";
+const count = ref(0);
+const textarea = ref("");
+let pageNum = ref(1);
+let pageSize = ref(7);
+let dataList = ref([]);
+let loading = ref(false);
+let noMore = ref(false);
+let userBgFlag = ref(0);
+let chatContents = ref([]);
+let mainChartContent = ref();
+let innerRef = ref();
+let max = ref();
+let currentAvatar = ref('https://static.turbosquid.com/Preview/001236/836/UV/Z-1.jpg');
+
+const disabled = computed(() => loading.value || noMore.value);
+const load = () => {
+  pageNum.value += 1;
+  selectUserList();
+};
+onMounted(() => {
+  
+
+  selectUserList();
+});
+
+const setBottom = () => {
+  setTimeout(() => {
+    mainChartContent.value.setScrollTop(1440);
+  }, 100);
+};
+
+const sendMsg = () => {
+  chatContents.value.push({
+    from: 2,
+    answer: textarea.value,
+  });
+  let contant1 = document.getElementById("contant1");
+  setBottom();
+
+  //循环所有回复的数据,得到id的集合,和phone和toUserPhone
+  let id = [];
+  let phone = "";
+  let toUserPhone = "";
+  if (chatContents.value.length > 0) {
+    for (let i = 0; i < chatContents.value.length; i++) {
+      if (chatContents.value[i].from == 1) {
+        phone = chatContents.value[i].toUserPhone;
+        toUserPhone = chatContents.value[i].phone;
+        id.push(chatContents.value[i].id);
+      }
+    }
+  }
+  axios
+    .post("/record/replyInfos", {
+      phone: phone,
+      toReplyTreeId: id,
+      toUserPhone: toUserPhone,
+      treeText: textarea.value,
+    })
+    .then((res) => {
+
+      //调用初始化方法
+      //将分页设置为1
+      pageNum.value = 1;
+      dataList.value = [];
+      chatContents.value = [];
+      selectUserList();
+    })
+    .catch((res) => {
+      
+    });
+
+  textarea.value = "";
+};
+const userSingle = (item: any, index: any) => {
+  chatContents.value = [];
+  userBgFlag.value = index;
+  currentAvatar.value = getAvatar(item.photoPath)
+  let tempStr = sessionStorage.getItem('userInfo') ?? '{}'
+  let userInfo = JSON.parse(tempStr)
+  let organId = userInfo.type == '1' ? userInfo.id : '';
+  axios
+    .get("/record/getNoReply", {
+      beginNum: 1,
+      pageSize: 500,
+      phone: item.phone,
+      organId:organId
+    })
+    .then((res) => {
+      for (let i = 0; i < res.data[0].data.length; i++) {
+        chatContents.value.push({
+          from: 1,
+          question: res.data[0].data[i].treeText,
+          phone: res.data[0].data[i].phone,
+          toUserPhone: res.data[0].data[i].toUserPhone,
+          id: res.data[0].data[i].id,
+        });
+      }
+      setBottom();
+    })
+    .catch((res) => {
+    });
+};
+const selectUserList = () => {
+  noMore.value = false;
+  loading.value = true;
+  let tempStr = sessionStorage.getItem('userInfo') ?? '{}'
+  let userInfo = JSON.parse(tempStr)
+  let organId = userInfo.type == '1' ? userInfo.id : '';
+  axios
+    .get("/record/getNoReply", {
+      beginNum: pageNum.value,
+      pageSize: pageSize.value,
+      phone: "",
+      organId:organId
+    })
+    .then((res) => {
+      if (res.data.length == 0) {
+        noMore.value = true;
+      } else {
+         
+        for (let i = 0; i < res.data.length; i++) {
+          dataList.value.push(res.data[i]);
+        }
+        if (pageNum.value === 1) {
+          userSingle(dataList.value[0], 0);
+        }
+      }
+      loading.value = false;
+    })
+    .catch((res) => {
+      
+    });
+};
+
+const getAvatar = (url:string) => {
+  return url ? `https://dcbt.jue-ming.com:8666/file/show?filePath=${url}`: 'https://static.turbosquid.com/Preview/001236/836/UV/Z-1.jpg'
+}
+</script>
+
+<style>
+.mainScroll{
+ background-color:#f7f7f7
+}
+.infinite-list-main {
+  height: 75vh;
+  width: 100%;
+  padding: 0;
+  margin: 0;
+  list-style: none;
+  background-color: #ffffff;
+}
+.infinite-list {
+  background-color: #f3f7ff;
+  height: 75vh;
+  padding: 0;
+  width: 260px;
+  margin: 0;
+  list-style: none;
+}
+.infinite-list-item {
+  width: 200px !important;
+}
+.infinite-list .infinite-list-item {
+  display: flex;
+  align-items: center;
+  justify-content: left;
+  height:70px;
+  background: #ffffff;
+  /* width:200px; */
+  /* background: #dde0e4; */
+  margin: 10px;
+  color: var(--el-color-primary);
+}
+.infinite-list-item:focus {
+  display: flex;
+  align-items: center;
+  justify-content: left;
+  height: 70px;
+  background: #dde0e4;
+  /* margin: 10px; */
+  color: var(--el-color-primary);
+}
+
+.infinite-list .infinite-list-item + .list-item {
+  margin-top: 10px;
+}
+.el-divider--horizontal {
+  display: block;
+  height: 1px px;
+  width: 100%;
+  margin: 0 0;
+  border-top: 1px var(--el-border-color) var(--el-border-style);
+}
+.el-textarea__inner {
+  box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color))
+    inset;
+}
+.el-textarea__inner:hover {
+  box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color))
+    inset;
+}
+.el-textarea__inner:focus {
+  box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color))
+    inset;
+}
+.img-wrapper {
+  display: flex;
+  /* width:20vh */
+}
+.message-wrapper {
+  /* width: 40vw; */
+  max-width: 40vw;
+}
+.message-wrapper-left {
+  margin-left: 5px;
+  margin-top: 30px;
+  background-color: #ffffff;
+  padding: 10px 20px 10px 5px;
+  border-radius: 0px 10px 10px 10px;
+}
+.message-wrapper-right {
+  display: inline-table;
+  margin-left: 5px;
+  margin-top: 30px;
+  background-color: #e7e8eb;
+  padding: 10px 20px 10px 5px;
+  border-radius: 10px 0px 10px 10px;
+}
+.main_answer_left {
+  display: flex;
+}
+
+.message_answer {
+  width: 40vw;
+  word-wrap: break-word;
+}
+
+.infinite-list::-webkit-scrollbar {
+  width: 4px;
+}
+.infinite-list::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+  background: rgba(165, 164, 164, 0.2);
+}
+.infinite-listinfinite-list::-webkit-scrollbar-track {
+  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+  border-radius: 0;
+  background: rgba(165, 164, 164, 0.2);
+}
+</style>

+ 323 - 0
vue/src/views/WangEditor.vue

@@ -0,0 +1,323 @@
+<template>
+  <div class="search-form">
+    <el-form :inline="true" :model="formInline">
+      <el-form-item label="标题">
+        <el-input v-model="formInline.title" placeholder="请输入文章标题" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="selectFun">查询</el-button>
+        <el-button type="primary" @click="clearPage(true)"> 添加新闻</el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+  <el-table :data="ariticleTableData" style="width: 100%" border :highlight-current-row="true"
+    :header-cell-style="{ background: '#ecf7f9' }">
+    <el-table-column label="标题" prop="title" width="300"> </el-table-column>
+    <el-table-column label="描述" :show-overflow-tooltip="true" prop="description" />
+    <el-table-column fixed="right" label="操作" width="200" align="center">
+      <template #default="scope">
+        <el-button type="primary" :icon="Edit" plain size="small" @click="editHandle(scope.row)">编辑</el-button>
+        <el-button type="danger" :icon="Delete" size="small" @click="detailPage(scope.row.id)">删除</el-button>
+      </template>
+    </el-table-column>
+  </el-table>
+  <div class="pagination-box">
+    <el-pagination v-model:currentPage="currentPage" v-model:page-size="pageSize" background small
+      :page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper" :total="totalSize"
+      @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+  </div>
+  <el-dialog v-model="centerDialogVisible" title="编辑新闻" width="50%" center>
+    <el-scrollbar height="500px">
+      <span>
+        <el-row>
+          <el-col :span="24" class="fileImageClass">
+            <el-row><el-col :span="3" class="titlePage">标题:&nbsp;</el-col>
+              <el-col :span="9"><el-input v-model="articleInfo.articelTitle" placeholder="请输入标题" /></el-col></el-row>
+          </el-col>
+          <el-col :span="24" class="fileImageClass">
+            <el-row><el-col :span="3" class="titlePage">简介:&nbsp;</el-col>
+              <el-col :span="9"><el-input v-model="articleInfo.articleDes" placeholder="请输入简介" /></el-col></el-row>
+          </el-col>
+          <el-col :span="24" class="fileImageClass">
+            <el-row><el-col :span="3" class="titlePage">优先级:&nbsp;</el-col>
+              <el-col :span="9">
+                <el-input-number v-model="articleInfo.articleNum" :min="1" :max="10" /></el-col></el-row>
+          </el-col>
+          <el-col :span="24" class="fileImageClass">
+            <el-row><el-col :span="3" class="titlePage">上传图片:&nbsp;</el-col>
+              <el-col :span="9">
+                <el-upload v-model:file-list="fileList" list-type="picture-card" method="post" :headers="uploadHeaders"
+                  :limit="1" action="https://dcbt.jue-ming.com:8666/file/upload" :on-success="imageSuccess"
+                  :on-error="imageError">
+                  <el-icon>
+                    <Plus />
+                  </el-icon>
+                </el-upload>
+              </el-col>
+            </el-row>
+          </el-col>
+        </el-row>
+        <div style="border: 1px solid #ccc" class="fileImageClass">
+          <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig"
+            :mode="mode" />
+          <Editor style="height: 500px; overflow-y: hidden" v-model="articleInfo.articleHtml"
+            :defaultConfig="editorConfig" :mode="mode" @onCreated="handleCreated" />
+        </div>
+      </span>
+    </el-scrollbar>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="centerDialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="submitAriticle" :disabled="buttonFlag">提交</el-button>
+      </span>
+    </template>
+  </el-dialog>
+</template>
+<script setup>
+import "@wangeditor/editor/dist/css/style.css"; // 引入 css
+import axios from "../utils/http";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { Delete, Edit, Plus } from '@element-plus/icons-vue'
+import { onBeforeUnmount, ref, shallowRef, onMounted, reactive } from "vue";
+import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
+import { SlateElement } from "@wangeditor/editor";
+const formInline = ref({ title: '' })
+const fileList = ref([])
+const uploadHeaders = reactive({
+  Authorization: sessionStorage.getItem('token') ? `Bearer ${sessionStorage.getItem('token')}` : ''
+})
+
+// 编辑器实例,必须用 shallowRef
+const editorRef = shallowRef();
+
+//文章列表tableData
+let ariticleTableData = ref([]);
+
+let articleInfo = ref({
+  id: '',
+  articelTitle: '',
+  articleDes: '',
+  articleNum: '',
+  imagePath: '',
+  articleHtml: ''
+})
+
+//分页字段
+let pageSize = ref(10);
+let currentPage = ref(1);
+let totalSize = ref(0);
+
+//添加新闻字段
+let centerDialogVisible = ref(false);
+//控制按钮单词点击
+let buttonFlag = ref(false);
+// 模拟 ajax 异步获取内容
+onMounted(() => {
+  selectFun();
+});
+
+const toolbarConfig = {
+  /* 工具栏配置 */
+  toolbarKeys: [
+    'redo',
+    'undo',
+    '|',
+    'headerSelect',
+    'bold',
+    'italic',
+    'underline',
+    'fontSize',
+    'fontFamily',
+    'color',
+    'bgColor',
+    'through',
+    'sub',
+    'sup',
+    'clearStyle',
+    'lineHeight',
+    'insertLink',
+    'divider',
+    'emotion',
+    'blockquote',
+    'justifyLeft',
+    'justifyRight',
+    'justifyCenter',
+    'justifyJustify',
+    {
+      key: 'group-image', // 必填,要以 group 开头
+      title: '图片', // 必填
+      iconSvg: '',
+      menuKeys: ['uploadImage',
+        'deleteImage']
+    },
+    'fullScreen',
+  ]
+}
+const editorConfig = { MENU_CONF: {} };
+editorConfig.MENU_CONF["uploadImage"] = {
+  // 其他配置...
+
+  // 小于该值就插入 base64 格式(而不上传),默认为 0
+  base64LimitSize: 50000 * 1024, // 5kb
+};
+
+// 组件销毁时,也及时销毁编辑器
+onBeforeUnmount(() => {
+  const editor = editorRef.value;
+  if (editor == null) return;
+  editor.destroy();
+});
+
+const handleCreated = (editor) => {
+  editorRef.value = editor; // 记录 editor 实例,重要!
+};
+const sub = () => {
+  const editor = editorRef.value;
+  editor.getHtml();
+  console.log(editor.getHtml());
+};
+const imageSuccess = (response, uploadFile, uploadFiles) => {
+  articleInfo.value.imagePath = response.data;
+  ElMessage({
+    message: "上传成功",
+    type: "success",
+  });
+};
+const imageError = () => {
+  ElMessage.error("上传失败,图片建议不大于1M");
+};
+
+const handleSizeChange = (val) => {
+  pageSize.value = val;
+  selectFun();
+};
+const handleCurrentChange = (val) => {
+  currentPage.value = val;
+  selectFun();
+};
+const submitAriticle = () => {
+  const editor = editorRef.value;
+  let content = editor.getHtml();
+  if (!articleInfo.value.articelTitle) {
+    ElMessage.warning('请输入标题!')
+    return
+  }
+
+  if (!articleInfo.value.articleDes) {
+    ElMessage.warning('请输入简介!')
+    return
+  }
+
+  if (!articleInfo.value.imagePath) {
+    ElMessage.warning('请上传封面!')
+    return
+  }
+
+  if (!articleInfo.value.content) {
+    ElMessage.warning('请输入文章内容')
+    return
+  }
+  buttonFlag.value = true;
+  axios
+    .post("/article/save", {
+      id: articleInfo.value.id,
+      title: articleInfo.value.articelTitle,
+      description: articleInfo.value.articleDes,
+      content: content,
+      cover: articleInfo.value.imagePath,
+      sort: articleInfo.value.ariticleNum,
+    })
+    .then((res) => {
+      buttonFlag.value = false;
+      clearPage(false)
+      ElMessage({
+        message: "提交成功",
+        type: "success",
+      });
+      selectFun();
+    })
+    .catch((err) => {
+      buttonFlag.value = false;
+      ElMessage({
+        message: "提交失败!",
+        type: "success",
+      });
+    });
+};
+//清空表单
+const clearPage = (status) => {
+  centerDialogVisible.value = status;
+  fileList.value = [];
+  articleInfo.value = {
+    id: '',
+    articelTitle: '',
+    articleDes: '',
+    articleNum: '',
+    imagePath: '',
+    articleHtml: ''
+  }
+};
+//查询列表选项
+const selectFun = () => {
+  axios.get("/article/find/", {
+    pageNum: currentPage.value,
+    pageSize: pageSize.value,
+    title: formInline.value.title
+  }).then((res) => {
+    if (res.code == "200") {
+      ariticleTableData.value = res.data.content;
+      totalSize.value = res.data.totalElements;
+    }
+  })
+    .catch((err) => { });
+};
+
+const editHandle = (row) => {
+  articleInfo.value = {
+    id: row.id,
+    articelTitle: row.title,
+    articleDes: row.description,
+    articleNum: row.sort,
+    imagePath: row.cover,
+    articleHtml: row.content
+  };
+  fileList.value = [
+    {
+      name: 'file',
+      url: `https://dcbt.jue-ming.com:8666/file/show?filePath=${row.cover}`
+    }
+  ]
+  centerDialogVisible.value = true;
+}
+
+const detailPage = (id) => {
+  ElMessageBox.alert("警告!您确定要删除吗?", {
+    confirmButtonText: "确定",
+    callback: (action) => {
+      deleteAriticle(id);
+    },
+  });
+};
+const deleteAriticle = (id) => {
+  console.log(id);
+  axios
+    .delete("/article/delete/" + id, {})
+    .then((res) => {
+      if (res.code == "200") {
+        console.log(res);
+        selectFun();
+      }
+    })
+    .catch((err) => { });
+};
+</script>    
+<style scoped>
+.titlePage {
+  text-align: right;
+  margin-top: 2px;
+}
+
+.fileImageClass {
+  margin-top: 10px;
+}
+</style>

+ 347 - 0
vue/src/views/WuRen.vue

@@ -0,0 +1,347 @@
+<template>
+  <div class="wuren-out">
+    <el-row>
+      <el-col :span="8"
+        ><span class="top-left1">
+          &nbsp;&nbsp;
+          <img
+            style="width: 15px; height: 15px; margin-top: 8px"
+            src="../assets/wifi.png"
+          />&nbsp;&nbsp;&nbsp;&nbsp; 0m/s</span
+        ><span class="top-left2"
+          >&nbsp;&nbsp;
+          <img
+            style="width: 15px; height: 15px; margin-top: 8px"
+            src="../assets/wifi.png"
+          />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0m</span
+        >
+        <span class="top-left3"
+          >&nbsp;&nbsp;
+          <img
+            style="width: 15px; height: 15px; margin-top: 8px"
+            src="../assets/wifi.png"
+          />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0m</span
+        ></el-col
+      >
+      <el-col :span="8" style="text-align: center">
+        <span class="top-left4">TASK OFF</span>
+      </el-col>
+      <el-col :span="8"
+        ><span class="top-left1">
+          &nbsp;&nbsp;
+          <img
+            style="width: 15px; height: 15px; margin-top: 8px"
+            src="../assets/wifi.png"
+          />&nbsp;0:00&nbsp;min</span
+        ><span class="top-left2"
+          >&nbsp;&nbsp;
+          <img
+            style="width: 15px; height: 15px; margin-top: 8px"
+            src="../assets/wifi.png"
+          />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 100%</span
+        >
+        <span class="top-left3"
+          >&nbsp;&nbsp;
+          <img
+            style="width: 15px; height: 15px; margin-top: 8px"
+            src="../assets/wifi.png"
+          />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 59%</span
+        ></el-col
+      >
+    </el-row>
+    <el-row>
+      <el-col :span="12">
+        <span class="top-left21">
+          <img
+            style="width: 15px; height: 15px; margin-top: 7px; margin-left: 8px"
+            src="../assets/wifi.png"
+          />
+        </span>
+      </el-col>
+      <el-col :span="12" style="text-align: right">
+        <span class="top-left22">
+          <img
+            style="width: 15px; height: 15px; margin-top: 7px; margin-left: 8px"
+            src="../assets/wifi.png"
+          />
+        </span>
+      </el-col>
+    </el-row>
+    <el-row>
+      <el-col :span="12">
+        <span class="top-left31">
+          <span class="top-left311">
+            <img
+              style="width: 20px; height: 20px; margin-top: 10px"
+              src="../assets/wifi.png"
+            /> </span
+          ><br />
+          <span class="top-left312">
+            <img
+              style="
+                width: 20px;
+                height: 20px;
+                margin-top: -5px;
+                margin-left: 5px;
+                display: inline-display;
+              "
+              src="../assets/wifi.png"
+            />
+            <img
+              style="
+                width: 20px;
+                height: 20px;
+                margin-top: -5px;
+                margin-left: 25px;
+                display: inline-display;
+              "
+              src="../assets/wifi.png"
+            />
+            <img
+              style="
+                width: 20px;
+                height: 20px;
+                margin-top: -5px;
+                margin-left: 25px;
+                display: inline-display;
+              "
+              src="../assets/wifi.png"
+            />
+          </span>
+          <span class="top-left313">
+            <img
+              style="width: 20px; height: 20px; margin-top: 10px"
+              src="../assets/wifi.png"
+            />
+          </span>
+          <!-- <img
+            style="width: 20px; height: 20px; margin-top: 7px; display: block"
+            src="../assets/wifi.png"
+          /> -->
+        </span>
+      </el-col>
+      <el-col :span="12" style="text-align: -webkit-center">
+        <span class="top-left32">
+          <span class="top-left311">
+            <img
+              style="width: 20px; height: 20px; margin-top: 10px"
+              src="../assets/wifi.png"
+            /> </span
+          ><br />
+          <span class="top-left312">
+            <img
+              style="
+                width: 20px;
+                height: 20px;
+                margin-top: -5px;
+                margin-left: 5px;
+                display: inline-display;
+              "
+              src="../assets/wifi.png"
+            />
+            <img
+              style="
+                width: 20px;
+                height: 20px;
+                margin-top: -5px;
+                margin-left: 25px;
+                display: inline-display;
+              "
+              src="../assets/wifi.png"
+            />
+            <img
+              style="
+                width: 20px;
+                height: 20px;
+                margin-top: -5px;
+                margin-left: 25px;
+                display: inline-display;
+              "
+              src="../assets/wifi.png"
+            />
+          </span>
+          <span class="top-left313">
+            <img
+              style="width: 20px; height: 20px; margin-top: 10px"
+              src="../assets/wifi.png"
+            />
+          </span>
+          <!-- <img
+            style="width: 20px; height: 20px; margin-top: 7px; display: block"
+            src="../assets/wifi.png"
+          /> -->
+        </span>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<script lang="ts">
+import Vue from "vue";
+</script>
+<style>
+.wuren-out {
+  width: 800px;
+  height: 450px;
+  background-image: url("../assets/back.png");
+}
+.top-left1 {
+  display: inline-flex;
+  color: white;
+  margin-left: 10px;
+  width: 80px;
+  text-align: left;
+  line-height: 30px;
+  border-top-left-radius: 20px;
+  border-bottom-left-radius: 20px;
+  background-color: rgb(61, 63, 63);
+  margin-top: 10px;
+  opacity: 0.4;
+  font-size: 10px;
+}
+.top-left2 {
+  font-size: 10px;
+  display: inline-flex;
+  color: white;
+  margin-left: 2px;
+  width: 80px;
+  text-align: left;
+  line-height: 30px;
+  /* border-top-left-radius: 20px;
+  border-bottom-left-radius: 20px; */
+  background-color: rgb(61, 63, 63);
+  margin-top: 10px;
+  opacity: 0.4;
+}
+.top-left3 {
+  font-size: 10px;
+  display: inline-flex;
+  color: white;
+  margin-left: 2px;
+  width: 80px;
+  text-align: left;
+  line-height: 30px;
+  border-top-right-radius: 20px;
+  border-bottom-right-radius: 20px;
+  background-color: rgb(61, 63, 63);
+  margin-top: 10px;
+  opacity: 0.4;
+}
+.top-left4 {
+  padding-left: 10px;
+  text-align: center;
+  font-size: 20px;
+  display: inline-flex;
+  color: white;
+  margin-left: 2px;
+  width: 100px;
+  text-align: left;
+  line-height: 30px;
+  background-color: rgb(36, 128, 128);
+  margin-top: 10px;
+}
+.top-left21 {
+  /* padding-left: 10px; */
+  text-align: center;
+  font-size: 20px;
+  display: inline-flex;
+  color: white;
+  /* margin-left: 2px; */
+  width: 30px;
+  height: 30px;
+  border-radius: 30px;
+  text-align: left;
+  /* line-height: 80px; */
+
+  background-color: rgb(61, 63, 63);
+  margin-top: 10px;
+  opacity: 0.4;
+  margin-left: 10px;
+  /* margin-top: 10px; */
+}
+.top-left22 {
+  /* padding-left: 10px; */
+  text-align: center;
+  font-size: 20px;
+  display: inline-flex;
+  color: white;
+  /* margin-left: 2px; */
+  width: 30px;
+  height: 30px;
+  border-radius: 30px;
+  text-align: left;
+  /* line-height: 80px; */
+
+  background-color: rgb(61, 63, 63);
+  margin-top: 10px;
+  opacity: 0.4;
+  margin-right: 10px;
+  /* margin-top: 10px; */
+}
+.top-left31 {
+  /* padding-left: 10px; */
+  text-align: center;
+  font-size: 20px;
+  display: block;
+  color: white;
+  /* margin-left: 2px; */
+  width: 120px;
+  height: 120px;
+  border-radius: 120px;
+  text-align: left;
+  /* line-height: 80px; */
+
+  background-color: rgb(61, 63, 63);
+  margin-top: 100px;
+  opacity: 0.4;
+  margin-left: 100px;
+  /* margin-top: 10px; */
+}
+.top-left32 {
+  /* padding-left: 10px; */
+  text-align: right;
+  font-size: 20px;
+  display: block;
+  color: white;
+  /* margin-left: 2px; */
+  width: 120px;
+  height: 120px;
+  border-radius: 120px;
+  text-align: left;
+  margin-right: -100px;
+  /* line-height: 80px; */
+
+  background-color: rgb(61, 63, 63);
+  margin-top: 100px;
+  opacity: 0.4;
+  /* margin-left: 100px; */
+  /* margin-top: 10px; */
+  /* margin-top: 10px; */
+}
+.top-left311 {
+  margin-top: 10px;
+  /* padding-left: 10px; */
+  width: 20px;
+  height: 20px;
+  margin-top: 7px;
+  margin-left: 50px;
+  display: block;
+
+  /* margin-top: 10px; */
+}
+.top-left312 {
+  display: inline-block;
+
+  /* margin-top: 10px; */
+}
+.top-left313 {
+  margin-top: 10px;
+  /* padding-left: 10px; */
+  width: 20px;
+  height: 20px;
+  margin-top: 4px;
+  margin-left: 50px;
+  display: block;
+
+  /* margin-top: 10px; */
+}
+</style>

+ 345 - 0
vue/src/views/institutionManage/index.vue

@@ -0,0 +1,345 @@
+<template>
+  <div class="search-form">
+    <el-form :inline="true" :model="formInline" class="demo-form-inline">
+      <el-form-item label="用户姓名">
+        <el-input v-model="organName" placeholder="请输入用户姓名" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="getOrginizeList">查询</el-button>
+        <el-button type="primary" @click="dialogFormVisible = true"
+          >新增</el-button
+        >
+      </el-form-item>
+    </el-form>
+  </div>
+  <el-table
+    :data="orginizeList"
+    border
+    style="width: 100%"
+    :highlight-current-row="true"
+    :header-cell-style="{ background: '#ecf7f9' }"
+  >
+    <el-table-column prop="Id" label="id" />
+    <el-table-column prop="UserName" label="用户名" />
+
+    <!-- <el-table-column prop="contactNumber" label="联系方式" /> -->
+    <el-table-column fixed="right" label="操作" width="200" align="center">
+      <template #default="scope">
+        <el-button
+          type="primary"
+          :icon="Edit"
+          size="small"
+          plain
+          @click="editHandle(scope.row)"
+          >重置密码</el-button
+        >
+        <!-- <el-button type="danger" :icon="Delete" size="small" @click="delHandle(scope.row.id)">删除</el-button> -->
+      </template>
+    </el-table-column>
+  </el-table>
+  <div class="pagination-box">
+    <el-pagination
+      v-model:currentPage="pageNum"
+      v-model:page-size="pageSize"
+      small
+      background
+      :page-sizes="[10, 20, 50, 100]"
+      layout="total, sizes, prev, pager, next, jumper"
+      :total="totalSize"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+    />
+  </div>
+  <el-dialog
+    v-model="dialogFormVisible"
+    title="用户信息"
+    width="480"
+    @close="cancelHandle"
+  >
+    <el-form ref="ruleFormRef" :model="orginizeInfo" :rules="rules">
+      <el-form-item label="用户名" :label-width="120" prop="organName">
+        <el-input v-model="orginizeInfo.organName" autocomplete="off" />
+      </el-form-item>
+
+      <!-- <el-form-item label="联系电话" :label-width="120" prop="contactNumber">
+        <el-input v-model="orginizeInfo.contactNumber" maxlength="11" type="tel" autocomplete="off" />
+      </el-form-item> -->
+      <el-form-item label="登录密码" :label-width="120" prop="password">
+        <el-input
+          v-model="orginizeInfo.password"
+          type="password"
+          autocomplete="off"
+        />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="cancelHandle">取消</el-button>
+        <el-button type="primary" @click="saveOriginize(ruleFormRef)">
+          保存
+        </el-button>
+      </span>
+    </template>
+  </el-dialog>
+</template>
+  
+<script lang="ts" setup>
+import { Delete, Edit } from "@element-plus/icons-vue";
+import { reactive, ref, onMounted } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import axios from "../../utils/http";
+import CryptoJS from "crypto-js";
+
+let pageNum = ref(1);
+let pageSize = ref(10);
+let totalSize = ref(0);
+let organName = ref("");
+let dialogFormVisible = ref(false);
+let orginizeList = ref([]);
+let orginizeInfo = reactive({
+  id: "",
+  organName: "",
+  contactNumber: "",
+  contactName: "",
+  organNumber: "",
+  type: 1,
+  password: "",
+});
+
+const ruleFormRef = ref();
+
+const validateTel = (rule, value, callback) => {
+  if (value === "") {
+    callback(new Error("请输入联系电话"));
+  } else {
+    if (!/^1[3456789]\d{9}$/.test(value)) {
+      callback(new Error("请输入正确的手机号码"));
+      return;
+    }
+    callback();
+  }
+};
+const validatePass = (rule, value, callback) => {
+  if (value === "") {
+    callback(new Error("请输入密码"));
+  } else {
+    const reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[a-zA-Z0-9]{6,12}$/;
+    if (!reg.test(value)) {
+      callback(new Error("密码需为6~12位的字母数字组合"));
+      return;
+    }
+    callback();
+  }
+};
+
+const rules = reactive({
+  organName: [{ required: true, message: "请输入机构名称", trigger: "blur" }],
+  organNumber: [
+    {
+      required: true,
+      message: "请输入机构编号",
+      trigger: "blur",
+    },
+    { type: "number", message: "机构编号需为数字", trigger: "blur" },
+  ],
+  contactNumber: [
+    {
+      required: true,
+      validator: validateTel,
+      trigger: "blur",
+    },
+  ],
+  contactName: [
+    {
+      required: true,
+      message: "请输输入联系人名称",
+      trigger: "blur",
+    },
+  ],
+  password: [
+    {
+      required: true,
+      validator: validatePass,
+      trigger: "blur",
+    },
+  ],
+});
+
+onMounted(() => {
+  getOrginizeList();
+});
+
+// 查询机构列表
+const getOrginizeList = () => {
+  axios
+    .post(`/v1/user/find`, {
+      pageNum: pageNum.value,
+      pageSize: pageSize.value,
+      role: 0,
+      userName: organName.value,
+    })
+    .then((res) => {
+      if (res.code == 200) {
+        orginizeList.value = res.data.data;
+        totalSize.value = res.data.total;
+        dialogFormVisible.value = false;
+      }
+    })
+    .catch((err) => {});
+};
+
+// 保存机构信息
+const saveOriginize = async (formEl) => {
+  if (!formEl) return;
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      let passW = CryptoJS.MD5(orginizeInfo.password).toString();
+      // orginizeInfo.password = CryptoJS.MD5(orginizeInfo.password).toString();
+      axios
+        .post(`/v1/user/register`, {
+          userName: orginizeInfo.organName,
+          password: passW,
+          role: 0,
+        })
+        .then((res) => {
+          if (res.code == 200) {
+            ElMessage({
+              message: "保存成功",
+              type: "success",
+            });
+            orginizeInfo = {
+              id: "",
+              organName: "",
+              contactNumber: "",
+              contactName: "",
+              organNumber: "",
+              type: 1,
+              password: "",
+            };
+            getOrginizeList();
+            dialogFormVisible.value = false;
+          }
+          if (res.code == 400) {
+            ElMessage({
+              message: res.message,
+              type: "error",
+            });
+          }
+        })
+        .catch((err) => {
+          ElMessage({
+            message: "注册失败",
+            type: "error",
+          });
+        });
+    } else {
+      ElMessage({
+        message: "请将信息填写完整",
+        type: "error",
+      });
+    }
+  });
+};
+
+const cancelHandle = () => {
+  ruleFormRef.value.resetFields();
+  dialogFormVisible.value = false;
+  ruleFormRef.value.clearValidate();
+};
+
+// 删除
+const delHandle = (id) => {
+  ElMessageBox.alert("确定要删除该条数据", {
+    confirmButtonText: "确定",
+    callback: (action) => {
+      if ("confirm" === action) delOriginize(id);
+    },
+  });
+};
+
+const editHandle = (info: any) => {
+  axios
+    .post(`/v1/user/reset`, {
+      username: JSON.parse(sessionStorage.getItem("userInfo") ?? "{}")
+        ?.organName,
+      usernameInit: info.UserName,
+    })
+    .then((res) => {
+      if (res.code == 200) {
+        ElMessage({
+          message: "重置成功",
+          type: "success",
+        });
+      }else{
+         ElMessage({
+          message:res.message,
+          type: "success",
+        });
+      }
+    })
+    .catch((err) => {
+      console.log(err)
+    });
+  // orginizeInfo = info;
+  // dialogFormVisible.value = true;
+};
+
+// 删除机构信息
+const delOriginize = (id) => {
+  axios
+    .delete(`/organ/delete/${id}`)
+    .then((res) => {
+      if (res.code == 200) {
+        ElMessage({
+          message: "删除成功",
+          type: "success",
+        });
+        getOrginizeList();
+      }
+    })
+    .catch((err) => {});
+};
+
+const handleSizeChange = (val: number) => {
+  pageSize.value = val;
+  getOrginizeList();
+};
+const handleCurrentChange = (val: number) => {
+  pageNum.value = val;
+  getOrginizeList();
+};
+
+const tableData = [
+  {
+    date: "2016-05-03",
+    name: "Tom",
+    address: "No. 189, Grove St, Los Angeles",
+  },
+  {
+    date: "2016-05-02",
+    name: "Tom",
+    address: "No. 189, Grove St, Los Angeles",
+  },
+  {
+    date: "2016-05-04",
+    name: "Tom",
+    address: "No. 189, Grove St, Los Angeles",
+  },
+  {
+    date: "2016-05-01",
+    name: "Tom",
+    address: "No. 189, Grove St, Los Angeles",
+  },
+];
+
+const formInline = reactive({
+  user: "",
+  region: "",
+});
+
+const onSubmit = () => {
+  console.log("submit!");
+};
+</script>
+  
+<style></style>

+ 220 - 0
vue/src/views/user/login.vue

@@ -0,0 +1,220 @@
+<template>
+  <div class="bg">
+    <div class="content">
+      <div class="wrap">
+        <div class="login_right">
+          <div class="login_box">
+            <div class="login_line"><em></em><span>请登录</span><em></em></div>
+            <p>
+              <span>账号</span
+              ><el-input
+                v-model="form.userName"
+                placeholder="请输入账号"
+              ></el-input>
+            </p>
+            <p>
+              <span>密码</span
+              ><el-input
+                v-model="form.password"
+                @keyup.enter.native="onSubmit"
+                placeholder="请输入密码"
+                show-password
+              ></el-input>
+            </p>
+            <el-radio-group v-model="type">
+              <el-radio :label="0">普通用户</el-radio>
+              <el-radio :label="1">管理员</el-radio>
+            </el-radio-group>
+            <div class="goRegister">
+              <!-- <span @click="registShow = true">没有账号去注册?</span>
+                            <span @click="forgetPsd = true">忘记密码?</span> -->
+            </div>
+            <p style="margin-top: 10px">
+              <el-button class="login_btn" type="primary" @click="onSubmit"
+                >登录</el-button
+              >
+            </p>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+  
+<script lang="ts" setup type="module">
+import {ref, reactive } from "vue";
+import { useRouter } from "vue-router";
+import axios from "../../utils/http";
+import CryptoJS from "crypto-js";
+import { ElMessage } from "element-plus";
+
+const router = useRouter();
+
+const type=ref(0)
+// do not use same name with ref
+const form = reactive({
+  userName: "",
+  password: "",
+});
+
+const onSubmit = () => {
+  axios
+    .post("/v1/user/login", {
+      username: form.userName,
+      password: CryptoJS.MD5(form.password).toString(),
+      role:type.value
+    })
+    .then((res) => {
+      if (res.code == 200) {
+       console.log(res.data.token)
+        sessionStorage.setItem("token", res.data.token);
+        sessionStorage.setItem("userInfo", JSON.stringify({organName:form.userName,type:type.value}));
+        ElMessage({
+          message: "登录成功",
+          type: "success",
+        });
+        setTimeout(() => {
+          router.push("/main/institutionManage");
+        }, 1000);
+      } else {
+        ElMessage({
+          message:res.message,
+          type: "error",
+        });
+      }
+    })
+    .catch((err) => {
+      ElMessage({
+        message: "账号或密码不正确",
+        type: "error",
+      });
+    });
+};
+</script>
+<style scoped>
+.bg {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  min-height: 100vh;
+  background: url(../../assets/login/login_banner.png) no-repeat center;
+  background-size: cover;
+}
+
+.content {
+  width: 100%;
+  flex: 1;
+}
+
+.content .wrap {
+  display: flex;
+  width: 1200px;
+  margin: 0 auto;
+  justify-content: space-between;
+  position: relative;
+}
+
+.login_banner {
+  margin: 97px 0 0 55px;
+}
+
+.login_right {
+  text-align: center;
+  position: absolute;
+  top: 12vw;
+  right: 3vw;
+}
+
+.login_box {
+  width: 336px;
+  background: rgb(255, 255, 255);
+  box-shadow: 0px 3px 6px rgba(87, 172, 187, 0.32);
+  opacity: 1;
+  border-radius: 12px;
+  padding: 24px 20px 30px;
+  margin-top: 39px;
+}
+
+.login_box p {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  line-height: 36px;
+  margin-top: 25px;
+}
+
+.login_box p span {
+  display: block;
+  width: 68px;
+  text-align: justify;
+  text-align-last: justify;
+  margin-right: 14px;
+}
+
+.login_box .el-select {
+  width: 220px;
+}
+
+.login_box .el-input {
+  width: 220px;
+}
+
+.login_box :deep() input.el-input__inner {
+  border-radius: 20px;
+}
+
+.login_line {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.login_line span {
+  width: 60px;
+  height: 28px;
+  font-size: 20px;
+  font-family: PingFang SC;
+  font-weight: 600;
+  line-height: 28px;
+  color: #101010;
+  opacity: 1;
+  margin: 0 20px;
+}
+
+.login_line em {
+  display: block;
+  width: 60px;
+  height: 2px;
+  background: rgb(87, 172, 187);
+  border-radius: 2px;
+}
+
+.goRegister {
+  margin-top: 10px;
+  padding: 10px 15px 10px 20px;
+  cursor: pointer;
+  display: flex;
+  justify-content: space-between;
+}
+
+.goRegister span {
+  font-size: 14px;
+  font-family: PingFang SC;
+  font-weight: 400;
+  line-height: 20px;
+  color: #57acbb;
+}
+
+.login_btn {
+  width: 298px;
+  height: 42px;
+  background: rgb(87, 172, 187);
+  opacity: 1;
+  border-radius: 22px;
+}
+
+#app {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 26 - 0
vue/vite.config.js

@@ -0,0 +1,26 @@
+import { fileURLToPath, URL } from 'node:url'
+
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+  plugins: [vue()],
+  server: {
+    host: true,
+    port: 9999,
+    proxy: {
+      '/api': {
+        target: 'http://10.113.248.4:8666/', //目标url
+        changeOrigin: true, //支持跨域
+        rewrite: (path) => path.replace(/^\/api/, ""),
+        //重写路径,替换/api
+      }
+    }
+  },
+  resolve: {
+    alias: {
+      '@': fileURLToPath(new URL('./src', import.meta.url))
+    }
+  }
+})