unknown 2 týždňov pred
rodič
commit
a78127cc18
100 zmenil súbory, kde vykonal 5060 pridanie a 82 odobranie
  1. 194 16
      package-lock.json
  2. 3 0
      package.json
  3. 23 6
      src/App.vue
  4. BIN
      src/assets/img/Admin.png
  5. BIN
      src/assets/img/Back.png
  6. BIN
      src/assets/img/FixedPoint/FixedPoint.png
  7. BIN
      src/assets/img/FixedPoint/PointNavigation.png
  8. BIN
      src/assets/img/FixedPoint/back.png
  9. BIN
      src/assets/img/FixedPoint/jieshu.png
  10. BIN
      src/assets/img/FixedPoint/kaishi.png
  11. BIN
      src/assets/img/FixedPoint/qingchu.png
  12. BIN
      src/assets/img/FixedPoint/queding.png
  13. BIN
      src/assets/img/FixedPoint/sayao.png
  14. BIN
      src/assets/img/FixedPoint/sayaohover.png
  15. BIN
      src/assets/img/FixedPoint/shexiangtou.png
  16. BIN
      src/assets/img/FixedPoint/shexiangtouhover.png
  17. BIN
      src/assets/img/FixedPoint/toushi.png
  18. BIN
      src/assets/img/FixedPoint/weizhi.png
  19. BIN
      src/assets/img/FixedPoint/xuandian.png
  20. BIN
      src/assets/img/PathPlan/A.png
  21. BIN
      src/assets/img/PathPlan/B.png
  22. BIN
      src/assets/img/PathPlan/back.png
  23. BIN
      src/assets/img/PathPlan/jieshu.png
  24. BIN
      src/assets/img/PathPlan/kaishi.png
  25. BIN
      src/assets/img/PathPlan/pathplan.png
  26. BIN
      src/assets/img/PathPlan/sayao.png
  27. BIN
      src/assets/img/PathPlan/sayaohover.png
  28. BIN
      src/assets/img/PathPlan/shebei.png
  29. BIN
      src/assets/img/PathPlan/shexiangtou.png
  30. BIN
      src/assets/img/PathPlan/toushi.png
  31. BIN
      src/assets/img/PathPlan/toushidi.png
  32. BIN
      src/assets/img/PathPlan/toushigao.png
  33. BIN
      src/assets/img/PathPlan/toushizhong.png
  34. BIN
      src/assets/img/PathPlan/toushizidong.png
  35. BIN
      src/assets/img/PathPlan/weizhi.png
  36. BIN
      src/assets/img/PathPlan/zuobiao.png
  37. BIN
      src/assets/img/PointNavigation/A.png
  38. BIN
      src/assets/img/PointNavigation/B.png
  39. BIN
      src/assets/img/PointNavigation/C.png
  40. BIN
      src/assets/img/PointNavigation/PointNavigation.png
  41. BIN
      src/assets/img/PointNavigation/back.png
  42. BIN
      src/assets/img/PointNavigation/jieshu.png
  43. BIN
      src/assets/img/PointNavigation/kaishi.png
  44. BIN
      src/assets/img/PointNavigation/qingchu.png
  45. BIN
      src/assets/img/PointNavigation/queding.png
  46. BIN
      src/assets/img/PointNavigation/sayao.png
  47. BIN
      src/assets/img/PointNavigation/sayaohover.png
  48. BIN
      src/assets/img/PointNavigation/shexiangtou.png
  49. BIN
      src/assets/img/PointNavigation/shexiangtouhover.png
  50. BIN
      src/assets/img/PointNavigation/toushi.png
  51. BIN
      src/assets/img/PointNavigation/weizhi.png
  52. BIN
      src/assets/img/PointNavigation/xuandian.png
  53. BIN
      src/assets/img/background.png
  54. BIN
      src/assets/img/computer.png
  55. BIN
      src/assets/img/deviceDetails/Camera.png
  56. BIN
      src/assets/img/deviceDetails/Feeding.png
  57. BIN
      src/assets/img/deviceDetails/dianyuan.png
  58. BIN
      src/assets/img/deviceDetails/fixedPoint.png
  59. BIN
      src/assets/img/deviceDetails/gongzuozhuangtai.png
  60. BIN
      src/assets/img/deviceDetails/guzhang.png
  61. BIN
      src/assets/img/deviceDetails/lishi.png
  62. BIN
      src/assets/img/deviceDetails/navigation.png
  63. BIN
      src/assets/img/deviceDetails/pathPlan.png
  64. BIN
      src/assets/img/deviceDetails/return.png
  65. BIN
      src/assets/img/deviceDetails/ship.png
  66. BIN
      src/assets/img/deviceDetails/sudu.png
  67. BIN
      src/assets/img/deviceDetails/toushi.png
  68. BIN
      src/assets/img/deviceDetails/water.png
  69. BIN
      src/assets/img/deviceDetails/yujing.png
  70. BIN
      src/assets/img/dy.png
  71. BIN
      src/assets/img/gogogo.png
  72. BIN
      src/assets/img/gzh.png
  73. BIN
      src/assets/img/left.png
  74. BIN
      src/assets/img/personal/contact.png
  75. BIN
      src/assets/img/personal/maintenance.png
  76. BIN
      src/assets/img/right.png
  77. BIN
      src/assets/img/waterQuality/PH.png
  78. BIN
      src/assets/img/waterQuality/shidu.png
  79. BIN
      src/assets/img/waterQuality/yang.png
  80. BIN
      src/assets/img/wx.png
  81. 0 60
      src/components/HelloWorld.vue
  82. 97 0
      src/components/home/FeedingRecord.vue
  83. 277 0
      src/components/home/FeedingToushi.vue
  84. 382 0
      src/components/home/FixedPoint.vue
  85. 538 0
      src/components/home/HomeIndex.vue
  86. 326 0
      src/components/home/PathPlan.vue
  87. 755 0
      src/components/home/PointNavigation.vue
  88. 285 0
      src/components/home/deviceCamera.vue
  89. 183 0
      src/components/home/deviceDetails.vue
  90. 203 0
      src/components/home/deviceHistory.vue
  91. 84 0
      src/components/home/errorRecord.vue
  92. 220 0
      src/components/home/waterQuality.vue
  93. 53 0
      src/components/pagination/pagination.vue
  94. 152 0
      src/components/personal/ContactUs.vue
  95. 0 0
      src/components/personal/FeedbackInformation.vue
  96. 186 0
      src/components/personal/RepairRecord.vue
  97. 303 0
      src/components/power/powerManagement.vue
  98. 241 0
      src/components/qHeader.vue
  99. 162 0
      src/components/qNav.vue
  100. 393 0
      src/components/role/roleManagement.vue

+ 194 - 16
package-lock.json

@@ -8,7 +8,10 @@
       "name": "nzznship",
       "version": "0.1.0",
       "dependencies": {
+        "@amap/amap-jsapi-loader": "^1.0.1",
+        "axios": "^1.9.0",
         "core-js": "^3.8.3",
+        "element-ui": "^2.15.14",
         "vue": "^2.6.14",
         "vue-router": "^3.5.1",
         "vuex": "^3.6.2"
@@ -43,6 +46,12 @@
         "node": "8 || 9 || 10 || 11 || 12 || 13 || 14 || 15 || 16 || 17 || 18 || 19 || 20 || 21 || 22"
       }
     },
+    "node_modules/@amap/amap-jsapi-loader": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
+      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==",
+      "license": "MIT"
+    },
     "node_modules/@ampproject/remapping": {
       "version": "2.3.0",
       "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz",
@@ -88,6 +97,7 @@
       "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "@ampproject/remapping": "^2.2.0",
         "@babel/code-frame": "^7.27.1",
@@ -2947,6 +2957,7 @@
       "integrity": "sha512-nV7tYQLe7YsTtzFrfOMIHc5N2hp5lHG2rpYr0aNja9rNljdgcPZLyQRb2YRivTHqTv7lI962UXFURcpStHgyFw==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "@babel/helper-compilation-targets": "^7.12.16",
         "@soda/friendly-errors-webpack-plugin": "^1.8.0",
@@ -3492,6 +3503,7 @@
       "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "bin": {
         "acorn": "bin/acorn"
       },
@@ -3538,6 +3550,7 @@
       "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.1",
         "fast-json-stable-stringify": "^2.0.0",
@@ -3746,6 +3759,20 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/async-validator": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-1.8.5.tgz",
+      "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
+      "dependencies": {
+        "babel-runtime": "6.x"
+      }
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "license": "MIT"
+    },
     "node_modules/at-least-node": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
@@ -3794,6 +3821,23 @@
         "postcss": "^8.1.0"
       }
     },
+    "node_modules/axios": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.9.0.tgz",
+      "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
+      "license": "MIT",
+      "dependencies": {
+        "follow-redirects": "^1.15.6",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
+      }
+    },
+    "node_modules/babel-helper-vue-jsx-merge-props": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+      "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==",
+      "license": "MIT"
+    },
     "node_modules/babel-loader": {
       "version": "8.4.1",
       "resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.4.1.tgz",
@@ -3881,6 +3925,24 @@
         "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
       }
     },
+    "node_modules/babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmmirror.com/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+      "license": "MIT",
+      "dependencies": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      }
+    },
+    "node_modules/babel-runtime/node_modules/core-js": {
+      "version": "2.6.12",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz",
+      "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+      "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+      "hasInstallScript": true,
+      "license": "MIT"
+    },
     "node_modules/balanced-match": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -4062,6 +4124,7 @@
         }
       ],
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "caniuse-lite": "^1.0.30001718",
         "electron-to-chromium": "^1.5.160",
@@ -4140,7 +4203,6 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
       "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "es-errors": "^1.3.0",
@@ -4475,6 +4537,18 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "license": "MIT",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/commander": {
       "version": "8.3.0",
       "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
@@ -4758,6 +4832,7 @@
       "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "icss-utils": "^5.1.0",
         "postcss": "^8.4.33",
@@ -4846,6 +4921,7 @@
       "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.3",
         "fast-uri": "^3.0.1",
@@ -5095,7 +5171,6 @@
       "version": "1.5.2",
       "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.5.2.tgz",
       "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=0.10.0"
@@ -5300,6 +5375,15 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/depd": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
@@ -5492,7 +5576,6 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
       "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "call-bind-apply-helpers": "^1.0.1",
@@ -5534,6 +5617,23 @@
       "dev": true,
       "license": "ISC"
     },
+    "node_modules/element-ui": {
+      "version": "2.15.14",
+      "resolved": "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.14.tgz",
+      "integrity": "sha512-2v9fHL0ZGINotOlRIAJD5YuVB8V7WKxrE9Qy7dXhRipa035+kF7WuU/z+tEmLVPBcJ0zt8mOu1DKpWcVzBK8IA==",
+      "license": "MIT",
+      "dependencies": {
+        "async-validator": "~1.8.1",
+        "babel-helper-vue-jsx-merge-props": "^2.0.0",
+        "deepmerge": "^1.2.0",
+        "normalize-wheel": "^1.0.1",
+        "resize-observer-polyfill": "^1.5.0",
+        "throttle-debounce": "^1.0.1"
+      },
+      "peerDependencies": {
+        "vue": "^2.5.17"
+      }
+    },
     "node_modules/emoji-regex": {
       "version": "8.0.0",
       "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -5636,7 +5736,6 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
       "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 0.4"
@@ -5646,7 +5745,6 @@
       "version": "1.3.0",
       "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
       "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 0.4"
@@ -5663,7 +5761,6 @@
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
       "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "es-errors": "^1.3.0"
@@ -5672,6 +5769,21 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/escalade": {
       "version": "3.2.0",
       "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
@@ -5706,6 +5818,7 @@
       "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "@babel/code-frame": "7.12.11",
         "@eslint/eslintrc": "^0.4.3",
@@ -5892,6 +6005,7 @@
       "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.3",
         "fast-uri": "^3.0.1",
@@ -6622,7 +6736,6 @@
       "version": "1.15.9",
       "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
       "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
-      "dev": true,
       "funding": [
         {
           "type": "individual",
@@ -6639,6 +6752,22 @@
         }
       }
     },
+    "node_modules/form-data": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.3.tgz",
+      "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
+      "license": "MIT",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
     "node_modules/forwarded": {
       "version": "0.2.0",
       "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
@@ -6722,7 +6851,6 @@
       "version": "1.1.2",
       "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
       "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
-      "dev": true,
       "license": "MIT",
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
@@ -6759,7 +6887,6 @@
       "version": "1.3.0",
       "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
       "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "call-bind-apply-helpers": "^1.0.2",
@@ -6784,7 +6911,6 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
       "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "dunder-proto": "^1.0.1",
@@ -6884,7 +7010,6 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
       "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 0.4"
@@ -6950,7 +7075,6 @@
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
       "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 0.4"
@@ -6959,6 +7083,21 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "license": "MIT",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/hash-sum": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz",
@@ -6970,7 +7109,6 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
       "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "function-bind": "^1.1.2"
@@ -8149,7 +8287,6 @@
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
       "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 0.4"
@@ -8263,7 +8400,6 @@
       "version": "1.52.0",
       "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
       "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 0.6"
@@ -8273,7 +8409,6 @@
       "version": "2.1.35",
       "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
       "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "mime-db": "1.52.0"
@@ -8319,6 +8454,7 @@
       "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.3",
         "fast-uri": "^3.0.1",
@@ -8632,6 +8768,12 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/normalize-wheel": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
+      "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==",
+      "license": "BSD-3-Clause"
+    },
     "node_modules/npm-run-path": {
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -9125,6 +9267,7 @@
         }
       ],
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "nanoid": "^3.3.11",
         "picocolors": "^1.1.1",
@@ -9878,6 +10021,12 @@
         "node": ">= 0.10"
       }
     },
+    "node_modules/proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+      "license": "MIT"
+    },
     "node_modules/pseudomap": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -10071,6 +10220,12 @@
         "node": ">=4"
       }
     },
+    "node_modules/regenerator-runtime": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+      "license": "MIT"
+    },
     "node_modules/regexpp": {
       "version": "3.2.0",
       "resolved": "https://registry.npmmirror.com/regexpp/-/regexpp-3.2.0.tgz",
@@ -10186,6 +10341,12 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==",
+      "license": "MIT"
+    },
     "node_modules/resolve": {
       "version": "1.22.10",
       "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.10.tgz",
@@ -11252,6 +11413,7 @@
       "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.3",
         "fast-uri": "^3.0.1",
@@ -11398,6 +11560,15 @@
         "url": "https://opencollective.com/webpack"
       }
     },
+    "node_modules/throttle-debounce": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
+      "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/thunky": {
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz",
@@ -11669,6 +11840,7 @@
       "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
       "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "@vue/compiler-sfc": "2.7.16",
         "csstype": "^3.1.0"
@@ -11847,6 +12019,7 @@
       "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "de-indent": "^1.0.2",
         "he": "^1.2.0"
@@ -11928,6 +12101,7 @@
       "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "@types/eslint-scope": "^3.7.7",
         "@types/estree": "^1.0.6",
@@ -12065,6 +12239,7 @@
       "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.3",
         "fast-uri": "^3.0.1",
@@ -12182,6 +12357,7 @@
       "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.3",
         "fast-uri": "^3.0.1",
@@ -12276,6 +12452,7 @@
       "integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "engines": {
         "node": ">=10.13.0"
       }
@@ -12293,6 +12470,7 @@
       "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
       "dev": true,
       "license": "MIT",
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.3",
         "fast-uri": "^3.0.1",

+ 3 - 0
package.json

@@ -8,7 +8,10 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@amap/amap-jsapi-loader": "^1.0.1",
+    "axios": "^1.9.0",
     "core-js": "^3.8.3",
+    "element-ui": "^2.15.14",
     "vue": "^2.6.14",
     "vue-router": "^3.5.1",
     "vuex": "^3.6.2"

+ 23 - 6
src/App.vue

@@ -1,20 +1,37 @@
 <template>
   <div id="app">
-    <nav>
-      <router-link to="/">Home</router-link> |
-      <router-link to="/about">About</router-link>
-    </nav>
-    <router-view/>
+    <router-view />
   </div>
 </template>
 
 <style lang="scss">
+* {
+  padding: 0;
+  margin: 0;
+}
+
 #app {
   font-family: Avenir, Helvetica, Arial, sans-serif;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
   text-align: center;
   color: #2c3e50;
+  overflow-y: auto;
+  scrollbar-width: none;
+  /* Firefox */
+  -ms-overflow-style: none;
+  /* IE10+ */
+}
+
+/* 去除滚动条但保留滚动 */
+::-webkit-scrollbar {
+  display: none;
+}
+
+/* 允许滚动 */
+body,
+html {
+  overflow: scroll;
 }
 
 nav {
@@ -29,4 +46,4 @@ nav {
     }
   }
 }
-</style>
+</style>

BIN
src/assets/img/Admin.png


BIN
src/assets/img/Back.png


BIN
src/assets/img/FixedPoint/FixedPoint.png


BIN
src/assets/img/FixedPoint/PointNavigation.png


BIN
src/assets/img/FixedPoint/back.png


BIN
src/assets/img/FixedPoint/jieshu.png


BIN
src/assets/img/FixedPoint/kaishi.png


BIN
src/assets/img/FixedPoint/qingchu.png


BIN
src/assets/img/FixedPoint/queding.png


BIN
src/assets/img/FixedPoint/sayao.png


BIN
src/assets/img/FixedPoint/sayaohover.png


BIN
src/assets/img/FixedPoint/shexiangtou.png


BIN
src/assets/img/FixedPoint/shexiangtouhover.png


BIN
src/assets/img/FixedPoint/toushi.png


BIN
src/assets/img/FixedPoint/weizhi.png


BIN
src/assets/img/FixedPoint/xuandian.png


