hzj18279462576@163.com преди 2 години
родител
ревизия
820176449c
променени са 66 файла, в които са добавени 9714 реда и са изтрити 0 реда
  1. 24 0
      .gitignore
  2. 3 0
      .vscode/extensions.json
  3. 36 0
      README.en.md
  4. 14 0
      index.html
  5. 941 0
      package-lock.json
  6. 34 0
      package.json
  7. 33 0
      src/App.vue
  8. 87 0
      src/api/admin.js
  9. 14 0
      src/api/home.js
  10. 110 0
      src/api/vidicons.js
  11. BIN
      src/assets/add.png
  12. BIN
      src/assets/affiche.png
  13. BIN
      src/assets/back.png
  14. BIN
      src/assets/bottom.png
  15. BIN
      src/assets/classX.png
  16. BIN
      src/assets/classes.png
  17. BIN
      src/assets/classesA.png
  18. BIN
      src/assets/close.png
  19. BIN
      src/assets/colorSelect.png
  20. BIN
      src/assets/del.png
  21. BIN
      src/assets/home.png
  22. BIN
      src/assets/house.png
  23. BIN
      src/assets/ledger.png
  24. BIN
      src/assets/ledgerS.png
  25. BIN
      src/assets/left.png
  26. BIN
      src/assets/login.png
  27. BIN
      src/assets/logo.png
  28. BIN
      src/assets/map.png
  29. BIN
      src/assets/order.png
  30. BIN
      src/assets/orderS.png
  31. BIN
      src/assets/right.png
  32. BIN
      src/assets/scheduling.png
  33. BIN
      src/assets/search.png
  34. BIN
      src/assets/statement.png
  35. BIN
      src/assets/statementA.png
  36. BIN
      src/assets/system.png
  37. BIN
      src/assets/systemS.png
  38. BIN
      src/assets/timer.png
  39. 1 0
      src/assets/vite.svg
  40. BIN
      src/assets/workTime.png
  41. 129 0
      src/layout/index.vue
  42. 478 0
      src/layout/sidebar/Navbar.vue
  43. 253 0
      src/layout/sidebar/SidevarItem.vue
  44. 28 0
      src/main.js
  45. 106 0
      src/router/index.js
  46. BIN
      src/static/daoxiang.mp3
  47. BIN
      src/static/gaobai.mp3
  48. 5 0
      src/store/getters.js
  49. 22 0
      src/store/index.js
  50. 98 0
      src/store/modules/user.js
  51. 89 0
      src/style.css
  52. 1 0
      src/style/mixin.scss
  53. 23 0
      src/utils/loadMap.js
  54. 46 0
      src/utils/request.js
  55. 22 0
      src/utils/rsa.js
  56. 879 0
      src/views/account/account.vue
  57. 849 0
      src/views/houseList/houseList.vue
  58. 905 0
      src/views/ledger/ledger.vue
  59. 323 0
      src/views/login/index.vue
  60. 21 0
      src/views/map/map.js
  61. 192 0
      src/views/map/map.vue
  62. 1308 0
      src/views/order/order.vue
  63. 1430 0
      src/views/roomInfo/roomInfo.vue
  64. 1105 0
      src/views/roomType/roomType.vue
  65. 22 0
      text.json
  66. 83 0
      vite.config.js

+ 24 - 0
.gitignore

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

+ 3 - 0
.vscode/extensions.json

@@ -0,0 +1,3 @@
+{
+  "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
+}

+ 36 - 0
README.en.md

@@ -0,0 +1,36 @@
+# 校园报修系统
+
+#### Description
+{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
+
+#### Software Architecture
+Software architecture description
+
+#### Installation
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Instructions
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Contribution
+
+1.  Fork the repository
+2.  Create Feat_xxx branch
+3.  Commit your code
+4.  Create Pull Request
+
+
+#### Gitee Feature
+
+1.  You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
+2.  Gitee blog [blog.gitee.com](https://blog.gitee.com)
+3.  Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
+4.  The most valuable open source project [GVP](https://gitee.com/gvp)
+5.  The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
+6.  The most popular members  [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 14 - 0
index.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="zh">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="./src/assets/vite.svg" />
+    <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>

+ 941 - 0
package-lock.json

@@ -0,0 +1,941 @@
+{
+  "name": "vite-project",
+  "version": "0.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@babel/parser": {
+      "version": "7.20.15",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.20.15.tgz",
+      "integrity": "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg=="
+    },
+    "@ctrl/tinycolor": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.5.0.tgz",
+      "integrity": "sha512-tlJpwF40DEQcfR/QF+wNMVyGMaO9FQp6Z1Wahj4Gk3CJQYHwA2xVG7iKDFdW6zuxZY9XWOpGcfNCTsX4McOsOg=="
+    },
+    "@easydarwin/easyplayer": {
+      "version": "5.0.7",
+      "resolved": "https://registry.npmmirror.com/@easydarwin/easyplayer/-/easyplayer-5.0.7.tgz",
+      "integrity": "sha512-cKsvrUwFN1ZmYR+grhTKiOUp6QG1mgu64XGPjeASsAWCc03TygKQBsKCHPndafotjCXFFwuG9g1HatOiNvd3dQ=="
+    },
+    "@element-plus/icons-vue": {
+      "version": "2.0.10",
+      "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.0.10.tgz",
+      "integrity": "sha512-ygEZ1mwPjcPo/OulhzLE7mtDrQBWI8vZzEWSNB2W/RNCRjoQGwbaK4N8lV4rid7Ts4qvySU3njMN7YCiSlSaTQ=="
+    },
+    "@esbuild/android-arm": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz",
+      "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-arm64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz",
+      "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-x64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.16.17.tgz",
+      "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-arm64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz",
+      "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-x64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz",
+      "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-arm64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz",
+      "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-x64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz",
+      "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz",
+      "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz",
+      "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ia32": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz",
+      "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-loong64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz",
+      "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-mips64el": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz",
+      "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ppc64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz",
+      "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-riscv64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz",
+      "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-s390x": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz",
+      "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-x64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz",
+      "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/netbsd-x64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz",
+      "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/openbsd-x64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz",
+      "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/sunos-x64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz",
+      "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-arm64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz",
+      "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-ia32": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz",
+      "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-x64": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz",
+      "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==",
+      "dev": true,
+      "optional": true
+    },
+    "@floating-ui/core": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.2.0.tgz",
+      "integrity": "sha512-GHUXPEhMEmTpnpIfesFA2KAoMJPb1SPQw964tToQwt+BbGXdhqTCWT1rOb0VURGylsxsYxiGMnseJ3IlclVpVA=="
+    },
+    "@floating-ui/dom": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.2.0.tgz",
+      "integrity": "sha512-QXzg57o1cjLz3cGETzKXjI3kx1xyS49DW9l7kV2jw2c8Yftd434t2hllX0sVGn2Q8MtcW/4pNm8bfE1/4n6mng==",
+      "requires": {
+        "@floating-ui/core": "^1.2.0"
+      }
+    },
+    "@jridgewell/gen-mapping": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+      "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+      "requires": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "@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=="
+    },
+    "@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=="
+    },
+    "@jridgewell/source-map": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+      "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+      "requires": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "@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=="
+    },
+    "@jridgewell/trace-mapping": {
+      "version": "0.3.17",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+      "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
+      "requires": {
+        "@jridgewell/resolve-uri": "3.1.0",
+        "@jridgewell/sourcemap-codec": "1.4.14"
+      }
+    },
+    "@liveqing/liveplayer-v3": {
+      "version": "3.7.10",
+      "resolved": "https://registry.npmmirror.com/@liveqing/liveplayer-v3/-/liveplayer-v3-3.7.10.tgz",
+      "integrity": "sha512-ZfgEObnH/vZJHotBXY0qY4adXTUnqHtNFsSXB7GBZ/WjOxq13saLG5NgoHjdvHiRyuhNkVzOqHZT4UmQpswoww=="
+    },
+    "@types/lodash": {
+      "version": "4.14.191",
+      "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.191.tgz",
+      "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ=="
+    },
+    "@types/lodash-es": {
+      "version": "4.17.6",
+      "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.6.tgz",
+      "integrity": "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==",
+      "requires": {
+        "@types/lodash": "*"
+      }
+    },
+    "@types/web-bluetooth": {
+      "version": "0.0.16",
+      "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
+      "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
+    },
+    "@vitejs/plugin-vue": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz",
+      "integrity": "sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==",
+      "dev": true
+    },
+    "@vue/compiler-core": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.47.tgz",
+      "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==",
+      "requires": {
+        "@babel/parser": "^7.16.4",
+        "@vue/shared": "3.2.47",
+        "estree-walker": "^2.0.2",
+        "source-map": "^0.6.1"
+      }
+    },
+    "@vue/compiler-dom": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz",
+      "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==",
+      "requires": {
+        "@vue/compiler-core": "3.2.47",
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "@vue/compiler-sfc": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz",
+      "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==",
+      "requires": {
+        "@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"
+      }
+    },
+    "@vue/compiler-ssr": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz",
+      "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==",
+      "requires": {
+        "@vue/compiler-dom": "3.2.47",
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "@vue/devtools-api": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz",
+      "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
+    },
+    "@vue/reactivity": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.47.tgz",
+      "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==",
+      "requires": {
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "@vue/reactivity-transform": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz",
+      "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==",
+      "requires": {
+        "@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"
+      }
+    },
+    "@vue/runtime-core": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.47.tgz",
+      "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==",
+      "requires": {
+        "@vue/reactivity": "3.2.47",
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "@vue/runtime-dom": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz",
+      "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==",
+      "requires": {
+        "@vue/runtime-core": "3.2.47",
+        "@vue/shared": "3.2.47",
+        "csstype": "^2.6.8"
+      }
+    },
+    "@vue/server-renderer": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.47.tgz",
+      "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==",
+      "requires": {
+        "@vue/compiler-ssr": "3.2.47",
+        "@vue/shared": "3.2.47"
+      }
+    },
+    "@vue/shared": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.47.tgz",
+      "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ=="
+    },
+    "@vueuse/core": {
+      "version": "9.12.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.12.0.tgz",
+      "integrity": "sha512-h/Di8Bvf6xRcvS/PvUVheiMYYz3U0tH3X25YxONSaAUBa841ayMwxkuzx/DGUMCW/wHWzD8tRy2zYmOC36r4sg==",
+      "requires": {
+        "@types/web-bluetooth": "^0.0.16",
+        "@vueuse/metadata": "9.12.0",
+        "@vueuse/shared": "9.12.0",
+        "vue-demi": "*"
+      }
+    },
+    "@vueuse/metadata": {
+      "version": "9.12.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.12.0.tgz",
+      "integrity": "sha512-9oJ9MM9lFLlmvxXUqsR1wLt1uF7EVbP5iYaHJYqk+G2PbMjY6EXvZeTjbdO89HgoF5cI6z49o2zT/jD9SVoNpQ=="
+    },
+    "@vueuse/shared": {
+      "version": "9.12.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.12.0.tgz",
+      "integrity": "sha512-TWuJLACQ0BVithVTRbex4Wf1a1VaRuSpVeyEd4vMUWl54PzlE0ciFUshKCXnlLuD0lxIaLK4Ypj3NXYzZh4+SQ==",
+      "requires": {
+        "vue-demi": "*"
+      }
+    },
+    "acorn": {
+      "version": "8.8.2",
+      "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.8.2.tgz",
+      "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw=="
+    },
+    "anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
+    },
+    "async-validator": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
+      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+    },
+    "axios": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.3.3.tgz",
+      "integrity": "sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==",
+      "requires": {
+        "follow-redirects": "^1.15.0",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
+      }
+    },
+    "binary-extensions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
+    },
+    "braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "requires": {
+        "fill-range": "^7.0.1"
+      }
+    },
+    "buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+    },
+    "chokidar": {
+      "version": "3.5.3",
+      "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz",
+      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+      "requires": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "fsevents": "~2.3.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      }
+    },
+    "combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+    },
+    "csstype": {
+      "version": "2.6.21",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz",
+      "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
+    },
+    "dayjs": {
+      "version": "1.11.8",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.8.tgz",
+      "integrity": "sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ=="
+    },
+    "deepmerge": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.0.tgz",
+      "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og=="
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+    },
+    "echarts": {
+      "version": "5.4.2",
+      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.4.2.tgz",
+      "integrity": "sha512-2W3vw3oI2tWJdyAz+b8DuWS0nfXtSDqlDmqgin/lfzbkB01cuMEN66KWBlmur3YMp5nEDEEt5s23pllnAzB4EA==",
+      "requires": {
+        "tslib": "2.3.0",
+        "zrender": "5.4.3"
+      }
+    },
+    "element-plus": {
+      "version": "2.2.29",
+      "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.2.29.tgz",
+      "integrity": "sha512-g4dcrURrKkR5uUX8n5RVnnqGnimoki9HfqS4yHHG6XwCHBkZGozdq4x+478BzeWUe31h++BO+7dakSx4VnM8RQ==",
+      "requires": {
+        "@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"
+      },
+      "dependencies": {
+        "@popperjs/core": {
+          "version": "npm:@sxzz/popperjs-es@2.11.7",
+          "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
+          "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
+        }
+      }
+    },
+    "esbuild": {
+      "version": "0.16.17",
+      "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.16.17.tgz",
+      "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==",
+      "dev": true,
+      "requires": {
+        "@esbuild/android-arm": "0.16.17",
+        "@esbuild/android-arm64": "0.16.17",
+        "@esbuild/android-x64": "0.16.17",
+        "@esbuild/darwin-arm64": "0.16.17",
+        "@esbuild/darwin-x64": "0.16.17",
+        "@esbuild/freebsd-arm64": "0.16.17",
+        "@esbuild/freebsd-x64": "0.16.17",
+        "@esbuild/linux-arm": "0.16.17",
+        "@esbuild/linux-arm64": "0.16.17",
+        "@esbuild/linux-ia32": "0.16.17",
+        "@esbuild/linux-loong64": "0.16.17",
+        "@esbuild/linux-mips64el": "0.16.17",
+        "@esbuild/linux-ppc64": "0.16.17",
+        "@esbuild/linux-riscv64": "0.16.17",
+        "@esbuild/linux-s390x": "0.16.17",
+        "@esbuild/linux-x64": "0.16.17",
+        "@esbuild/netbsd-x64": "0.16.17",
+        "@esbuild/openbsd-x64": "0.16.17",
+        "@esbuild/sunos-x64": "0.16.17",
+        "@esbuild/win32-arm64": "0.16.17",
+        "@esbuild/win32-ia32": "0.16.17",
+        "@esbuild/win32-x64": "0.16.17"
+      }
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+    },
+    "estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+    },
+    "fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "requires": {
+        "to-regex-range": "^5.0.1"
+      }
+    },
+    "follow-redirects": {
+      "version": "1.15.2",
+      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz",
+      "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
+    },
+    "form-data": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
+      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "fsevents": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz",
+      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "optional": true
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
+    "has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1"
+      }
+    },
+    "hls.js": {
+      "version": "1.3.4",
+      "resolved": "https://registry.npmmirror.com/hls.js/-/hls.js-1.3.4.tgz",
+      "integrity": "sha512-iFEwVqtEDk6sKotcTwtJ5OMo/nuDTk9PrpB8FI2J2WYf8EriTVfR4FaK0aNyYtwbYeRSWCXJKlz23xeREdlNYg=="
+    },
+    "immutable": {
+      "version": "4.2.4",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.2.4.tgz",
+      "integrity": "sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w=="
+    },
+    "is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "requires": {
+        "binary-extensions": "^2.0.0"
+      }
+    },
+    "is-core-module": {
+      "version": "2.11.0",
+      "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.11.0.tgz",
+      "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
+    },
+    "is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+    },
+    "jsencrypt": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmmirror.com/jsencrypt/-/jsencrypt-3.3.1.tgz",
+      "integrity": "sha512-dVvV54GdFuJgmEKn+oBiaifDMen4p6o6j/lJh0OVMcouME8sST0bJ7bldIgKBQk4za0zyGn0/pm4vOznR25mLw=="
+    },
+    "klona": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz",
+      "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="
+    },
+    "lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
+    "lodash-es": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
+      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+    },
+    "lodash-unified": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
+      "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ=="
+    },
+    "magic-string": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
+      "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
+      "requires": {
+        "sourcemap-codec": "^1.4.8"
+      }
+    },
+    "memoize-one": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
+      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
+    },
+    "mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+    },
+    "mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "requires": {
+        "mime-db": "1.52.0"
+      }
+    },
+    "nanoid": {
+      "version": "3.3.4",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz",
+      "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw=="
+    },
+    "neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
+    },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+    },
+    "normalize-wheel-es": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
+      "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
+    },
+    "path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+    },
+    "picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
+    },
+    "postcss": {
+      "version": "8.4.21",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.21.tgz",
+      "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
+      "requires": {
+        "nanoid": "^3.3.4",
+        "picocolors": "^1.0.0",
+        "source-map-js": "^1.0.2"
+      }
+    },
+    "proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+    },
+    "readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "requires": {
+        "picomatch": "^2.2.1"
+      }
+    },
+    "resolve": {
+      "version": "1.22.1",
+      "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz",
+      "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+      "dev": true,
+      "requires": {
+        "is-core-module": "^2.9.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      }
+    },
+    "rollup": {
+      "version": "3.14.0",
+      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-3.14.0.tgz",
+      "integrity": "sha512-o23sdgCLcLSe3zIplT9nQ1+r97okuaiR+vmAPZPTDYB7/f3tgWIYNyiQveMsZwshBT0is4eGax/HH83Q7CG+/Q==",
+      "dev": true,
+      "requires": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "sass": {
+      "version": "1.58.0",
+      "resolved": "https://registry.npmmirror.com/sass/-/sass-1.58.0.tgz",
+      "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==",
+      "requires": {
+        "chokidar": ">=3.0.0 <4.0.0",
+        "immutable": "^4.0.0",
+        "source-map-js": ">=0.6.2 <2.0.0"
+      }
+    },
+    "sass-loader": {
+      "version": "13.2.0",
+      "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-13.2.0.tgz",
+      "integrity": "sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==",
+      "requires": {
+        "klona": "^2.0.4",
+        "neo-async": "^2.6.2"
+      }
+    },
+    "shvl": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/shvl/-/shvl-2.0.3.tgz",
+      "integrity": "sha512-V7C6S9Hlol6SzOJPnQ7qzOVEWUQImt3BNmmzh40wObhla3XOYMe4gGiYzLrJd5TFa+cI2f9LKIRJTTKZSTbWgw=="
+    },
+    "source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+    },
+    "source-map-js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz",
+      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
+    },
+    "source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "sourcemap-codec": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
+    },
+    "supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "dev": true
+    },
+    "terser": {
+      "version": "5.16.5",
+      "resolved": "https://registry.npmmirror.com/terser/-/terser-5.16.5.tgz",
+      "integrity": "sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==",
+      "requires": {
+        "@jridgewell/source-map": "^0.3.2",
+        "acorn": "^8.5.0",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      }
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "requires": {
+        "is-number": "^7.0.0"
+      }
+    },
+    "tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+    },
+    "vite": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/vite/-/vite-4.1.1.tgz",
+      "integrity": "sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==",
+      "dev": true,
+      "requires": {
+        "esbuild": "^0.16.14",
+        "fsevents": "~2.3.2",
+        "postcss": "^8.4.21",
+        "resolve": "^1.22.1",
+        "rollup": "^3.10.0"
+      }
+    },
+    "vue": {
+      "version": "3.2.47",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.2.47.tgz",
+      "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==",
+      "requires": {
+        "@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"
+      }
+    },
+    "vue-demi": {
+      "version": "0.13.11",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz",
+      "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A=="
+    },
+    "vue-router": {
+      "version": "4.0.10",
+      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.0.10.tgz",
+      "integrity": "sha512-YbPf6QnZpyyWfnk7CUt2Bme+vo7TLfg1nGZNkvYqKYh4vLaFw6Gn8bPGdmt5m4qrGnKoXLqc4htAsd3dIukICA==",
+      "requires": {
+        "@vue/devtools-api": "^6.0.0-beta.14"
+      }
+    },
+    "vuex": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/vuex/-/vuex-4.0.2.tgz",
+      "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
+      "requires": {
+        "@vue/devtools-api": "^6.0.0-beta.11"
+      }
+    },
+    "vuex-persistedstate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/vuex-persistedstate/-/vuex-persistedstate-4.1.0.tgz",
+      "integrity": "sha512-3SkEj4NqwM69ikJdFVw6gObeB0NHyspRYMYkR/EbhR0hbvAKyR5gksVhtAfY1UYuWUOCCA0QNGwv9pOwdj+XUQ==",
+      "requires": {
+        "deepmerge": "^4.2.2",
+        "shvl": "^2.0.3"
+      }
+    },
+    "zrender": {
+      "version": "5.4.3",
+      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.4.3.tgz",
+      "integrity": "sha512-DRUM4ZLnoaT0PBVvGBDO9oWIDBKFdAVieNWxWwK0niYzJCMwGchRk21/hsE+RKkIveH3XHCyvXcJDkgLVvfizQ==",
+      "requires": {
+        "tslib": "2.3.0"
+      }
+    }
+  }
+}

+ 34 - 0
package.json

@@ -0,0 +1,34 @@
+{
+  "name": "vite-project",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "@easydarwin/easyplayer": "^5.0.7",
+    "@element-plus/icons-vue": "^2.0.10",
+    "@liveqing/liveplayer-v3": "^3.7.10",
+    "axios": "^1.3.2",
+    "dayjs": "^1.11.8",
+    "echarts": "^5.4.2",
+    "element-plus": "^2.2.29",
+    "hls.js": "^1.3.4",
+    "jsencrypt": "^3.3.1",
+    "lodash": "^4.17.21",
+    "sass": "^1.58.0",
+    "sass-loader": "^13.2.0",
+    "terser": "^5.16.5",
+    "vue": "^3.2.45",
+    "vue-router": "^4.0.10",
+    "vuex": "^4.0.2",
+    "vuex-persistedstate": "^4.1.0"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^4.0.0",
+    "vite": "^4.1.0"
+  }
+}

+ 33 - 0
src/App.vue

@@ -0,0 +1,33 @@
+<script setup>
+import { ref, reactive, nextTick, onBeforeMount, onUnmounted } from "vue";
+import { useRouter } from "vue-router";
+import { useStore } from "vuex";
+const store = useStore();
+const router = useRouter();
+onBeforeMount(() => {
+  // store.dispatch("pathSelect");
+  // store.dispatch("busNum");
+  // store.dispatch("newsAsync");
+  // store.dispatch("sm_time");
+});
+</script>
+
+<template>
+  <router-view></router-view>
+</template>
+
+<style lang="scss">
+#app {
+  max-width: 1920px;
+  width: 1920px;
+  min-height: 100vh;
+  max-height: 1080px;
+  margin: 0;
+  padding: 0;
+  text-align: unset;
+  // width: 100%;
+  // height: 100%;
+  // margin: 0;
+  // padding: 0;
+}
+</style>

+ 87 - 0
src/api/admin.js

@@ -0,0 +1,87 @@
+import request from "@/utils/request";
+const requests = '/api'// 线上
+// const requests = '/video/transcoding/transcoding'//线下
+export default {
+    // 登录账号
+    // async adminLogin(data) {
+    //     let requestData = await request({
+    //         url: `${requests}/carBook/adminlogin.action`,
+    //         method: "POST",
+    //         // headers: { "Content-Type": "application/json;charset=utf-8" },
+    //         data: data,
+    //     });
+    //     return requestData;
+    // },
+
+    // 账号列表
+    // async adminList(params) {
+    //     let requestData = await request({
+    //         url: `${requests}/carBook/adminlist.action`,
+    //         method: "GET",
+    //         headers: { "Content-Type": "multipart/form-data" },
+    //         params,
+    //     });
+    //     return requestData;
+    // },
+
+    // 新增管理员
+    async adminAdd(data) {
+        let requestData = await request({
+            url: `${requests}/carBook/admininsert.action`,
+            method: "POST",
+            data,
+        });
+        return requestData;
+    },
+    // 修改管理员
+    async adminUpdate(data) {
+        let requestData = await request({
+            url: `${requests}/carBook/adminupdate.action`,
+            method: "POST",
+            data,
+        });
+        return requestData;
+    },
+    // 修改密码
+    // async updatePassword(data) {
+    //     let requestData = await request({
+    //         url: `${requests}/videoAdmin/updatePassword`,
+    //         method: "PUT",
+    //         data,
+    //     });
+    //     return requestData;
+    // },
+    // 删除管理员
+    async adminDel(data) {
+        let requestData = await request({
+            url: `${requests}/carBook/admindel.action`,
+            method: "POST",
+            data,
+        });
+        return requestData;
+    },
+
+    // 导出管理员信息
+    async download(params) {
+        let requestData = await request({
+            url: `${requests}/carBook/admintoExcel.action`,
+            method: "GET",
+            headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" },
+            responseType: "blob",
+            params,
+        });
+        return requestData;
+    },
+
+    // 导入监控信息
+    // async importByExcel(data) {
+    //     let requestData = await request({
+    //         // url: "/api/video/videoAdmin/importByExcel",
+    //         url: `${requests}/camera/importByExcel`,
+    //         method: "POST",
+    //         headers: { "Content-Type": "multipart/form-data" },
+    //         data: data,
+    //     });
+    //     return requestData;
+    // },
+};

+ 14 - 0
src/api/home.js

@@ -0,0 +1,14 @@
+import request from "@/utils/request";
+// const request='/api'
+export default {
+    /*搜索*/
+
+    async getHomeList(data) {
+        let requestData = await request({
+            url: "/api",
+            method: "POST",
+            data: data,
+        });
+        return requestData;
+    }
+}

+ 110 - 0
src/api/vidicons.js

@@ -0,0 +1,110 @@
+import request from "@/utils/request";
+const requests = '/video/transcoding'// 线上
+// const requests = '/video/transcoding/transcoding'// 线下
+export default {
+    // 添加监控信息
+    async addCamera(data) {
+        let requestData = await request({
+            url: `${requests}/camera/addCamera`,
+            method: "POST",
+            headers: { "Content-Type": "application/json; charset=utf-8" },
+            data: data,
+        });
+        return requestData;
+    },
+
+    // 删除监控信息
+    async delCamera(data) {
+        let requestData = await request({
+            url: `${requests}/camera/delete`,
+            method: "DELETE",
+            data
+        });
+        return requestData;
+    },
+
+    // 修改监控信息
+    async updateCamera(data) {
+        let requestData = await request({
+            url: `${requests}/camera/updateCamera`,
+            method: "PUT",
+            headers: { "Content-Type": "application/json; charset=utf-8" },
+            data,
+        });
+        return requestData;
+    },
+
+    // 监控信息列表
+    async queryCamera(data) {
+        let requestData = await request({
+            url: `${requests}/camera/queryCamera`,
+            method: "POST",
+            headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" },
+            params: data,
+        });
+        return requestData;
+    },
+    // 导出监控信息
+    async download(params) {
+        let requestData = await request({
+            url: `${requests}/camera/download`,
+            method: "GET",
+            headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" },
+            responseType: "blob",
+            params,
+        });
+        return requestData;
+    },
+    // 导入监控信息
+    async importByExcel(data) {
+        let requestData = await request({
+            url: `${requests}/camera/importByExcel`,
+            method: "POST",
+            headers: { "Content-Type": "multipart/form-data" },
+            data,
+        });
+        return requestData;
+    },
+
+    // 使用Stream推拉流
+    async addStreamSource(data) {
+        let requestData = await request({
+            url: `${requests}/stream/addStreamSource`,
+            method: "POST",
+            headers: { "Content-Type": "application/json; charset=utf-8" },
+            data,
+        });
+        return requestData;
+    },
+
+    // 关闭Stream推拉流
+    async delStreamSource(data) {
+        let requestData = await request({
+            url: `${requests}/stream/delStreamSource`,
+            method: "POST",
+            headers: { "Content-Type": "application/json; charset=utf-8" },
+            data,
+        });
+        return requestData;
+    },
+    // 更新输出链接
+    async updateCameraLink(params) {
+        let requestData = await request({
+            url: `${requests}/camera/updateCameraLink`,
+            method: "GET",
+            headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" },
+            params,
+        });
+        return requestData;
+    },
+    // 关闭当前播放回写剩下的播放链接、
+    async delAndUpdateLink(params) {
+        let requestData = await request({
+            url: `${requests}/stream/delAndUpdateLink`,
+            method: "GET",
+            headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" },
+            params,
+        });
+        return requestData;
+    },
+};

BIN
src/assets/add.png


BIN
src/assets/affiche.png


BIN
src/assets/back.png


BIN
src/assets/bottom.png


BIN
src/assets/classX.png


BIN
src/assets/classes.png


BIN
src/assets/classesA.png


BIN
src/assets/close.png


BIN
src/assets/colorSelect.png


BIN
src/assets/del.png


BIN
src/assets/home.png


BIN
src/assets/house.png


BIN
src/assets/ledger.png


BIN
src/assets/ledgerS.png


BIN
src/assets/left.png


BIN
src/assets/login.png


BIN
src/assets/logo.png


BIN
src/assets/map.png


BIN
src/assets/order.png


BIN
src/assets/orderS.png


BIN
src/assets/right.png


BIN
src/assets/scheduling.png


BIN
src/assets/search.png


BIN
src/assets/statement.png


BIN
src/assets/statementA.png


BIN
src/assets/system.png


BIN
src/assets/systemS.png


BIN
src/assets/timer.png


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
src/assets/vite.svg


BIN
src/assets/workTime.png


+ 129 - 0
src/layout/index.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="body-box">
+    <SidevarItem></SidevarItem>
+    <div class="content">
+      <Navbar></Navbar>
+      <router-view></router-view>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onBeforeMount, onMounted, watch } from "vue";
+import Navbar from "./sidebar/Navbar.vue";
+import SidevarItem from "./sidebar/SidevarItem.vue";
+import { useStore } from "vuex";
+import axios from "axios";
+import { useRouter } from "vue-router";
+const store = useStore();
+const router = useRouter();
+const api = ref("");
+const flag = ref(true);
+watch(
+  () => router.currentRoute.value.fullPath,
+  (newValue, oldValue) => {
+    console.log(newValue);
+    store.commit("indexUp", newValue);
+    sessionStorage.setItem("sidevarItem", newValue);
+  }
+);
+
+const tableData = reactive({
+  list: [],
+});
+
+onBeforeMount(async () => {
+  api.value = store.state.user.api;
+});
+</script>
+
+<style scoped lang="scss">
+.body-box {
+  display: flex;
+  .content {
+    // min-width: 1740px;
+    max-width: calc(100vw - 81px);
+    min-width: calc(100vw - 200px);
+    width: 100%;
+    height: calc(100vh);
+    background-color: rgba(238, 238, 238, 1);
+    :deep(.el-dialog__header .el-dialog__headerbtn) {
+      outline: none;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.is-message-box {
+  .el-message-box__header {
+    .el-message-box__headerbtn {
+      outline: none;
+    }
+  }
+  .el-message-box__btns {
+    .el-button--primary {
+      background-color: rgba(61, 81, 232, 1);
+      border: 0.5px solid rgba(61, 81, 232, 1);
+    }
+    .el-button--primary:hover {
+      background-color: rgb(119, 133, 239);
+      border: 0.5px solid rgb(119, 133, 239);
+    }
+  }
+}
+.el-dialog__body {
+  .el-input {
+    .el-input__suffix-inner {
+      color: rgba(61, 81, 232, 1);
+    }
+  }
+}
+.pw {
+  .el-dialog__body {
+    .el-form {
+      .el-form-item {
+        .queding {
+          background-color: rgba(61, 81, 232, 1);
+          border: 0.5px solid rgba(61, 81, 232, 1);
+        }
+        .queding:hover {
+          background-color: rgb(119, 133, 239);
+          border: 0.5px solid rgb(119, 133, 239);
+        }
+      }
+    }
+  }
+}
+
+.tangram-suggestion-main {
+  z-index: 999999;
+  .tangram-suggestion {
+    height: 150px;
+    overflow: auto;
+  }
+}
+
+#notification_1 {
+  .el-notification__group {
+    .el-notification__title {
+      color: red;
+    }
+  }
+}
+*::-webkit-scrollbar-track {
+  background-color: #fff;
+}
+
+*::-webkit-scrollbar {
+  background-color: #57b2ff;
+  height: 0;
+  width: 0;
+}
+
+*::-webkit-scrollbar-thumb {
+  background: #57b2ff;
+  border-radius: 4px;
+  height: 0;
+  width: 0;
+}
+</style>

+ 478 - 0
src/layout/sidebar/Navbar.vue

@@ -0,0 +1,478 @@
+<template>
+  <el-menu
+    :default-active="activeIndex"
+    class="el-menu-demo"
+    mode="horizontal"
+    background-color=""
+    text-color="#000"
+    active-text-color="#4392f7"
+    @select="handleSelect"
+  >
+    <!-- <el-icon
+      :size="20"
+      v-show="!menuclose"
+      class="fold"
+      @click="SpreadMenu(true)"
+      ><Fold
+    /></el-icon>
+    <el-icon
+      :size="20"
+      v-show="menuclose"
+      class="fold"
+      @click="SpreadMenu(false)"
+      ><Expand
+    /></el-icon> -->
+
+    <div class="logo">
+      <!-- <img src="@/assets/nanchang.png" style="width: 30px; height: 30px" /> -->
+      <span>靖安乡村民宿管理平台</span>
+    </div>
+    <div class="login">
+      <span class="dateTime">{{ dateTime }}</span>
+      <!-- <el-badge :value="titlenumber" class="item" v-if="titlenumber">
+        <img
+          src="@/assets/news.png"
+          @click="newsClick"
+          style="width: 20px; height: 20px; cursor: pointer"
+          alt=""
+        />
+      </el-badge>
+      <img
+        v-else
+        src="@/assets/news.png"
+        @click="newsClick"
+        style="width: 20px; height: 20px; cursor: pointer"
+        alt=""
+      /> -->
+      <div class="flex flex-wrap items-center" style="cursor: pointer">
+        <el-dropdown :hide-on-click="false" trigger="click">
+          <el-avatar :size="30">
+            <img
+              src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+            />
+          </el-avatar>
+          <template #dropdown>
+            <el-dropdown-menu>
+              <el-dropdown-item @click="uppassword">
+                <el-icon class="switchButton" :size="20" color="#000">
+                  <Lock />
+                </el-icon>
+                <span>修改密码</span>
+              </el-dropdown-item>
+              <el-dialog
+                :append-to-body="true"
+                custom-class="pw"
+                v-model="uppasswordShow"
+                title="修改密码"
+                width="30%"
+                :before-close="uppasswordClose"
+                align-center
+                :close-on-click-modal="false"
+              >
+                <el-form
+                  ref="ruleFormRef"
+                  :model="ruleForm"
+                  :rules="rules"
+                  label-width="100px"
+                  class="demo-ruleForm"
+                  :size="formSize"
+                  label-position="left"
+                  status-icon
+                >
+                  <!-- <el-form-item label="原密码" prop="oldpass">
+                    <el-input
+                      v-model="ruleForm.oldpass"
+                      placeholder="请输入原密码"
+                      clearable
+                    />
+                  </el-form-item> -->
+                  <el-form-item label="新密码" prop="nowpass">
+                    <el-input
+                      v-model="ruleForm.nowpass"
+                      placeholder="请输入新密码"
+                      clearable
+                    />
+                  </el-form-item>
+                  <el-form-item
+                    label="确定新密码"
+                    prop="correctpass"
+                    style="
+                      padding-bottom: 40px;
+                      border-bottom: 1px solid rgba(230, 230, 230, 1);
+                    "
+                  >
+                    <el-input
+                      v-model="ruleForm.correctpass"
+                      placeholder="请再次输入新密码"
+                      clearable
+                    />
+                  </el-form-item>
+
+                  <el-form-item class="options">
+                    <el-button
+                      class="queding"
+                      type="primary"
+                      color="rgba(9, 101, 98, 1)"
+                      @click="submitForm(ruleFormRef)"
+                    >
+                      确定
+                    </el-button>
+                    <el-button class="congzhi" @click="resetForm(ruleFormRef)"
+                      >重置</el-button
+                    >
+                  </el-form-item>
+                </el-form>
+                <!-- <template #footer>
+                  <span class="dialog-footer">
+                    <el-button @click="dialogVisible = false">取消</el-button>
+                    <el-button type="primary" @click="dialogVisible = false">
+                      确定
+                    </el-button>
+                  </span>
+                </template> -->
+              </el-dialog>
+              <el-dropdown-item @click="loginOut">
+                <el-icon class="switchButton" :size="20" color="#000">
+                  <SwitchButton />
+                </el-icon>
+                <span>退出登录</span>
+              </el-dropdown-item>
+            </el-dropdown-menu>
+          </template>
+        </el-dropdown>
+      </div>
+      <span class="name">{{ username }}</span>
+    </div>
+  </el-menu>
+</template>
+
+<script setup>
+import { ref, reactive, onBeforeMount, onMounted, watch } from "vue";
+import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
+import { useStore } from "vuex";
+import { useRouter } from "vue-router";
+import { dayjs } from "element-plus";
+import axios from "axios";
+
+const api = ref();
+const store = useStore();
+const router = useRouter();
+const username = ref(); // 账号名称
+const titlenumber = ref(1); //  消息条数
+const activeIndex = ref(); // 路由路径
+const loginOutDialogVisible = ref(false); // 退出按钮
+const menuclose = ref(false); // 左边状态栏展开按钮状态
+const uppasswordShow = ref(false); // 修改密码展示框
+const ruleForm = reactive({
+  oldpass: "",
+  nowpass: "",
+  correctpass: "",
+});
+const ruleFormRef = ref();
+// 表单验证
+const rules = reactive({
+  oldpass: [
+    {
+      required: true,
+      message: "密码不能为空",
+      trigger: "blur",
+    },
+  ],
+  nowpass: [
+    {
+      required: true,
+      message: "确认密码不能为空",
+      trigger: "blur",
+    },
+    {
+      min: 8,
+      max: 20,
+      pattern:
+        /^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\._\+(){}])[0-9a-zA-Z!@#$%^&*,\\._\+(){}]{8,20}$/,
+      message: "请输入8-20位正确密码(大小写字母·字符·数字)",
+      trigger: "blur",
+    },
+  ],
+  correctpass: [
+    {
+      required: true,
+      message: "确认密码不能为空",
+      trigger: "blur",
+    },
+    {
+      min: 8,
+      max: 20,
+      pattern:
+        /^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\._\+(){}])[0-9a-zA-Z!@#$%^&*,\\._\+(){}]{8,20}$/,
+      message: "请输入8-20位正确密码(大小写字母·字符·数字)",
+      trigger: "blur",
+    },
+  ],
+  // desc: [{ required: true, message: "Please input activity form", trigger: "blur" }],
+});
+
+// 监控消息通知数量
+watch(
+  () => store.state.user.newsNum,
+  (newValue, oldValue) => {
+    titlenumber.value = newValue;
+    console.log(newValue, "监控消息数量");
+  }
+);
+
+// 点击消息通知
+const newsClick = () => {
+  store.commit("indexUp", 0);
+  sessionStorage.setItem("sidevarItem", 0);
+  router.push({
+    path: `/repairs/news`,
+  });
+};
+const dateTime = ref(
+  dayjs().format("YYYY-MM-DD") + ` 星期四 ` + dayjs().format("HH:mm:ss")
+); // 时间
+
+// 选择菜单
+const handleSelect = (key, keyPath) => {
+  store.commit("navbarUpdata", key);
+  activeIndex.value = key;
+};
+
+// 展开按钮
+const SpreadMenu = (flag) => {
+  store.commit("menuClose", flag);
+  menuclose.value = flag;
+};
+// 修改密码
+const uppassword = () => {
+  uppasswordShow.value = true;
+};
+const uppasswordClose = () => {
+  uppasswordShow.value = false;
+  ruleFormRef.value.resetFields();
+};
+// 提交修改密码表单
+const submitForm = async (formEl) => {
+  if (!formEl) return;
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      let data = {
+        newPassword: ruleForm.nowpass,
+        confirmPassword: ruleForm.correctpass,
+        id: sessionStorage.getItem("token"),
+      };
+      if (ruleForm.nowpass == ruleForm.correctpass) {
+        let resUpdata = await axios({
+          method: "post",
+          url: api.value + "/mhotel/managerAdminupdateAdminManager.action",
+          headers: {
+            // token: sessionStorage.getItem("token"),
+            // user_head: sessionStorage.getItem("userhead"),
+          },
+          params: data,
+        });
+        if (resUpdata.data.code == 200) {
+          ElMessage({
+            type: "success",
+            showClose: true,
+            message: resUpdata.data.message,
+            center: true,
+          });
+          sessionStorage.removeItem("token");
+          // localStorage.removeItem("pass");
+          uppasswordShow.value = false;
+          ruleFormRef.value.resetFields();
+          ElNotification({
+            type: "warning",
+            title: "提示!!!",
+            message: "密码已修改,请重新登录页面",
+            // duration: 0,
+            // position: "top-right",
+          });
+        } else {
+          ElMessage({
+            type: "error",
+            showClose: true,
+            message: res.data.message,
+            center: true,
+          });
+        }
+      } else {
+        ElMessage({
+          type: "error",
+          showClose: true,
+          message: "两次密码输入不正确",
+          center: true,
+        });
+      }
+    } else {
+      console.log("error submit!", fields);
+    }
+  });
+};
+// 重置表单
+const resetForm = (formEl) => {
+  // console.log("重置表单");
+  if (!formEl) return;
+  formEl.resetFields();
+};
+
+const loginOut = () => {
+  ElMessageBox.confirm("是否退出登录?", "提示", {
+    confirmButtonText: "确认",
+    cancelButtonText: "取消",
+    type: "warning",
+  })
+    .then(() => {
+      sessionStorage.removeItem("token");
+      router.push({
+        path: `/login`,
+      });
+      ElMessage({
+        type: "success",
+        message: "退出成功",
+      });
+    })
+    .catch(() => {
+      ElMessage({
+        type: "info",
+        message: "已取消登录",
+      });
+    });
+};
+
+onMounted(() => {
+  api.value = store.state.user.api;
+  activeIndex.value = store.state.user.navbar;
+  if (sessionStorage.getItem("newsNum") == 0) {
+    titlenumber.value = "";
+  } else {
+    titlenumber.value = sessionStorage.getItem("newsNum");
+  }
+
+  username.value = sessionStorage.getItem("username");
+  setInterval(() => {
+    var week = ["日", "一", "二", "三", "四", "五", "六"];
+    var datas = dayjs().day();
+    dateTime.value =
+      dayjs().format("YYYY-MM-DD") +
+      ` 星期${week[datas]} ` +
+      dayjs().format("HH:mm:ss");
+  }, 1000);
+});
+</script>
+
+<style scoped lang="scss">
+.el-menu--horizontal {
+  border-bottom: none;
+  display: flex;
+  align-items: center;
+  height: 65px;
+  // width: 100%;
+  background-color: #fff;
+  box-shadow: 5px 5px 10px 0px rgba(213, 228, 252, 1);
+  .logo {
+    left: 90px;
+    display: flex;
+    align-items: center;
+    span {
+      margin-left: 20px;
+      font-size: 24px;
+      font-weight: 600;
+    }
+  }
+  .login {
+    color: #000;
+    display: flex;
+    align-items: center;
+    position: absolute;
+    right: 10px;
+    top: 17px;
+
+    .dateTime {
+      margin-right: 20px;
+    }
+    .el-badge {
+      display: flex;
+      align-items: center;
+      // :deep(.el-badge__content) {
+      //   width: 2px;
+      //   height: 14px;
+      // }
+    }
+    .items-center {
+      margin-left: 20px;
+    }
+    .name {
+      height: 20px;
+      line-height: 20px;
+      text-decoration: underline;
+      padding: 0 10px;
+      margin: 0 10px;
+      border-left: 2px solid #ccc;
+    }
+    .switchButton {
+      cursor: pointer;
+    }
+  }
+  .login:focus {
+    outline: none;
+  }
+  .fold {
+    width: 46px;
+    height: 65px;
+  }
+  .fold:hover {
+    cursor: pointer;
+    background-color: rgba(67, 146, 249, 0.1);
+  }
+}
+.el-dialog__body {
+  .options {
+    display: flex;
+    flex-direction: row-reverse;
+    :deep(.el-form-item__content) {
+      margin-left: 0 !important;
+      flex: none;
+    }
+    :deep(.queding) {
+      background-color: rgba(9, 101, 98, 1) !important;
+      border: 0.5px solid rgba(9, 101, 98, 1) !important;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.el-overlay {
+  .el-message-box__btns {
+    .el-button--primary {
+      background-color: rgba(9, 101, 98, 1) !important;
+      border: 0.5px solid rgba(9, 101, 98, 1) !important;
+    }
+  }
+  .el-overlay-dialog {
+    .pw {
+      border-radius: 11px;
+
+      .el-dialog__header {
+        border-radius: 11px 11px 0 0;
+        background: rgba(237, 241, 245, 1);
+        font-weight: 600;
+        margin: 0;
+        .el-dialog__headerbtn {
+          outline: none;
+        }
+      }
+      .el-dialog__body {
+        padding: 30px 20px 10px 20px;
+        .el-input {
+          width: 200px;
+        }
+        .options {
+          margin-left: 170px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 253 - 0
src/layout/sidebar/SidevarItem.vue

@@ -0,0 +1,253 @@
+<template>
+  <div class="box-item">
+    <el-menu
+      class="el-menu-vertical-demo"
+      text-color="#fff"
+      active-color="rgba(9, 101, 98, 1)"
+      :default-active="activeIndex"
+      :collapse="menuClose"
+      @select="handleSelect"
+      :default-openeds="[34]"
+      :router="true"
+    >
+      <div class="logo el-menu-item">
+        <el-icon :size="20"
+          ><img src="@/assets/logo.png" style="width: 30px; height: 24px"
+        /></el-icon>
+      </div>
+      <el-menu-item index="/seniorCelebrity/order">
+        <img
+          v-if="activeIndex == '/seniorCelebrity/order'"
+          src="@/assets/orderS.png"
+          alt=""
+          style="width: 22px; height: 22px; margin: 0 18px"
+        />
+        <img
+          v-else
+          src="@/assets/order.png"
+          alt=""
+          style="width: 22px; height: 22px; margin: 0 18px"
+        />
+        <span>订单管理</span>
+      </el-menu-item>
+      <el-menu-item index="/seniorCelebrity/ledger">
+        <img
+          v-if="activeIndex == '/seniorCelebrity/ledger'"
+          src="@/assets/ledgerS.png"
+          alt=""
+          style="width: 22px; height: 22px; margin: 0 18px"
+        />
+        <img
+          v-else
+          src="@/assets/ledger.png"
+          alt=""
+          style="width: 22px; height: 22px; margin: 0 18px"
+        />
+        <span>台账管理</span>
+      </el-menu-item>
+      <el-sub-menu :index="34">
+        <template #title>
+          <img
+            src="@/assets/house.png"
+            style="width: 22px; height: 22px; margin: 0 20px 0 18px"
+            alt=""
+          />
+          <span>民宿管理</span>
+        </template>
+        <el-menu-item index="/seniorCelebrity/houseInfo">
+          <template #title>
+            <!-- <img src="@/assets/home.png" alt="" /> -->
+            <span>民宿信息</span>
+          </template>
+        </el-menu-item>
+        <el-menu-item index="/seniorCelebrity/houseType">
+          <template #title>
+            <!-- <img src="@/assets/home.png" alt="" /> -->
+            <span>房型管理</span>
+          </template>
+        </el-menu-item>
+        <el-menu-item index="/seniorCelebrity/houseList">
+          <template #title>
+            <!-- <img src="@/assets/home.png" alt="" /> -->
+            <span>房源信息</span>
+          </template>
+        </el-menu-item>
+      </el-sub-menu>
+      <el-menu-item
+        index="/seniorCelebrity/account"
+        v-if="store.state.user.level == 2"
+      >
+        <img
+          v-if="activeIndex == '/seniorCelebrity/account'"
+          src="@/assets/systemS.png"
+          alt=""
+          style="width: 20px; height: 20px; margin: 0 20px"
+        />
+        <img
+          v-else
+          src="@/assets/system.png"
+          alt=""
+          style="width: 20px; height: 20px; margin: 0 21px"
+        />
+        <span>账号管理</span>
+      </el-menu-item>
+    </el-menu>
+  </div>
+</template>
+
+<script setup>
+import { ref, onBeforeMount, onMounted, watch, reactive } from "vue";
+import { useStore } from "vuex";
+
+import { useRouter } from "vue-router";
+
+const store = useStore();
+const router = useRouter();
+
+const menuClose = ref(false);
+const activeIndex = ref(1);
+const acitveItems = reactive({ list: [] });
+
+watch(
+  () => store.state.user.collapse,
+  (newValue, oldValue) => {
+    menuClose.value = newValue;
+  }
+);
+watch(
+  () => store.state.user.activeIndex,
+  (newValue, oldValue) => {
+    console.log(newValue);
+    activeIndex.value = newValue;
+  }
+);
+
+const handleSelect = (key, keyPath) => {
+  // store.commit("indexUp", key);
+  // activeIndex.value = key;
+  // sessionStorage.setItem("sidevarItem", key);
+  console.log(key, keyPath);
+
+  router.push({
+    path: `${key}`,
+  });
+
+  activeIndex.value = key;
+  store.commit("indexUp", key);
+  sessionStorage.setItem("sidevarItem", key);
+  // if (activeIndex.value == 1) {
+  //   router.push({
+  //     path: `/seniorCelebrity/order`,
+  //   });
+  // }
+  // if (activeIndex.value == 2) {
+  //   router.push({
+  //     path: `/seniorCelebrity/ledger`,
+  //   });
+  // }
+
+  // if (activeIndex.value == 3) {
+  //   router.push({
+  //     path: `/seniorCelebrity/houseInfo`,
+  //   });
+  // }
+  // if (activeIndex.value == 4) {
+  //   router.push({
+  //     path: `/seniorCelebrity/houseType`,
+  //   });
+  // }
+  // if (activeIndex.value == 5) {
+  //   router.push({
+  //     path: `/seniorCelebrity/houseList`,
+  //   });
+  // }
+  // if (activeIndex.value == 6) {
+  //   router.push({
+  //     path: `/seniorCelebrity/account`,
+  //   });
+  // }
+};
+onBeforeMount(() => {
+  activeIndex.value = sessionStorage.getItem("sidevarItem");
+});
+</script>
+
+<style lang="scss" scoped>
+.el-menu-vertical-demo:not(.el-menu--collapse) {
+  width: 200px;
+  // min-height: 400px;
+}
+.el-menu {
+  width: 100%;
+  height: 100%;
+  // background: linear-gradient(
+  //   0deg,
+  //   rgba(134, 132, 255, 1) 0%,
+  //   rgba(60, 80, 232, 1) 100%
+  // );
+  background: rgba(9, 101, 98, 1);
+  box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.16);
+
+  .logo {
+    height: 65px;
+    color: rgb(255, 255, 255);
+    cursor: default;
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+  }
+  .logo:hover {
+    background-color: transparent !important;
+  }
+  .el-sub-menu {
+    .el-menu-item {
+      // background-color: rgba(255, 255, 255, 1);
+      // color: rgba(9, 101, 98, 1);
+      padding: 0 20px 0 78px;
+    }
+    :deep(.el-tooltip__trigger) {
+      padding: 0 20px;
+    }
+    :deep(.el-sub-menu__title):hover {
+      color: rgba(9, 101, 98, 1);
+      background-color: rgb(214, 214, 214);
+      span {
+        color: rgba(9, 101, 98, 1);
+      }
+    }
+
+    .el-menu--inline {
+      background-color: rgba(9, 101, 98, 1);
+    }
+  }
+  .el-menu {
+    .el-menu-item {
+      background-color: rgba(9, 101, 98, 1);
+      // padding-left: 30px;
+    }
+    .el-menu-item:hover {
+      color: rgba(9, 101, 98, 1);
+      background-color: rgb(214, 214, 214);
+    }
+  }
+  .el-sub-menu:hover {
+    color: rgba(9, 101, 98, 1);
+  }
+
+  .el-menu-item:hover {
+    background-color: rgb(214, 214, 214);
+    color: rgba(9, 101, 98, 1);
+  }
+  .el-menu-item.is-active {
+    background-color: rgba(255, 255, 255, 1);
+    color: rgba(9, 101, 98, 1);
+  }
+}
+
+// .el-menu-item.is-active {
+//   box-sizing: border-box;
+//   // background-color: #fff;
+//   background-color: rgba(111, 182, 184, 1);
+//   color: #fff;
+// }
+</style>

+ 28 - 0
src/main.js

@@ -0,0 +1,28 @@
+import { createApp } from 'vue'
+import './style.css'
+import ElementPlus from 'element-plus'
+import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
+import 'element-plus/dist/index.css'
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
+import App from './App.vue'
+
+
+import router from "@/router";
+import store from '@/store'
+
+
+
+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(store)
+
+
+app.mount('#app')
+app.config.devtools = true;

+ 106 - 0
src/router/index.js

@@ -0,0 +1,106 @@
+import {
+  createRouter,
+  createWebHistory,
+  createWebHashHistory,
+} from "vue-router";
+import Layout from "@/layout/index.vue";
+import store from "@/store";
+const routes = [
+  {
+    path: "/login",
+    component: () => import("@/views/login/index.vue"),
+  },
+  {
+    path: "/",
+    redirect: "/login",
+  },
+  {
+    path: "/seniorCelebrity",
+    name: "seniorCelebrity",
+    component: Layout,
+    children: [
+      {
+        path: "order",
+        name: "order",
+        component: () => import("@/views/order/order.vue"),
+        meta: { title: "Dashboard", icon: "dashboard" },
+      },
+      {
+        path: "ledger",
+        name: "ledger",
+        component: () => import("@/views/ledger/ledger.vue"),
+        meta: { title: "Dashboard", icon: "dashboard" },
+      },
+      {
+        path: "houseInfo",
+        name: "houseInfo",
+        component: () => import("@/views/roomInfo/roomInfo.vue"),
+        meta: { title: "Dashboard", icon: "dashboard" },
+      },
+      {
+        path: "houseType",
+        name: "houseType",
+        component: () => import("@/views/roomType/roomType.vue"),
+        meta: { title: "Dashboard", icon: "dashboard" },
+      },
+      {
+        path: "houseList",
+        name: "houseList",
+        component: () => import("@/views/houseList/houseList.vue"),
+        meta: { title: "Dashboard", icon: "dashboard" },
+      },
+      // {
+      //   path: "account",
+      //   component: () => import("@/views/account/account.vue"),
+      //   meta: { title: "Dashboard", icon: "dashboard" },
+      // },
+    ],
+  },
+  {
+    path: "/houseInfo/houseMap",
+    component: () => import("@/views/map/map.vue"),
+    meta: { title: "Dashboard", icon: "dashboard" },
+  },
+];
+const router = createRouter({
+  // history: createWebHashHistory("/carstop/dist6"), // 线上地址
+  // history: createWebHashHistory("/testingServertomcat/dist6"), // 测试环境发布地址
+  history: createWebHashHistory("/hotelReservation/pc3/"), // 测试环境发布地址
+  routes: routes,
+});
+export default router;
+router.beforeEach(async (to, from, next) => {
+  let hasRoutes = store.state.user.hasRoutes;
+  if (sessionStorage.getItem("token")) {
+    if (!hasRoutes || to.path == "/login") {
+      console.log("第一次登录也触发");
+
+      store.commit("SET_ROUTES_STATE", true);
+      let res = await store.dispatch("login", {
+        adminName: sessionStorage.getItem("username"),
+        password: sessionStorage.getItem("name"),
+      });
+      if (res == "success") {
+        if (store.state.user.level == 2) {
+          let modules = import.meta.glob("../views/**/*.vue");
+          let arr = {
+            path: "account",
+            name: "account",
+            component: modules[`../views/account/account.vue`],
+          };
+          router.addRoute("seniorCelebrity", arr);
+        }
+      }
+      next({ ...to, replace: true }); //----------解决
+
+      // next({ path: "/index" }); //----------解决
+    }
+    next(); //放行
+  } else {
+    if (to.path == "/login") {
+      next();
+    } else {
+      next(`/login`);
+    }
+  }
+});

BIN
src/static/daoxiang.mp3


BIN
src/static/gaobai.mp3


+ 5 - 0
src/store/getters.js

@@ -0,0 +1,5 @@
+//store/getters
+const getters = {
+    age: state => state.user.age //导出age
+}
+export default getters;

+ 22 - 0
src/store/index.js

@@ -0,0 +1,22 @@
+//store/index.js
+
+import createPersistedstate from 'vuex-persistedstate' //持久化插件
+import { createStore } from 'vuex'; //引入vuex
+import user from './modules/user'; //引入modules的方法;
+import getters from './getters' //引入getters
+const store = createStore({
+    modules: {
+        user
+    },
+    getters,
+    // plugins: [
+    //     createPersistedstate({
+    //         // key: 'userStore', //存储持久状态的键。(默认:vuex)
+    //         paths: ['user'], //部分持续状态的任何路径的数组。如果不加,默认所有。
+    //         storage: window.sessionStorage //默认存储到localStorage,想要存储到sessionStorage
+    //     })
+    // ]
+
+})
+
+export default store;

+ 98 - 0
src/store/modules/user.js

@@ -0,0 +1,98 @@
+import axios from "axios";
+
+//store/modules/user.js
+
+// 声明变量
+const state = {
+  collapse: false,
+  activeIndex: 1,
+  username: "",
+  password: "",
+  // api: "/carstop/carbook", // 线上
+  api: "/hotelReservation", // 测试
+  islogin: 1,
+  hasRoutes: false,
+  level: 1,
+};
+
+// 修改变量(state不能直接赋值修改,只能通过mutations)
+const mutations = {
+  menuClose: (state, value) => {
+    state.collapse = value;
+  },
+  indexUp: (state, value) => {
+    state.activeIndex = value;
+  },
+  userName: (state, value) => {
+    state.username = value;
+  },
+  passWord: (state, value) => {
+    state.password = value;
+  },
+  SET_ROUTES_STATE: (state, value) => {
+    state.hasRoutes = value;
+  },
+  LEVEL: (state, value) => {
+    state.level = value;
+    console.log("设置level", value);
+  },
+};
+// mutations的值由actions传入(异步)
+const actions = {
+  newsAsync: async ({ commit, state }) => {
+    let data = new FormData();
+    let res = await axios({
+      method: "post",
+      url: state.api + "/carBook/usermesUnRead.action",
+      headers: {
+        token: sessionStorage.getItem("token"),
+      },
+      data: data,
+    });
+    console.log(res, "系统消息");
+
+    commit("newsUp", res.data.u_count);
+    sessionStorage.setItem("newsNum", res.data.u_count);
+    console.log("vuex", res.data.u_count);
+  },
+  // 系统扫码时间
+  login: async ({ commit, state }, data) => {
+    return new Promise(async (resolve, reject) => {
+      let res = await axios({
+        method: "get",
+        url: state.api + "/mhotel/managerAdminloginAdmin.action",
+        params: data,
+      });
+
+      console.log(res, "登录账号");
+      if (res.data.code == 200) {
+        sessionStorage.setItem("name", data.password);
+
+        sessionStorage.setItem("token", res.data.data.managerId);
+        // 1 是  0 否
+        if (res.data.isLogin == 1) {
+          sessionStorage.setItem("isLogin", 1);
+        } else {
+          sessionStorage.setItem("isLogin", 0);
+        }
+        sessionStorage.setItem("username", res.data.data.adminName);
+        commit("LEVEL", res.data.data.level);
+
+        commit("userName", data.user);
+
+        // commit("roles", asyncRouter);
+        // sessionStorage.setItem("roles", JSON.stringify(asyncRouter));
+
+        resolve("success");
+      } else {
+        reject("reject");
+      }
+    });
+  },
+};
+
+export default {
+  state,
+  mutations,
+  actions,
+};

+ 89 - 0
src/style.css

@@ -0,0 +1,89 @@
+:root {
+  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+  line-height: 1.5;
+  font-weight: 400;
+
+  color-scheme: light dark;
+  color: rgba(255, 255, 255, 0.87);
+  background-color: #242424;
+
+  font-synthesis: none;
+  text-rendering: optimizeLegibility;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-text-size-adjust: 100%;
+}
+
+a {
+  font-weight: 500;
+  color: #646cff;
+  text-decoration: inherit;
+}
+a:hover {
+  color: #535bf2;
+}
+
+a {
+  font-weight: 500;
+  color: #646cff;
+  text-decoration: inherit;
+}
+a:hover {
+  color: #535bf2;
+}
+
+body {
+  margin: 0;
+  display: flex;
+  place-items: center;
+  min-width: 320px;
+  min-height: 100vh;
+}
+
+h1 {
+  font-size: 3.2em;
+  line-height: 1.1;
+}
+
+button {
+  border-radius: 8px;
+  border: 1px solid transparent;
+  padding: 0.6em 1.2em;
+  font-size: 1em;
+  font-weight: 500;
+  font-family: inherit;
+  background-color: #1a1a1a;
+  cursor: pointer;
+  transition: border-color 0.25s;
+}
+button:hover {
+  border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+  outline: 4px auto -webkit-focus-ring-color;
+}
+
+.card {
+  padding: 2em;
+}
+
+/* #app {
+  max-width: 1280px;
+  margin: 0 auto;
+  padding: 2rem;
+  text-align: center;
+} */
+
+@media (prefers-color-scheme: light) {
+  :root {
+    color: #213547;
+    background-color: #ffffff;
+  }
+  a:hover {
+    color: #747bff;
+  }
+  button {
+    background-color: #f9f9f9;
+  }
+}

+ 1 - 0
src/style/mixin.scss

@@ -0,0 +1 @@
+$default: red

+ 23 - 0
src/utils/loadMap.js

@@ -0,0 +1,23 @@
+/**
+ * 动态加载百度地图api函数
+ * @param {String} ak  百度地图AK,必传
+ */
+export default function loadBMap(ak) {
+  return new Promise((resolve, reject) => {
+    if (typeof window.BMap !== "undefined") {
+      resolve(window.BMap);
+      return true;
+    }
+    window.onBMapCallback = function () {
+      resolve(window.BMap);
+      console.log("百度地图脚本初始化成功...");
+      return true;
+    };
+    const script = document.createElement("script");
+    script.type = "text/javascript";
+    script.src = `https://api.map.baidu.com/api?v=3.0&ak=${ak}&callback=onBMapCallback&s=1`;
+    script.onerror = reject;
+    document.head.appendChild(script);
+    return true;
+  });
+}

+ 46 - 0
src/utils/request.js

@@ -0,0 +1,46 @@
+import axios from "axios";
+const service = axios.create({
+    baseURL: import.meta.env.VITE_BASE_API, //接口统一域名
+    timeout: 6000, //设置超时
+   
+});
+
+// request拦截器
+service.interceptors.request.use(
+    (config) => {
+        config.data = JSON.stringify(config.data); //数据转化,也可以使用qs转换
+        // config.headers = {
+        //     'Content-Type': 'application/json' //配置请求头
+        // }
+        // config.headers = { 'Content-Type': 'application/x-www-form-urlencoded' } //配置请求头
+        //如有需要:注意使用token的时候需要引入cookie方法或者用本地localStorage等方法,推荐js-cookie
+        // const token = sessionStorage.getItem("token"); //这里取token之前,你肯定需要先拿到token,存一下
+        // if (token) {
+        //     // config.params = { 'admin_token': token } //如果要求携带在参数中
+        //     config.headers["token"] = token; //如果要求携带在请求头中
+        // }
+        return config;
+    },
+    (error) => {
+        Promise.reject(error);
+    }
+);
+// 响应拦截器
+service.interceptors.response.use(
+    (response) => {
+        const res = response.data;
+
+        return response.data;
+    },
+    (error) => {
+        /* Message({
+                      message: '服务器调用错误',
+                      type: 'error',
+                      duration: 5 * 1000
+                    }) */
+        console.log(error);
+
+        return Promise.reject(error);
+    }
+);
+export default service;

+ 22 - 0
src/utils/rsa.js

@@ -0,0 +1,22 @@
+import { JSEncrypt } from 'jsencrypt';
+let publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMOcPB06u5yKyQsPjfVWiWgbEIrd14kiXNNihciaVKb6HnkQvq7zpQuZ80WEX94spnUMI3iOAl/GmIvHrpGwcbB4hJbznm+PajiwnUSPuCCXA68YJF640cJKb/8KeM7WVz69OFkIEPHhVxOy4FFF5QWe/kt6zOZ19HmE+ak+5x/QIDAQAB'
+let privateKey = '这里是封装的私钥'
+//加密方法
+export function RSAencrypt(pas) {
+    //实例化jsEncrypt对象
+    let jse = new JSEncrypt();
+    //设置公钥
+    jse.setPublicKey(publicKey);
+    console.log('加密:' + jse.encrypt(pas))
+    return jse.encrypt(pas);
+}
+
+//解密方法
+export function RSAdecrypt(pas) {
+    let jse = new JSEncrypt();
+    // 私钥
+    jse.setPrivateKey(privateKey)
+    console.log('解密:' + jse.decrypt(pas))
+    return jse.decrypt(pas);
+}
+

+ 879 - 0
src/views/account/account.vue

@@ -0,0 +1,879 @@
+<template>
+  <div class="content-box">
+    <div class="left">
+      <!-- <el-icon :size="23" class="camera"><VideoCameraFilled /></el-icon> -->
+      <span class="cameratxt">账号管理</span>
+    </div>
+    <div class="middle">
+      <div class="filter">
+        <div class="condition">
+          <span>关键字 : </span>
+          <el-input
+            clearable
+            v-model="searchInput.adminName"
+            @clear="searchBtn"
+            class="w-50 m-2"
+            placeholder="请输入用户名"
+            style="width: 150px"
+          />
+        </div>
+
+        <el-button
+          style="margin-left: 20px"
+          color="rgba(9, 101, 98, 1)"
+          type="primary"
+          class="search"
+          @click="searchBtn"
+          ><el-icon><Search /></el-icon> <span>查询</span></el-button
+        >
+      </div>
+      <!-- 按钮列表 -->
+      <div class="gongneng">
+        <el-button type="primary" color="rgba(9, 101, 98, 1)" @click="addlist"
+          ><el-icon><CirclePlus /></el-icon><span>新增账号</span></el-button
+        >
+      </div>
+    </div>
+    <div class="footer">
+      <el-table
+        :row-class-name="tableRowClassName"
+        :data="tableData.list"
+        @selection-change="handleSelectionChange"
+        style="width: 100%"
+        :header-cell-style="{
+          background: 'rgba(240, 243, 247, 1)',
+          height: '50px',
+          border: 0,
+        }"
+      >
+        <!-- <el-table-column align="center" type="selection" width="80" /> -->
+        <el-table-column
+          width="150"
+          align="center"
+          label="序号"
+          type="index"
+          index="1"
+        />
+        <el-table-column align="center" prop="corpnPhone" label="手机" />
+        <el-table-column align="center" prop="adminName" label="用户名" />
+        <el-table-column align="center" prop="corpnName" label="姓名" />
+        <el-table-column align="center" label="角色">
+          <template #default="{ row }">
+            {{ row.level == 1 ? "管理员" : "超级管理员" }}
+          </template>
+        </el-table-column>
+        <el-table-column align="center" prop="remark" label="备注" />
+
+        <el-table-column align="center" label="操作" width="220">
+          <template #default="scope">
+            <div class="options">
+              <div class="reset" @click="reset(scope.row)">密码重置</div>
+              <div class="look" @click="edit(scope.row)">修改</div>
+              <el-popconfirm
+                width="220"
+                confirm-button-text="确认"
+                cancel-button-text="取消"
+                :icon="InfoFilled"
+                icon-color="#f89626"
+                title="是否删除此账号?"
+                @confirm="del(scope.row)"
+                @cancel="cancelEvent"
+              >
+                <template #reference>
+                  <div class="del">删除</div>
+                </template>
+              </el-popconfirm>
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 添加车辆弹窗 -->
+      <el-dialog
+        class="addStaff"
+        v-model="addDialogVisible"
+        :close-on-click-modal="false"
+        :close-on-press-escape="false"
+        :title="dialongTitle"
+        align-center
+        width="609"
+        :before-close="cancelAdd"
+      >
+        <el-form
+          ref="ruleFormRef"
+          :model="ruleForm"
+          :rules="rules"
+          label-width="100px"
+          class="demo-ruleForm"
+          :size="formSize"
+          label-position="left"
+          status-icon
+        >
+          <el-form-item label="用户名 :" prop="adminName">
+            <el-input
+              v-model="ruleForm.adminName"
+              placeholder="请输入用户名"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="姓名 :" prop="corpnName">
+            <el-input
+              v-model="ruleForm.corpnName"
+              placeholder="请输入姓名"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="手机号码 :" prop="corpnPhone">
+            <el-input
+              v-model="ruleForm.corpnPhone"
+              placeholder="请输入手机号码"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="密码 :" prop="password">
+            <el-input
+              v-model="ruleForm.password"
+              placeholder="请输入密码"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="确认密码 :" prop="againPass">
+            <el-input
+              v-model="ruleForm.againPass"
+              placeholder="请再一次输入密码"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="角色 :" prop="level">
+            <el-radio-group v-model="ruleForm.level">
+              <el-radio :label="1" v-if="ruleForm.level == 1">管理员</el-radio>
+              <el-radio :label="2" v-if="ruleForm.level == 2"
+                >超级管理员</el-radio
+              >
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="简介 :" prop="remark">
+            <el-input
+              v-model="ruleForm.remark"
+              :rows="3"
+              type="textarea"
+              placeholder="请输入民宿简介信息"
+            />
+          </el-form-item>
+
+          <el-form-item class="options">
+            <el-button
+              color="rgba(9, 101, 98, 1)"
+              class="queding"
+              type="primary"
+              @click="submitAdd(ruleFormRef)"
+            >
+              确定
+            </el-button>
+            <el-button @click="cancelAdd(ruleFormRef)">取消</el-button>
+          </el-form-item>
+        </el-form>
+      </el-dialog>
+    </div>
+
+    <!-- 分页组件 -->
+    <el-pagination
+      background
+      :current-page="currentPage"
+      :page-size="pageSize"
+      layout="total, prev, pager, next, jumper, slot"
+      :total="total"
+      @update:current-page="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, nextTick, onBeforeMount, onUnmounted } from "vue";
+import { useRouter } from "vue-router";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { Calendar } from "@element-plus/icons-vue";
+import { dayjs } from "element-plus";
+import lodash, { reduce } from "lodash";
+import axios from "axios";
+import { useStore } from "vuex";
+const store = useStore();
+const router = useRouter();
+// 表格数据
+const tableData = reactive({
+  list: [
+    // {
+    //   phone: 1234,
+    //   adminName: "admin",
+    //   userName: "张三",
+    //   level: 1,
+    //   remark: "测试",
+    // },
+    // {
+    //   phone: 1234,
+    //   adminName: "test",
+    //   userName: "李四",
+    //   level: 1,
+    //   remark: "测试11",
+    // },
+    // {
+    //   phone: 1234,
+    //   adminName: "admin1",
+    //   userName: "张三",
+    //   level: 1,
+    //   remark: "测试",
+    // },
+    // {
+    //   phone: 1234,
+    //   adminName: "admin2",
+    //   userName: "张三",
+    //   level: 1,
+    //   remark: "测试",
+    // },
+  ],
+});
+const activeIndex = ref(); // 默认跳转路由
+const dialongTitle = ref("新增账号"); // 弹窗标题
+
+const searchInput = reactive({
+  adminName: "",
+}); // 搜索按钮数据
+5;
+
+const currentPage = ref(1); // 当前页
+const pageSize = ref(10);
+const total = ref(); // 当前总数
+const selectData = reactive({
+  list: [],
+}); // 多选框选择的数据
+const api = ref("");
+const addDialogVisible = ref(false); // 控制添加员工弹窗
+
+// 表单数据
+const formSize = ref("default");
+const ruleFormRef = ref();
+const ruleForm = reactive({
+  corpnPhone: "",
+  adminName: "",
+  corpnName: "",
+  level: 1,
+  remark: "",
+  password: "",
+  againPass: "",
+  id: "",
+});
+var checkUserName = (rule, value, callback) => {
+  if (!value) {
+    return callback(new Error("请输入用户名)"));
+  }
+
+  var reg = /^[a-zA-Z0-9]{6,16}$/;
+  if (!reg.test(value)) {
+    callback(new Error("必须为6-16个数字或字母!"));
+  } else {
+    callback();
+  }
+};
+var checkFullName = (rule, value, callback) => {
+  if (!value) {
+    return callback(new Error("请输入姓名"));
+  }
+
+  var reg = /^[\u4e00-\u9fa5]{2,6}$/;
+  if (!reg.test(value)) {
+    callback(new Error("必须为2-6个汉字!"));
+  } else {
+    callback();
+  }
+};
+var checkPhone = (rule, value, callback) => {
+  if (!value) {
+    return callback(new Error("请输入手机号"));
+  }
+  setTimeout(() => {
+    var reg = /^1[3456789]\d{9}$/;
+    if (!reg.test(value)) {
+      callback(new Error("手机号格式不对"));
+    } else {
+      callback();
+    }
+  }, 100);
+};
+// 表单验证
+const rules = reactive({
+  corpnName: [
+    { required: true, message: "姓名不能为空", trigger: "blur" },
+    { validator: checkFullName, trigger: "blur" },
+  ],
+  adminName: [
+    { required: true, message: "用户名不能为空", trigger: "blur" },
+    { validator: checkUserName, trigger: "blur" },
+  ],
+  // ^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\._\+(){}])[0-9a-zA-Z!@#$%^&*,\\._\+(){}]{8,20}$
+  password: [
+    {
+      required: true,
+      message: "密码不能为空",
+      trigger: "blur",
+    },
+    {
+      min: 8,
+      max: 20,
+      pattern:
+        /^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\._\+(){}])[0-9a-zA-Z!@#$%^&*,\\._\+(){}]{8,20}$/,
+      message: "请输入8-20位正确密码(大小写字母·字符·数字)",
+      trigger: "blur",
+    },
+  ],
+  againPass: [
+    {
+      required: true,
+      message: "确认密码不能为空",
+      trigger: "blur",
+    },
+    {
+      min: 8,
+      max: 20,
+      pattern:
+        /^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\._\+(){}])[0-9a-zA-Z!@#$%^&*,\\._\+(){}]{8,20}$/,
+      message: "请输入8-20位正确密码(大小写字母·字符·数字)",
+      trigger: "blur",
+    },
+  ],
+  level: [
+    {
+      required: true,
+      message: "角色不能为空",
+      trigger: "blur",
+    },
+  ],
+  remark: [
+    {
+      required: true,
+      message: "备注不能为空",
+      trigger: "blur",
+    },
+  ],
+  corpnPhone: [
+    {
+      required: true,
+      message: "电话号码不能为空",
+      trigger: "blur",
+    },
+    { validator: checkPhone, trigger: "blur" },
+  ],
+
+  // desc: [{ required: true, message: "Please input activity form", trigger: "blur" }],
+});
+// 获取账户列表
+const getList = async () => {
+  // if (searchInput.account) {
+  //   data.adminName = searchInput.adminName;
+  // }
+  let data = {
+    page: currentPage.value, // 当前页
+    rows: pageSize.value, // 一页数据条数
+    adminName: searchInput.adminName, //用户名
+    managerId: sessionStorage.getItem("token"),
+  };
+  let res = await axios({
+    method: "get",
+    url: api.value + "/mhotel/managerAdminqueryPage.action",
+    headers: {
+      // token: sessionStorage.getItem("token"),
+    },
+    params: data,
+  });
+  console.log(res, "账号信息");
+  if (res.data.code == 200) {
+    tableData.list = res.data.data.pageList;
+    total.value = res.data.data.total;
+    // ElMessage({
+    //   type: "success",
+    //   showClose: true,
+    //   message: res.data.message,
+    //   center: true,
+    // });
+  } else {
+    ElMessage({
+      type: "error",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  }
+};
+
+// 搜索功能
+const searchBtn = lodash.debounce(async () => {
+  getList();
+}, 300);
+
+// 添加员工
+const addlist = () => {
+  dialongTitle.value = "新增账号";
+  addDialogVisible.value = true;
+  ruleForm.corpnPhone = "";
+  ruleForm.adminName = "";
+  ruleForm.corpnName = "";
+  ruleForm.level = 1;
+  ruleForm.remake = "";
+  ruleForm.password = "";
+  ruleForm.againPass = "";
+  ruleForm.reamark = "";
+};
+// 取消添加员工
+const cancelAdd = () => {
+  addDialogVisible.value = false;
+  ruleFormRef.value.resetFields();
+};
+//编辑按钮
+const edit = (row) => {
+  dialongTitle.value = "编辑信息";
+  addDialogVisible.value = true;
+  ruleForm.adminName = row.adminName;
+  ruleForm.corpnName = row.corpnName;
+  ruleForm.level = Number(row.level);
+  ruleForm.remark = row.remark;
+  ruleForm.password = row.password;
+  ruleForm.againPass = row.password;
+  ruleForm.corpnPhone = row.corpnPhone;
+  ruleForm.id = row.id;
+};
+// 确认添加员工
+const submitAdd = lodash.debounce(async (formEl) => {
+  if (!formEl) return;
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      if (dialongTitle.value == "新增账号") {
+        if (ruleForm.password == ruleForm.againPass) {
+          let data = {
+            adminName: ruleForm.adminName,
+            corpnName: ruleForm.corpnName,
+            level: ruleForm.level,
+            remark: ruleForm.remark,
+            password: ruleForm.password,
+            corpnPhone: ruleForm.corpnPhone,
+            managerId: sessionStorage.getItem("token"),
+          };
+          let res = await axios({
+            method: "post",
+            url: api.value + "/mhotel/managerAdmininsertAdminManager.action",
+            headers: {
+              // token: sessionStorage.getItem("token"),
+            },
+            params: data,
+          });
+          console.log(res, "添加账号");
+          if (res.data.code == 200) {
+            getList();
+            ElMessage({
+              type: "success",
+              showClose: true,
+              message: res.data.message,
+              center: true,
+            });
+            addDialogVisible.value = false;
+            ruleFormRef.value.resetFields();
+          } else {
+            ElMessage({
+              type: "error",
+              showClose: true,
+              message: res.data.message,
+              center: true,
+            });
+          }
+        } else {
+          ElMessage({
+            type: "error",
+            showClose: true,
+            message: "两次密码输入不一致",
+            center: true,
+          });
+        }
+      } else {
+        if (ruleForm.password == ruleForm.againPass) {
+          let data = {
+            adminName: ruleForm.adminName,
+            corpnName: ruleForm.corpnName,
+            level: ruleForm.level,
+            remark: ruleForm.remark,
+            password: ruleForm.password,
+            corpnPhone: ruleForm.corpnPhone,
+            id: ruleForm.id,
+          };
+          let res = await axios({
+            method: "post",
+            url: api.value + "/mhotel/managerAdminupdateAdminManager.action",
+            headers: {
+              // token: sessionStorage.getItem("token"),
+              // user_head: sessionStorage.getItem("userhead"),
+            },
+            params: data,
+          });
+          // console.log(res, "修改账号");
+          if (res.data.code == 200) {
+            getList();
+            ElMessage({
+              type: "success",
+              showClose: true,
+              message: res.data.message,
+              center: true,
+            });
+            addDialogVisible.value = false;
+            ruleFormRef.value.resetFields();
+          } else {
+            ElMessage({
+              type: "error",
+              showClose: true,
+              message: res.data.message,
+              center: true,
+            });
+          }
+        } else {
+          ElMessage({
+            type: "error",
+            showClose: true,
+            message: "两次密码输入不一致",
+            center: true,
+          });
+        }
+      }
+    } else {
+      console.log("error submit!", fields);
+    }
+  });
+}, 1000);
+
+//删除按钮
+const del = async (row) => {
+  // console.log(row);
+  let data = {
+    id: row.id,
+  };
+  let res = await axios({
+    method: "post",
+    url: api.value + "/mhotel/managerAdmindelAdmin.action",
+    headers: {
+      // token: sessionStorage.getItem("token"),
+      // user_head: sessionStorage.getItem("userhead"),
+    },
+    params: data,
+  });
+  if (res.data.code == 200) {
+    if (tableData.list.length == 1 && currentPage.value != 1) {
+      currentPage.value = currentPage.value - 1;
+    }
+    getList();
+    ElMessage({
+      type: "success",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  } else {
+    ElMessage({
+      type: "error",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  }
+  // console.log(res);
+};
+// 取消删除
+const cancelEvent = () => {
+  ElMessage({
+    type: "info",
+    showClose: true,
+    message: "取消删除",
+    center: true,
+  });
+};
+// 重置密码
+const reset = async (row) => {
+  // console.log(row);
+  let data = {
+    id: row.id,
+  };
+  let res = await axios({
+    method: "post",
+    url: api.value + "/mhotel/managerAdminremovePwd.action",
+    headers: {
+      // token: sessionStorage.getItem("token"),
+      // user_head: sessionStorage.getItem("userhead"),
+    },
+    params: data,
+  });
+  if (res.data.code == 200) {
+    getList();
+    ElMessage({
+      type: "success",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  } else {
+    ElMessage({
+      type: "error",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  }
+};
+
+// 多选框功能
+// const handleSelectionChange = (val) => {
+//   console.log(val);
+//   selectData.list = val;
+// };
+
+// 表格斑马纹颜色修改
+const tableRowClassName = ({ row, rowIndex }) => {
+  if (rowIndex % 2 === 0) {
+    return "even";
+  } else if (rowIndex % 2 !== 0) {
+    return "odd";
+  }
+  return "";
+};
+// 分页
+const handleCurrentChange = (value) => {
+  // console.log(value);
+  currentPage.value = value;
+  getList();
+};
+
+onBeforeMount(() => {
+  api.value = store.state.user.api;
+  getList();
+});
+onUnmounted(() => {
+  // document.removeEventListener("keyup", Enters);
+});
+</script>
+
+<style scoped lang="scss">
+.content-box {
+  width: 97.5%;
+  height: 89%;
+  margin: 20px auto;
+  background-color: #fff;
+  color: #fff;
+  display: flex;
+  flex-direction: column;
+  box-shadow: 0px 3px 10px rgba(0, 97, 255, 0.2);
+
+  .left {
+    // width: calc(100wh - 40px);
+    display: flex;
+    align-items: center;
+    height: 60px;
+    margin: 0 30px;
+    border-bottom: 1px solid #ccc;
+    color: #000;
+    font-size: 18px;
+    font-weight: 600;
+    .camera {
+      margin-right: 15px;
+      color: #4392f7;
+    }
+  }
+  .middle {
+    width: 96%;
+    margin: 0 auto;
+
+    color: #000;
+    // border-bottom: 1px solid rgb(231, 231, 231);
+    .filter {
+      display: flex;
+      flex-wrap: wrap;
+      align-items: center;
+      margin: 10px 0 0 0;
+      .search {
+        margin-left: 0 !important;
+        color: #fff;
+      }
+      .condition {
+        display: flex;
+        align-items: center;
+        margin: 10px 30px 10px 0;
+        :deep(.el-input .el-input__inner) {
+          font-size: 14px;
+        }
+        span {
+          margin: 0 10px 0 0;
+        }
+      }
+    }
+    .gongneng {
+      margin: 10px 0;
+      .el-button {
+        color: #fff;
+      }
+    }
+    :deep(.cont) {
+      width: 60%;
+      margin: 20px auto;
+    }
+    :deep(.download) {
+      display: flex;
+      align-items: center;
+      margin: 10px;
+    }
+    :deep(.download span) {
+      font-size: 16px;
+      margin-left: 20px;
+    }
+    :deep(.cont .el-button) {
+      margin-left: 60px;
+      margin-bottom: 30px;
+    }
+
+    :deep(.cont .accomplish) {
+      width: 100%;
+      display: flex;
+      justify-content: center;
+    }
+    :deep(.cont .accomplish .el-button) {
+      width: 50%;
+      margin: 0;
+    }
+  }
+  .footer {
+    width: 96%;
+    height: 550px;
+    margin: 10px auto 10px;
+    .el-table--fit {
+      height: 100%;
+      :deep(.el-table__header-wrapper) {
+        background-color: #000;
+        font-size: 15px;
+        color: #000;
+        .cell {
+          color: #000;
+        }
+      }
+      :deep(.el-table__row) {
+        height: 50px;
+        font-size: 15px;
+        color: #000;
+      }
+      :deep(.el-table__row td) {
+        padding: 0;
+        border: 0;
+      }
+
+      .el-button--primary {
+        margin-left: 5px;
+      }
+      :deep(.el-table__body .even) {
+        background-color: #fff;
+      }
+      :deep(.el-table__body .odd) {
+        background-color: rgba(240, 243, 247, 1);
+      }
+      :deep(.options) {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        .reset {
+          color: rgba(9, 101, 98, 1);
+          cursor: pointer;
+        }
+        .look {
+          margin: 0 15px;
+          color: rgba(30, 125, 251, 1);
+          cursor: pointer;
+        }
+        .del {
+          color: rgba(212, 48, 48, 1);
+          cursor: pointer;
+        }
+      }
+    }
+
+    // 添加员工弹窗样式
+    :deep(.addStaff) {
+      //   height: 420px;
+      border-radius: 11px;
+      .el-dialog__header {
+        border-radius: 11px 11px 0 0;
+        background: rgba(237, 241, 245, 1);
+        font-weight: 600;
+        margin: 0;
+        .el-dialog__headerbtn {
+          outline: none;
+        }
+      }
+      .el-dialog__body {
+        padding: 30px 20px 10px 20px;
+        .el-input {
+          width: 200px;
+          .el-input__suffix-inner {
+            color: rgba(61, 81, 232, 1);
+          }
+        }
+
+        .options {
+          margin: 10px 20px 20px 0;
+          width: 100%;
+          .el-form-item__content {
+            display: flex;
+            flex-direction: row-reverse;
+          }
+          .queding {
+            color: #fff;
+            margin-left: 15px;
+          }
+        }
+      }
+    }
+  }
+  .el-pagination {
+    // width: 1600px;
+    width: 96%;
+    margin: 20px auto 18px;
+    justify-content: flex-end;
+    :deep(.el-pagination__total) {
+      color: #000;
+    }
+    :deep(.el-pagination__goto) {
+      color: #000;
+    }
+    :deep(.el-pagination__classifier) {
+      color: #000;
+    }
+    :deep(.el-input__wrapper) {
+      border: 1px solid rgba(0, 0, 0, 1);
+      border-radius: 5px;
+      box-shadow: none;
+    }
+    :deep(.el-pager li) {
+      margin: 0 5px;
+      border: 1px solid rgba(0, 0, 0, 1);
+      border-radius: 5px;
+      background-color: transparent;
+    }
+    :deep(.el-pager li.is-active) {
+      background-color: rgba(111, 182, 184, 1);
+    }
+    :deep(.btn-prev) {
+      margin-right: 5px;
+      border: 1px solid rgba(0, 0, 0, 1);
+      border-radius: 5px;
+      background-color: transparent;
+    }
+    :deep(.btn-next) {
+      margin-left: 5px;
+      border: 1px solid rgba(0, 0, 0, 1);
+      border-radius: 5px;
+      background-color: transparent;
+    }
+  }
+}
+.el-input {
+  width: 192px;
+}
+</style>

+ 849 - 0
src/views/houseList/houseList.vue

@@ -0,0 +1,849 @@
+<template>
+  <div class="content-box">
+    <div class="left">
+      <!-- <el-icon :size="23" class="camera"><VideoCameraFilled /></el-icon> -->
+      <span class="cameratxt">民宿管理/房源信息</span>
+    </div>
+    <div class="middle">
+      <div class="filter">
+        <div class="condition">
+          <span>日期 : </span>
+          <el-date-picker
+            v-model="searchInput.createTime"
+            type="date"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+            :prefix-icon="Calendar"
+            placeholder="请选择日期"
+          />
+        </div>
+        <div class="condition">
+          <span>关键字 : </span>
+          <el-input
+            clearable
+            @clear="searchBtn"
+            v-model="searchInput.account"
+            class="w-50 m-2"
+            placeholder="请输入房型"
+            style="width: 150px"
+          />
+        </div>
+
+        <el-button
+          style="margin-left: 20px"
+          color="rgba(9, 101, 98, 1)"
+          type="primary"
+          class="search"
+          @click="searchBtn"
+          ><el-icon><Search /></el-icon> <span>查询</span></el-button
+        >
+      </div>
+      <!-- 按钮列表 -->
+      <!-- <div class="gongneng">
+        <el-button type="primary" color="rgba(9, 101, 98, 1)" @click="addlist"
+          ><el-icon><CirclePlus /></el-icon><span>新增账号</span></el-button
+        >
+      </div> -->
+    </div>
+    <div class="footer">
+      <el-table
+        :row-class-name="tableRowClassName"
+        :data="tableData.list"
+        @selection-change="handleSelectionChange"
+        style="width: 100%"
+        :header-cell-style="{
+          background: 'rgba(240, 243, 247, 1)',
+          height: '50px',
+          border: 0,
+        }"
+      >
+        <!-- <el-table-column align="center" type="selection" width="80" /> -->
+        <!-- <el-table-column
+          width="150"
+          align="center"
+          label="序号"
+          type="index"
+          index="1"
+        /> -->
+        <el-table-column align="center" prop="orderStartTime" label="日期" />
+        <el-table-column align="center" prop="houseName" label="房型" />
+        <el-table-column align="center" prop="houseLockNum" label="锁定房间" />
+        <el-table-column align="center" prop="houseDueNum" label="预定房间" />
+        <el-table-column
+          align="center"
+          prop="houseResidueNum"
+          label="剩余房数"
+        />
+        <el-table-column align="center" prop="houseNum" label="总房数" />
+
+        <!-- <el-table-column align="center" label="操作" width="220">
+          <template #default="scope">
+            <div class="options">
+              <div class="reset" @click="reset(scope.row)">密码重置</div>
+              <div class="look" @click="edit(scope.row)">修改</div>
+              <el-popconfirm
+                width="220"
+                confirm-button-text="确认"
+                cancel-button-text="取消"
+                :icon="InfoFilled"
+                icon-color="#f89626"
+                title="是否删除此账号?"
+                @confirm="del(scope.row)"
+                @cancel="cancelEvent"
+              >
+                <template #reference>
+                  <div class="del">删除</div>
+                </template>
+              </el-popconfirm>
+            </div>
+          </template>
+        </el-table-column> -->
+      </el-table>
+
+      <!-- 添加车辆弹窗 -->
+      <!-- <el-dialog
+        class="addStaff"
+        v-model="addDialogVisible"
+        :close-on-click-modal="false"
+        :close-on-press-escape="false"
+        :title="dialongTitle"
+        align-center
+        width="609"
+        :before-close="cancelAdd"
+      >
+        <el-form
+          ref="ruleFormRef"
+          :model="ruleForm"
+          :rules="rules"
+          label-width="100px"
+          class="demo-ruleForm"
+          :size="formSize"
+          label-position="left"
+          status-icon
+        >
+          <el-form-item label="用户名 :" prop="name">
+            <el-input
+              v-model="ruleForm.name"
+              placeholder="请输入用户名"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="姓名 :" prop="name">
+            <el-input
+              v-model="ruleForm.name"
+              placeholder="请输入姓名"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="手机号码 :">
+            <el-input
+              v-model="ruleForm.phone"
+              placeholder="请输入手机号码"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="密码 :" prop="post">
+            <el-input
+              v-model="ruleForm.phone"
+              placeholder="请输入密码"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="确认密码 :" prop="name">
+            <el-input
+              v-model="ruleForm.name"
+              placeholder="请再一次输入密码"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="角色 :" prop="post">
+            <el-checkbox-group v-model="checkList">
+              <el-checkbox label="超级管理员" />
+              <el-checkbox label="管理员" />
+            </el-checkbox-group>
+          </el-form-item>
+          <el-form-item label="简介 :" prop="cardnumber">
+            <el-input
+              v-model="ruleForm.phone"
+              :rows="3"
+              type="textarea"
+              placeholder="请输入民宿简介信息"
+            />
+          </el-form-item>
+
+          <el-form-item class="options">
+            <el-button
+              color="rgba(9, 101, 98, 1)"
+              class="queding"
+              type="primary"
+              @click="submitAdd(ruleFormRef)"
+            >
+              确定
+            </el-button>
+            <el-button @click="cancelAdd(ruleFormRef)">取消</el-button>
+          </el-form-item>
+        </el-form>
+      </el-dialog> -->
+    </div>
+
+    <!-- 分页组件 -->
+    <el-pagination
+      background
+      :current-page="currentPage"
+      :page-size="pageSize"
+      layout="total, prev, pager, next, jumper, slot"
+      :total="total"
+      @update:current-page="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script setup>
+import {
+  ref,
+  reactive,
+  nextTick,
+  watch,
+  onBeforeMount,
+  onUnmounted,
+} from "vue";
+import { useRouter } from "vue-router";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { Calendar } from "@element-plus/icons-vue";
+import { dayjs } from "element-plus";
+import lodash, { reduce } from "lodash";
+import axios from "axios";
+import { useStore } from "vuex";
+const store = useStore();
+const router = useRouter();
+// 表格数据
+const tableData = reactive({
+  list: [
+    // {
+    //   date: "2023-08-01",
+    //   house: "双人房",
+    //   house1: "5",
+    //   house2: 3,
+    //   house3: "12",
+    //   house4: 21,
+    // },
+    // {
+    //   date: "2023-08-01",
+    //   house: "双人房",
+    //   house1: "5",
+    //   house2: 3,
+    //   house3: "12",
+    //   house4: 21,
+    // },
+    // {
+    //   date: "2023-08-01",
+    //   house: "双人房",
+    //   house1: "5",
+    //   house2: 3,
+    //   house3: "12",
+    //   house4: 21,
+    // },
+    // {
+    //   date: "2023-08-01",
+    //   house: "双人房",
+    //   house1: "5",
+    //   house2: 3,
+    //   house3: "12",
+    //   house4: 21,
+    // },
+    // {
+    //   date: "2023-08-01",
+    //   house: "双人房",
+    //   house1: "5",
+    //   house2: 3,
+    //   house3: "12",
+    //   house4: 21,
+    // },
+  ],
+});
+const activeIndex = ref(); // 默认跳转路由
+const dialongTitle = ref("新增账号"); // 弹窗标题
+
+const searchInput = reactive({
+  account: "",
+  createTime: "",
+}); // 搜索按钮数据
+5;
+
+const currentPage = ref(1); // 当前页
+const pageSize = ref(10);
+const total = ref(); // 当前总数
+const selectData = reactive({ list: [] }); // 多选框选择的数据
+const api = ref("");
+const addDialogVisible = ref(false); // 控制添加员工弹窗
+
+// 表单数据
+const formSize = ref("default");
+const ruleFormRef = ref();
+const ruleForm = reactive({
+  name: "",
+  account: "",
+  pass: "",
+  phone: "",
+  id: "",
+});
+// 表单验证
+const rules = reactive({
+  account: [
+    { required: true, message: "账号不能为空", trigger: "blur" },
+    // { min: 3, max: 5, message: "Length should be 3 to 5", trigger: "blur" },
+    // {
+    //   pattern: /^[a-zA-z]\w{3,15}$/,
+    //   message: "请输入正确账号",
+    //   trigger: "blur",
+    // },
+  ],
+  // ^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\._\+(){}])[0-9a-zA-Z!@#$%^&*,\\._\+(){}]{8,20}$
+  pass: [
+    {
+      required: true,
+      message: "密码不能为空",
+      trigger: "blur",
+    },
+    // {
+    //   min: 8,
+    //   max: 20,
+    //   pattern:
+    //     /^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\._\+(){}])[0-9a-zA-Z!@#$%^&*,\\._\+(){}]{8,20}$/,
+    //   message: "请输入8-20位正确密码(大小写字母·字符·数字)",
+    //   trigger: "blur",
+    // },
+  ],
+  name: [
+    {
+      required: true,
+      message: "用户名称不能为空",
+      trigger: "blur",
+    },
+  ],
+  phone: [
+    {
+      required: true,
+      message: "手机号码不能为空",
+      trigger: "blur",
+    },
+  ],
+
+  // desc: [{ required: true, message: "Please input activity form", trigger: "blur" }],
+});
+watch(
+  () => searchInput.createTime,
+  (newVal, oldVal) => {
+    console.log("监听时间:", newVal);
+    if (newVal == null) {
+      getList();
+    }
+  }
+);
+// 获取账户列表
+const getList = async () => {
+  let data = {
+    page: currentPage.value, // 当前页
+    rows: pageSize.value, // 一页数据条数
+    hName: searchInput.account, // 房型关键字
+    managerId: sessionStorage.getItem("token"),
+  };
+  if (searchInput.createTime) {
+    data.orderTime = searchInput.createTime;
+  }
+  let res = await axios({
+    method: "post",
+    url: api.value + "/mhotel/housequeryPageHouseSum.action",
+    headers: {},
+    params: data,
+  });
+  console.log(res, "房源信息");
+  if (res.data.code == 200) {
+    tableData.list = res.data.data.pageList;
+    total.value = res.data.data.total;
+    // ElMessage({
+    //   type: "success",
+    //   showClose: true,
+    //   message: res.data.message,
+    //   center: true,
+    // });
+  } else {
+    ElMessage({
+      type: "error",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  }
+};
+
+// 搜索功能
+const searchBtn = lodash.debounce(async () => {
+  getList();
+}, 300);
+
+// 重置搜索
+const searchRefresh = lodash.debounce(async () => {
+  searchInput.carnumber = "";
+  searchInput.createTime = "";
+  currentPage.value = 1;
+  getList();
+}, 300);
+
+//导出功能
+const importExcel = async () => {
+  if (searchInput.createTime == null) {
+    searchInput.createTime = "";
+  }
+  let data = new FormData();
+  data.set("number", searchInput.carnumber);
+  data.set("create_time", searchInput.createTime);
+  let res = await axios({
+    method: "post",
+    url: api.value + "/carBook/admintoExcel.action",
+    headers: {
+      token: sessionStorage.getItem("token"),
+    },
+    data: data,
+  });
+  // console.log(res, "导出账号");
+  if (res.data.code == 200) {
+    // const elt = document.createElement("a");
+    // elt.setAttribute(
+    //   "href",
+    //   "https://chtech.ncjti.edu.cn/carstop" + res.data.downurl
+    // );
+    // // elt.setAttribute("download", "file.xlsx");
+    // // elt.style.display = "none";
+    // document.body.appendChild(elt);
+    var downloadPath = "https://chtech.ncjti.edu.cn/carstop" + res.data.downurl;
+    console.log("获得地址数据:", downloadPath);
+    var downloadLink = document.createElement("a");
+    downloadLink.style.display = "none"; // 使其隐藏
+    downloadLink.href = downloadPath;
+    downloadLink.download = "";
+    downloadLink.click();
+    document.body.appendChild(downloadLink);
+    document.body.removeChild(downloadLink);
+    elt.click();
+    ElMessage({
+      type: "success",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  } else {
+    ElMessage({
+      type: "error",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  }
+};
+// 添加员工
+const addlist = () => {
+  dialongTitle.value = "新增账号";
+  addDialogVisible.value = true;
+  ruleForm.name = "";
+  ruleForm.account = "";
+  ruleForm.pass = "";
+  ruleForm.phone = "";
+};
+// 取消添加员工
+const cancelAdd = () => {
+  addDialogVisible.value = false;
+  ruleFormRef.value.resetFields();
+};
+//编辑按钮
+const edit = (row) => {
+  dialongTitle.value = "编辑信息";
+  addDialogVisible.value = true;
+  console.log(row);
+  ruleForm.pass = row.password;
+  ruleForm.phone = row.phone;
+  ruleForm.name = row.username;
+  ruleForm.account = row.account;
+  ruleForm.id = row.id;
+};
+// 确认添加员工
+const submitAdd = async (formEl) => {
+  if (!formEl) return;
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      if (dialongTitle.value == "新增账号") {
+        let data = {
+          username: ruleForm.name,
+          account: ruleForm.account,
+          password: ruleForm.pass,
+          phone: ruleForm.phone,
+        };
+        let res = await axios({
+          method: "post",
+          url: api.value + "/repairAdmin/insertRepairAdmin",
+          headers: {
+            token: sessionStorage.getItem("token"),
+            user_head: sessionStorage.getItem("userhead"),
+          },
+          data: data,
+        });
+        console.log(res, "添加账号");
+        if (res.data.code == 200) {
+          getList();
+          ElMessage({
+            type: "success",
+            showClose: true,
+            message: res.data.message,
+            center: true,
+          });
+          addDialogVisible.value = false;
+          ruleFormRef.value.resetFields();
+        } else {
+          ElMessage({
+            type: "error",
+            showClose: true,
+            message: res.data.message,
+            center: true,
+          });
+        }
+      } else {
+        let data = {
+          username: ruleForm.name,
+          phone: ruleForm.phone,
+          id: ruleForm.id,
+        };
+        let res = await axios({
+          method: "post",
+          url: api.value + "/repairAdmin/updateRepairAdminById",
+          headers: {
+            token: sessionStorage.getItem("token"),
+            user_head: sessionStorage.getItem("userhead"),
+          },
+          data: data,
+        });
+        // console.log(res, "修改账号");
+        if (res.data.code == 200) {
+          getList();
+          ElMessage({
+            type: "success",
+            showClose: true,
+            message: res.data.message,
+            center: true,
+          });
+          addDialogVisible.value = false;
+          ruleFormRef.value.resetFields();
+        } else {
+          ElMessage({
+            type: "error",
+            showClose: true,
+            message: res.data.message,
+            center: true,
+          });
+        }
+      }
+    } else {
+      console.log("error submit!", fields);
+    }
+  });
+};
+
+//删除按钮
+const del = async (row) => {
+  console.log(row);
+  let data = {
+    id: row.id,
+  };
+  let res = await axios({
+    method: "get",
+    url: api.value + "/repairAdmin/deleteRepairAdminById",
+    headers: {
+      token: sessionStorage.getItem("token"),
+      user_head: sessionStorage.getItem("userhead"),
+    },
+    params: data,
+  });
+  if (res.data.code == 200) {
+    if (tableData.list.length == 1 && currentPage.value != 1) {
+      currentPage.value = currentPage.value - 1;
+    }
+    getList();
+    ElMessage({
+      type: "success",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  } else {
+    ElMessage({
+      type: "error",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  }
+  console.log(res);
+};
+// 取消删除
+const cancelEvent = () => {
+  ElMessage({
+    type: "info",
+    showClose: true,
+    message: "取消删除",
+    center: true,
+  });
+};
+
+// 多选框功能
+// const handleSelectionChange = (val) => {
+//   console.log(val);
+//   selectData.list = val;
+// };
+
+// 表格斑马纹颜色修改
+const tableRowClassName = ({ row, rowIndex }) => {
+  if (rowIndex % 2 === 0) {
+    return "even";
+  } else if (rowIndex % 2 !== 0) {
+    return "odd";
+  }
+  return "";
+};
+// 分页
+const handleCurrentChange = (value) => {
+  // console.log(value);
+  currentPage.value = value;
+  getList();
+};
+
+onBeforeMount(() => {
+  api.value = store.state.user.api;
+  getList();
+});
+onUnmounted(() => {
+  // document.removeEventListener("keyup", Enters);
+});
+</script>
+
+<style scoped lang="scss">
+.content-box {
+  width: 97.5%;
+  height: 89%;
+  margin: 20px auto;
+  background-color: #fff;
+  color: #fff;
+  display: flex;
+  flex-direction: column;
+  box-shadow: 0px 3px 10px rgba(0, 97, 255, 0.2);
+
+  .left {
+    // width: calc(100wh - 40px);
+    display: flex;
+    align-items: center;
+    height: 60px;
+    margin: 0 30px;
+    border-bottom: 1px solid #ccc;
+    color: #000;
+    font-size: 18px;
+    font-weight: 600;
+    .camera {
+      margin-right: 15px;
+      color: #4392f7;
+    }
+  }
+  .middle {
+    width: 96%;
+    margin: 0 auto;
+
+    color: #000;
+    // border-bottom: 1px solid rgb(231, 231, 231);
+    .filter {
+      display: flex;
+      flex-wrap: wrap;
+      align-items: center;
+      margin: 20px 0 0 0;
+      .search {
+        margin-left: 0 !important;
+        color: #fff;
+      }
+      .condition {
+        display: flex;
+        align-items: center;
+        margin: 10px 30px 10px 0;
+        :deep(.el-input .el-input__inner) {
+          font-size: 14px;
+        }
+        span {
+          margin: 0 10px 0 0;
+        }
+      }
+    }
+    .gongneng {
+      margin: 10px 0;
+      .el-button {
+        color: #fff;
+      }
+    }
+    :deep(.cont) {
+      width: 60%;
+      margin: 20px auto;
+    }
+    :deep(.download) {
+      display: flex;
+      align-items: center;
+      margin: 10px;
+    }
+    :deep(.download span) {
+      font-size: 16px;
+      margin-left: 20px;
+    }
+    :deep(.cont .el-button) {
+      margin-left: 60px;
+      margin-bottom: 30px;
+    }
+
+    :deep(.cont .accomplish) {
+      width: 100%;
+      display: flex;
+      justify-content: center;
+    }
+    :deep(.cont .accomplish .el-button) {
+      width: 50%;
+      margin: 0;
+    }
+  }
+  .footer {
+    width: 96%;
+    height: 550px;
+    margin: 10px auto 10px;
+    .el-table--fit {
+      height: 100%;
+      :deep(.el-table__header-wrapper) {
+        background-color: #000;
+        font-size: 15px;
+        color: #000;
+        .cell {
+          color: #000;
+        }
+      }
+      :deep(.el-table__row) {
+        height: 50px;
+        font-size: 15px;
+        color: #000;
+      }
+      :deep(.el-table__row td) {
+        padding: 0;
+        border: 0;
+      }
+
+      .el-button--primary {
+        margin-left: 5px;
+      }
+      :deep(.el-table__body .even) {
+        background-color: #fff;
+      }
+      :deep(.el-table__body .odd) {
+        background-color: rgba(240, 243, 247, 1);
+      }
+      :deep(.options) {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        .reset {
+          color: rgba(9, 101, 98, 1);
+          cursor: pointer;
+        }
+        .look {
+          margin: 0 10px;
+          color: rgba(30, 125, 251, 1);
+          cursor: pointer;
+        }
+        .del {
+          color: rgba(212, 48, 48, 1);
+          cursor: pointer;
+        }
+      }
+    }
+
+    // 添加员工弹窗样式
+    :deep(.addStaff) {
+      //   height: 420px;
+      border-radius: 11px;
+      .el-dialog__header {
+        border-radius: 11px 11px 0 0;
+        background: rgba(237, 241, 245, 1);
+        font-weight: 600;
+        margin: 0;
+        .el-dialog__headerbtn {
+          outline: none;
+        }
+      }
+      .el-dialog__body {
+        padding: 30px 20px 10px 20px;
+        .el-input {
+          width: 200px;
+          .el-input__suffix-inner {
+            color: rgba(61, 81, 232, 1);
+          }
+        }
+
+        .options {
+          margin: 10px 20px 20px 0;
+          width: 100%;
+          .el-form-item__content {
+            display: flex;
+            flex-direction: row-reverse;
+          }
+          .queding {
+            color: #fff;
+            margin-left: 15px;
+          }
+        }
+      }
+    }
+  }
+  .el-pagination {
+    // width: 1600px;
+    width: 96%;
+    margin: 20px auto 18px;
+    justify-content: flex-end;
+    :deep(.el-pagination__total) {
+      color: #000;
+    }
+    :deep(.el-pagination__goto) {
+      color: #000;
+    }
+    :deep(.el-pagination__classifier) {
+      color: #000;
+    }
+    :deep(.el-input__wrapper) {
+      border: 1px solid rgba(0, 0, 0, 1);
+      border-radius: 5px;
+      box-shadow: none;
+    }
+    :deep(.el-pager li) {
+      margin: 0 5px;
+      border: 1px solid rgba(0, 0, 0, 1);
+      border-radius: 5px;
+      background-color: transparent;
+    }
+    :deep(.el-pager li.is-active) {
+      background-color: rgba(111, 182, 184, 1);
+    }
+    :deep(.btn-prev) {
+      margin-right: 5px;
+      border: 1px solid rgba(0, 0, 0, 1);
+      border-radius: 5px;
+      background-color: transparent;
+    }
+    :deep(.btn-next) {
+      margin-left: 5px;
+      border: 1px solid rgba(0, 0, 0, 1);
+      border-radius: 5px;
+      background-color: transparent;
+    }
+  }
+}
+.el-input {
+  width: 192px;
+}
+</style>

+ 905 - 0
src/views/ledger/ledger.vue

@@ -0,0 +1,905 @@
+<template>
+  <div class="content-box">
+    <div class="left">
+      <!-- <el-icon :size="23" class="camera"><VideoCameraFilled /></el-icon> -->
+      <span class="cameratxt">台账管理</span>
+    </div>
+    <div>
+      <div class="middle">
+        <div class="filter">
+          <div class="condition">
+            <span>关键字 : </span>
+            <el-input
+              :clearable="true"
+              @clear="searchBtn"
+              v-model="searchInput.keyWord"
+              class="w-50 m-2"
+              placeholder="请输入订单、预定人、手机号"
+              style="width: 250px"
+            />
+          </div>
+          <div class="condition">
+            <span>支付时间 : </span>
+            <el-date-picker
+              v-model="searchInput.createTime"
+              type="daterange"
+              range-separator="-"
+              start-placeholder="起始时间"
+              end-placeholder="结束时间"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              :prefix-icon="Calendar"
+              placeholder="请选择日期"
+            />
+          </div>
+
+          <el-button
+            style="margin-left: 20px"
+            color="rgba(9, 101, 98, 1)"
+            type="primary"
+            class="search"
+            @click="searchBtn"
+            ><el-icon><Search /></el-icon> <span>查询</span></el-button
+          >
+          <el-button
+            style="margin-left: 20px"
+            color="rgba(9, 101, 98, 1)"
+            type="primary"
+            class="search"
+            @click="importExcel"
+            ><span>导出订单</span></el-button
+          >
+        </div>
+      </div>
+      <div class="footer">
+        <el-table
+          :row-class-name="tableRowClassName"
+          :data="tableData.list"
+          @selection-change="handleSelectionChange"
+          style="width: 100%"
+          :header-cell-style="{
+            background: 'rgba(240, 243, 247, 1)',
+            height: '50px',
+            border: 0,
+          }"
+        >
+          <!-- <el-table-column align="center" type="selection" width="80" /> -->
+          <!-- <el-table-column
+              width="150"
+              align="center "
+              type="index"
+              label="序号"
+            /> -->
+          <el-table-column
+            align="center"
+            prop="orderNum"
+            label="已消费订单号"
+          />
+
+          <el-table-column align="center" prop="userName" label="预订人" />
+          <el-table-column align="center" prop="userPhone" label="手机号码" />
+          <el-table-column
+            align="center"
+            prop="houseOrderNumber"
+            label="房间数(间)"
+          />
+          <el-table-column
+            align="center"
+            prop="houseTotalPrice"
+            label="订单金额(元)"
+          />
+
+          <el-table-column align="center" prop="payTime" label="支付时间" />
+
+          <!-- <el-table-column
+            align="center"
+            fixed="right"
+            label="操作"
+            width="150"
+          >
+            <template #default="scope">
+              <div class="edit">
+                <div class="look" @click="edit(scope.row)">编辑</div>
+                <el-popconfirm
+                  width="220"
+                  confirm-button-text="确认"
+                  cancel-button-text="取消"
+                  :icon="InfoFilled"
+                  icon-color="#f89626"
+                  title="是否删除此员工?"
+                  @confirm="del(scope.row)"
+                  @cancel="cancelEvent"
+                >
+                  <template #reference>
+                    <div class="look">删除</div>
+                  </template>
+                </el-popconfirm>
+              </div>
+            </template>
+          </el-table-column> -->
+        </el-table>
+      </div>
+
+      <!-- 分页组件 -->
+      <div class="pageSize">
+        <span></span>
+        <el-pagination
+          background
+          :current-page="currentPage"
+          :page-size="pageSize"
+          layout="total, prev, pager, next, jumper, slot"
+          :total="total"
+          @update:current-page="handleCurrentChange"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import {
+  ref,
+  reactive,
+  nextTick,
+  watch,
+  onBeforeMount,
+  onUnmounted,
+} from "vue";
+import { useRouter } from "vue-router";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { Calendar } from "@element-plus/icons-vue";
+import vidiconsApi from "@/api/vidicons.js";
+import { dayjs } from "element-plus";
+import lodash from "lodash";
+import axios from "axios";
+import { useStore } from "vuex";
+const store = useStore();
+const api = ref("");
+const router = useRouter();
+// 表格数据
+const tableData = reactive({
+  list: [
+    // {
+    //   userName: "111233342",
+    //   userName2: "张三",
+    //   userPhone: "1121311",
+    //   teamName: 12,
+    //   schoolName: 1200,
+    //   workTypeName: "2023-08-01 12:09:08",
+    // },
+    // {
+    //   userName: "111233342",
+    //   userName2: "张三",
+    //   userPhone: "1121311",
+    //   teamName: 12,
+    //   schoolName: 1200,
+    //   workTypeName: "2023-08-01 12:09:08",
+    // },
+    // {
+    //   userName: "111233342",
+    //   userName2: "张三",
+    //   userPhone: "1121311",
+    //   teamName: 12,
+    //   schoolName: 1200,
+    //   workTypeName: "2023-08-01 12:09:08",
+    // },
+    // {
+    //   userName: "111233342",
+    //   userName2: "张三",
+    //   userPhone: "1121311",
+    //   teamName: 12,
+    //   schoolName: 1200,
+    //   workTypeName: "2023-08-01 12:09:08",
+    // },
+    // {
+    //   userName: "111233342",
+    //   userName2: "张三",
+    //   userPhone: "1121311",
+    //   teamName: 12,
+    //   schoolName: 1200,
+    //   workTypeName: "2023-08-01 12:09:08",
+    // },
+  ],
+});
+
+// 添加员工弹窗数据 (------------------------------------)
+const dialongTitle = ref("添加员工"); // 弹窗标题
+
+const checkAll = ref(false); // 判断物品种类是否全选
+const articleIdsList = ref(); //  关联报修类型数据
+const isIndeterminate = ref(false); // 不确定状态,表示只选择一部分
+const checkedCities = ref([]); // 选中的数据
+
+const userzzIdsList = ref(); //  身份下拉数据
+const workTypeList = ref(); //  工种下拉数据
+const props = reactive();
+const treeValue = reactive({}); // 关联楼栋树形结构数据
+
+const searchInput = reactive({
+  keyWord: "",
+  teamId: "",
+  schoolId: "",
+  createTime: "",
+}); // 搜索按钮数据
+
+const currentPage = ref(1); // 当前页
+const pageSize = ref(10);
+const total = ref(); // 当前总数
+const selectData = reactive({ list: [] }); // 多选框选择的数据
+
+const addDialogVisible = ref(false); // 控制添加员工弹窗
+
+// 添加员工表单数据
+const formSize = ref("default");
+const ruleFormRef = ref();
+const articleIdsRef = ref(); // 关联报修类型ref
+const buildIdsRef = ref(); // 关联楼栋ref
+const ruleForm = reactive({
+  userName: "",
+  cardNumber: "",
+  userzzId: "",
+  userPhone: "",
+  schoolId: "",
+  workType: "",
+  articleIds: [],
+  buildIds: [],
+  teamId: "",
+  acceptanceTime: "",
+  maintenanceTime: "",
+  id: "",
+});
+// 表单验证
+const rules = reactive({
+  // serial: [{ required: true, message: "序列号不能为空", trigger: "blur" }],
+  userName: [{ required: true, message: "姓名不能为空", trigger: "blur" }],
+  cardNumber: [
+    { required: true, message: "微校卡号不能为空", trigger: "blur" },
+  ],
+  userzzId: [{ required: true, message: "身份不能为空", trigger: "blur" }],
+  userPhone: [{ required: true, message: "手机号码不能为空", trigger: "blur" }],
+  schoolId: [{ required: true, message: "校区不能为空", trigger: "blur" }],
+  workType: [{ required: true, message: "工种不能为空", trigger: "blur" }],
+  teamId: [{ required: true, message: "维修班不能为空", trigger: "blur" }],
+  articleIds: [
+    { required: true, message: "关联报修类型不能为空", trigger: "blur" },
+  ],
+  buildIds: [{ required: true, message: "关联楼栋不能为空", trigger: "blur" }],
+  acceptanceTime: [
+    { required: true, message: "接单考核时间不能为空", trigger: "blur" },
+  ],
+  maintenanceTime: [
+    { required: true, message: "维修考核时间不能为空", trigger: "blur" },
+  ],
+});
+
+watch(
+  () => searchInput.createTime,
+  (newVal, oldVal) => {
+    console.log("监听时间:", newVal);
+    if (newVal == null) {
+      getList();
+    }
+  }
+);
+
+// 查看员工列表
+const getList = async () => {
+  let data = {
+    page: currentPage.value,
+    rows: pageSize.value,
+    ledgerParam: searchInput.keyWord, // 关键字查询
+    managerId: sessionStorage.getItem("token"),
+  };
+  if (searchInput.createTime) {
+    data.payStartTime = searchInput.createTime[0];
+    data.payEndTime = searchInput.createTime[1];
+  }
+  let res = await axios({
+    method: "post",
+    url: api.value + "/mhotel/bookquearyLedgerPage.action",
+    headers: {
+      // token: sessionStorage.getItem("token"),
+      // user_head: sessionStorage.getItem("userhead"),
+    },
+    params: data,
+  });
+  console.log(res, "台账数据");
+  if (res.data.code == 200) {
+    tableData.list = res.data.data.bookIPage.pageList;
+    total.value = res.data.data.bookIPage.total;
+    // ElMessage({
+    //   type: "success",
+    //   showClose: true,
+    //   message: res.data.message,
+    //   center: true,
+    // });
+  } else {
+    ElMessage({
+      type: "error",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  }
+};
+
+// 搜索功能
+const searchBtn = lodash.debounce(async () => {
+  getList();
+}, 300);
+
+// 改变校区  关联楼栋和关联报修类型也改变(---------------)
+const changeSchool = async (val) => {
+  if (val == 1) {
+    ruleForm.schoolId = 1;
+  } else {
+    ruleForm.schoolId = 2;
+  }
+  //  报修(故障类型)类型关联 (接口-------)
+  let data = {
+    schoolId: val,
+  };
+  let resss = await axios({
+    method: "get",
+    url: api.value + "/repairArticleType/queryRepairArticleType",
+    headers: {
+      token: sessionStorage.getItem("token"),
+      user_head: sessionStorage.getItem("userhead"),
+    },
+    params: data,
+  });
+  console.log(resss, "报修(故障类型)类型关联数据");
+  articleIdsList.value = resss.data.data;
+  // 关联楼栋数据 (接口---------)
+  let datas = { schoolId: val };
+  let res = await axios({
+    method: "get",
+    url: api.value + "/repairArea/queryRepairAreaSecond",
+    headers: {
+      token: sessionStorage.getItem("token"),
+      user_head: sessionStorage.getItem("userhead"),
+    },
+    params: datas,
+  });
+  console.log(res, "关联楼栋数据");
+  treeValue.list = res.data.data;
+};
+
+//新增员工 (--------------------------------------)
+const addlist = async () => {
+  dialongTitle.value = "添加员工";
+  changeSchool(1);
+  addDialogVisible.value = true;
+  ruleForm.userName = "";
+  ruleForm.cardNumber = "";
+  ruleForm.userzzId = "";
+  ruleForm.userPhone = "";
+  ruleForm.workType = "";
+  ruleForm.articleIds = [];
+  ruleForm.buildIds = [];
+  ruleForm.teamId = "";
+  ruleForm.acceptanceTime = "";
+  ruleForm.maintenanceTime = "";
+  ruleForm.id = "";
+};
+// 种类是否全选按钮
+// const handleCheckAllChange = (val) => {
+//   console.log(val);
+//   console.log(articleIdsList.value);
+//   let checkedCitie = [];
+//   articleIdsList.value.forEach((item) => {
+//     checkedCitie.push(item.name);
+//   });
+//   checkedCities.value = val ? checkedCitie : [];
+//   isIndeterminate.value = false;
+// };
+// //单独勾选种类
+// const handleCheckedCitiesChange = (value) => {
+//   console.log(value);
+//   const checkedCount = value.length;
+//   checkAll.value = checkedCount === articleIdsList.value.length;
+//   isIndeterminate.value =
+//     checkedCount > 0 && checkedCount < articleIdsList.value.length;
+// };
+
+// 关联报修类型  当复选框被点击的时候触发
+const handleArticleIds = (data, checked, indeterminate) => {
+  console.log(data, checked, indeterminate);
+  // let keys = articleIdsRef.value.getCheckedNodes();
+  let keys = articleIdsRef.value.getCheckedKeys();
+  // console.log(keys);
+  // let arr = [];
+  // keys.forEach((item) => {
+  //   if (item.parentId != 1) {
+  //     arr.push(item.id);
+  //   }
+  // });
+  ruleForm.articleIds = keys;
+};
+//  关联楼栋 当复选框被点击的时候触发
+const handleCheckChange = (data, checked, indeterminate) => {
+  // console.log(data, checked);
+  let keys = buildIdsRef.value.getCheckedNodes();
+  let arr = [];
+  keys.forEach((item) => {
+    if (item.parentId != 1) {
+      arr.push(item.id);
+    }
+  });
+  ruleForm.buildIds = arr;
+};
+
+//编辑按钮  (-------------------------------------------)
+const edit = (row) => {
+  changeSchool(row.schoolId);
+  // console.log(row.articleIds, row.buildIds);
+  dialongTitle.value = "编辑员工";
+  addDialogVisible.value = true;
+  ruleForm.userName = row.userName;
+  ruleForm.cardNumber = row.cardNumber;
+  ruleForm.userzzId = row.userZzid;
+  ruleForm.userPhone = row.userPhone;
+  ruleForm.schoolId = row.schoolId;
+  ruleForm.workType = row.workType;
+  ruleForm.teamId = row.teamId;
+  ruleForm.acceptanceTime = row.acceptanceTime;
+  ruleForm.maintenanceTime = row.maintenanceTime;
+  ruleForm.id = row.id;
+  nextTick(() => {
+    articleIdsRef.value.setCheckedKeys(row.articleIds);
+    buildIdsRef.value.setCheckedKeys(row.buildIds);
+  });
+  ruleForm.articleIds = row.articleIds;
+  ruleForm.buildIds = row.buildIds;
+};
+// 取消添加员工
+const cancelAdd = () => {
+  addDialogVisible.value = false;
+  ruleFormRef.value.resetFields();
+};
+// 确认添加员工
+const submitAdd = async (formEl) => {
+  if (!formEl) return;
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      if (dialongTitle.value == "添加员工") {
+        let data = {
+          userName: ruleForm.userName,
+          cardNumber: ruleForm.cardNumber,
+          userzzId: ruleForm.userzzId,
+          userPhone: ruleForm.userPhone,
+          schoolId: ruleForm.schoolId,
+          workType: ruleForm.workType,
+          articleIds: ruleForm.articleIds,
+          buildIds: ruleForm.buildIds,
+          teamId: ruleForm.teamId,
+          acceptanceAssessTime: ruleForm.acceptanceTime,
+          maintenanceAssessTime: ruleForm.maintenanceTime,
+        };
+        let res = await axios({
+          method: "post",
+          url: api.value + "/repairUser/insertRepairUserSetting",
+          headers: {
+            token: sessionStorage.getItem("token"),
+            user_head: sessionStorage.getItem("userhead"),
+          },
+          data: data,
+        });
+        console.log(res, "添加员工");
+        if (res.data.code == 200) {
+          getList();
+          ElMessage({
+            type: "success",
+            showClose: true,
+            message: res.data.message,
+            center: true,
+          });
+          addDialogVisible.value = false;
+          ruleFormRef.value.resetFields();
+        } else {
+          ElMessage({
+            type: "error",
+            showClose: true,
+            message: res.data.message,
+            center: true,
+          });
+        }
+      } else {
+        let data = {
+          userName: ruleForm.userName,
+          cardNumber: ruleForm.cardNumber,
+          userzzId: ruleForm.userzzId,
+          userPhone: ruleForm.userPhone,
+          schoolId: ruleForm.schoolId,
+          workType: ruleForm.workType,
+          articleIds: ruleForm.articleIds,
+          buildIds: ruleForm.buildIds,
+          teamId: ruleForm.teamId,
+          acceptanceAssessTime: ruleForm.acceptanceTime,
+          maintenanceAssessTime: ruleForm.maintenanceTime,
+          id: ruleForm.id,
+        };
+        let res = await axios({
+          method: "post",
+          url: api.value + "/repairUser/updateRepairUserSettingById",
+          headers: {
+            token: sessionStorage.getItem("token"),
+            user_head: sessionStorage.getItem("userhead"),
+          },
+          data: data,
+        });
+        console.log(res, "编辑员工");
+        if (res.data.code == 200) {
+          getList();
+          ElMessage({
+            type: "success",
+            showClose: true,
+            message: res.data.message,
+            center: true,
+          });
+          addDialogVisible.value = false;
+          ruleFormRef.value.resetFields();
+        } else {
+          ElMessage({
+            type: "error",
+            showClose: true,
+            message: res.data.message,
+            center: true,
+          });
+        }
+      }
+    } else {
+      console.log("error submit!", fields);
+    }
+  });
+};
+
+//删除按钮
+const del = async (row) => {
+  let data = {
+    id: row.id,
+  };
+  let res = await axios({
+    method: "get",
+    url: api.value + "/repairUser/deleteRepairUserSettingById",
+    headers: {
+      token: sessionStorage.getItem("token"),
+      user_head: sessionStorage.getItem("userhead"),
+    },
+    params: data,
+  });
+  if (res.data.code == 200) {
+    if (tableData.list.length == 1 && currentPage.value != 1) {
+      currentPage.value = currentPage.value - 1;
+    }
+    getList();
+    ElMessage({
+      type: "success",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  } else {
+    ElMessage({
+      type: "error",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  }
+  console.log(res);
+};
+
+// 多选框功能
+const handleSelectionChange = (val) => {
+  console.log(val);
+  selectData.list = val;
+};
+//导出功能
+const importExcel = lodash.debounce(async () => {
+  let data = {
+    ledgerParam: searchInput.keyWord, // 关键字查询
+    managerId: sessionStorage.getItem("token"),
+  };
+  if (searchInput.createTime) {
+    data.payStartTime = searchInput.createTime[0];
+    data.payEndTime = searchInput.createTime[1];
+  }
+  let res = await axios({
+    method: "post",
+    url: api.value + "/mhotel/booktoLedgerExcel.action",
+    headers: {
+      // token: sessionStorage.getItem("token"),
+    },
+    params: data,
+  });
+  console.log(res, "导出台账管理");
+  if (res.data.code == 200) {
+    var downloadPath = res.data.downurl;
+    // window.open(downloadPath);
+    window.location.href = downloadPath;
+    var downloadLink = document.createElement("a");
+    downloadLink.style.display = "none"; // 使其隐藏
+    downloadLink.href = downloadPath;
+    downloadLink.download = "";
+    downloadLink.click();
+    document.body.appendChild(downloadLink);
+    document.body.removeChild(downloadLink);
+    ElMessage({
+      type: "success",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  } else {
+    ElMessage({
+      type: "error",
+      showClose: true,
+      message: res.data.message,
+      center: true,
+    });
+  }
+}, 1000);
+
+// 表格斑马纹颜色修改
+const tableRowClassName = ({ row, rowIndex }) => {
+  if (rowIndex % 2 === 0) {
+    return "even";
+  } else if (rowIndex % 2 !== 0) {
+    return "odd";
+  }
+  return "";
+};
+// 分页
+const handleCurrentChange = (value) => {
+  // console.log(value);
+  currentPage.value = value;
+  getList();
+};
+
+onBeforeMount(async () => {
+  api.value = store.state.user.api;
+  getList();
+});
+onUnmounted(() => {
+  // document.removeEventListener("keyup", Enters);
+});
+</script>
+
+<style scoped lang="scss">
+.content-box {
+  width: 97.5%;
+  height: 89%;
+  margin: 20px auto;
+  background-color: #fff;
+  color: #fff;
+  display: flex;
+  flex-direction: column;
+  box-shadow: 0px 3px 10px rgba(0, 97, 255, 0.2);
+
+  .left {
+    // width: calc(100wh - 40px);
+    display: flex;
+    align-items: center;
+    height: 60px;
+    margin: 0 30px;
+    border-bottom: 1px solid #ccc;
+    color: rgb(0, 0, 0);
+    font-size: 18px;
+    font-weight: 600;
+    span {
+      margin-right: 20px;
+      cursor: pointer;
+    }
+    .is_active {
+      color: rgba(111, 182, 184, 1);
+    }
+  }
+  .middle {
+    width: 96%;
+    margin: 0 auto;
+
+    color: #000;
+    // border-bottom: 1px solid rgb(231, 231, 231);
+    .filter {
+      display: flex;
+      flex-wrap: wrap;
+      align-items: center;
+      margin: 15px 0 15px 0;
+      .search {
+        color: #fff;
+      }
+      .condition {
+        display: flex;
+        align-items: center;
+        margin: 10px 30px 10px 0;
+        :deep(.el-input .el-input__inner) {
+          font-size: 14px;
+        }
+        span {
+          margin: 0 10px 0 0;
+        }
+      }
+    }
+    .gongneng {
+      margin: 10px 0 20px 0;
+      span {
+        color: #fff;
+      }
+    }
+    :deep(.cont) {
+      width: 60%;
+      margin: 20px auto;
+    }
+    :deep(.download) {
+      display: flex;
+      align-items: center;
+      margin: 10px;
+    }
+    :deep(.download span) {
+      font-size: 16px;
+      margin-left: 20px;
+    }
+    :deep(.cont .el-button) {
+      margin-left: 60px;
+      margin-bottom: 30px;
+    }
+
+    :deep(.cont .accomplish) {
+      width: 100%;
+      display: flex;
+      justify-content: center;
+    }
+    :deep(.cont .accomplish .el-button) {
+      width: 50%;
+      margin: 0;
+    }
+  }
+  .footer {
+    width: 96%;
+    height: 550px;
+    margin: 10px auto 30px;
+    .el-table--fit {
+      height: 100%;
+      :deep(.el-table__header-wrapper) {
+        background-color: #000;
+        font-size: 15px;
+        tr {
+          color: #000;
+        }
+      }
+      :deep(.el-table__row) {
+        height: 50px;
+        font-size: 15px;
+        color: #000;
+      }
+      :deep(.el-table__row):nth-child(2n) {
+        .el-table-fixed-column--right {
+          background-color: rgba(240, 243, 247, 1);
+        }
+      }
+      :deep(.el-table__row td) {
+        padding: 0;
+        border: 0;
+      }
+
+      .el-button--primary {
+        margin-left: 5px;
+      }
+      :deep(.el-table__body .even) {
+        background-color: #fff;
+      }
+      :deep(.el-table__body .odd) {
+        background-color: rgba(240, 243, 247, 1);
+      }
+      :deep(.edit) {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        color: rgba(111, 182, 184, 1);
+      }
+      :deep(.look) {
+        padding: 0 10px;
+        cursor: pointer;
+      }
+      :deep(.look):hover {
+        color: red;
+      }
+    }
+
+    // 添加员工弹窗样式
+    :deep(.addStaff) {
+      //   height: 420px;
+      border-radius: 11px;
+      .el-dialog__header {
+        border-radius: 11px 11px 0 0;
+        background: rgba(237, 241, 245, 1);
+        font-weight: 600;
+        margin: 0;
+        .el-dialog__headerbtn {
+          outline: none;
+        }
+      }
+      .el-dialog__body {
+        padding: 30px 20px 10px 20px;
+        .el-input {
+          width: 200px;
+        }
+        // 关联报修类型样式(-----------------)
+        // .checkbox {
+        //   .el-form-item__content {
+        //     display: flex;
+        //     flex-direction: column;
+        //     align-items: flex-start;
+        //     .el-checkbox-group {
+        //       display: flex;
+        //       flex-direction: column;
+        //     }
+        //   }
+        // }
+
+        .options {
+          .el-form-item__content {
+            .queding {
+              margin-left: 20px;
+              color: #fff;
+            }
+            display: flex;
+            flex-direction: row-reverse;
+          }
+        }
+      }
+    }
+  }
+  .pageSize {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin: 0 30px;
+    span {
+      color: #000;
+    }
+    .el-pagination {
+      // width: 1600px;
+      :deep(.el-pagination__total) {
+        color: #000;
+      }
+      :deep(.el-pagination__goto) {
+        color: #000;
+      }
+      :deep(.el-pagination__classifier) {
+        color: #000;
+      }
+      :deep(.el-input__wrapper) {
+        border: 1px solid rgba(0, 0, 0, 1);
+        border-radius: 5px;
+        box-shadow: none;
+      }
+      :deep(.el-pager li) {
+        margin: 0 5px;
+        border: 1px solid rgba(0, 0, 0, 1);
+        border-radius: 5px;
+        background-color: transparent;
+      }
+      :deep(.el-pager li.is-active) {
+        background-color: rgba(111, 182, 184, 1);
+      }
+      :deep(.btn-prev) {
+        margin-right: 5px;
+        border: 1px solid rgba(0, 0, 0, 1);
+        border-radius: 5px;
+        background-color: transparent;
+      }
+      :deep(.btn-next) {
+        margin-left: 5px;
+        border: 1px solid rgba(0, 0, 0, 1);
+        border-radius: 5px;
+        background-color: transparent;
+      }
+    }
+  }
+}
+.el-input {
+  width: 192px;
+}
+</style>

+ 323 - 0
src/views/login/index.vue

@@ -0,0 +1,323 @@
+<template>
+  <div class="box">
+    <!-- <div class="middle"></div> -->
+    <div class="left">
+      <div class="rLogin">
+        <div class="titles">
+          <div class="title">欢迎登陆</div>
+          <div class="title">靖安乡村民宿民宿端</div>
+        </div>
+      </div>
+      <div class="loginForm">
+        <div
+          style="
+            display: flex;
+            align-items: center;
+            flex-direction: column;
+            justify-content: center;
+            margin-top: 104px;
+            margin-bottom: 80px;
+          "
+        >
+          <!-- <img
+            src="@/assets/nanchang.png"
+            alt=""
+            style="width: 56px; height: 56px"
+          /> -->
+          <span
+            style="
+              font-size: 50px;
+              font-weight: 600;
+              letter-spacing: 2px;
+              color: rgba(0, 0, 0, 1);
+            "
+            >靖安乡村民宿</span
+          >
+          <span
+            style="
+              font-size: 80px;
+              font-weight: 600;
+              letter-spacing: 2px;
+              color: rgba(9, 101, 98, 1);
+            "
+            >民宿端</span
+          >
+        </div>
+        <el-form
+          ref="ruleFormRef"
+          :model="ruleForm"
+          status-icon
+          :rules="rules"
+          label-width="120px"
+          class="demo-ruleForm"
+        >
+          <el-form-item label="" prop="user">
+            <el-input
+              :prefix-icon="User"
+              v-model="ruleForm.user"
+              placeholder="请输入登录名"
+              autocomplete="off"
+            />
+          </el-form-item>
+          <el-form-item label="" prop="pass">
+            <el-input
+              :prefix-icon="Lock"
+              show-password
+              v-model="ruleForm.pass"
+              type="password"
+              autocomplete="off"
+              placeholder="请输入登录密码"
+            />
+          </el-form-item>
+          <!-- <el-checkbox v-model="checked" class="remeberPwd el-form-item"
+            >记住密码</el-checkbox
+          > -->
+          <el-form-item>
+            <el-button
+              :loading="loading"
+              type="primary"
+              color="rgba(9, 101, 98, 1)"
+              @click="submitForm(ruleFormRef)"
+              >登录</el-button
+            >
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, onUnmounted } from "vue";
+import { User, Lock } from "@element-plus/icons-vue";
+import { useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import { JSEncrypt } from "jsencrypt"; // 加密密码
+import adminApi from "@/api/admin.js";
+import { useStore } from "vuex";
+import axios from "axios";
+
+const router = useRouter();
+const api = ref("");
+const store = useStore();
+const loading = ref(false);
+const ruleFormRef = ref();
+const ruleForm = reactive({
+  user: "",
+  pass: "",
+});
+const checked = ref(false); // 记住密码
+
+const rules = reactive({
+  user: [{ required: true, message: "请填写用户名", trigger: "blur" }],
+  pass: [{ required: true, message: "请填写密码", trigger: "blur" }],
+});
+
+const submitForm = (formEl) => {
+  // router.push({
+  //   path: `/seniorCelebrity/order`,
+  // });
+  // sessionStorage.setItem("sidevarItem", 1);
+  // store.commit("indexUp", 1);
+  if (!formEl) return;
+  formEl.validate(async (valid) => {
+    if (valid) {
+      loading.value = true;
+
+      let data = {
+        adminName: ruleForm.user,
+        password: ruleForm.pass,
+      };
+      let res;
+      try {
+        res = await store.dispatch("login", data);
+      } catch (e) {
+        console.log(e);
+      }
+      console.log(res);
+      // sessionStorage.setItem("name", ruleForm.pass);
+      if (res == "success") {
+        router.push({ path: `/seniorCelebrity/order` });
+        store.commit("indexUp", "/seniorCelebrity/order");
+        sessionStorage.setItem("sidevarItem", "/seniorCelebrity/order");
+        ElMessage({
+          type: "success",
+          showClose: true,
+          message: "登录成功",
+          center: true,
+        });
+      } else {
+        loading.value = false;
+        ElMessage({
+          type: "error",
+          showClose: true,
+          message: "用户名或密码错误",
+          center: true,
+        });
+      }
+    } else {
+      return false;
+    }
+  });
+};
+const Enters = (e) => {
+  // console.log("按键:", e.key);
+  if (e.key == "Enter") {
+    submitForm(ruleFormRef.value);
+  }
+};
+onMounted(() => {
+  api.value = store.state.user.api;
+  if (localStorage.getItem("pass") && localStorage.getItem("user")) {
+    ruleForm.user = localStorage.getItem("user");
+    ruleForm.pass = localStorage.getItem("pass");
+    checked.value = true;
+  }
+  if (localStorage.getItem("user")) {
+    ruleForm.user = localStorage.getItem("user");
+  }
+  document.addEventListener("keyup", Enters);
+});
+onUnmounted(() => {
+  document.removeEventListener("keyup", Enters);
+});
+</script>
+
+<style lang="scss" scoped>
+.box {
+  width: 100%;
+  height: 100vh;
+  // background: url(@/assets/login.png);
+  background-size: cover;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  // .middle {
+  //   width: 1180px;
+  //   height: 740px;
+  //   position: absolute;
+
+  // }
+  .left {
+    // box-shadow: 39px 30px 58px 0px rgba(8, 53, 115, 0.55);
+
+    width: 100%;
+    height: 100%;
+    border-radius: 18px;
+    display: flex;
+    align-items: center;
+    // flex-direction: row-reverse;
+    // background-image: url(@/assets/login2.png);
+    background-size: 110% 116%;
+    // background-position: -19px -28px;
+    .loginForm {
+      flex: 1;
+      height: 740px;
+      // background-color: #fff;
+      border-radius: 18px 0 0 18px;
+
+      .el-form {
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+        .el-form-item {
+          width: 420px;
+          height: 60px;
+          margin-bottom: 30px;
+
+          :deep(.el-form-item__content) {
+            margin-left: 0 !important;
+
+            .el-input {
+              height: 60px;
+
+              .el-input__wrapper {
+                border-radius: 12px;
+                .el-input__prefix {
+                  margin: 0 10px 0 12px;
+                }
+              }
+
+              .el-icon {
+                width: 24px;
+                height: 24px;
+                svg {
+                  width: 24px;
+                  height: 24px;
+                }
+              }
+              .el-input__inner {
+                height: 100%;
+                font-size: 24px;
+              }
+            }
+            .el-form-item__error {
+              font-size: 16px;
+            }
+            .el-button {
+              width: 100%;
+              height: 60px;
+              font-size: 24px;
+              border-radius: 56px;
+            }
+          }
+
+          .el-button--primary {
+            width: 380px;
+          }
+        }
+        .remeberPwd {
+          height: 30px;
+          margin-bottom: 30px;
+          :deep(.el-checkbox__input) {
+            .el-checkbox__inner {
+              width: 18px;
+              height: 18px;
+            }
+            .el-checkbox__inner::after {
+              width: 6px;
+              height: 12px;
+              top: -1px;
+            }
+          }
+          :deep(.el-checkbox__label) {
+            font-size: 18px;
+          }
+        }
+      }
+    }
+    .rLogin {
+      width: 796px;
+      height: 100%;
+      // border-radius: 0 18px 18px 0;
+      background-image: url("@/assets/login.png");
+      background-repeat: no-repeat;
+      background-position: -150px 0;
+      background-size: cover;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      color: #fff;
+      .titles {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+      }
+      .title:nth-child(1) {
+        font-size: 80px;
+        font-weight: 600;
+        letter-spacing: 10px;
+        margin-bottom: 20px;
+      }
+      .title:nth-child(2) {
+        font-size: 40px;
+        font-weight: 600;
+        letter-spacing: 10px;
+      }
+    }
+  }
+}
+</style>

+ 21 - 0
src/views/map/map.js

@@ -0,0 +1,21 @@
+export function LoadBaiduMapScript() {
+  const BMap_URL =
+    "https://api.map.baidu.com/api?v=3.0&ak=XXXX&callback=onBMapCallback";
+  return new Promise((resolve, _reject) => {
+    // 如果已加载直接返回
+    if (typeof BMap !== "undefined") {
+      resolve(BMap);
+      return true;
+    }
+    // 百度地图异步加载回调处理
+    window.onBMapCallback = function () {
+      console.log("百度地图脚本初始化成功...");
+      resolve(BMap);
+    };
+    // 插入script脚本
+    const scriptNode = document.createElement("script");
+    scriptNode.setAttribute("type", "text/javascript");
+    scriptNode.setAttribute("src", BMap_URL);
+    document.body.appendChild(scriptNode);
+  });
+}

+ 192 - 0
src/views/map/map.vue

@@ -0,0 +1,192 @@
+<template>
+  <div id="map"></div>
+  <div class="address">
+    <span class="lng">请输入地址:</span>
+    <el-input id="suggestId" v-model="address" placeholder="请输入地点" />
+  </div>
+  <div class="address">
+    <span class="lng">地址:{{ address }}</span>
+    <span class="lng">lng:{{ lng }}</span>
+    <span class="lat">lat:{{ lat }}</span>
+  </div>
+  <div class="options">
+    <el-button
+      color="rgba(9, 101, 98, 1)"
+      class="queding"
+      type="primary"
+      @click="mapAddress(true)"
+    >
+      确定
+    </el-button>
+    <el-button @click="mapAddress(false)">取消</el-button>
+  </div>
+</template>
+
+<script setup>
+import loadBMap from "@/utils/loadMap.js";
+import { ref, reactive, onBeforeMount, onMounted, watch } from "vue";
+const mapInit = loadBMap("jmkawuXGwcepLcsAqcAi3FeDMfaLhnOE");
+
+const lng = ref("--");
+const lat = ref("--");
+const address = ref("");
+const map = ref();
+
+const emit = defineEmits(["mapClick"]);
+// 确定按钮
+const mapAddress = (flag) => {
+  let data = {
+    address: address.value,
+    lng: lng.value,
+    lat: lat.value,
+    flag: flag,
+  };
+  emit("mapClick", data);
+};
+
+const getList = () => {
+  mapInit.then((BMap) => {
+    //创建地图实例,位于BMap命名空间下的Map类表示地图,通过new操作符可以创建一个地图实例。其参数可以是元素id也可以是元素对象。
+    map.value = new BMap.Map("map");
+    map.value.centerAndZoom("江西", 12); // 初始化地图,设置城市和地图级别
+    map.value.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
+
+    const ac = new BMap.Autocomplete({
+      input: "suggestId",
+      location: map.value,
+    });
+    //建立一个自动完成的对象
+    ac.addEventListener("onconfirm", function (e) {
+      //鼠标点击下拉列表后的事件
+      const tempValue = e.item.value;
+      const searchValue =
+        tempValue.province +
+        tempValue.city +
+        tempValue.district +
+        tempValue.street +
+        tempValue.business;
+      console.log(searchValue, "输入框选中的值");
+
+      setPlace(BMap, map.value, searchValue);
+    });
+    // 点击地图(获取当前点击点的经纬度)
+    map.value.addEventListener("click", function handleClick(e) {
+      map.value.clearOverlays(); //清除地图上所有覆盖物
+      console.log(e);
+      address.value = "";
+      console.log("点击的经纬度:" + e.Af.lng + ", " + e.Af.lat);
+      lat.value = e.Af.lat.toFixed(8);
+      lng.value = e.Af.lng.toFixed(8);
+      map.value.addOverlay(
+        new BMap.Marker({
+          lng: e.Af.lng.toFixed(8),
+          lat: e.Af.lat.toFixed(8),
+        })
+      );
+    });
+    // map.value.removeEventListener("click", handleClick); // 移除当前点击点的经纬度事件监听
+  });
+};
+
+/**
+ * 根据输入框的值在地图上添加标记点
+ * @param
+ *   BMap:地图对象
+ *   searchValue:输入框下拉数据选中的值
+ * **/
+const setPlace = (BMap, map, searchValue) => {
+  map.clearOverlays(); //清除地图上所有覆盖物
+  const local = new BMap.LocalSearch(map, {
+    //智能搜索
+    onSearchComplete: (res) => {
+      console.log(res);
+
+      const pp = local.getResults().getPoi(0).point; //获取第一个智能搜索的结果
+      console.log(pp);
+
+      map.centerAndZoom(pp, 21);
+      map.addOverlay(new BMap.Marker(pp)); //添加标注
+      movePoint(BMap, map, res.Vr[0].point);
+    },
+  });
+  local.search(searchValue);
+};
+/**
+ * 移动标记点
+ * @param
+ *   BMap:地图对象
+ *   latlng:经纬度
+ * **/
+const movePoint = (BMap, map, latlng) => {
+  map.clearOverlays(); //清除地图上所有覆盖物
+  //使用BMap命名空间下的Point类来创建一个坐标点
+  const point = new BMap.Point(latlng.lng, latlng.lat);
+  const marker = new BMap.Marker(point, {
+    enableDragging: true,
+  });
+  map.addOverlay(marker);
+  latlngToAddress(BMap, latlng);
+
+  // 覆盖物拖拽开始事件
+  marker.addEventListener("dragstart", function (e) {
+    // 清除一些覆盖物
+    console.log("[开始]", e);
+  });
+  // 覆盖物拖拽事件
+  marker.addEventListener("dragend", function () {
+    const nowPoint = marker.getPosition(); // 拖拽完成之后坐标的位置(经纬度)
+    latlngToAddress(BMap, nowPoint);
+  });
+};
+/**
+ * 地址解析
+ * @param
+ *   BMap:地图对象
+ *   latlng:经纬度
+ * **/
+const latlngToAddress = (BMap, latlng) => {
+  const geoc = new BMap.Geocoder();
+  geoc.getLocation(latlng, function (rs) {
+    console.log(rs.surroundingPois[0]);
+    address.value = rs.surroundingPois[0].address + rs.surroundingPois[0].title;
+    lat.value = rs.surroundingPois[0].point.lat.toFixed(8);
+    lng.value = rs.surroundingPois[0].point.lng.toFixed(8);
+  });
+};
+onBeforeMount(async () => {
+  getList();
+});
+</script>
+
+<style lang="scss" scoped>
+#map {
+  border: 1px solid red;
+  box-sizing: border-box;
+  width: 100%;
+  height: 600px;
+}
+#suggestId {
+  // border: 1px solid red;
+  width: 120px !important;
+  height: 30px;
+}
+.el-input {
+  width: 350px;
+}
+.address {
+  margin: 10px 20px;
+}
+.lng {
+  margin-right: 20px;
+}
+.options {
+  width: 98%;
+
+  .queding {
+    margin-left: 20px;
+    color: #fff;
+  }
+  display: flex;
+  flex-direction: row-reverse;
+}
+</style>

Файловите разлики са ограничени, защото са твърде много
+ 1308 - 0
src/views/order/order.vue


Файловите разлики са ограничени, защото са твърде много
+ 1430 - 0
src/views/roomInfo/roomInfo.vue


Файловите разлики са ограничени, защото са твърде много
+ 1105 - 0
src/views/roomType/roomType.vue


+ 22 - 0
text.json

@@ -0,0 +1,22 @@
+MD5( "${HA1}:${nonce}:${nc}:${cno
+nce}:${qop}:${HA2}" ) =
+6629fae49393a05397450978507c4
+ef1
+
+
+HA1 =
+MD5( "${username}:${realm}:${pas
+sword}" ) =
+939e7578ed9e3c518a452acee763
+bce9
+HA2 = MD5( "POST:${uri}" ) =
+39aff3a2bab6126f332b942af96d33
+66
+
+username="admin",realm="127.0.0.1host .com",nonce="dcd98b7102dd2f0e8b11d0f600bfh0c093"
+,uri="/dir/index,html",gop="auth",nc=00000001, cnonce="0a4f113b",response="f8877dald712423e963da0aed9fb7cf8",opague="5ccc069c403ebaf9f0171e9517f40e41"
+
+
+qop="auth",opaque="5ccc069c403ebaf9f0171e9517f40e41",realm="127.0.0.1@host.com",nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093"
+
+username="admin",realm="127.0.0.1@host.com",nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",uri="/dir/index,html",qop="auth",nc=00000001,cnonce="0a4f113b",response="f8877dald712423e963da0aed9fb7cf8",opague="5ccc069c403ebaf9f0171e9517f40e41"

+ 83 - 0
vite.config.js

@@ -0,0 +1,83 @@
+import { defineConfig } from "vite";
+import vue from "@vitejs/plugin-vue";
+import path from "path";
+import { resolve, join } from "path";
+// https://vitejs.dev/config/
+export default defineConfig({
+  plugins: [vue()],
+  resolve: {
+    alias: {
+      "@": path.resolve("./src"), // @代替src
+    },
+  },
+  css: {
+    preprocessorOptions: {
+      scss: {
+        additionalData: `@import "./src/style/mixin.scss";`, // 此处全局的scss文件
+      },
+    },
+  },
+  server: {
+    host: "0.0.0.0",
+    port: 8686,
+    // 是否开启 https
+    // https: false,
+    // 线上地址 https://chtech.ncjti.edu.cn/hotelReservation/pc3/
+    proxy: {
+      "/hotelReservation": {
+        target: "https://chtech.ncjti.edu.cn/hotelReservation",
+        // target: "http://gf43w4.natappfree.cc",
+        changeOrigin: true,
+        rewrite: (path) => path.replace(/^\/hotelReservation/, ""),
+      },
+    }, // https://chtech.ncjti.edu.cn/hotelReservation/pc2
+
+    // // 测试地址
+    // proxy: {
+    //   "/hotelReservation/pc2": {
+    //     target: "https://chtech.ncjti.edu.cn/hotelReservation/pc2", // 测试环境
+    //     changeOrigin: true,
+    //     rewrite: (path) => path.replace(/^\/hotelReservation\/pc2/, ""),
+    //   },
+    // },
+  },
+  publicDir: "public",
+  base: "./",
+  // 打包配置
+  build: {
+    target: "modules", //设置最终构建的浏览器兼容目标  //es2015(编译成es5) | modules
+    outDir: "dist", // 构建得包名  默认:dist
+    assetsDir: "static", // 静态资源得存放路径文件名  assets
+    // sourcemap: false, //构建后是否生成 source map 文件
+    // brotliSize: false, // 启用/禁用 brotli 压缩大小报告。 禁用该功能可能会提高大型项目的构建性能
+    chunkSizeWarningLimit: 1000, //chunk 大小警告的限制(以 kbs 为单位)默认:500
+    // cssTarget: 'chrome61' //防止 vite 将 rgba() 颜色转化为 #RGBA 十六进制符号的形式  (要兼容的场景是安卓微信中的 webview 时,它不支持 CSS 中的 #RGBA 十六进制颜色符号)
+    rollupOptions: {
+      input: {
+        index: resolve(__dirname, "index.html"),
+      },
+      output: {
+        manualChunks(id) {
+          if (id.includes("node_modules")) {
+            return id
+              .toString()
+              .split("node_modules/")[1]
+              .split("/")[0]
+              .toString();
+          }
+        },
+        chunkFileNames: "static/js/[name]-[hash].js",
+        entryFileNames: "static/js/[name]-[hash].js",
+        assetFileNames: "static/[ext]/name-[hash].[ext]",
+      },
+    },
+    minify: "terser", // 项目压缩 :boolean | 'terser' | 'esbuild'
+    terserOptions: {
+      // 生产环境移除console
+      compress: {
+        drop_console: true,
+        drop_debugger: true,
+      },
+    },
+  },
+});