BIN
src/assets/img/PathPlan/A.png


BIN
src/assets/img/PathPlan/B.png


BIN
src/assets/img/PathPlan/back.png


BIN
src/assets/img/PathPlan/jieshu.png


BIN
src/assets/img/PathPlan/kaishi.png


BIN
src/assets/img/PathPlan/pathplan.png


BIN
src/assets/img/PathPlan/sayao.png


BIN
src/assets/img/PathPlan/sayaohover.png


BIN
src/assets/img/PathPlan/shebei.png


BIN
src/assets/img/PathPlan/shexiangtou.png


BIN
src/assets/img/PathPlan/toushi.png


BIN
src/assets/img/PathPlan/toushidi.png


BIN
src/assets/img/PathPlan/toushigao.png


BIN
src/assets/img/PathPlan/toushizhong.png


BIN
src/assets/img/PathPlan/toushizidong.png


BIN
src/assets/img/PathPlan/weizhi.png


BIN
src/assets/img/PathPlan/zuobiao.png


BIN
src/assets/img/PointNavigation/A.png


BIN
src/assets/img/PointNavigation/B.png


BIN
src/assets/img/PointNavigation/C.png


BIN
src/assets/img/PointNavigation/PointNavigation.png


BIN
src/assets/img/PointNavigation/back.png


BIN
src/assets/img/PointNavigation/jieshu.png


BIN
src/assets/img/PointNavigation/kaishi.png


BIN
src/assets/img/PointNavigation/qingchu.png


BIN
src/assets/img/PointNavigation/queding.png


BIN
src/assets/img/PointNavigation/sayao.png


BIN
src/assets/img/PointNavigation/sayaohover.png


BIN
src/assets/img/PointNavigation/shexiangtou.png


BIN
src/assets/img/PointNavigation/shexiangtouhover.png


BIN
src/assets/img/PointNavigation/toushi.png


BIN
src/assets/img/PointNavigation/weizhi.png


BIN
src/assets/img/PointNavigation/xuandian.png


BIN
src/assets/img/background.png


BIN
src/assets/img/computer.png


BIN
src/assets/img/deviceDetails/Camera.png


BIN
src/assets/img/deviceDetails/Feeding.png


BIN
src/assets/img/deviceDetails/dianyuan.png


BIN
src/assets/img/deviceDetails/fixedPoint.png


BIN
src/assets/img/deviceDetails/gongzuozhuangtai.png


BIN
src/assets/img/deviceDetails/guzhang.png


BIN
src/assets/img/deviceDetails/lishi.png


BIN
src/assets/img/deviceDetails/navigation.png


BIN
src/assets/img/deviceDetails/pathPlan.png


BIN
src/assets/img/deviceDetails/return.png


BIN
src/assets/img/deviceDetails/ship.png


BIN
src/assets/img/deviceDetails/sudu.png


BIN
src/assets/img/deviceDetails/toushi.png


BIN
src/assets/img/deviceDetails/water.png


BIN
src/assets/img/deviceDetails/yujing.png


BIN
src/assets/img/dy.png


BIN
src/assets/img/gogogo.png


BIN
src/assets/img/gzh.png


BIN
src/assets/img/left.png


BIN
src/assets/img/personal/contact.png


BIN
src/assets/img/personal/maintenance.png


BIN
src/assets/img/right.png


BIN
src/assets/img/waterQuality/PH.png


BIN
src/assets/img/waterQuality/shidu.png


BIN
src/assets/img/waterQuality/yang.png


BIN
src/assets/img/wx.png


+ 0 - 60
src/components/HelloWorld.vue

@@ -1,60 +0,0 @@
-<template>
-  <div class="hello">
-    <h1>{{ msg }}</h1>
-    <p>
-      For a guide and recipes on how to configure / customize this project,<br>
-      check out the
-      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
-    </p>
-    <h3>Installed CLI Plugins</h3>
-    <ul>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
-    </ul>
-    <h3>Essential Links</h3>
-    <ul>
-      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
-      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
-      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
-      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
-      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
-    </ul>
-    <h3>Ecosystem</h3>
-    <ul>
-      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
-      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
-      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
-      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
-      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
-    </ul>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'HelloWorld',
-  props: {
-    msg: String
-  }
-}
-</script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped lang="scss">
-h3 {
-  margin: 40px 0 0;
-}
-ul {
-  list-style-type: none;
-  padding: 0;
-}
-li {
-  display: inline-block;
-  margin: 0 10px;
-}
-a {
-  color: #42b983;
-}
-</style>

+ 97 - 0
src/components/home/FeedingRecord.vue

@@ -0,0 +1,97 @@
+<template>
+    <div class="FeedingRecord">
+        <el-button style="position: absolute; top: 40px; left: 66px;" size="medium" round icon="el-icon-back"
+            @click="handleBack()">返回</el-button>
+        <el-table :data="tableData" height="350px" style="width: 100%" :header-cell-class-name="HeaderCell" stripe
+            border>
+            <el-table-column label="序号" type="index" width="80" align="center">
+            </el-table-column>
+            <el-table-column label="投食重量" align="center">
+                <template slot-scope="scope">
+                    <span style="margin-left: 10px">{{ scope.row.weight
+                        }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="投食时间" align="center">
+                <template slot-scope="scope">
+                    <span style="margin-left: 10px">{{ scope.row.time }}</span>
+                </template>
+            </el-table-column>
+
+
+        </el-table>
+
+    </div>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            data: {
+                name: "",
+            },
+            token: "",
+            tableData: [
+                {
+                    time: "2025-05-06 12:25:06",
+                    weight: "8955",
+                },
+                {
+                    time: "2025-05-06 12:25:06",
+                    weight: "66%",
+                },
+                {
+                    time: "2025-05-06 12:25:06",
+                    weight: "66%",
+                },
+                {
+                    time: "2025-05-06 12:25:06",
+                    weight: "66%",
+                },
+                {
+                    time: "2025-05-06 12:25:06",
+                    weight: "66%",
+                }
+            ]
+        };
+    },
+    methods: {
+
+        handleBack() {
+            this.$router.push({
+                name: 'deviceDetails'
+            })
+        },
+        // 表头单元格样式
+        HeaderCell() {
+            return 'HeaderCellClass';
+        },
+    },
+    mounted() {
+
+    },
+    created() {
+    },
+    computed: {
+
+    },
+};
+
+</script>
+<style lang="scss" scoped>
+.FeedingRecord::v-deep {
+    margin-top: 100px;
+    padding: 10px;
+    background-color: #fff;
+    box-shadow: 0 0 5px #d0d0d0;
+    border-radius: 5px;
+
+
+    .HeaderCellClass {
+        background: #859CB7;
+        color: #fff;
+    }
+
+
+}
+</style>

+ 277 - 0
src/components/home/FeedingToushi.vue

@@ -0,0 +1,277 @@
+<template>
+  <div class="FeedingToushi" id="FeedingToushi">
+    <div class="Header">
+      <img
+        @click="handleBack"
+        src="../../assets/img/PathPlan/back.png"
+        alt=""
+      />
+      <div class="mode">
+        <img src="../../assets/img/PathPlan/weizhi.png" alt="" />
+        <span>上合经济创业园</span>
+        <img src="../../assets/img/PathPlan/pathplan.png" alt="" />
+        <span>路径规划模式</span>
+      </div>
+      <div class="data">
+        <div class="name">
+          饲料
+          <span>54 kg</span>
+        </div>
+        <div class="name">
+          船速
+          <span>2.8 m/s</span>
+        </div>
+        <div class="name">
+          电量
+          <span>61%</span>
+        </div>
+      </div>
+    </div>
+
+    <div class="body">
+      <div class="title">手动模式</div>
+      <div class="title2">
+        <span> 投料速度</span>
+        <div class="radio-group">
+          <el-radio v-model="FeedingForm.radio1" label="0" border
+            >低速</el-radio
+          >
+          <el-radio v-model="FeedingForm.radio1" label="1" border
+            >中速</el-radio
+          >
+          <el-radio v-model="FeedingForm.radio1" label="2" border
+            >高速</el-radio
+          >
+          <el-radio v-model="FeedingForm.radio1" label="3" border
+            >自动模式</el-radio
+          >
+        </div>
+      </div>
+      <div class="title3">
+        <span>定时定量投食</span>
+
+        <el-form class="time-box" ref="FeedingForm" :model="FeedingForm">
+          <el-form-item>
+            <el-time-picker
+              class="time-picker"
+              v-model="FeedingForm.value1"
+              :picker-options="{
+                selectableRange: '18:30:00 - 20:30:00',
+              }"
+              placeholder="请选择时间"
+            >
+            </el-time-picker>
+          </el-form-item>
+          <el-form-item>
+            <el-input
+              v-model="FeedingForm.weight"
+              placeholder="请输入投食重量"
+            ></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-select v-model="FeedingForm.value" placeholder="请选择历史路线">
+              <el-option
+                v-for="item in FeedingForm.options"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              >
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="onSubmit">确定</el-button>
+            <el-button>取消</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import apiServe from "@/utils/api";
+
+export default {
+  data() {
+    return {
+      FeedingForm: {
+        radio1: "1",
+        value1: new Date(2016, 9, 10, 18, 40),
+        weight: "",
+        options: [
+          {
+            value: "选项1",
+            label: "黄金糕",
+          },
+          {
+            value: "选项2",
+            label: "双皮奶",
+          },
+          {
+            value: "选项3",
+            label: "蚵仔煎",
+          },
+          {
+            value: "选项4",
+            label: "龙须面",
+          },
+          {
+            value: "选项5",
+            label: "北京烤鸭",
+          },
+        ],
+        value: "",
+      },
+    };
+  },
+  mounted() {},
+
+  methods: {
+    handleBack() {
+      this.$router.push({
+        name: "deviceDetails",
+      });
+    },
+    onSubmit() {
+      // 如果是自动传递type为0,手动还需要传递速度
+      let data = {
+        // 当radio1为0、1、2时,type赋值为1;其他情况type赋值为0
+        type: [0, 1, 2].includes(parseInt(this.FeedingForm.radio1)) ? 1 : 0,
+        speed: this.FeedingForm.radio1,
+        mode: 1,
+        shipId: 1,
+      };
+      apiServe.FeedingMode("post", data).then((res) => {
+        console.log(res);
+      });
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.FeedingToushi::v-deep {
+  .Header {
+    z-index: 2;
+    position: fixed;
+    top: 137px;
+    width: 1594px;
+    height: 100px;
+    background: #f8fbff;
+    display: flex;
+    border-radius: 12px;
+    > img {
+      cursor: pointer;
+    }
+    .mode {
+      display: flex;
+      align-items: center;
+      margin-left: 5px;
+      > img:first-child {
+        margin-right: 10px;
+      }
+      > img:nth-child(3) {
+        margin-left: 45px;
+        margin-right: 10px;
+      }
+      > span:nth-child(2) {
+        font-family: PingFang SC;
+        font-weight: 500;
+        font-size: 28px;
+        color: #000000;
+        line-height: 50px;
+      }
+      > span:nth-child(4) {
+        font-family: PingFang SC;
+        font-weight: bold;
+        font-size: 36px;
+        color: #000000;
+        line-height: 50px;
+      }
+    }
+
+    .data {
+      display: flex;
+      align-items: center;
+      margin-left: 200px;
+
+      .name {
+        font-family: PingFang SC;
+        font-weight: 500;
+        font-size: 28px;
+        color: #626262;
+        line-height: 50px;
+        margin-right: 50px;
+        > span {
+          margin-left: 25px;
+          font-family: PingFang SC;
+          font-weight: bold;
+          font-size: 36px;
+          color: #000000;
+          line-height: 50px;
+        }
+      }
+    }
+  }
+  .body {
+    position: fixed;
+    top: 237px;
+    width: 1594px;
+    height: 800px;
+    background: #ffffff;
+    border-radius: 20px;
+    margin-top: 10px;
+    .title {
+      font-family: PingFang SC;
+      font-weight: bold;
+      font-size: 36px;
+      color: #000000;
+      line-height: 50px;
+      display: flex;
+      margin-left: 50px;
+    }
+    .title2 {
+      > span {
+        font-family: PingFang SC;
+        font-weight: 500;
+        font-size: 32px;
+        color: #000000;
+        line-height: 50px;
+        display: flex;
+        margin-left: 50px;
+        margin-top: 30px;
+      }
+      .radio-group {
+        display: flex;
+        margin-left: 150px;
+        margin-top: 30px;
+      }
+    }
+    .title3 {
+      > span {
+        font-family: PingFang SC;
+        font-weight: bold;
+        font-size: 36px;
+        color: #000000;
+        line-height: 50px;
+        display: flex;
+        margin-left: 50px;
+        margin-top: 30px;
+      }
+      .time-box {
+        margin-left: 150px;
+        display: flex;
+        margin-top: 30px;
+      }
+      .el-form-item:nth-child(2),
+      .el-form-item:nth-child(3) {
+        margin-left: 20px;
+      }
+      .el-form-item:last-child {
+        position: fixed;
+        bottom: 119px;
+        right: 152px;
+      }
+    }
+  }
+}
+</style>

+ 382 - 0
src/components/home/FixedPoint.vue

@@ -0,0 +1,382 @@
+<template>
+  <div class="FixedPoint" id="FixedPoint">
+    <div class="Header">
+      <img
+        @click="handleBack"
+        src="../../assets/img/FixedPoint/back.png"
+        alt=""
+      />
+      <div class="mode">
+        <img src="../../assets/img/FixedPoint/weizhi.png" alt="" />
+        <span>上合经济创业园</span>
+        <img src="../../assets/img/FixedPoint/FixedPoint.png" alt="" />
+        <span>定点模式</span>
+      </div>
+      <div class="data">
+        <div class="name">
+          饲料
+          <span>54 kg</span>
+        </div>
+        <div class="name">
+          船速
+          <span>2.8 m/s</span>
+        </div>
+        <div class="name">
+          电量
+          <span>61%</span>
+        </div>
+      </div>
+    </div>
+
+    <div class="Left">
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == ''"
+        src="../../assets/img/PathPlan/toushi.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '高速'"
+        src="../../assets/img/PathPlan/toushigao.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '中速'"
+        src="../../assets/img/PathPlan/toushizhong.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '低速'"
+        src="../../assets/img/PathPlan/toushidi.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '自动投食(根据鱼群密度自动投食)'"
+        src="../../assets/img/PathPlan/toushizidong.png"
+        alt=""
+      />
+
+      <!-- 撒药模式 -->
+      <el-dialog
+        title="撒药模式"
+        :modal-append-to-body="false"
+        :visible.sync="dialogFormVisible"
+        style="margin-top: 25vh"
+        width="30%"
+      >
+        <el-form ref="form" :model="Sayaoform" label-width="80px">
+          <el-form-item label="投食速度">
+            <el-radio-group v-model="Sayaoform.radio1">
+              <el-radio-button label="低速"></el-radio-button>
+              <el-radio-button label="中速"></el-radio-button>
+              <el-radio-button label="高速"></el-radio-button>
+              <el-radio-button
+                label="自动投食(根据鱼群密度自动投食)"
+              ></el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormVisible = false">取 消</el-button>
+          <el-button type="primary" @click="dialogFormVisible = false"
+            >确 定</el-button
+          >
+        </div>
+      </el-dialog>
+      <img
+        v-if="Sayao"
+        @click="handleSayao()"
+        src="../../assets/img/FixedPoint/sayao.png"
+        alt=""
+      />
+      <img
+        v-if="Sayao == false"
+        @click="handleSayao()"
+        src="../../assets/img/FixedPoint/sayaohover.png"
+        alt=""
+      />
+      <!-- <img
+        v-if="Shexiangtou"
+        @click="handleShexiangtou()"
+        src="../../assets/img/FixedPoint/shexiangtou.png"
+        alt=""
+      />
+      <img
+        v-if="Shexiangtou == false"
+        @click="handleShexiangtou()"
+        src="../../assets/img/FixedPoint/shexiangtouhover.png"
+        alt=""
+      /> -->
+    </div>
+
+    <!-- 摄像头 -->
+    <!-- <div class="video" v-if="Shexiangtou == false">
+      <iframe
+        width="100%"
+        height="100%"
+        frameborder="0"
+        id="ysOpenDevice"
+        :src="iframeSrc"
+        allowfullscreen
+      >
+      </iframe>
+    </div> -->
+    <div class="Left-Bottom">
+      <img
+        v-if="Xuandian"
+        src="../../assets/img/FixedPoint/xuandian.png"
+        alt=""
+        @click="handleXuandian()"
+      />
+      <img
+        v-if="Xuandian == false"
+        src="../../assets/img/FixedPoint/queding.png"
+        alt=""
+        @click="handleQueding()"
+      />
+      <img
+        v-if="Xuandian == false"
+        src="../../assets/img/FixedPoint/qingchu.png"
+        alt=""
+        @click="handleQingchu()"
+      />
+    </div>
+
+    <div class="button">
+      <img
+        v-if="Start"
+        src="../../assets/img/FixedPoint/kaishi.png"
+        alt=""
+        @click="handleStart()"
+      />
+      <img
+        v-if="Start == false"
+        src="../../assets/img/FixedPoint/jieshu.png"
+        alt=""
+        @click="handleEnd()"
+      />
+    </div>
+  </div>
+</template>
+<script>
+import AMapLoader from "@amap/amap-jsapi-loader";
+import axios from "axios";
+export default {
+  data() {
+    return {
+      Sayao: true,
+      Start: true,
+      Xuandian: true,
+      Shexiangtou: true,
+      token: "",
+      dialogFormVisible: false,
+      Sayaoform: {
+        radio1: "",
+      },
+    };
+  },
+  mounted() {
+    this.initAMap();
+    this.GetToken();
+  },
+  computed: {
+    iframeSrc() {
+      return `https://open.ys7.com/console/jssdk/pc.html?accessToken=${this.token}&url=ezopen://open.ys7.com/FC9834568/1.live&themeId=pcLive`;
+    },
+  },
+  beforeDestroy() {
+    this.map?.destroy();
+  },
+  methods: {
+    // 摄像头
+    GetToken() {
+      axios
+        .post(
+          "https://open.ys7.com/api/lapp/token/get",
+          {
+            appKey: "1e0fd35277444a3986f4984788a0ee82",
+            appSecret: "4bc97fa347f130fa3f0180f53c71edfd",
+          },
+          {
+            headers: {
+              "Content-Type": "application/x-www-form-urlencoded",
+              Accept: "application/json",
+            },
+          }
+        )
+        .then((res) => {
+          this.token = res.data.data.accessToken;
+        })
+        .catch((error) => {
+          console.error("Error:", error);
+        });
+    },
+    initAMap() {
+      window._AMapSecurityConfig = {
+        securityJsCode: "93bceef67b80451f0817024a81dc6170",
+      };
+      AMapLoader.load({
+        key: "f470b3bf9c52d2514824bc38ca6383b9", // 申请好的Web端开发者Key,首次调用 load 时必填
+        version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+        plugins: ["AMap.Scale"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
+      })
+        .then((AMap) => {
+          this.map = new AMap.Map("FixedPoint", {
+            // 设置地图容器id
+            viewMode: "2D", //地图模式
+            zoom: 16, //初始化地图层级
+            center: [120.072896, 36.155971], //初始地图中心经纬度
+            terrain: true, //开启地形图
+            mapStyle: "amap://styles/normal", //设置地图的显示样式
+          });
+        })
+        .catch((e) => {
+          console.log(e);
+        });
+    },
+    handleToushi() {
+      this.dialogFormVisible = true;
+    },
+    handleBack() {
+      this.$router.push({
+        name: "deviceDetails",
+      });
+    },
+    handleXuandian() {
+      this.Xuandian = false;
+    },
+    handleQueding() {
+      this.Xuandian = true;
+    },
+    handleQingchu() {},
+    handleSayao() {
+      this.Sayao = !this.Sayao;
+    },
+    handleShexiangtou() {
+      this.Shexiangtou = !this.Shexiangtou;
+    },
+    // 开始按钮
+    handleStart() {
+      this.Start = false;
+    },
+    // 结束按钮
+    handleEnd() {
+      this.Start = true;
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+#FixedPoint {
+  width: 100%;
+  height: 900px;
+  z-index: 1;
+  position: relative;
+}
+.FixedPoint::v-deep {
+  .Header {
+    z-index: 2;
+    position: fixed;
+    top: 137px;
+    width: 1594px;
+    height: 100px;
+    background: #f8fbff;
+    display: flex;
+    border-radius: 12px;
+    > img {
+      cursor: pointer;
+    }
+    .mode {
+      display: flex;
+      align-items: center;
+      margin-left: 5px;
+      > img:first-child {
+        margin-right: 10px;
+      }
+      > img:nth-child(3) {
+        margin-left: 45px;
+        margin-right: 10px;
+      }
+      > span:nth-child(2) {
+        font-family: PingFang SC;
+        font-weight: 500;
+        font-size: 28px;
+        color: #000000;
+        line-height: 50px;
+      }
+      > span:nth-child(4) {
+        font-family: PingFang SC;
+        font-weight: bold;
+        font-size: 36px;
+        color: #000000;
+        line-height: 50px;
+      }
+    }
+
+    .data {
+      display: flex;
+      align-items: center;
+      margin-left: 200px;
+
+      .name {
+        font-family: PingFang SC;
+        font-weight: 500;
+        font-size: 28px;
+        color: #626262;
+        line-height: 50px;
+        margin-right: 50px;
+        > span {
+          margin-left: 25px;
+          font-family: PingFang SC;
+          font-weight: bold;
+          font-size: 36px;
+          color: #000000;
+          line-height: 50px;
+        }
+      }
+    }
+  }
+  .Left {
+    z-index: 2;
+    position: fixed;
+    top: 247px;
+    width: 250px;
+    height: 325px;
+    cursor: pointer;
+  }
+  .Left-Bottom {
+    z-index: 1;
+    position: fixed;
+    bottom: 0px;
+    width: 250px;
+    height: 156px;
+    cursor: pointer;
+    display: flex;
+    justify-content: center;
+  }
+  .button {
+    z-index: 1;
+    position: fixed;
+    bottom: 0px;
+    display: flex;
+    right: 55px;
+    width: 250px;
+    height: 156px;
+    cursor: pointer;
+    flex-direction: row;
+    align-items: center;
+  }
+  .video {
+    z-index: 1;
+    width: 640px;
+    height: 360px;
+    position: fixed;
+    left: 485px;
+    top: 259px;
+  }
+}
+</style>

+ 538 - 0
src/components/home/HomeIndex.vue

@@ -0,0 +1,538 @@
+<template>
+  <div class="device">
+    <div class="form-header">
+      <div></div>
+      <el-form :inline="true" :model="formInline" class="demo-form-inline">
+        <el-form-item label="名称">
+          <el-input v-model="formInline.user" clearable></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button
+            type="primary"
+            icon="el-icon-search"
+            @click="onSubmit"
+            style="font-weight: 300"
+            >查询</el-button
+          >
+          <el-button
+            type="success"
+            icon="el-icon-plus"
+            @click="handleAdd"
+            style="font-weight: 300"
+            >新增</el-button
+          >
+        </el-form-item>
+      </el-form>
+    </div>
+    <!-- <div class="form-box">
+            <el-table :data="tableData" style="width: 100%" border>
+                    <el-table-column label="序号" type="index" width="80" align="center">
+                    </el-table-column>
+                <el-table-column label="名称" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.name }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="创建时间" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.date }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center">
+                     <template slot-scope="scope">
+                        <el-button size="mini" type="success" @click="handleMap(scope.$index, scope.row)">查看</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div> -->
+
+    <!-- 设备列表 -->
+    <div style="display: flex; flex-direction: row; flex-wrap: wrap; gap: 10px">
+      <div class="table-form" v-for="item in tableData" :key="item.id">
+        <!-- 顶部 -->
+        <div class="table-top">
+          <div class="table-top1">
+            <span>无人船刀刀来了</span>
+            <br />
+            <span>{{ item.date }}</span>
+          </div>
+
+          <div :class="`table-top-state${item.status}`">
+            <div class="spot"></div>
+            <span>{{
+              item.status === 1
+                ? "在线"
+                : item.status === 2
+                ? "离线"
+                : item.status === 3
+                ? "维护"
+                : " 运行"
+            }}</span>
+          </div>
+          <div class="table-content">
+            <dl class="data-list">
+              <dt>经度</dt>
+              <dd>24</dd>
+              <dt style="margin-left: auto">纬度</dt>
+              <dd>456</dd>
+            </dl>
+            <dl class="data-list">
+              <dt>偏航角度</dt>
+              <dd>32</dd>
+              <dt style="margin-left: auto">俯仰角度</dt>
+              <dd>48</dd>
+            </dl>
+          </div>
+          <div class="table-bottom">
+            <el-button type="primary" @click="handleMap(item)">查看</el-button>
+            <el-button type="info">删除</el-button>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 第四步绑定自定义属性 -->
+    <pagination :total="obj.total"> </pagination>
+    <!-- 弹出框 -->
+    <div>
+      <el-dialog
+        title="新增设备"
+        top="30vh"
+        :modal="true"
+        center
+        :visible.sync="dialogFormVisible"
+      >
+        <el-form :model="form" label-position="top">
+          <el-form-item label="设备名称" :label-width="formLabelWidth">
+            <el-input v-model="form.name" autocomplete="off"></el-input>
+          </el-form-item>
+          <el-form-item label="设备类型" :label-width="formLabelWidth">
+            <el-select
+              v-model="form.region"
+              placeholder="请选择设备类型"
+              style="width: 100%"
+            >
+              <el-option label="无人船" value="0"></el-option>
+              <el-option label="无人车" value="1"></el-option>
+              <el-option label="无人机" value="2"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="设备id" :label-width="formLabelWidth">
+            <el-input v-model="form.id" autocomplete="off"></el-input>
+          </el-form-item>
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormVisible = false">取 消</el-button>
+          <el-button type="primary" @click="handleAddqd">确 定</el-button>
+        </div>
+      </el-dialog>
+    </div>
+  </div>
+</template>
+
+<script>
+import apiServe from "@/utils/api";
+// 第一步引入组件
+import pagination from "../pagination/pagination.vue";
+export default {
+  // 第二步 注册组件
+  components: {
+    pagination,
+  },
+  data() {
+    return {
+      // 查询
+      formInline: {
+        shipname: "",
+      },
+
+      obj: {
+        // 页码
+        page: 1,
+        // 每页多少条
+        rows: 10,
+        // 默认选中哪一页
+        currentPage: 1,
+        // 定义总条数
+        total: null,
+      },
+      tableData: [
+        {
+          date: "2016-05-02",
+          name: "无人船一",
+          status: 1,
+          longitude: "经度",
+          latitude: "纬度",
+          yaw: "偏航角度",
+          pitch: "偏航角度",
+          id: 1,
+        },
+        {
+          date: "2016-05-04",
+          name: "无人船二",
+          status: 2,
+          longitude: "经度2",
+          latitude: "纬度2",
+          yaw: "偏航角度2",
+          pitch: "偏航角度2",
+          id: 2,
+        },
+        {
+          date: "2025-05-04",
+          name: "无人车",
+          status: 3,
+          address: "1",
+          longitude: "经度3",
+          latitude: "纬度3",
+          yaw: "偏航角度3",
+          pitch: "偏航角度3",
+          id: 3,
+        },
+        {
+          date: "2025-05-04",
+          name: "无人车",
+          status: 4,
+          address: "1",
+          longitude: "经度4",
+          latitude: "纬度4",
+          yaw: "偏航角度4",
+          pitch: "偏航角度4",
+          id: 4,
+        },
+        {
+          date: "2025-05-04",
+          name: "无人车",
+          status: 1,
+          address: "1",
+          longitude: "经度4",
+          latitude: "纬度4",
+          yaw: "偏航角度4",
+          pitch: "偏航角度4",
+          id: 5,
+        },
+        {
+          date: "2025-05-04",
+          name: "无人车",
+          status: 2,
+          address: "1",
+          longitude: "经度4",
+          latitude: "纬度4",
+          yaw: "偏航角度4",
+          pitch: "偏航角度4",
+          id: 6,
+        },
+      ],
+
+      form: {
+        name: "",
+        region: "",
+        id: "",
+      },
+      dialogFormVisible: false,
+      formLabelWidth: "120px",
+    };
+  },
+  methods: {
+    // 查询
+    onSubmit() {
+      console.log("submit!");
+    },
+    // 新增
+    handleAdd() {
+      this.dialogFormVisible = true;
+      // 清空验证并清空内容
+      this.form = {};
+    },
+    handleAddqd() {
+      let data = {
+        deviceType: this.form.region,
+        deviceId: this.form.id,
+        deviceName: this.form.name,
+      };
+      apiServe.deviceXZ("post", data).then((res) => {
+        console.log(res);
+        if (res.code == 200) {
+          this.$message({
+            type: "success",
+            message: "新增成功",
+          });
+        } else {
+          this.$message({
+            type: "error",
+            message: "新增失败",
+          });
+        }
+      });
+
+      this.dialogFormVisible = false;
+    },
+    // 跳转
+    handleMap(index) {
+      console.log(index);
+      localStorage.setItem("tempData", JSON.stringify(index));
+      this.$router.push({
+        path: "/index/deviceDetails",
+        query: {
+          // id: index.id,
+          // name: index.name,
+          // status: index.status,
+          // longitude: index.longitude,
+          // latitude: index.latitude,
+          // yaw: index.yaw,
+          // pitch: index.pitch,
+          // data: JSON.stringify(index) // 序列化对象/数组
+        },
+      });
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.device::v-deep {
+  ul,
+  li {
+    list-style: none;
+  }
+
+  .form-header {
+    box-shadow: 0 0 5px #d0d0d0;
+    border-radius: 5px;
+    text-align: left;
+    background-color: #fff;
+    padding: 10px;
+    padding-left: 30px;
+
+    .el-form-item {
+      margin-bottom: 0;
+    }
+  }
+
+  .form-box {
+    margin-top: 10px;
+    padding: 10px;
+    background-color: #fff;
+    box-shadow: 0 0 5px #d0d0d0;
+    border-radius: 5px;
+    /* // calc():高度时100%-超出的部分 */
+    height: calc(100vh - 235px);
+  }
+
+  .table-form {
+    width: 490px;
+    height: 330px;
+    background: #ffffff;
+    border-radius: 10px;
+    margin: 15px;
+    position: relative;
+    flex: 0 0 30%;
+    margin-left: 25px;
+
+    .table-top {
+      padding: 35px;
+
+      // 名称+日期
+      .table-top1 {
+        display: flex;
+        flex-direction: column;
+
+        > span:first-child {
+          font-family: Microsoft YaHei;
+          font-weight: bold;
+          font-size: 22px;
+          color: #000000;
+          line-height: 26px;
+          display: inline;
+          order: 1;
+          display: block;
+          text-align: left;
+        }
+
+        > span:nth-child(3) {
+          margin-top: 20px;
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          font-size: 18px;
+          color: #8c95a4;
+          line-height: 26px;
+          order: 2;
+          align-items: flex-start;
+          display: block;
+          text-align: left;
+        }
+      }
+
+      // 状态
+      // 在线
+      .table-top-state1 {
+        position: absolute;
+        right: 34px;
+        top: 53px;
+        width: 56px;
+        height: 26px;
+        background: #c7f3df;
+        border-radius: 4px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+
+        > span {
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          font-size: 14px;
+          color: #23b371;
+          line-height: 26px;
+          vertical-align: middle;
+          /* 垂直居中 */
+          padding-left: 5px;
+        }
+
+        .spot {
+          width: 6px;
+          height: 6px;
+          background: #23b371;
+          border-radius: 50%;
+          vertical-align: middle;
+          /* 垂直居中 */
+        }
+      }
+
+      // 离线
+      .table-top-state2 {
+        position: absolute;
+        right: 34px;
+        top: 53px;
+        width: 56px;
+        height: 26px;
+        background: #ffd5d5;
+        border-radius: 4px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+
+        > span {
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          font-size: 14px;
+          color: #f31c1c;
+          line-height: 26px;
+          vertical-align: middle;
+          /* 垂直居中 */
+          padding-left: 5px;
+        }
+
+        .spot {
+          width: 6px;
+          height: 6px;
+          background: #f31c1c;
+          border-radius: 50%;
+          vertical-align: middle;
+          /* 垂直居中 */
+        }
+      }
+
+      // 维护
+      .table-top-state3 {
+        position: absolute;
+        right: 34px;
+        top: 53px;
+        width: 56px;
+        height: 26px;
+        background: #ffeecc;
+        border-radius: 4px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+
+        > span {
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          font-size: 14px;
+          color: #f6a913;
+          line-height: 26px;
+          vertical-align: middle;
+          /* 垂直居中 */
+          padding-left: 5px;
+        }
+
+        .spot {
+          width: 6px;
+          height: 6px;
+          background: #f6a913;
+          border-radius: 50%;
+          vertical-align: middle;
+          /* 垂直居中 */
+        }
+      }
+
+      // 运行
+      .table-top-state4 {
+        position: absolute;
+        right: 34px;
+        top: 53px;
+        width: 56px;
+        height: 26px;
+        background: #d6e6ff;
+        border-radius: 4px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+
+        > span {
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          font-size: 14px;
+          color: #1c6fec;
+          line-height: 26px;
+          vertical-align: middle;
+          /* 垂直居中 */
+          padding-left: 5px;
+        }
+
+        .spot {
+          width: 6px;
+          height: 6px;
+          background: #1c6fec;
+          border-radius: 50%;
+          vertical-align: middle;
+          /* 垂直居中 */
+        }
+      }
+
+      // 内容
+      .table-content {
+        margin-top: 30px;
+
+        .data-list {
+          display: flex;
+          justify-content: space-between;
+          /* 背景颜色 */
+          padding: 10px;
+          font-family: Arial, sans-serif;
+          margin-bottom: 10px;
+          align-items: baseline;
+        }
+
+        .data-list dt {
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          font-size: 18px;
+          color: #8c95a4;
+          padding-right: 6px;
+        }
+
+        .data-list dd {
+          font-family: "Microsoft YaHei";
+          /* 应用微软雅黑字体 */
+          font-weight: bold;
+          font-size: 18px;
+          color: #58616d;
+        }
+      }
+
+      // 按钮
+      .table-bottom {
+        text-align: right;
+      }
+    }
+  }
+}
+</style>

+ 326 - 0
src/components/home/PathPlan.vue

@@ -0,0 +1,326 @@
+<template>
+  <div class="PathPlan" id="PathPlan">
+    <div class="Header">
+      <img
+        @click="handleBack"
+        src="../../assets/img/PathPlan/back.png"
+        alt=""
+      />
+      <div class="mode">
+        <img src="../../assets/img/PathPlan/weizhi.png" alt="" />
+        <span>{{ locationName }}</span>
+        <img src="../../assets/img/PathPlan/pathplan.png" alt="" />
+        <span>路径规划模式</span>
+      </div>
+      <div class="data">
+        <div class="name">
+          饲料
+          <span>54 kg</span>
+        </div>
+        <div class="name">
+          船速
+          <span>2.8 m/s</span>
+        </div>
+        <div class="name">
+          电量
+          <span>61%</span>
+        </div>
+      </div>
+    </div>
+
+    <div class="Left">
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == ''"
+        src="../../assets/img/PathPlan/toushi.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '高速'"
+        src="../../assets/img/PathPlan/toushigao.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '中速'"
+        src="../../assets/img/PathPlan/toushizhong.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '低速'"
+        src="../../assets/img/PathPlan/toushidi.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '自动投食(根据鱼群密度自动投食)'"
+        src="../../assets/img/PathPlan/toushizidong.png"
+        alt=""
+      />
+
+      <!-- 撒药模式 -->
+      <el-dialog
+        title="撒药模式"
+        :modal-append-to-body="false"
+        :visible.sync="dialogFormVisible"
+        style="margin-top: 25vh"
+        width="30%"
+      >
+        <el-form ref="form" :model="Sayaoform" label-width="80px">
+          <el-form-item label="投食速度">
+            <el-radio-group v-model="Sayaoform.radio1">
+              <el-radio-button label="低速"></el-radio-button>
+              <el-radio-button label="中速"></el-radio-button>
+              <el-radio-button label="高速"></el-radio-button>
+              <el-radio-button
+                label="自动投食(根据鱼群密度自动投食)"
+              ></el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormVisible = false">取 消</el-button>
+          <el-button type="primary" @click="dialogFormVisible = false"
+            >确 定</el-button
+          >
+        </div>
+      </el-dialog>
+      <img
+        v-if="Sayao"
+        @click="handleSayao()"
+        src="../../assets/img/PathPlan/sayao.png"
+        alt=""
+      />
+      <img
+        v-if="Sayao == false"
+        @click="handleSayao()"
+        src="../../assets/img/PathPlan/sayaohover.png"
+        alt=""
+      />
+      <!-- <img src="../../assets/img/PathPlan/shexiangtou.png" alt="" /> -->
+    </div>
+
+    <div class="button">
+      <img
+        v-if="Start"
+        src="../../assets/img/PathPlan/kaishi.png"
+        alt=""
+        @click="handleStart()"
+      />
+      <img
+        v-if="Start == false"
+        src="../../assets/img/PathPlan/jieshu.png"
+        alt=""
+        @click="handleEnd()"
+      />
+    </div>
+  </div>
+</template>
+<script>
+import apiServe from "@/utils/api";
+import AMapLoader from "@amap/amap-jsapi-loader";
+export default {
+  data() {
+    return {
+      map: null,
+      locationName: "", // 存储获取到的地点名称
+      // 模拟后端传递的经纬度数据(实际从API获取)
+      backendLocation: {
+        longitude: 120.072896,
+        latitude: 36.155971,
+      },
+      Start: true,
+      Sayao: true,
+      dialogFormVisible: false,
+      Sayaoform: {
+        radio1: "",
+      },
+    };
+  },
+  mounted() {
+    this.initAMap();
+  },
+  beforeDestroy() {
+    this.map?.destroy();
+  },
+  methods: {
+    initAMap() {
+      // 1. 安全配置(必须在load之前)
+      window._AMapSecurityConfig = {
+        securityJsCode: "93bceef67b80451f0817024a81dc6170",
+      };
+
+      // 2. 加载地图(添加Geocoder插件)
+      AMapLoader.load({
+        key: "f470b3bf9c52d2514824bc38ca6383b9",
+        version: "2.0",
+        plugins: ["AMap.Geocoder", "AMap.Scale"], // 添加Geocoder插件
+      })
+        .then((AMap) => {
+          // 3. 初始化地图
+          this.map = new AMap.Map("PathPlan", {
+            viewMode: "2D",
+            zoom: 16,
+            center: [
+              this.backendLocation.longitude,
+              this.backendLocation.latitude,
+            ],
+            terrain: true,
+            mapStyle: "amap://styles/normal",
+          });
+
+          // 4. 创建地理编码器实例
+          const geocoder = new AMap.Geocoder({
+            radius: 1000, // 搜索半径(米)
+            extensions: "all", // 返回详细信息
+          });
+
+          // 5. 执行逆地理编码
+          geocoder.getAddress(
+            [this.backendLocation.longitude, this.backendLocation.latitude],
+            (status, result) => {
+              if (status === "complete" && result.info === "OK") {
+                // 成功获取地址信息
+                const address = result.regeocode;
+                this.locationName = address.formattedAddress; // 完整地址
+
+                // 如果需要更精确的名称(如POI名称)
+                if (address.pois && address.pois.length > 0) {
+                  this.locationName = address.pois[0].name; // 最近POI的名称
+                }
+
+                console.log("地点名称:", this.locationName);
+              } else {
+                console.error("逆地理编码失败:", result);
+              }
+            }
+          );
+        })
+        .catch((e) => {
+          console.error("地图初始化失败:", e);
+        });
+    },
+    handleToushi() {
+      this.dialogFormVisible = true;
+    },
+    handleSayao() {
+      this.Sayao = !this.Sayao;
+      apiServe
+        .SetShipFeedingMode("post", {
+          shipId: 123456789,
+          mode: this.Sayao === true ? "1" : "0",
+        })
+        .then((res) => {
+          console.log(res);
+        });
+    },
+    // 开始按钮
+    handleStart() {
+      this.Start = false;
+    },
+    // 结束按钮
+    handleEnd() {
+      this.Start = true;
+    },
+    handleBack() {
+      this.$router.push({
+        name: "deviceDetails",
+      });
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+#PathPlan {
+  width: 100%;
+  height: 900px;
+  z-index: 1;
+  position: relative;
+}
+.PathPlan::v-deep {
+  .Header {
+    z-index: 2;
+    position: fixed;
+    top: 137px;
+    width: 1594px;
+    height: 100px;
+    background: #f8fbff;
+    display: flex;
+    border-radius: 12px;
+    > img {
+      cursor: pointer;
+    }
+    .mode {
+      display: flex;
+      align-items: center;
+      margin-left: 5px;
+      > img:first-child {
+        margin-right: 10px;
+      }
+      > img:nth-child(3) {
+        margin-left: 45px;
+        margin-right: 10px;
+      }
+      > span:nth-child(2) {
+        font-family: PingFang SC;
+        font-weight: 500;
+        font-size: 28px;
+        color: #000000;
+        line-height: 50px;
+      }
+      > span:nth-child(4) {
+        font-family: PingFang SC;
+        font-weight: bold;
+        font-size: 36px;
+        color: #000000;
+        line-height: 50px;
+      }
+    }
+
+    .data {
+      display: flex;
+      align-items: center;
+      margin-left: 200px;
+
+      .name {
+        font-family: PingFang SC;
+        font-weight: 500;
+        font-size: 28px;
+        color: #626262;
+        line-height: 50px;
+        margin-right: 50px;
+        > span {
+          margin-left: 25px;
+          font-family: PingFang SC;
+          font-weight: bold;
+          font-size: 36px;
+          color: #000000;
+          line-height: 50px;
+        }
+      }
+    }
+  }
+  .Left {
+    z-index: 2;
+    position: fixed;
+    top: 247px;
+    width: 250px;
+    height: 625px;
+    cursor: pointer;
+  }
+  .button {
+    z-index: 1;
+    position: fixed;
+    bottom: 0px;
+    display: flex;
+    right: 55px;
+    width: 250px;
+    height: 156px;
+    cursor: pointer;
+    flex-direction: row;
+    align-items: center;
+  }
+}
+</style>

+ 755 - 0
src/components/home/PointNavigation.vue

@@ -0,0 +1,755 @@
+<template>
+  <div class="PointNavigation" id="PointNavigation">
+    <div class="Header">
+      <img
+        @click="handleBack"
+        src="../../assets/img/PointNavigation/back.png"
+        alt=""
+      />
+      <div class="mode">
+        <img src="../../assets/img/PointNavigation/weizhi.png" alt="" />
+        <span>{{ locationName }}</span>
+        <img
+          src="../../assets/img/PointNavigation/PointNavigation.png"
+          alt=""
+        />
+        <span>多点导航模式</span>
+      </div>
+      <div class="data">
+        <div class="name">
+          饲料
+          <span>{{ ShipStatus.feedWeight }} kg</span>
+        </div>
+        <div class="name">
+          船速
+          <span>{{ ShipStatus.speed }} m/s</span>
+        </div>
+        <div class="name">
+          电量
+          <span>{{ ShipStatus.power }}%</span>
+        </div>
+      </div>
+    </div>
+
+    <div class="Left">
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == ''"
+        src="../../assets/img/PathPlan/toushi.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '2'"
+        src="../../assets/img/PathPlan/toushigao.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '1'"
+        src="../../assets/img/PathPlan/toushizhong.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '0'"
+        src="../../assets/img/PathPlan/toushidi.png"
+        alt=""
+      />
+      <img
+        @click="handleToushi"
+        v-if="Sayaoform.radio1 == '3'"
+        src="../../assets/img/PathPlan/toushizidong.png"
+        alt=""
+      />
+
+      <!-- 撒药模式 -->
+      <el-dialog
+        title="撒药模式"
+        :modal-append-to-body="false"
+        :visible.sync="dialogFormVisible"
+        style="margin-top: 25vh"
+        width="30%"
+      >
+        <el-form ref="form" :model="Sayaoform" label-width="80px">
+          <el-form-item label="投食速度">
+            <el-radio-group v-model="Sayaoform.radio1">
+              <el-radio-button label="0">低速</el-radio-button>
+              <el-radio-button label="1">中速</el-radio-button>
+              <el-radio-button label="2">高速</el-radio-button>
+              <el-radio-button label="3"
+                >自动投食(根据鱼群密度自动投食)</el-radio-button
+              >
+            </el-radio-group>
+          </el-form-item>
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormVisible = false">取 消</el-button>
+          <el-button type="primary" @click="ToushiOnsubmit()">确 定</el-button>
+        </div>
+      </el-dialog>
+      <img
+        v-if="Sayao"
+        @click="handleSayao()"
+        src="../../assets/img/PointNavigation/sayao.png"
+        alt=""
+      />
+      <img
+        v-if="Sayao == false"
+        @click="handleSayao()"
+        src="../../assets/img/PointNavigation/sayaohover.png"
+        alt=""
+      />
+      <!-- <img
+        v-if="Shexiangtou"
+        @click="handleShexiangtou()"
+        src="../../assets/img/PointNavigation/shexiangtou.png"
+        alt=""
+      />
+      <img
+        v-if="Shexiangtou == false"
+        @click="handleShexiangtou()"
+        src="../../assets/img/PointNavigation/shexiangtouhover.png"
+        alt=""
+      /> -->
+    </div>
+
+    <!-- 摄像头 -->
+    <!-- <div class="video" v-if="Shexiangtou == false">
+      <iframe
+        width="100%"
+        height="100%"
+        frameborder="0"
+        id="ysOpenDevice"
+        :src="iframeSrc"
+        allowfullscreen
+      >
+      </iframe>
+    </div> -->
+    <div class="Left-Bottom">
+      <img
+        v-if="Xuandian"
+        src="../../assets/img/PointNavigation/xuandian.png"
+        alt=""
+        @click="handleXuandian()"
+      />
+      <img
+        v-if="Xuandian == false"
+        src="../../assets/img/PointNavigation/queding.png"
+        alt=""
+        @click="handleQueding()"
+      />
+      <img
+        v-if="Xuandian == false"
+        src="../../assets/img/PointNavigation/qingchu.png"
+        alt=""
+        @click="handleQingchu()"
+      />
+    </div>
+
+    <div class="button">
+      <img
+        v-if="Start == 1"
+        src="../../assets/img/PointNavigation/kaishi.png"
+        alt=""
+        @click="handleStart()"
+      />
+      <img
+        v-if="Start == 2"
+        src="../../assets/img/PointNavigation/jieshu.png"
+        alt=""
+        @click="handleEnd()"
+      />
+    </div>
+  </div>
+</template>
+<script>
+import apiServe from "@/utils/api";
+import AMapLoader from "@amap/amap-jsapi-loader";
+import axios from "axios";
+export default {
+  data() {
+    return {
+      Sayao: true,
+      Start: 0,
+      Xuandian: true,
+      Shexiangtou: true,
+      token: "",
+      dialogFormVisible: false,
+      Sayaoform: {
+        radio1: "",
+      },
+      locationName: "", // 存储获取到的地点名称
+      // 模拟后端传递的经纬度数据(实际从API获取)
+      backendLocation: {
+        longitude: 120.072896,
+        latitude: 36.155971,
+      },
+      // 多点导航参数
+      ArrayDate: {
+        data: [], // 用于保存最终的经纬度数据
+        routeId: "",
+      },
+      map: null, // 地图实例
+      polylineNavigation: null, // 折线实例
+      selectedPaths: [], // 存储用户点击的经纬度点路径
+      markerList: [], // 存储所有的标记点
+      ShipId: 123456789,
+      // 定时器
+      intervalI: null,
+      // 船状态定时器
+      timeInterval: null,
+      intervalId: null,
+      // 船状态信息每五秒刷新
+      ShipStatus: {
+        // gps错误
+        gpsWarning: null,
+        // 遥控器错误
+        joyWarning: null,
+        // 设备ID
+        deviceId: null,
+        // 投食重量
+        feedWeight: null,
+        // 经度
+        longitude: null,
+        // 纬度
+        latitude: null,
+        // 电量
+        power: null,
+        // 速度
+        speed: null,
+        // 船状态
+        Status: null,
+      },
+    };
+  },
+  mounted() {
+    this.initAMap();
+    this.GetToken();
+    this.handleReceiveQuery();
+    this.GetShipStatus();
+    this.GetTimer();
+  },
+  computed: {
+    iframeSrc() {
+      return `https://open.ys7.com/console/jssdk/pc.html?accessToken=${this.token}&url=ezopen://open.ys7.com/FC9834568/1.live&themeId=pcLive`;
+    },
+  },
+  // 离开该页面时销毁定时器
+  beforeDestroy() {
+    this.map?.destroy();
+    clearInterval(this.timeInterval);
+    this.timeInterval = null; // 清除引用
+    clearInterval(this.intervalId);
+  },
+  methods: {
+    //获取船的状态数据
+    GetShipStatus() {
+      apiServe.GetShipStatus("get", { id: this.ShipId }).then((res) => {
+        // console.log(res, "获取船的状态数据");
+        if (res) {
+          this.shipStatus = res.data;
+          console.log(this.shipStatus);
+          // 根据船的状态信息来弹出警告
+          if (this.shipStatus.gpsWarning == 1) {
+            this.$message({
+              showClose: true,
+              message: "GPS错误警告!!!",
+              type: "warning",
+            });
+          }
+          if (this.shipStatus.joyWarning == 1) {
+            this.$message({
+              showClose: true,
+              message: "遥控器错误警告!!!",
+              type: "warning",
+            });
+          }
+        }
+      });
+    },
+    // 定时器
+    GetTimer() {
+      this.timeInterval = setInterval(() => {
+        this.GetShipStatus();
+      }, 5000);
+    },
+
+    // 摄像头
+    GetToken() {
+      axios
+        .post(
+          "https://open.ys7.com/api/lapp/token/get",
+          {
+            appKey: "1e0fd35277444a3986f4984788a0ee82",
+            appSecret: "4bc97fa347f130fa3f0180f53c71edfd",
+          },
+          {
+            headers: {
+              "Content-Type": "application/x-www-form-urlencoded",
+              Accept: "application/json",
+            },
+          }
+        )
+        .then((res) => {
+          this.token = res.data.data.accessToken;
+        })
+        .catch((error) => {
+          console.error("Error:", error);
+        });
+    },
+    initAMap() {
+      window._AMapSecurityConfig = {
+        securityJsCode: "93bceef67b80451f0817024a81dc6170",
+      };
+      AMapLoader.load({
+        key: "f470b3bf9c52d2514824bc38ca6383b9", // 申请好的Web端开发者Key,首次调用 load 时必填
+        version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+        plugins: ["AMap.Scale"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
+      })
+        .then((AMap) => {
+          this.map = new AMap.Map("PointNavigation", {
+            // 设置地图容器id
+            viewMode: "2D", //地图模式
+            zoom: 16, //初始化地图层级
+            center: [
+              this.backendLocation.longitude,
+              this.backendLocation.latitude,
+            ],
+            terrain: true, //开启地形图
+            mapStyle: "amap://styles/normal", //设置地图的显示样式
+          });
+          // 4. 创建地理编码器实例
+          const geocoder = new AMap.Geocoder({
+            radius: 1000, // 搜索半径(米)
+            extensions: "all", // 返回详细信息
+          });
+
+          // 5. 执行逆地理编码
+          geocoder.getAddress(
+            [this.backendLocation.longitude, this.backendLocation.latitude],
+            (status, result) => {
+              if (status === "complete" && result.info === "OK") {
+                // 成功获取地址信息
+                const address = result.regeocode;
+                this.locationName = address.formattedAddress; // 完整地址
+
+                // 如果需要更精确的名称(如POI名称)
+                if (address.pois && address.pois.length > 0) {
+                  this.locationName = address.pois[0].name; // 最近POI的名称
+                }
+
+                console.log("地点名称:", this.locationName);
+              } else {
+                console.error("逆地理编码失败:", result);
+              }
+            }
+          );
+          // 根据从上个页面传递过来的路线并且画出该路线
+          // 转换坐标数据格式
+          // 判断是否是从上一个页面跳转来的
+          if (this.ArrayDate.data) {
+            console.log(this.ArrayDate.data);
+            if (Array.isArray(this.ArrayDate.data)) {
+              console.log("这是一个数组");
+            } else {
+              console.log("这不是一个数组");
+              this.ArrayDate.data = JSON.parse(this.ArrayDate.data);
+            }
+            // 将一个一维数组转换成二维数组
+            const coordinates = this.ArrayDate.data.reduce(
+              (acc, curr, index, arr) => {
+                if (index % 2 === 0) {
+                  acc.push([arr[index], arr[index + 1]]);
+                }
+                return acc;
+              },
+              []
+            );
+
+            // 创建折线实例
+            const polylineHistory = new AMap.Polyline({
+              path: coordinates, // 折线路径坐标数组
+              strokeColor: "#3366FF", // 线颜色
+              strokeWeight: 5, // 线宽
+              strokeStyle: "solid", // 线样式
+              lineJoin: "round", // 折线拐点样式
+            });
+
+            // 将折线添加到地图
+            polylineHistory.setMap(this.map);
+
+            // 自动调整视野范围
+            this.map.setFitView([polylineHistory]);
+          }
+          // 添加鼠标点击事件
+          this.map.on("click", (e) => {
+            if (this.Xuandian == true) {
+              return;
+            }
+            // 获取点击的经纬度
+            const lnglat = e.lnglat;
+            // 路径
+            this.selectedPaths.push(lnglat);
+            // 创建新的Marrker实例
+            // 定义创建一个新的 NavigationIcon 实例
+            const NavigationIcon = new AMap.Icon({
+              size: new AMap.Size(40, 40),
+              image: require("../../assets/img/PointNavigation/B.png"), // 修改为你的图标路径
+              imageOffset: new AMap.Pixel(0, 0),
+              imageSize: new AMap.Size(48, 56),
+              anchor: "top-center",
+            });
+            // 使用这个定义的icon
+            const NavigationMarker = new AMap.Marker({
+              position: lnglat,
+              icon: NavigationIcon,
+              offset: new AMap.Pixel(-21, -43),
+            });
+            // 添加到地图
+            NavigationMarker.setMap(this.map);
+            //  保存标记点
+            this.markerList.push(NavigationMarker);
+            // 如果已有线,更新线的位置,否则创建新的线
+            if (this.polylineNavigation) {
+              this.polylineNavigation.setPath(this.selectedPaths);
+            } else {
+              this.polylineNavigation = new AMap.Polyline({
+                path: this.selectedPaths,
+                strokeColor: "#0F97FF",
+                strokeOpacity: 1,
+                strokeWeight: 6,
+                strokeStyle: "solid",
+                lineJoin: "round",
+                lineCap: "round",
+                zIndex: 50,
+              });
+            }
+            this.polylineNavigation.setMap(this.map);
+          });
+
+          var PointPath = []; //存储开启导航的点
+          var PointPolyline; //存储开启导航的线
+          var markerPoint = null;
+          const fetchData = () => {
+            console.log("开始导航", this.Start, this.ArrayDate.routeId);
+            if (this.Start !== 2 && this.ArrayDate.routeId == undefined) {
+              console.log("未开始导航");
+              return;
+            }
+            apiServe.GetShipStatus("get", { id: 123456789 }).then((res) => {
+              const PointData = res.data;
+
+              // console.log(PointData);
+              if (PointData) {
+                if (PointData.latitude === null) {
+                  clearInterval(this.intervalId);
+                  console.log("航线已完成");
+                  return;
+                }
+                if (PointData.latitude && PointData.longitude) {
+                  const PointLnglat = new AMap.LngLat(
+                    PointData.longitude,
+                    PointData.latitude
+                  );
+                  PointPath.push(PointLnglat); //将接口的经纬度添加到路径数组
+                  // 如果已经有线了,更新线的位置
+                  if (PointPolyline) {
+                    PointPolyline.setPath(PointPath);
+                  } else {
+                    PointPolyline = new AMap.Polyline({
+                      path: PointPath,
+                      strokeColor: "#1DC007",
+                      strokeOpacity: 1, //透明度
+                      strokeWeight: 5, //线宽
+                    });
+                    PointPolyline.setMap(this.map);
+                  }
+                  // 如果marker存在则更新位置否则创建一个新的marker
+                  if (markerPoint) {
+                    markerPoint.setPosition(PointLnglat);
+                  } else {
+                    const PointIcon = new AMap.Icon({
+                      size: new AMap.Size(40, 40),
+                      image: require("../../assets/img/PointNavigation/A.png"), // 修改为你的图标路径
+                      imageOffset: new AMap.Pixel(0, 0),
+                      imageSize: new AMap.Size(48, 56),
+                      anchor: "top-center",
+                    });
+                    markerPoint = new AMap.Marker({
+                      icon: PointIcon,
+                      position: PointLnglat,
+                      offset: new AMap.Pixel(-23, -37),
+                    });
+                    this.map.add(markerPoint);
+                  }
+                  // 设置地图中心到新添加的点
+                  this.map.setCenter(PointLnglat);
+                }
+              }
+            });
+          };
+          this.intervalId = setInterval(fetchData, 10000); // 每隔1秒获取一次数据
+        })
+        .catch((e) => {
+          console.log(e);
+        });
+    },
+    handleToushi() {
+      this.dialogFormVisible = true;
+    },
+    ToushiOnsubmit() {
+      this.dialogFormVisible = false;
+      // 如果是自动传递type为0,手动还需要传递速度
+      let data = {
+        // 当radio1为0、1、2时,type赋值为1;其他情况type赋值为0
+        type: [0, 1, 2].includes(parseInt(this.Sayaoform.radio1)) ? 1 : 0,
+        speed: this.Sayaoform.radio1,
+        mode: 1,
+        shipId: 1,
+      };
+      apiServe.FeedingMode("post", data).then((res) => {
+        console.log(res);
+      });
+    },
+    handleBack() {
+      this.$router.push({
+        name: "deviceDetails",
+      });
+    },
+    handleXuandian() {
+      this.Xuandian = false;
+    },
+    handleQueding() {
+      if (this.selectedPaths.length == 0) {
+        this.$message({
+          type: "error",
+          message: "请选择导航点位!",
+        });
+        return;
+      }
+      this.Xuandian = true;
+      this.Start = 1;
+    },
+    // 清除点位
+    handleQingchu() {
+      this.$confirm("是否清除点位?", "清除点位", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          // 清除所有标记点
+          this.markerList.forEach((marker) => {
+            marker.setMap(null); // 从地图移除
+          });
+          this.markerList = []; // 清空数组
+
+          // 清除路线
+          if (this.polylineNavigation) {
+            this.polylineNavigation.setMap(null);
+            this.polylineNavigation = null; // 释放内存
+          }
+
+          // 清空路径数据
+          this.selectedPaths = [];
+          this.$message({
+            type: "success",
+            message: "已成功清除点位!",
+          });
+        })
+        .catch(() => {});
+    },
+    handleSayao() {
+      this.Sayao = !this.Sayao;
+      apiServe
+        .SetShipFeedingMode("post", {
+          shipId: 123456789,
+          mode: this.Sayao === true ? "1" : "0",
+        })
+        .then((res) => {
+          console.log(res);
+        });
+    },
+    handleShexiangtou() {
+      this.Shexiangtou = !this.Shexiangtou;
+    },
+    //
+    //
+    // 开启导航路线规划
+    handleFetch() {
+      if (this.Start == true) {
+        return;
+      }
+    },
+    // 开始规划按钮
+    handleStart() {
+      this.Start = 2;
+    },
+    // 结束按钮
+    handleEnd() {
+      this.Start = 3;
+      clearInterval(this.intervalId);
+      this.$prompt("是否保存该路线", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+      })
+        .then(({ value }) => {
+          this.$message({
+            type: "success",
+            message: "路线名称: " + value,
+          });
+          // 将之前选中的点进行处理
+          const flatCoordinates = this.selectedPaths.reduce((acc, cur) => {
+            acc.push(cur.lng, cur.lat);
+            return acc;
+          }, []);
+
+          apiServe.AddHistoryRoute("post", {
+            routeName: value,
+            routePoints: flatCoordinates,
+            routeType: 1,
+            shipId: 123456789,
+          });
+        })
+        .catch(() => {
+          // 清除所有标记点
+          this.markerList.forEach((marker) => {
+            marker.setMap(null); // 从地图移除
+          });
+          this.markerList = []; // 清空数组
+
+          // 清除路线
+          if (this.polylineNavigation) {
+            this.polylineNavigation.setMap(null);
+            this.polylineNavigation = null; // 释放内存
+          }
+
+          // 清空路径数据
+          this.selectedPaths = [];
+          this.$message({
+            type: "info",
+            message: "取消保存",
+          });
+        });
+    },
+
+    // 接收从上个页面跳转来的query参数
+    handleReceiveQuery() {
+      //  console.log(this.ArrayDate);
+      console.log(this.$route.query);
+      this.ArrayDate = this.$route.query;
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+#PointNavigation {
+  width: 100%;
+  height: 900px;
+  z-index: 1;
+  position: relative;
+}
+.PointNavigation::v-deep {
+  .Header {
+    z-index: 2;
+    position: fixed;
+    top: 137px;
+    width: 1594px;
+    height: 100px;
+    background: #f8fbff;
+    display: flex;
+    border-radius: 12px;
+    > img {
+      cursor: pointer;
+    }
+    .mode {
+      display: flex;
+      align-items: center;
+      margin-left: 5px;
+      > img:first-child {
+        margin-right: 10px;
+      }
+      > img:nth-child(3) {
+        margin-left: 45px;
+        margin-right: 10px;
+      }
+      > span:nth-child(2) {
+        font-family: PingFang SC;
+        font-weight: 500;
+        font-size: 28px;
+        color: #000000;
+        line-height: 50px;
+      }
+      > span:nth-child(4) {
+        font-family: PingFang SC;
+        font-weight: bold;
+        font-size: 36px;
+        color: #000000;
+        line-height: 50px;
+      }
+    }
+
+    .data {
+      display: flex;
+      align-items: center;
+      margin-left: 200px;
+
+      .name {
+        font-family: PingFang SC;
+        font-weight: 500;
+        font-size: 28px;
+        color: #626262;
+        line-height: 50px;
+        margin-right: 50px;
+        > span {
+          margin-left: 25px;
+          font-family: PingFang SC;
+          font-weight: bold;
+          font-size: 36px;
+          color: #000000;
+          line-height: 50px;
+        }
+      }
+    }
+  }
+  .Left {
+    z-index: 2;
+    position: fixed;
+    top: 247px;
+    width: 250px;
+    height: 325px;
+    cursor: pointer;
+  }
+  .Left-Bottom {
+    z-index: 1;
+    position: fixed;
+    bottom: 0px;
+    width: 250px;
+    height: 156px;
+    cursor: pointer;
+    display: flex;
+    justify-content: center;
+  }
+  .button {
+    z-index: 1;
+    position: fixed;
+    bottom: 0px;
+    display: flex;
+    right: 55px;
+    width: 250px;
+    height: 156px;
+    cursor: pointer;
+    flex-direction: row;
+    align-items: center;
+  }
+  .video {
+    z-index: 1;
+    width: 640px;
+    height: 360px;
+    position: fixed;
+    left: 485px;
+    top: 259px;
+  }
+}
+</style>

+ 285 - 0
src/components/home/deviceCamera.vue

@@ -0,0 +1,285 @@
+<template>
+  <div class="deviceCamera">
+    <el-button
+      style="position: absolute; top: 66px; left: 66px"
+      size="medium"
+      round
+      icon="el-icon-back"
+      @click="handleBack()"
+      >返回</el-button
+    >
+    <div class="deviceCamera-left">
+      <div class="deviceCamera-title">
+        <span>{{ data.name }}</span>
+        <div class="video">
+          <iframe
+            width="100%"
+            height="100%"
+            frameborder="0"
+            id="ysOpenDevice"
+            :src="iframeSrc"
+            allowfullscreen
+          >
+          </iframe>
+        </div>
+      </div>
+    </div>
+    <div class="deviceCamera-right">
+      <div class="deviceCamera-right-title">
+        <img src="../../assets/img/deviceDetails/ship.png" alt="" />
+        <span>25</span>
+        <span>船只编号</span>
+      </div>
+      <div class="deviceCamera-right-content">
+        <div class="deviceCamera-item">
+          <img
+            src="../../assets/img/deviceDetails/gongzuozhuangtai.png"
+            alt=""
+          />
+          <span>正常</span>
+          <span>工作状态</span>
+        </div>
+        <div class="deviceCamera-xiantiao"></div>
+        <div class="deviceCamera-item">
+          <img src="../../assets/img/deviceDetails/sudu.png" alt="" />
+          <span>4m/s</span>
+          <span>当前速度</span>
+        </div>
+      </div>
+      <div class="deviceCamera-right-content2">
+        <div class="datacontent">
+          <div class="data-row">
+            <span class="data-label">经度:</span>
+            <span>5285</span>
+          </div>
+          <div class="data-row">
+            <span class="data-label">纬度:</span>
+            <span>256</span>
+          </div>
+        </div>
+        <div class="datacontent">
+          <div class="data-row">
+            <span class="data-label">偏航角度:</span>
+            <span>6985</span>
+          </div>
+          <div class="data-row">
+            <span class="data-label">俯仰角度:</span>
+            <span>6141</span>
+          </div>
+        </div>
+      </div>
+      <div class="deviceCamera-right-content3">
+        <img src="../../assets/img/deviceDetails/dianyuan.png" alt="" />
+        <div class="deviceCamera-right-content3-title">
+          <span>电量</span>
+          <span>100%</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import axios from "axios";
+export default {
+  data() {
+    return {
+      data: {
+        name: "",
+      },
+      token: "",
+    };
+  },
+  methods: {
+    GetToken() {
+      axios
+        .post(
+          "https://open.ys7.com/api/lapp/token/get",
+          {
+            appKey: "baf82eae9cce4c7b9306a8b992e25ef8",
+            appSecret: "36fb23c7e3afcaf85024139c1468bcb6",
+          },
+          {
+            headers: {
+              "Content-Type": "application/x-www-form-urlencoded",
+              Accept: "application/json",
+            },
+          }
+        )
+        .then((res) => {
+          this.token = res.data.data.accessToken;
+        })
+        .catch((error) => {
+          console.error("Error:", error);
+        });
+    },
+    handleBack() {
+      this.$router.push({
+        name: "deviceDetails",
+      });
+    },
+  },
+  mounted() {
+    const tempData = localStorage.getItem("tempData");
+    if (tempData) {
+      this.data = JSON.parse(tempData);
+    }
+    // 通过路由参数获取数据
+    // if (this.$route.query.data) {
+    //     this.data = JSON.parse(this.$route.query.data)
+    // }
+    this.GetToken();
+  },
+  created() {},
+  computed: {
+    iframeSrc() {
+      return `https://open.ys7.com/console/jssdk/pc.html?accessToken=${this.token}&url=ezopen://open.ys7.com/BE4405574/1.hd.live`;
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.deviceCamera::v-deep {
+  display: flex;
+
+  .deviceCamera-left {
+    width: 1174px;
+
+    .deviceCamera-title {
+      > span {
+        font-family: Microsoft YaHei;
+        font-weight: bold;
+        font-size: 22px;
+        color: #000000;
+        margin-top: 99px;
+        display: block;
+      }
+    }
+
+    .video {
+      width: 1090px;
+      height: 613px;
+      margin-left: 42px;
+      margin-top: 30px;
+    }
+  }
+
+  .deviceCamera-right {
+    width: 400px;
+
+    // 顶部船信息
+    .deviceCamera-right-title {
+      display: flex;
+      align-items: center;
+      flex-direction: column;
+      margin-top: 33px;
+
+      > span:nth-child(2) {
+        font-family: Microsoft YaHei;
+        font-weight: bold;
+        font-size: 26px;
+        color: #000000;
+        display: block;
+      }
+
+      > span:nth-child(3) {
+        font-family: Microsoft YaHei;
+        font-weight: 400;
+        font-size: 16px;
+        color: #8c95a4;
+        display: block;
+      }
+    }
+
+    // 船的状态信息
+    .deviceCamera-right-content {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-evenly;
+      margin-top: 42px;
+
+      .deviceCamera-item {
+        display: flex;
+        align-items: center;
+        flex-direction: column;
+
+        > span:nth-child(2) {
+          font-family: Microsoft YaHei;
+          font-weight: bold;
+          font-size: 20px;
+          color: #000000;
+          display: block;
+        }
+
+        > span:nth-child(3) {
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          font-size: 16px;
+          color: #8c95a4;
+          line-height: 70px;
+        }
+      }
+
+      // 中间线条
+      .deviceCamera-xiantiao {
+        width: 1px;
+        height: 116px;
+        background: #e2eaf3;
+      }
+    }
+
+    // 船的轨迹信息
+    .deviceCamera-right-content2 {
+      display: flex;
+      flex-direction: row;
+      margin-left: 75px;
+
+      .datacontent {
+        display: flex;
+        flex-direction: column;
+
+        .data-row {
+          display: flex;
+
+          > span:nth-child(2) {
+            font-family: Microsoft YaHei;
+            font-weight: 400;
+            font-size: 16px;
+            color: #000000;
+            margin: 10px;
+          }
+
+          .data-label {
+            font-family: Microsoft YaHei;
+            font-weight: 400;
+            font-size: 16px;
+            color: #8c95a4;
+            margin: 10px;
+          }
+        }
+      }
+    }
+
+    // 电源
+    .deviceCamera-right-content3 {
+      margin-top: 40px;
+
+      .deviceCamera-right-content3-title {
+        > span:nth-child(1) {
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          font-size: 16px;
+          color: #8c95a4;
+        }
+
+        > span:nth-child(2) {
+          font-family: Microsoft YaHei;
+          font-weight: bold;
+          font-size: 20px;
+          color: #000000;
+          margin-left: 15px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 183 - 0
src/components/home/deviceDetails.vue

@@ -0,0 +1,183 @@
+<template>
+  <div class="deviceDetails">
+    <div class="deviceDetails-box">
+      <div class="deviceDetails-title">
+        <img
+          src="../../assets/img/deviceDetails/pathPlan.png"
+          alt=""
+          @click="handlePathPlan()"
+        />
+        <img
+          src="../../assets/img/deviceDetails/navigation.png"
+          alt=""
+          @click="handleNavigation()"
+        />
+        <img
+          @click="handleFixedPoint()"
+          src="../../assets/img/deviceDetails/fixedPoint.png"
+          alt=""
+        />
+        <img
+          @click="handleFeedingToushi()"
+          src="../../assets/img/deviceDetails/Feeding.png"
+          alt=""
+        />
+        <img
+          @click="handleCamera()"
+          src="../../assets/img/deviceDetails/Camera.png"
+          alt=""
+        />
+        <img
+          @click="handleReturn()"
+          src="../../assets/img/deviceDetails/return.png"
+          alt=""
+        />
+      </div>
+      <div class="deviceDetails-content">
+        <div class="device-box" @click="handleHistory()">
+          <img src="../../assets/img/deviceDetails/lishi.png" alt="" />
+          <span>历史记录</span>
+        </div>
+        <div class="device-box" @click="handleWater()">
+          <img src="../../assets/img/deviceDetails/water.png" alt="" />
+          <span>水质检测</span>
+        </div>
+        <div class="device-box" @click="handleFeeding()">
+          <img src="../../assets/img/deviceDetails/toushi.png" alt="" />
+          <span>投食记录</span>
+        </div>
+        <div class="device-box" @click="handleError()">
+          <img src="../../assets/img/deviceDetails/guzhang.png" alt="" />
+          <span>错误信息</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      data: {},
+    };
+  },
+  methods: {
+    handleFeedingToushi() {
+      this.$router.push({
+        path: "/index/FeedingToushi",
+      });
+    },
+    handleFixedPoint() {
+      this.$router.push({
+        path: "/index/FixedPoint",
+      });
+    },
+    handleNavigation() {
+      this.$router.push({
+        path: "/index/PointNavigation",
+      });
+    },
+    handlePathPlan() {
+      this.$router.push({
+        path: "/index/PathPlan",
+      });
+    },
+    handleWater() {
+      this.$router.push({
+        path: "/index/waterQuality",
+      });
+    },
+    handleFeeding() {
+      this.$router.push({
+        path: "/index/FeedingRecord",
+      });
+    },
+    handleError() {
+      this.$router.push({
+        path: "/index/errorRecord",
+      });
+    },
+    handleHistory() {
+      this.$router.push({
+        path: "/index/deviceHistory",
+      });
+    },
+    handleCamera() {
+      const tempData = localStorage.getItem("tempData");
+      if (tempData) {
+        this.data = JSON.parse(tempData);
+      }
+      this.$router.push({
+        path: "/index/deviceCamera",
+        query: {
+          // data: JSON.stringify(this.data) // 序列化对象/数组
+        },
+      });
+    },
+    handleReturn() {
+      this.$confirm("此操作将一键返航, 是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.$message({
+            type: "success",
+            message: "返航成功!",
+          });
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消返航",
+          });
+        });
+    },
+  },
+  mounted() {
+    // 通过路由参数获取数据
+    // if (this.$route.query.data) {
+    //     this.data = JSON.parse(this.$route.query.data)
+    // }
+  },
+  created() {},
+  beforeDestroy() {},
+};
+</script>
+<style lang="scss" scoped>
+.deviceDetails::v-deep {
+  width: 1594px;
+  height: calc(100vh * 905 / 1080);
+  background: #ffffff;
+  border-radius: 12px;
+
+  .deviceDetails-box {
+    padding-top: 144px;
+    padding-left: 30px;
+
+    .deviceDetails-title {
+      display: flex;
+      align-items: center;
+
+      > img {
+        margin-left: 25px;
+        cursor: pointer;
+      }
+    }
+
+    .deviceDetails-content {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      .device-box {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        margin-left: 66px;
+        cursor: pointer;
+      }
+    }
+  }
+}
+</style>

+ 203 - 0
src/components/home/deviceHistory.vue

@@ -0,0 +1,203 @@
+<template>
+  <div class="errorRecord">
+    <el-button
+      style="position: absolute; top: 40px; left: 66px"
+      size="medium"
+      round
+      icon="el-icon-back"
+      @click="handleBack()"
+      >返回</el-button
+    >
+    <el-table
+      :data="tableData"
+      height="350px"
+      style="width: 100%"
+      :header-cell-class-name="HeaderCell"
+      stripe
+      border
+    >
+      <el-table-column label="序号" type="index" width="80" align="center">
+      </el-table-column>
+      <el-table-column label="路线名称" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">{{ scope.row.routeName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="保存时间" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">{{ scope.row.createTime }}</span>
+        </template>
+      </el-table-column>
+      <!-- 0是路线规划模式,1是多点导航模式 -->
+      <el-table-column label="路线类型" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">
+            {{
+              scope.row.routeType === 1 ? "多点导航模式" : "路线记录模式"
+            }}</span
+          >
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center">
+        <template slot-scope="scope">
+          <el-button
+            style="margin-left: 50px"
+            size="mini"
+            type="primary"
+            @click="handlePreview(scope.$index, scope.row)"
+            >预览</el-button
+          >
+          <el-button
+            size="mini "
+            type="success"
+            @click="handleOpen(scope.$index, scope.row)"
+            >开启</el-button
+          >
+          <el-button
+            size="mini"
+            type="danger"
+            @click="handleDelete(scope.$index, scope.row)"
+            >删除</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 第四步绑定自定义属性 -->
+    <pagination
+      :total="obj.total"
+      @handleSize="handleSizeChange"
+      @handleCurrent="handleCurrentChange"
+    >
+    </pagination>
+  </div>
+</template>
+<script>
+import apiServe from "@/utils/api";
+// 第一步引入组件
+import pagination from "../pagination/pagination.vue";
+export default {
+  // 第二步 注册组件
+  components: {
+    pagination,
+  },
+  data() {
+    return {
+      data: {
+        name: "",
+      },
+      token: "",
+      tableData: [],
+      obj: {
+        // 页码
+        page: 1,
+        // 每页多少条
+        rows: 10,
+        // 默认选中哪一页
+        currentPage: 1,
+        // 定义总条数
+        total: null,
+      },
+    };
+  },
+  methods: {
+    handleBack() {
+      this.$router.push({
+        name: "deviceDetails",
+      });
+    },
+    // 表头单元格样式
+    HeaderCell() {
+      return "HeaderCellClass";
+    },
+    handleData() {
+      let data = {
+        pageNo: this.obj.page,
+        pageSize: this.obj.rows,
+      };
+      apiServe.HistoryRoute("get", data).then((res) => {
+        console.log(res.data);
+        this.tableData = res.data.list;
+        this.obj.total = Number(res.data.total);
+      });
+    },
+    handleEdit(id, row) {
+      console.log(id, row);
+    },
+    // 分页开始
+    handleSizeChange(val) {
+      // console.log(val, "接收");
+      // 当我点击每页多少条的时候赋值并重新渲染页面
+      this.obj.rows = val;
+      this.handleData();
+    },
+    handleCurrentChange(val) {
+      // console.log(val, "接收");
+      // 当我点击页码的时候将页码赋值给变量并重新渲染页面
+      this.obj.page = val;
+      this.handleData();
+    },
+    // 分页结束
+
+    // 预览详情
+    handlePreview(id, row) {
+      apiServe.HistoryRouteDetail("get", { id: row.id }).then((res) => {
+        // 跳转到另一个页面并且传递数据
+        this.$router.push({
+          path: "/index/PointNavigation",
+          query: {
+            id: row.id,
+            data: res.data.route,
+          },
+        });
+      });
+    },
+    handleOpen(id, row) {
+      console.log(row);
+      apiServe
+        .SelectRoutePoints("post", {
+          routeId: row.id,
+          shipId: 123456789,
+          routeMode: 1,
+        })
+        .then(() => {
+          // 跳转到另一个页面并且传递数据
+          this.$router.push({
+            path: "/index/PointNavigation",
+            query: { routeId: row.id },
+          });
+        });
+    },
+    handleDelete(id, row) {
+      apiServe.DeleteHistoryRoute("delete", { id: row.id }).then((res) => {
+        console.log(res);
+        if (res.code == 200) {
+          this.$message({
+            message: "删除成功",
+            type: "success",
+          });
+          this.handleData();
+        }
+      });
+    },
+  },
+  mounted() {
+    this.handleData();
+  },
+  created() {},
+  computed: {},
+};
+</script>
+<style lang="scss" scoped>
+.errorRecord::v-deep {
+  margin-top: 100px;
+  padding: 10px;
+  background-color: #fff;
+  box-shadow: 0 0 5px #d0d0d0;
+  border-radius: 5px;
+
+  .HeaderCellClass {
+    background: #859cb7;
+    color: #fff;
+  }
+}
+</style>

+ 84 - 0
src/components/home/errorRecord.vue

@@ -0,0 +1,84 @@
+<template>
+  <div class="errorRecord">
+    <el-button
+      style="position: absolute; top: 40px; left: 66px"
+      size="medium"
+      round
+      icon="el-icon-back"
+      @click="handleBack()"
+      >返回</el-button
+    >
+    <el-table
+      :data="tableData"
+      height="350px"
+      style="width: 100%"
+      :header-cell-class-name="HeaderCell"
+      stripe
+      border
+    >
+      <el-table-column label="序号" type="index" width="80" align="center">
+      </el-table-column>
+      <el-table-column label="错误信息" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">{{ scope.row.detail }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="投食时间" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">{{ scope.row.createTime }}</span>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+<script>
+import apiServe from "@/utils/api";
+
+export default {
+  data() {
+    return {
+      data: {
+        name: "",
+      },
+      token: "",
+      tableData: [],
+    };
+  },
+  methods: {
+    handleBack() {
+      this.$router.push({
+        name: "deviceDetails",
+      });
+    },
+    // 表头单元格样式
+    HeaderCell() {
+      return "HeaderCellClass";
+    },
+    handleData() {
+      apiServe.ErrorMessage("get", {}).then((res) => {
+        console.log(res.data);
+        this.tableData = res.data.list;
+      });
+    },
+  },
+  mounted() {
+    this.handleData();
+  },
+  created() {},
+  computed: {},
+};
+</script>
+<style lang="scss" scoped>
+.errorRecord::v-deep {
+  margin-top: 100px;
+  padding: 10px;
+  background-color: #fff;
+  box-shadow: 0 0 5px #d0d0d0;
+  border-radius: 5px;
+
+  .HeaderCellClass {
+    background: #859cb7;
+    color: #fff;
+  }
+}
+</style>

+ 220 - 0
src/components/home/waterQuality.vue

@@ -0,0 +1,220 @@
+<template>
+  <div class="waterQuality">
+    <el-button
+      style="position: absolute; top: 40px; left: 66px"
+      size="medium"
+      round
+      icon="el-icon-back"
+      @click="handleBack()"
+      >返回</el-button
+    >
+
+    <div class="waterQuality-box">
+      <div class="waterQuality-box-top">
+        <span>当前水质监测</span>
+        <span>实时更新</span>
+        <span style="position: absolute; right: 80px"
+          >2025-05-06 12:25:06 已更新</span
+        >
+      </div>
+      <div class="waterQuality-box-content">
+        <div class="item">
+          <img src="../../assets/img/waterQuality/shidu.png" alt="" />
+          <div class="item-content">
+            <div class="item-content-title">66%</div>
+            <div class="item-content-value">湿度</div>
+          </div>
+        </div>
+
+        <div class="item">
+          <img src="../../assets/img/waterQuality/yang.png" alt="" />
+          <div class="item-content">
+            <div class="item-content-title">30.9%</div>
+            <div class="item-content-value">溶氧度</div>
+          </div>
+        </div>
+        <div class="item">
+          <img src="../../assets/img/waterQuality/PH.png" alt="" />
+          <div class="item-content">
+            <div class="item-content-title">9.9PH</div>
+            <div class="item-content-value">PH值</div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="waterQuality-box-bottom">
+      <el-table
+        :data="tableData"
+        height="350px"
+        style="width: 100%"
+        :header-cell-class-name="HeaderCell"
+        stripe
+        border
+      >
+        <el-table-column label="序号" type="index" width="80" align="center">
+        </el-table-column>
+        <el-table-column label="时间" align="center">
+          <template slot-scope="scope">
+            <span style="margin-left: 10px">{{ scope.row.time }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="湿度" align="center">
+          <template slot-scope="scope">
+            <span style="margin-left: 10px">{{ scope.row.humidity }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="溶氧度" align="center">
+          <template slot-scope="scope">
+            <span style="margin-left: 10px">{{ scope.row.oxygen }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="PH值" align="center">
+          <template slot-scope="scope">
+            <span style="margin-left: 10px">{{ scope.row.PH }}</span>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      data: {
+        name: "",
+      },
+      token: "",
+      tableData: [
+        {
+          time: "2025-05-06 12:25:06",
+          humidity: "66%",
+          oxygen: "30.9%",
+          PH: "9.9PH",
+        },
+        {
+          time: "2025-05-06 12:25:06",
+          humidity: "66%",
+          oxygen: "30.9%",
+          PH: "9.9PH",
+        },
+        {
+          time: "2025-05-06 12:25:06",
+          humidity: "66%",
+          oxygen: "30.9%",
+          PH: "9.9PH",
+        },
+        {
+          time: "2025-05-06 12:25:06",
+          humidity: "66%",
+          oxygen: "30.9%",
+          PH: "9.9PH",
+        },
+        {
+          time: "2025-05-06 12:25:06",
+          humidity: "66%",
+          oxygen: "30.9%",
+          PH: "9.9PH",
+        },
+      ],
+    };
+  },
+  methods: {
+    handleBack() {
+      this.$router.push({
+        name: "deviceDetails",
+      });
+    },
+    // 表头单元格样式
+    HeaderCell() {
+      return "HeaderCellClass";
+    },
+  },
+  mounted() {},
+  created() {},
+  computed: {},
+};
+</script>
+<style lang="scss" scoped>
+.waterQuality::v-deep {
+  margin: 30px;
+
+  .waterQuality-box {
+    width: 1544px;
+    height: 216px;
+    background: #ffffff;
+    border-radius: 10px;
+
+    .waterQuality-box-top {
+      display: flex;
+      padding-top: 40px;
+      padding-left: 30px;
+
+      > span:first-child {
+        font-family: Microsoft YaHei;
+        font-weight: bold;
+        font-size: 22px;
+        color: #000000;
+        line-height: 50px;
+      }
+
+      > span:nth-child(2) {
+        padding-left: 10px;
+        font-family: Microsoft YaHei;
+        font-weight: 400;
+        font-size: 16px;
+        color: #666666;
+        line-height: 50px;
+      }
+    }
+
+    .waterQuality-box-content {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-evenly;
+
+      .item {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+
+        .item-content {
+          margin-left: 30px;
+          display: flex;
+          flex-direction: column;
+
+          .item-content-title {
+            font-family: Microsoft YaHei;
+            font-weight: bold;
+            font-size: 30px;
+            color: #000000;
+            line-height: 50px;
+          }
+
+          .item-content-value {
+            font-family: Microsoft YaHei;
+            font-weight: 400;
+            font-size: 18px;
+            color: #000000;
+            line-height: 50px;
+            opacity: 0.66;
+          }
+        }
+      }
+    }
+  }
+
+  .waterQuality-box-bottom {
+    margin-top: 10px;
+    padding: 10px;
+    background-color: #fff;
+    box-shadow: 0 0 5px #d0d0d0;
+    border-radius: 5px;
+
+    .HeaderCellClass {
+      background: #859cb7;
+      color: #fff;
+    }
+  }
+}
+</style>

+ 53 - 0
src/components/pagination/pagination.vue

@@ -0,0 +1,53 @@
+    <template>
+    <div>
+        <div class="pagination">
+            <!-- 
+                @size-change:每页多少条,pageSize 改变时会触发
+                @current-change:当前页,currentPage 改变时会触发
+                :current-page:默认选中哪一页
+                :page-sizes:定义每页多少条列表
+                :page-size:默认定义每页多少条
+                :total:一共多少条数据
+                layout="显示分页的插件"
+                    total:总条数插件
+                    sizes:每页多少条插件
+                    prev/next:上一页/下一页插件
+                    pager:页码插件
+                    jumper:前往那一页插件
+                -->
+            <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
+                :current-page="obj.currentPage" :page-sizes="[10, 20, 50, 100,200]" :page-size="10"
+                layout="total, sizes, prev, pager, next, jumper" :total="total">
+            </el-pagination>
+        </div>
+    </div>
+</template>
+<script>
+    export default {
+        props: {
+            total: {
+                type: Number
+            }
+        },
+        data() {
+            return {
+                obj: {
+                    currentPage: 1,
+                },
+            }
+        },
+        methods: {
+
+            handleSizeChange(val) {
+                // 发送数据
+                this.$emit("handleSize", val)
+            },
+            // 当前页
+            handleCurrentChange(val) {
+                // 发送数据
+                this.$emit("handleCurrent", val)
+            }
+            // 分页结束
+        }
+    }
+</script>

+ 152 - 0
src/components/personal/ContactUs.vue

@@ -0,0 +1,152 @@
+<template>
+  <div class="repair">
+    <div style="padding: 20px 0px 0px 30px">
+      <el-button
+        style="position: absolute; top: 20px; right: 66px"
+        size="medium"
+        round
+        icon="el-icon-back"
+        @click="handleBack()"
+        >返回</el-button
+      >
+      <div class="repair-box-top">
+        <span>联系我们</span>
+        <div class="repair-xiantiao"></div>
+      </div>
+      <div class="repair-box-item">
+        <span class="item1">官方电话</span>
+        <div class="phone1">
+          <span>18596992323</span>
+        </div>
+        <span class="item2">官方微信</span>
+        <div class="phone2">
+          <span>18596992323</span>
+        </div>
+        <span class="item3">公众号二维码</span>
+        <img class="gzh" src="../../assets/img/gzh.png" alt="" />
+        <span class="item4">抖音二维码</span>
+        <img class="dy" src="../../assets/img/dy.png" alt="" />
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  data() {
+    return {};
+  },
+  mounted() {},
+  methods: {
+    handleBack() {
+      this.$router.push({
+        name: "personalCenter",
+      });
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.repair::v-deep {
+  width: 1594px;
+  height: calc(100vh * 905 / 1080);
+  background: #ffffff;
+  border-radius: 12px;
+
+  .repair-box-top {
+    text-align: left;
+
+    > span:first-child {
+      font-family: Microsoft YaHei;
+      font-weight: bold;
+      font-size: 22px;
+      color: #000000;
+      line-height: 50px;
+      text-align: left;
+    }
+
+    .repair-xiantiao {
+      width: 1534px;
+      height: 2px;
+      background: #eff2f6;
+    }
+  }
+
+  .repair-box-item {
+    position: relative;
+
+    .item1 {
+      position: absolute;
+      top: 20px;
+      left: 30px;
+    }
+
+    .phone1 {
+      position: absolute;
+      top: 90px;
+      left: 15px;
+    }
+
+    .item2 {
+      position: absolute;
+      top: 20px;
+      right: 700px;
+    }
+
+    .phone2 {
+      position: absolute;
+      top: 90px;
+      right: 30px;
+    }
+
+    .item3 {
+      position: absolute;
+      top: 230px;
+      left: 30px;
+    }
+
+    .item4 {
+      position: absolute;
+      right: 681px;
+      top: 230px;
+    }
+    .gzh {
+      width: 200px;
+      height: 200px;
+      position: fixed;
+      top: 530px;
+      left: 334px;
+    }
+    .dy {
+      width: 200px;
+      height: 200px;
+      position: fixed;
+      top: 530px;
+      left: 1103px;
+    }
+    > span {
+      font-family: Microsoft YaHei;
+      font-weight: 400;
+      font-size: 20px;
+      color: #000000;
+      line-height: 50px;
+    }
+
+    .phone1,
+    .phone2 {
+      width: 752px;
+      height: 76px;
+      background: #f4f6f9;
+      border-radius: 14px;
+      text-align: left;
+
+      > span {
+        font-family: Microsoft YaHei;
+        font-weight: 400;
+        font-size: 18px;
+        color: #626262;
+        line-height: 76px;
+      }
+    }
+  }
+}
+</style>

+ 0 - 0
src/components/personal/FeedbackInformation.vue


+ 186 - 0
src/components/personal/RepairRecord.vue

@@ -0,0 +1,186 @@
+<template>
+  <div class="RepairRecord">
+    <el-table
+      :data="tableData"
+      height="350px"
+      style="width: 100%"
+      :header-cell-class-name="HeaderCell"
+      stripe
+      border
+    >
+      <el-table-column label="序号" type="index" width="80" align="center">
+      </el-table-column>
+      <el-table-column label="故障类型" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">
+            <span v-if="scope.row.faultType === 0">结构故障</span>
+            <span v-else-if="scope.row.faultType === 1">动力故障</span>
+            <span v-else-if="scope.row.faultType === 2">船体故障</span>
+            <span v-else>其他问题</span></span
+          >
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">{{ scope.row.createTime }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="设备ID" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">{{ scope.row.shipId }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="用户ID" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">{{ scope.row.createBy }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="联系方式" align="center">
+        <template slot-scope="scope">
+          <span style="margin-left: 10px">{{ scope.row.contactWay }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="primary"
+            @click="handlePreview(scope.$index, scope.row)"
+            >处理</el-button
+          >
+
+          <el-button
+            size="mini"
+            type="danger"
+            @click="handleDelete(scope.$index, scope.row)"
+            >删除</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 第四步绑定自定义属性 -->
+    <pagination
+      :total="obj.total"
+      @handleSize="handleSizeChange"
+      @handleCurrent="handleCurrentChange"
+    >
+    </pagination>
+  </div>
+</template>
+<script>
+import apiServe from "@/utils/api";
+// 第一步引入组件
+import pagination from "../pagination/pagination.vue";
+export default {
+  // 第二步 注册组件
+  components: {
+    pagination,
+  },
+  data() {
+    return {
+      data: {
+        name: "",
+      },
+      token: "",
+      tableData: [],
+      obj: {
+        // 页码
+        page: 1,
+        // 每页多少条
+        rows: 10,
+        // 默认选中哪一页
+        currentPage: 1,
+        // 定义总条数
+        total: null,
+      },
+    };
+  },
+  methods: {
+    // 表头单元格样式
+    HeaderCell() {
+      return "HeaderCellClass";
+    },
+    handleData() {
+      let data = {
+        pageNo: this.obj.page,
+        pageSize: this.obj.rows,
+      };
+      apiServe.GetWarrantRepair("get", data).then((res) => {
+        this.tableData = res.data.list;
+        this.obj.total = Number(res.data.total);
+      });
+    },
+    handleEdit(id, row) {
+      console.log(id, row);
+    },
+    // 分页开始
+    handleSizeChange(val) {
+      //   console.log(val, "接收");
+      // 当我点击每页多少条的时候赋值并重新渲染页面
+      this.obj.rows = val;
+      this.handleData();
+    },
+    handleCurrentChange(val) {
+      // console.log(val, "接收");
+      // 当我点击页码的时候将页码赋值给变量并重新渲染页面
+      this.obj.page = val;
+      this.handleData();
+    },
+    // 分页结束
+
+    // 处理
+    handlePreview(id, row) {
+      console.log(id, row);
+      apiServe
+        .UpdateWarrantRepair("put", {
+          id: row.id,
+          status: row.status === 1 ? 0 : 1,
+        })
+        .then((res) => {
+          console.log(res);
+          this.handleData();
+          this.$message({
+            showClose: true,
+            message: "已成功处理",
+            type: "success",
+          });
+        });
+    },
+    handleDelete(id, row) {
+      apiServe.DeleteWarrantRepair("delete", { id: row.id }).then((res) => {
+        console.log(res);
+        if (res.code == 200) {
+          this.$message({
+            message: "删除成功",
+            type: "success",
+          });
+          this.handleData();
+        }
+      });
+    },
+  },
+  mounted() {
+    this.handleData();
+  },
+  created() {},
+  computed: {},
+};
+</script>
+<style lang="scss" scoped>
+.RepairRecord::v-deep {
+  margin-top: 50px;
+  padding: 10px;
+  background-color: #fff;
+  box-shadow: 0 0 5px #d0d0d0;
+  border-radius: 5px;
+
+  .HeaderCellClass {
+    background: #859cb7;
+    color: #fff;
+  }
+  .pagination {
+    margin-top: 30px;
+    margin-bottom: 20px;
+  }
+}
+</style>

+ 303 - 0
src/components/power/powerManagement.vue

@@ -0,0 +1,303 @@
+<template>
+    <div class="userManagement">
+        <div class="form-header">
+            <el-form :inline="true" :model="formInline" class="demo-form-inline">
+                <el-button type="success" icon="el-icon-plus" @click="handleAdd()">新增</el-button>
+
+            </el-form>
+
+        </div>
+        <div class="form-box">
+            <el-table :data="tableData" height="650px" style="width: 100%" :header-cell-class-name="HeaderCell" stripe
+                border>
+                <el-table-column label="序号" type="index" width="80" align="center">
+                </el-table-column>
+                <el-table-column label="管理模块类型" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.comment }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="管理名称" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.name }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="管理路径" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.path }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="id" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.id }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="操作" width="284px" align="center">
+                    <template slot-scope="scope">
+                        <el-button size="mini" type="warning" @click="handleXG(scope.row.id)"
+                            icon="el-icon-edit">修改</el-button>
+                        <el-button size="mini" type="danger" @click="handleDE(scope.row.id)"
+                            icon="el-icon-delete">删除</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+
+        <!-- 弹出框 -->
+        <!-- 详情弹出框 -->
+        <el-dialog :title="title" :visible.sync="dialogFormVisible">
+            <el-form ref="gridData" :model="gridData" :rules="rules">
+                <el-form-item label="权限路径" :label-width="formLabelWidth" prop="path">
+                    <el-input v-model="gridData.path" autocomplete="off"></el-input>
+                </el-form-item>
+                <el-form-item label="权限名称" :label-width="formLabelWidth" prop="name">
+                    <el-input v-model="gridData.name" autocomplete="off"></el-input>
+                </el-form-item>
+                <el-form-item label="权限描述" :label-width="formLabelWidth" prop="comment">
+                    <el-input v-model="gridData.comment" autocomplete="off"></el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button @click="dialogFormVisible = false">取 消</el-button>
+                <el-button type="primary" @click=handleAdd1(1) v-if="title == '新增租户'">确 定</el-button>
+                <el-button type="primary" @click=handleAdd1(2) v-if="title == '编辑租户'">确 定</el-button>
+            </div>
+
+
+        </el-dialog>
+
+
+
+    </div>
+
+
+
+</template>
+<script>
+// 第一步引入组件
+import apiServe from "@/utils/api.js";
+import axios from "axios";
+export default {
+    data() {
+        return {
+            // 详情弹出框
+            dialogFormVisible: false,
+            // 详情数据tabledata
+            gridData: {
+                path: "",
+                name: "",
+                comment: "",
+                id: "",
+
+            },
+            title: "",
+            // 新增选项
+            types: [{
+                value: 1,
+                label: '企业'
+            }, {
+                value: 2,
+                label: '个人'
+            }],
+            XG: "",
+            rules: {
+                path: [
+                    { required: true, message: "请输入权限路径", trigger: "blur" },
+                ],
+                name: [
+                    { required: true, message: "请输入权限名称", trigger: "blur" },
+                ],
+                comment: [
+                    { required: true, message: "请输入权限描述", trigger: "blur" },
+                ],
+
+            },
+            tenantId: "",
+            // 查询
+            formInline: {
+                shipname: "",
+            },
+            tableData: [],
+
+            formLabelWidth: '120px'
+        }
+    },
+    methods: {
+        // 表头单元格样式
+        HeaderCell() {
+            return 'HeaderCellClass';
+        },
+        handleData() {
+            apiServe.PowerList("get", {}).then((res) => {
+                console.log(res);
+                // 将请求成功的数据赋值给表格
+                if (res) {
+                    this.tableData = res.data;
+
+
+                }
+            });
+        },
+        // 详情
+        handleXQ(id) {
+            this.title = "租户信息详情";
+            this.dialogFormVisible = true;
+            apiServe.TenantXQ("get", {
+                id: id,
+            }).then((res) => {
+                console.log(res);
+                // 将请求成功的数据赋值给表格
+                if (res) {
+                    console.log(res.data);
+                    this.gridData = res.data;
+
+                }
+            })
+        },
+        // 新增
+        handleAdd() {
+            this.title = "新增租户";
+            this.dialogFormVisible = true;
+            // 清空验证并清空内容
+            this.$nextTick(() => {
+                this.$refs.gridData.resetFields();
+            });
+
+        },
+        // 编辑
+        handleXG(id) {
+            this.XG = id
+            this.title = "编辑租户";
+            this.dialogFormVisible = true;
+            apiServe.PowerCX("get", { id: id }).then((res) => {
+                console.log(res.data);
+                this.gridData = res.data
+            })
+
+        },
+        // 新增确定
+        handleAdd1(val) {
+            this.$refs.gridData.validate((valid) => {
+                if (valid) {
+                    if (val == 1) {
+                        let data = {
+                            path: this.gridData.path,
+                            name: this.gridData.name,
+                            comment: this.gridData.comment,
+                        };
+                        apiServe.PowerXZ("post", data).then((res) => {
+                            console.log(res);
+                        })
+                        console.log(data);
+                        this.$message({
+                            message: '恭喜你,添加成功',
+                            type: 'success'
+                        });
+                        this.handleData()
+                        // 清空验证并清空内容
+                        this.$nextTick(() => {
+                            this.$refs.gridData.resetFields();
+                        });
+                    } else {
+                        let data = {
+                            path: this.gridData.path,
+                            name: this.gridData.name,
+                            comment: this.gridData.comment,
+                            id: this.XG,
+                        };
+                        apiServe.PowerXG("put", data).then((res) => {
+                            console.log(res);
+                            this.handleData()
+                        })
+                        console.log(data);
+                        this.$message({
+                            message: '恭喜你,修改成功',
+                            type: 'success'
+                        });
+                    }
+
+                    this.dialogFormVisible = false;
+                } else {
+                    console.log("error submit!!");
+                    return false;
+                }
+            });
+
+        },
+        handleDE(ids) {
+            const token = localStorage.getItem('token');
+            console.log(token);
+            this.$confirm(`此操作将永久删除选中的 id为${ids} 的文件, 是否继续?`, '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                axios.delete("http://81.70.146.224:11500/users/permission-manage/" + ids, {
+                    headers: {
+                        'Authorization': `${token}`, // 将 token 放在请求头中
+                    }
+                }).then((res) => {
+                    if (res) {
+                        this.$message({
+                            type: 'success',
+                            message: '删除成功!'
+                        });
+                        this.handleData(); // 刷新数据
+                    }
+                }).catch((error) => {
+                    this.$message({
+                        type: 'error',
+                        message: '删除失败: ' + (error.message || '未知错误')
+                    });
+                });
+            }).catch(() => {
+                this.$message({
+                    type: 'info',
+                    message: '已取消删除'
+                });
+            });
+        },
+
+    },
+    mounted() {
+        // 从本地读取数据
+        this.tenantId = localStorage.getItem("tenantId")
+        console.log(this.tenantId)
+        this.handleData()
+    }
+}
+</script>
+<style lang="scss" scoped>
+.userManagement::v-deep {
+    .form-header {
+        box-shadow: 0 0 5px #d0d0d0;
+        border-radius: 5px;
+        text-align: left;
+        background-color: #fff;
+        padding: 10px;
+        padding-left: 30px;
+
+        .el-form-item {
+            margin-bottom: 0;
+        }
+    }
+
+    .form-box {
+        margin-top: 10px;
+        padding: 10px;
+        background-color: #fff;
+        box-shadow: 0 0 5px #d0d0d0;
+        border-radius: 5px;
+        /* // calc():高度时100%-超出的部分 */
+        height: calc(100vh - 235px);
+
+        .HeaderCellClass {
+            background: #859CB7;
+            color: #fff;
+        }
+    }
+
+
+
+}
+</style>

+ 241 - 0
src/components/qHeader.vue

@@ -0,0 +1,241 @@
+<template>
+  <div class="qheader">
+    <el-header style="height:calc(100vh * 76 / 1080);">
+      <div class="header">
+        <div class="computer"><img src="../assets/img/computer.png" alt=""></div>
+        <div class="title">{{ msg }}</div>
+
+      </div>
+      <div>
+        <div class="ellink">
+          <span class="tit1"> {{ currentTime }}</span>
+          <span class="tit2">{{ weekDay }} {{ formattedDate }}</span>
+          <img class="tit3" src="../assets/img/Admin.png" alt="">
+          <span class="tit4">Admin</span>
+          <!-- 点击退出登录 -->
+          <img @click="handleOut" class="tit5" src="../assets/img/Back.png" alt="">
+        </div>
+        <!-- 线条 -->
+        <div class="ellink1">
+
+        </div>
+        <!-- 当前位置 -->
+        <div>
+          <span class="titl1">当前位置:</span>
+          <span class="titl2">{{ this.$store.state.activeMenuItem }} </span>
+          <!-- 当前位置 -->
+          <div class="titl3">
+
+            <img src="../assets/img/left.png">
+            <span>{{ this.$route.meta.title }}</span>
+            <img src="../assets/img/right.png">
+          </div>
+
+        </div>
+      </div>
+
+
+    </el-header>
+  </div>
+</template>
+<script>
+
+export default {
+  data() {
+    return {
+      date: new Date(),
+      timeInterval: null,
+      msg: "无人船数字管理平台",
+      userName: localStorage.getItem("userName"),
+    };
+  },
+
+  methods: {
+    handleOut() {
+      this.$confirm("此操作将退出系统, 是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          localStorage.removeItem("role");
+          localStorage.removeItem("name");
+          localStorage.removeItem("userName");
+          localStorage.removeItem("token");
+          this.$message({
+            type: "success",
+            message: "退出成功!",
+          });
+          // 退出登录页面
+          this.$router.push("/login");
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消退出",
+          });
+        });
+    },
+
+  },
+  computed: {
+    currentTime() {
+      return this.date.toTimeString().slice(0, 8); // 获取时分秒
+    },
+    weekDay() {
+      return this.date.toLocaleDateString(undefined, { weekday: 'short' }); // 获取星期几
+    },
+    formattedDate() {
+      return this.date.toLocaleDateString(); // 获取年月日
+    },
+  },
+  mounted() {
+
+  },
+  created() {
+
+    this.timeInterval = setInterval(() => {
+      this.date = new Date(); // 更新date以触发计算属性重新计算
+    }, 1000);
+  },
+  beforeDestroy() {
+    clearInterval(this.timeInterval); // 清除定时器
+  },
+};
+</script>
+<style lang="scss" scoped>
+.qheader::v-deep {
+  z-index: 0;
+  width: 100vw;
+  height: calc(100vh * 198 / 1080);
+  opacity: 0.96;
+  background: rgba(0, 88, 196, 0.96);
+  position: relative;
+
+  // 电脑图标
+  .computer {
+    width: 30px;
+    height: 27px;
+    // background: #FFFFFF;
+    position: absolute;
+    left: 32px;
+    top: 25px;
+  }
+
+  // 无人船数字后台管理系统
+  .title {
+    width: 253px;
+    height: 28px;
+    font-family: Microsoft YaHei;
+    font-weight: bold;
+    font-size: 28px;
+    color: #FFFFFF;
+    line-height: 26px;
+    position: absolute;
+    left: 78px;
+    top: 24px;
+  }
+
+  .el-header {
+    padding: 0;
+
+  }
+
+
+  .ellink {
+    .tit1 {
+      font-family: SourceHanSansCN;
+      font-weight: 400;
+      font-size: 20px;
+      color: #FFFFFF;
+      position: absolute;
+      top: 20px;
+      right: 196px;
+
+    }
+
+    .tit2 {
+      font-family: SourceHanSansCN;
+      font-weight: 400;
+      font-size: 14px;
+      color: #FFFFFF;
+      position: absolute;
+      top: 47px;
+      right: 178px;
+    }
+
+    .tit3 {
+      position: absolute;
+      top: 21px;
+      right: 109px;
+    }
+
+    .tit4 {
+      position: absolute;
+      top: 31px;
+      right: 61px;
+    }
+
+    .tit5 {
+      position: absolute;
+      top: 30px;
+      right: 30px;
+    }
+  }
+
+  .ellink1 {
+    width: 100vw;
+    height: 1px;
+    background: #F2F5FA;
+    opacity: 0.26;
+    position: absolute;
+    top: 76px;
+  }
+
+  .titl1 {
+    font-family: Microsoft YaHei;
+    font-weight: 400;
+    font-size: 15px;
+    color: #FFFFFF;
+    opacity: 0.56;
+    position: absolute;
+    left: 297px;
+    top: 101px;
+  }
+
+  .titl2 {
+    font-family: Microsoft YaHei;
+    font-weight: 400;
+    font-size: 15px;
+    color: #FFFFFF;
+    position: absolute;
+    left: 375px;
+    top: 101px;
+  }
+
+  .titl3 {
+    position: absolute;
+    left: 460px;
+    top: 96px;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+
+    >span {
+      font-family: Microsoft YaHei;
+      font-weight: 400;
+      font-size: 15px;
+      color: #000000;
+      vertical-align: middle;
+      width: 106px;
+      height: 30px;
+      line-height: 30px;
+      background: #FFFFFF;
+      border-radius: 5px;
+      margin-left: 5px;
+      margin-right: 5px;
+
+    }
+  }
+}
+</style>

+ 162 - 0
src/components/qNav.vue

@@ -0,0 +1,162 @@
+<template>
+  <div id="box-main">
+    <div class="main-container">
+      <aside class="sidebar">
+        <nav class="menu">
+          <router-link
+            v-for="item in menuItems"
+            :key="item.path"
+            :to="item.path"
+            @click.native="setActiveMenu(item.title)"
+            class="menu-item"
+          >
+            <i :class="`${item.icon}`"></i>
+            <span>{{ item.title }}</span>
+            <img
+              style="margin-left: 68px"
+              src="../assets/img/gogogo.png"
+              alt=""
+            />
+          </router-link>
+        </nav>
+      </aside>
+      <main class="content-area">
+        <router-view />
+      </main>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      str: false,
+      menuItems: [
+        {
+          path: "/index/homepage",
+          icon: "el-icon-s-unfold",
+          title: "设备管理",
+          name: "Device",
+        }, // 新增唯一name
+        {
+          path: "/index/userManagement",
+          icon: "el-icon-s-custom",
+          title: "用户管理",
+          name: "User",
+        },
+        {
+          path: "/index/roleManagement",
+          icon: "el-icon-user",
+          title: "角色管理",
+          name: "Role",
+        }, // 修改icon
+        {
+          path: "/index/powerManagement",
+          icon: "el-icon-s-check",
+          title: "权限管理",
+          name: "Power",
+        }, // 修改icon
+        {
+          path: "/index/tenantManagement",
+          icon: "el-icon-menu",
+          title: "租户管理",
+          name: "zuhu",
+        },
+        {
+          path: "/index/ContactUs",
+          icon: "el-icon-phone",
+          title: "联系我们",
+          name: "ContactUs",
+        },
+        {
+          path: "/index/RepairRecord",
+          icon: "el-icon-s-tools",
+          title: "报修记录",
+          name: "RepairRecord",
+        },
+        {
+          path: "/index/FeedbackInformation",
+          icon: "el-icon-chat-dot-square",
+          title: "反馈信息",
+          name: "FeedbackInformation",
+        },
+      ],
+    };
+  },
+  methods: {
+    setActiveMenu(menuItemTitle) {
+      this.$store.dispatch("updateActiveMenuItem", menuItemTitle);
+    },
+  },
+  mounted() {},
+};
+</script>
+<style lang="scss" scoped>
+#box-main::v-deep {
+  .main-container {
+    position: absolute;
+    left: 0;
+    top: calc(100vh * 198 / 1080);
+    bottom: 0;
+    width: 100%;
+    background: #dee6ef;
+    display: flex;
+    flex-direction: row;
+    flex: 1;
+
+    .sidebar {
+      width: 268px;
+      height: calc(100vh * 970 / 1080);
+      background: #021327;
+      box-shadow: 6px 0px 9px 0px rgba(27, 30, 46, 0.26);
+      border-radius: 0px 12px 0px 0px;
+      position: absolute;
+      top: calc(100vh * -88 / 1080);
+      z-index: 111;
+    }
+
+    .content-area {
+      display: block;
+      flex: 1;
+      flex-basis: auto;
+      overflow: auto;
+      box-sizing: border-box;
+      position: absolute;
+      left: 268px;
+      top: -50px;
+      bottom: 0;
+      right: 0;
+      margin: 20px;
+      width: 1594px;
+      height: 83.7962962963vh;
+      background: #f1f5fa;
+      border-radius: 12px;
+    }
+
+    .menu {
+      .menu-item {
+        display: flex;
+        align-items: center;
+        padding: 15px;
+        font-family: "Microsoft YaHei";
+        font-weight: bold;
+        font-size: 16px;
+        color: #d2e0f1;
+        text-decoration: none;
+        background: transparent; // 默认背景
+        border-radius: 0; // 默认圆角
+
+        &.router-link-exact-active {
+          color: #ffffff;
+          background: #1c6fec;
+          border-radius: 10px;
+        }
+
+        span {
+          padding-left: 15px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 393 - 0
src/components/role/roleManagement.vue

@@ -0,0 +1,393 @@
+<template>
+    <div class="userManagement">
+        <div class="form-header">
+            <el-form :inline="true" :model="formInline" class="demo-form-inline">
+                <el-form-item label="角色名称">
+                    <el-input v-model="formInline.roleName" clearable></el-input>
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" icon="el-icon-search" @click="handleData()">查询</el-button>
+                    <el-button type="success" icon="el-icon-plus" @click="handleAdd()">新增</el-button>
+                </el-form-item>
+                <!-- <el-form-item label="租户名称">
+                    <el-select v-model="formInline.tenantId" clearable placeholder="请选择所属租户">
+                        <el-option v-for="item in tenantIdoptions" :key="item.id" :label="item.label" :value="item.id">
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" icon="el-icon-search" @click="handleData()">查询</el-button>
+                </el-form-item> -->
+            </el-form>
+
+        </div>
+        <div class="form-box">
+            <el-table :data="tableData" height="350px" style="width: 100%" :header-cell-class-name="HeaderCell" stripe
+                border>
+                <el-table-column label="序号" type="index" width="80" align="center">
+                </el-table-column>
+                <el-table-column label="id" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.id }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="创建时间" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.createTime }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="名称" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.tenantName }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="用户名" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.comment }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="角色" align="center">
+                    <template slot-scope="scope">
+                        <span style="margin-left: 10px">{{ scope.row.roleName }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="操作" width="384px" align="center">
+                    <template slot-scope="scope">
+                        <el-button size="mini" type="success" @click="handleXQ(scope.row.id)"
+                            icon="el-icon-document">详情</el-button>
+                        <el-button size="mini" type="info" @click="handleXG(scope.row.id)"
+                            icon="el-icon-edit">修改</el-button>
+                        <el-button size="mini" type="danger" @click="handleDE(scope.row.id)"
+                            icon="el-icon-delete">删除</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+            <!-- 第四步绑定自定义属性 -->
+            <pagination :total="obj.total" @handleSize="handleSizeChange" @handleCurrent="handleCurrentChange">
+            </pagination>
+        </div>
+        <!-- 弹出框 -->
+        <el-dialog :title="title" :visible.sync="dialogFormVisible" top="30vh">
+            <el-form ref="gridData" :model="gridData" :rules="rules">
+                <el-form-item label="角色名称" :label-width="formLabelWidth" prop="roleName">
+                    <el-input v-model="gridData.roleName" autocomplete="off" :disabled="title == '角色信息详情'"></el-input>
+                </el-form-item>
+                <el-form-item label="修改人" :label-width="formLabelWidth" v-if="title == '角色信息详情'">
+                    <el-input v-model="gridData.updateBy" autocomplete="off" :disabled="title == '角色信息详情'"></el-input>
+                </el-form-item>
+                <el-form-item label="创建人" :label-width="formLabelWidth" v-if="title == '角色信息详情'">
+                    <el-input v-model="gridData.createBy" autocomplete="off" :disabled="title == '角色信息详情'"></el-input>
+                </el-form-item>
+                <el-form-item label="修改时间" :label-width="formLabelWidth" v-if="title == '角色信息详情'">
+                    <el-input v-model="gridData.updateTime" autocomplete="off" :disabled="title == '角色信息详情'"></el-input>
+                </el-form-item>
+                <el-form-item label="租户" :label-width="formLabelWidth" prop="tenantId" v-if="title == '新增角色'">
+                    <el-select v-model="gridData.tenantId" placeholder="请选择租户" style="width: 100%;">
+                        <el-option v-for="item in tenantIdoptions" :key="item.id" :label="item.label" :value="item.id">
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="角色描述" :label-width="formLabelWidth" prop="comment">
+                    <el-input v-model="gridData.comment" autocomplete="off" :disabled="title == '角色信息详情'"></el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button @click="dialogFormVisible = false">取 消</el-button>
+                <el-button type="primary" @click=handleAdd1(1) v-if="title == '新增角色'">确 定</el-button>
+                <el-button type="primary" @click=handleAdd1(2) v-if="title == '修改信息'">确 定</el-button>
+            </div>
+
+
+        </el-dialog>
+
+    </div>
+
+
+
+</template>
+<script>
+// 第一步引入组件
+import pagination from "../pagination/pagination.vue";
+import apiServe from "@/utils/api.js";
+import axios from "axios";
+export default {
+    // 第二步 注册组件
+    components: {
+        pagination,
+    },
+    data() {
+        return {
+            // 详情弹出框
+            dialogFormVisible: false,
+            // 详情数据tabledata
+            gridData: {
+                tenantId: "",
+                comment: "",
+                roleName: "",
+
+            },
+            title: "",
+            // 新增选项
+            types: [{
+                value: 1,
+                label: '企业'
+            }, {
+                value: 2,
+                label: '个人'
+            }],
+            XG: "",
+            rules: {
+                roleName: [
+                    { required: true, message: "请输入角色名称", trigger: "blur" },
+                ],
+                tenantId: [
+                    { required: true, message: "请选择租户id", trigger: "blur" },
+                ],
+                comment: [
+                    { required: true, message: "请输入角色描述", trigger: "blur" },
+                ],
+
+            },
+            tenantId: "",
+            data: [],
+            // 查询
+            formInline: {
+                tenantId: "",
+                roleName: "",
+            },
+            tenantIdoptions: [],
+            tableData: [],
+            obj: {
+                // 页码
+                page: 1,
+                // 每页多少条
+                rows: 10,
+                // 默认选中哪一页
+                currentPage: 1,
+                // 定义总条数
+                total: null,
+            },
+            formLabelWidth: '120px'
+        }
+    },
+    methods: {
+        // 表头单元格样式
+        HeaderCell() {
+            return 'HeaderCellClass';
+        },
+        handleData() {
+            // 获取租户选项
+            apiServe.TenantXZ('get', {}).then(res => {
+                // console.log(res.data.list);
+                // 防止赋值undefined
+                if (res.data.list) {
+                    this.tenantIdoptions = res.data.list.map(item => ({
+                        id: item.id,
+                        label: item.name
+                    }));
+                }
+            });
+            let data = {
+                pageNo: this.obj.page,
+                pageSize: this.obj.rows,
+                tenantId: this.formInline.tenantId,
+                roleName: this.formInline.roleName,
+            };
+            apiServe.RoleManagement("get", data).then((res) => {
+                // console.log(res);
+                // 将请求成功的数据赋值给表格
+                if (res) {
+                    this.data = res.data;
+                    this.tableData = res.data.list;
+                    this.obj.total = Number(res.data.total)
+                    // console.log(this.obj.total);
+
+                }
+            });
+        },
+        // 新增
+        handleAdd() {
+            this.dialogFormVisible = true;
+            this.title = "新增角色";
+            // 重置表单数据
+            this.gridData = {
+                tenantId: "",
+                roleName: "",
+                comment: "",
+            };
+            // 等待 DOM 更新后重置表单验证状态
+            this.$nextTick(() => {
+                if (this.$refs.gridData) {
+                    this.$refs.gridData.resetFields();
+                }
+            });
+            // 获取租户选项
+            apiServe.TenantXZ('get', {}).then(res => {
+                // console.log(res.data);
+                this.tenantIdoptions = res.data.map(item => ({
+                    id: item.id,
+                    label: item.name
+                }));
+            });
+
+
+
+        },
+        // 修改
+        handleXG(id) {
+            this.dialogFormVisible = true;
+            this.title = "修改信息";
+            apiServe.RoleUserCX("get", { id: id }).then((res) => {
+                // console.log(res.data);
+                this.gridData.comment = res.data.comment
+                this.gridData.roleName = res.data.roleName
+                this.gridData.tenantId = res.data.id
+
+            });
+        },
+        // 删除
+        handleDE(id) {
+            const token = localStorage.getItem('token');
+            this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                axios.delete("http://81.70.146.224:11500/users/role-manage/" + id, {
+                    headers: {
+                        'Authorization': `${token}`, // 将 token 放在请求头中
+                    }
+                }).then((res) => {
+                    console.log(res);
+                });
+
+                this.$message({
+                    type: 'success',
+                    message: '删除成功!'
+                });
+            }).catch(() => {
+                this.$message('取消删除');
+            })
+        },
+        handleXQ(id) {
+            this.dialogFormVisible = true;
+            this.title = "角色信息详情";
+            apiServe.RoleUserCX("get", { id: id }).then((res) => {
+                // console.log(res.data);
+                this.gridData.comment = res.data.comment
+                this.gridData.roleName = res.data.roleName
+                this.gridData.updateTime = res.data.updateTime
+                this.gridData.createBy = res.data.createBy
+                this.gridData.updateBy = res.data.updateBy
+            });
+        },
+        // 新增确定
+        handleAdd1(val) {
+            this.$refs.gridData.validate((valid) => {
+                if (valid) {
+                    if (val == 1) {
+                        let data = {
+                            roleName: this.gridData.roleName,
+                            tenantId: this.gridData.tenantId,
+                            comment: this.gridData.comment,
+                        };
+                        apiServe.RoleUserXZ("post", data).then((res) => {
+                            console.log(res);
+                        })
+                        // console.log(data);
+                        this.$message({
+                            message: '恭喜你,添加成功',
+                            type: 'success'
+                        });
+                        this.handleData()
+                        // 清空验证并清空内容
+                        this.$nextTick(() => {
+                            this.$refs.gridData.resetFields();
+                        });
+                        this.handleData()
+                    } else {
+                        let data = {
+                            roleName: this.gridData.roleName,
+                            id: this.gridData.tenantId,
+                            comment: this.gridData.comment,
+                        };
+                        apiServe.RoleUserXG("put", data).then((res) => {
+                            console.log(res);
+                            this.handleData()
+                        })
+                        // console.log(data);
+                        this.$message({
+                            message: '恭喜你,修改成功',
+                            type: 'success'
+                        });
+                    }
+
+                    this.dialogFormVisible = false;
+                } else {
+                    console.log("error submit!!");
+                    return false;
+                }
+            });
+
+        },
+        // 分页开始
+        handleSizeChange(val) {
+            // console.log(val, "接收");
+            // 当我点击每页多少条的时候赋值并重新渲染页面
+            this.obj.rows = val;
+            this.handleData();
+        },
+        handleCurrentChange(val) {
+            // console.log(val, "接收");
+            // 当我点击页码的时候将页码赋值给变量并重新渲染页面
+            this.obj.page = val;
+            this.handleData();
+        },
+        // 分页结束
+
+    },
+    mounted() {
+        // 从本地读取数据
+        this.tenantId = localStorage.getItem("tenantId")
+        // console.log(this.tenantId)
+        this.handleData()
+    }
+}
+</script>
+<style lang="scss" scoped>
+.userManagement::v-deep {
+    .form-header {
+        box-shadow: 0 0 5px #d0d0d0;
+        border-radius: 5px;
+        text-align: left;
+        background-color: #fff;
+        padding: 10px;
+        padding-left: 30px;
+
+        .el-form-item {
+            margin-bottom: 0;
+        }
+    }
+
+    .form-box {
+        margin-top: 10px;
+        padding: 10px;
+        background-color: #fff;
+        box-shadow: 0 0 5px #d0d0d0;
+        border-radius: 5px;
+        /* // calc():高度时100%-超出的部分 */
+        height: calc(100vh - 235px);
+
+        .HeaderCellClass {
+            background: #859CB7;
+            color: #fff;
+        }
+    }
+
+    .pagination {
+        padding-top: 10px;
+        text-align: center;
+    }
+
+}
+</style>

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov