Ver código fonte

初次提交

datou 2 meses atrás
pai
commit
2c2fe46906
100 arquivos alterados com 3386 adições e 1020 exclusões
  1. 2 2
      .env.development
  2. 2 2
      .env.production
  3. 2 2
      .env.staging
  4. 1 1
      index.html
  5. 1 1
      package.json
  6. 10 0
      src/api/shipxy/index.js
  7. 1 0
      src/assets/icons/svg/CO2nongdu.svg
  8. 0 0
      src/assets/icons/svg/a-jizhuangxiangchuanxin.svg
  9. 1 0
      src/assets/icons/svg/alternator.svg
  10. 1 0
      src/assets/icons/svg/back.svg
  11. 1 0
      src/assets/icons/svg/boiler.svg
  12. 3 0
      src/assets/icons/svg/draft.svg
  13. 1 0
      src/assets/icons/svg/electric.svg
  14. 1 0
      src/assets/icons/svg/electricfill.svg
  15. 0 0
      src/assets/icons/svg/engineRoom.svg
  16. 1 0
      src/assets/icons/svg/fengsu.svg
  17. 0 0
      src/assets/icons/svg/fengsufengxiangyi.svg
  18. 3 0
      src/assets/icons/svg/inclination.svg
  19. 1 0
      src/assets/icons/svg/jiayouzhan.svg
  20. 0 0
      src/assets/icons/svg/jiayouzhan_1.svg
  21. 1 0
      src/assets/icons/svg/route.svg
  22. 0 0
      src/assets/icons/svg/routePoints.svg
  23. 1 0
      src/assets/icons/svg/threeArrows.svg
  24. BIN
      src/assets/images/20240529135050.png
  25. BIN
      src/assets/images/bigModa.png
  26. BIN
      src/assets/images/bigscree.png
  27. BIN
      src/assets/images/bigship_yh.png
  28. BIN
      src/assets/images/diancBg-black.png
  29. BIN
      src/assets/images/diancBg.png
  30. BIN
      src/assets/images/finish-icon.png
  31. BIN
      src/assets/images/gps.png
  32. BIN
      src/assets/images/icon.png
  33. BIN
      src/assets/images/login-background.jpg
  34. BIN
      src/assets/images/maozi.png
  35. BIN
      src/assets/images/maozi_no.png
  36. BIN
      src/assets/images/map-end.png
  37. BIN
      src/assets/images/map-start.png
  38. BIN
      src/assets/images/mask.jpg
  39. BIN
      src/assets/images/mask.png
  40. BIN
      src/assets/images/minscreen.png
  41. BIN
      src/assets/images/money-icon.png
  42. BIN
      src/assets/images/novideo.png
  43. BIN
      src/assets/images/offline.png
  44. BIN
      src/assets/images/oldbigship.png
  45. BIN
      src/assets/images/online.png
  46. BIN
      src/assets/images/profile.jpg
  47. BIN
      src/assets/images/psc.jfif
  48. BIN
      src/assets/images/ship-icon.png
  49. BIN
      src/assets/images/ship.png
  50. BIN
      src/assets/images/shipWhei.png
  51. BIN
      src/assets/images/ship_tblr.png
  52. BIN
      src/assets/images/ship_tblr_yh.png
  53. BIN
      src/assets/images/shipnum.png
  54. BIN
      src/assets/images/shipnumbg.png
  55. BIN
      src/assets/images/speed-bigship.png
  56. BIN
      src/assets/images/speed-ship.png
  57. BIN
      src/assets/images/stop-icon.png
  58. BIN
      src/assets/images/tabbg.png
  59. BIN
      src/assets/images/tabcenter.png
  60. BIN
      src/assets/images/tableft.png
  61. BIN
      src/assets/images/tabright.png
  62. BIN
      src/assets/images/time-icon.png
  63. BIN
      src/assets/images/warn-bigship.png
  64. BIN
      src/assets/images/warn-ship.png
  65. BIN
      src/assets/images/yhTitle.png
  66. BIN
      src/assets/logo/logo.jpg
  67. BIN
      src/assets/logo/logo.png
  68. 252 0
      src/assets/styles/login.css
  69. 74 1
      src/assets/styles/main.scss
  70. 219 0
      src/components/AlarmSetting/index.vue
  71. 181 0
      src/components/EcaRegional/index.vue
  72. 123 0
      src/components/Echarts/BarChart/index.vue
  73. 125 0
      src/components/Echarts/LineChart/index.vue
  74. 124 0
      src/components/Echarts/annularChart/index.vue
  75. 3 3
      src/components/Echarts/barDataColor/index.vue
  76. 143 0
      src/components/Echarts/gaugeChart/index.vue
  77. 0 116
      src/components/Echarts/newChart/DashChart.vue
  78. 0 117
      src/components/Echarts/newChart/GaugeChart.vue
  79. 0 127
      src/components/Echarts/newChart/LineChart.vue
  80. 0 134
      src/components/Echarts/newChart/exLineChart.vue
  81. 0 148
      src/components/Echarts/newChart/roundDashChart.vue
  82. 99 0
      src/components/Echarts/pieCircularChart/index.vue
  83. 137 102
      src/components/Echarts/pieRoseTypeSimple/index.vue
  84. 136 0
      src/components/Echarts/roundbDashChart/roundbDashChart.vue
  85. 222 0
      src/components/FuelRecord/index.vue
  86. 52 0
      src/components/Progress/index.vue
  87. 118 0
      src/components/TimeZone/index.vue
  88. 1 1
      src/layout/components/AppMain.vue
  89. 136 173
      src/layout/components/Navbar.vue
  90. 56 66
      src/layout/components/Sidebar/Logo.vue
  91. 4 7
      src/layout/components/Sidebar/index.vue
  92. 53 0
      src/layout/components/Sidebar/tabMeun.vue
  93. 3 5
      src/layout/index.vue
  94. 30 0
      src/router/index.js
  95. 5 12
      src/views/desktop/index.vue
  96. 217 0
      src/views/efficiencyAnalysis/contRast/index.vue
  97. 288 0
      src/views/efficiencyAnalysis/distriBution/index.vue
  98. 242 0
      src/views/efficiencyAnalysis/historyPage/index.vue
  99. 84 0
      src/views/efficiencyAnalysis/index.vue
  100. 225 0
      src/views/efficiencyMana/AlarmMana/index.vue

+ 2 - 2
.env.development

@@ -1,10 +1,10 @@
 # 页面标题
-VITE_APP_TITLE = 扬海航运船舶管理系统(开发)
+VITE_APP_TITLE = 智能能效管理系统(开发)
 
 # 开发环境配置
 VITE_APP_ENV = 'development'
 
-# 扬海航运船舶管理系统/开发环境
+# 智能能效管理系统/开发环境
 VITE_APP_BASE_API = '/dev-api'
 # VITE_APP_BASE_API = 'http://121.37.6.200:8889'
 # VITE_APP_BASE_API = 'http://192.168.4.78:8889'

+ 2 - 2
.env.production

@@ -1,10 +1,10 @@
 # 页面标题
-VITE_APP_TITLE = 扬海船舶管理系统
+VITE_APP_TITLE = 智能能效管理系统
 
 # 生产环境配置
 VITE_APP_ENV = 'production'
 
-# 扬海船舶管理系统/生产环境
+# 智能能效管理系统/生产环境
 VITE_APP_BASE_API = 'http://121.37.6.200:8889'
 
 # 是否在打包时开启压缩,支持 gzip 和 brotli

+ 2 - 2
.env.staging

@@ -1,10 +1,10 @@
 # 页面标题
-VITE_APP_TITLE = 扬海船舶管理系统
+VITE_APP_TITLE = 智能能效管理系统
 
 # 生产环境配置
 VITE_APP_ENV = 'staging'
 
-# 扬海船舶管理系统/生产环境
+# 智能能效管理系统/生产环境
 VITE_APP_BASE_API = '/stage-api'
 
 # 是否在打包时开启压缩,支持 gzip 和 brotli

+ 1 - 1
index.html

@@ -10,7 +10,7 @@
   <meta http-equiv="expires" content="0" />
   <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
   <link rel="icon" href="/favicon.ico">
-  <title>扬海航运船舶管理系统</title>
+  <title>智能能效管理系统</title>
   <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
   <style>
     html,

+ 1 - 1
package.json

@@ -1,7 +1,7 @@
 {
   "name": "ruoyi",
   "version": "3.8.2",
-  "description": "扬海航运船舶管理系统",
+  "description": "智能能效管理系统",
   "author": "若依",
   "license": "MIT",
   "scripts": {

+ 10 - 0
src/api/shipxy/index.js

@@ -0,0 +1,10 @@
+import request from '@/utils/request'
+
+// 查询缓存详细
+export function getManyShip() {
+  return request({
+    // url: "http://api.shipxy.com/apicall/GetSingleETA?k=ca524b733c154f6caef59a8cb7b2c4db&mmsi=413572060,413295250&portcode=CNSHA",
+	url: "http://api.shipxy.com/apicall/GetSingleETA?k=ca524b733c154f6caef59a8cb7b2c4db&mmsi=413572060&portcode=BDCGP",
+    method: "get"
+  })
+}

+ 1 - 0
src/assets/icons/svg/CO2nongdu.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M886.3 474.5c-38-38-86.6-61.7-139.1-68.4-3.6-67.6-31.2-130.7-78.8-179-51.2-52.1-119.4-80.8-192-80.8s-140.8 28.7-192 80.8c-51 51.9-79.2 120.8-79.2 194.1 0 1.9 0 3.8 0.1 5.8-36.9 17.4-68.7 43.8-92.8 77.4-29.4 40.9-44.9 89.3-44.9 139.8 0 64.1 25 124.4 70.3 169.8 45.3 45.3 105.6 70.3 169.8 70.3h408.8c64.1 0 124.4-25 169.8-70.3 45.3-45.3 70.3-105.6 70.3-169.8s-25-124.3-70.3-169.7zM716.5 794.4H307.7c-82.8 0-150.1-67.3-150.1-150.1 0-63.3 40-120.1 99.7-141.4 25.8-9.2 41.8-34.7 39-62-0.7-6.5-1-13-1-19.6 0-102 81.3-184.9 181.1-184.9s181.1 83 181.1 184.9c0 3.4-0.1 6.9-0.3 10.3-0.9 16.2 5 32.3 16.2 44.1 11.1 11.8 26.8 18.5 43 18.5 82.8 0 150.1 67.3 150.1 150.1s-67.2 150.1-150 150.1z"  /><path fill="#ffffff" d="M412.9 667.8c-11.4 12.4-24.5 18.7-38.8 18.7-29.3 0-46.7-24.3-46.7-65 0-37.7 19.5-64.1 47.3-64.1 12.5 0 22.8 4.7 35.5 16.1l3.9 3.5 33.9-41.6-3.1-3.2c-11.2-11.4-35.3-30.5-71.1-30.5-30 0-57.6 11.4-77.8 32-21.8 22.2-33.3 53.2-33.3 89.6 0 36.8 11.2 67.5 32.4 88.9 19.4 19.6 46.8 30.3 76.9 30.3 30.5 0 56.9-12 76.4-34.6l2.8-3.2-34.5-41.1-3.8 4.2z"  /><path fill="#ffffff" d="M556.2 501.8c-31.7 0-58.5 10.8-77.4 31.4-19.3 21-29.5 51.4-29.5 87.8 0 73.9 42 121.6 106.9 121.6 65 0 106.9-47.7 106.9-121.6 0-36.4-10.2-66.7-29.5-87.7-18.9-20.6-45.7-31.5-77.4-31.5z m0 184.8c-26.1 0-42.2-25.1-42.2-65.6 0-39.7 15.8-63.5 42.2-63.5 26.6 0 42.5 23.7 42.5 63.5 0.1 40.4-16.2 65.6-42.5 65.6zM731.2 706.2c13.7-15.2 25.9-31.9 25.9-48.4 0-23.5-17.1-40-41.5-40-16.2 0-27.9 5.4-40.5 18.7l-3.4 3.6 21.5 21.3 3.5-3.5c5.1-5.1 9.8-9.3 15.3-9.3 4.1 0 9.5 1.1 9.5 10.7 0 13.3-20.8 32.8-44.9 55.2L675 716v22.4h87.1V706h-25.5c-1.6 0-3.5 0.1-5.4 0.2z"  /></svg>

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
src/assets/icons/svg/a-jizhuangxiangchuanxin.svg


+ 1 - 0
src/assets/icons/svg/alternator.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1717491930017" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="21701" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M810.67 85.33H213.33v725.33h597.33V85.33z m-85.34 640H298.67V170.67h426.67v554.66zM128 853.33h768v85.33H128zM853.33 256h85.33v384h-85.33zM85.33 256h85.33v384H85.33z" p-id="21702"></path><path d="M387.34 422.15h66.81c3.31 0 5.8 2.79 5.15 5.77l-41.91 193.65c-0.02 0.05 0.03 0.09 0.07 0.09 0.02 0 0.04-0.01 0.06-0.02L640.5 364.16c1.74-2.01 0.18-4.99-2.62-4.99h-84.36c-3.31 0-5.38-3.29-3.72-5.93l47.83-76.16c1.12-1.79-0.28-4.02-2.53-4.02H474.74c-5.12 0-9.81 2.64-12.14 6.84l-77.13 139.44c-0.71 1.29 0.31 2.81 1.87 2.81z" p-id="21703"></path></svg>

+ 1 - 0
src/assets/icons/svg/back.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1717150064737" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6719" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M609.701647 230.159059h-491.52v92.16h491.52c165.767529 0 294.731294 119.687529 294.731294 276.299294 0 156.611765-119.747765 276.299294-285.515294 276.299294H47.887059c-27.648 0-46.08 18.432-46.08 46.08 0 27.587765 18.432 46.019765 46.08 46.019765h571.030588c211.847529 0 377.675294-165.767529 377.675294-368.399059S821.488941 230.098824 609.641412 230.098824z" p-id="6720"></path><path d="M16.865882 241.965176L278.287059 12.167529a47.525647 47.525647 0 0 1 66.921412 3.373177c17.468235 19.275294 15.962353 49.392941-3.312942 66.921412l-220.461176 192.572235L338.522353 436.284235c20.48 16.143059 23.913412 46.140235 7.830588 66.56a47.525647 47.525647 0 0 1-66.56 7.830589L19.576471 315.211294a46.923294 46.923294 0 0 1-15.420236-21.985882c-5.782588-19.335529-1.325176-38.610824 12.649412-51.260236z" p-id="6721"></path></svg>

+ 1 - 0
src/assets/icons/svg/boiler.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1717491954660" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22721" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M814.1312 651.5712V387.5328a275.3536 275.3536 0 0 0-203.6736-265.8304V100.864c0-6.5024-0.9728-12.8-2.6112-18.8416h6.4512a34.0992 34.0992 0 0 0 29.3888-16.9984 33.9968 33.9968 0 0 0-29.3888-50.944H455.8848a33.7408 33.7408 0 0 0-29.3888 16.9984 33.9968 33.9968 0 0 0 29.3888 50.944h13.9264c-1.6896 6.144-2.56 12.4416-2.56 18.8416v20.7872a275.5072 275.5072 0 0 0-203.008 247.04h-19.5584c-0.4608 0-0.8704 0.1536-1.2288 0.256a15.0528 15.0528 0 0 0-17.6128 14.7968v279.0912a15.1552 15.1552 0 0 0 17.6128 14.848c0.4096 0.0512 0.768 0.256 1.2288 0.256h20.1728a274.5344 274.5344 0 0 0 90.368 178.688l-76.6464 153.1904h75.4176l32.3584-129.0752a275.1488 275.1488 0 0 0 304.7424 0.256l30.0544 128.8704h70.4512l-70.8096-151.7056a274.8416 274.8416 0 0 0 93.3376-206.592z m-190.6688 48.4864s16.5888-52.2752 18.176-71.168c1.28-18.7392-2.4064-48.0256-29.184-82.432-61.7984 39.8848-54.528 105.0112-54.528 105.0112l-39.936-67.3792-21.8624-78.9504s-23.296 33.8944-25.3952 60.0064c-2.2528 26.4704-4.4032 59.2896 10.9056 89.9584-32.1024-6.7584-65.536-89.9584-65.536-89.9584s-17.7664 56.9856 32.7168 131.1232c-9.0112-0.6144-151.9104-68.9152-108.8512-198.4512 31.1808 53.9136 43.4688 52.3776 43.4688 52.3776s8.0896-87.552 47.3088-164.7104c39.3216-77.1584 123.5968-59.8016 123.5968-59.8016s-26.9824 33.536-25.4464 74.9056c1.3824 41.0112 50.7904 116.0192 50.7904 116.0192s6.656-50.9952 18.2272-89.9072c15.3088 80.896 98.2016 83.2 109.0048 146.0224 13.1072 79.3088-83.456 127.3344-83.456 127.3344z" p-id="22722"></path></svg>

Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 0
src/assets/icons/svg/draft.svg


+ 1 - 0
src/assets/icons/svg/electric.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1716552365818" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="41492" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M668.038095 146.285714V0H355.961905v146.285714H131.657143v877.714286h755.809524V146.285714h-219.428572zM453.485714 97.52381h121.904762v48.761904H453.485714V97.52381z m341.333334 828.95238H229.180952V243.809524h560.761905v682.666666z" p-id="41493"></path><path d="M555.885714 404.72381l-87.771428-39.009524L351.085714 633.904762h170.666667l-58.514286 131.657143 92.647619 39.009524 117.028572-268.190477h-175.542857z" p-id="41494"></path></svg>

+ 1 - 0
src/assets/icons/svg/electricfill.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1716552173169" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20288" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M360.947512 114.887805V38.961951c0-20.87961 17.083317-37.962927 39.861073-37.962927h225.879415c20.87961 0 39.861073 17.083317 39.861073 39.861074V114.887805H774.743415c43.657366 0 79.722146 34.166634 77.824 74.027707v761.056781c0 39.861073-36.06478 74.027707-79.722147 74.027707H250.855024c-43.657366 0-79.722146-32.268488-79.722146-74.027707V188.915512c0-39.861073 36.06478-74.027707 79.722146-74.027707h110.092488z m149.853659 269.836488l-106.296195 170.83317c-7.592585 11.388878 1.898146 26.574049 17.083317 26.574049h70.231414l-13.287024 140.462829c-1.898146 18.981463 26.574049 28.472195 36.06478 11.388879l106.296196-170.833171c7.592585-11.388878-1.898146-26.574049-17.083318-26.574049h-70.231414l13.287024-140.462829c1.898146-18.981463-26.574049-28.472195-36.06478-11.388878z" p-id="20289"></path></svg>

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
src/assets/icons/svg/engineRoom.svg


+ 1 - 0
src/assets/icons/svg/fengsu.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M835.284 510.744c88.957-50.421 119.131-162.623 67.39-250.608-51.741-87.987-165.798-118.442-254.758-68.021-72.964 41.357-50.185 147.807-94.521 248.144 18.976-76.923-7.179-186.369-42.874-249.347-50.423-88.957-162.623-119.131-250.613-67.392-87.985 51.741-118.439 165.8-68.016 254.76 41.353 72.961 147.796 50.187 248.127 94.516-76.921-18.968-186.357 7.187-249.33 42.879-88.96 50.421-119.131 162.625-67.392 250.611 51.739 87.987 165.8 118.442 254.758 68.019 72.932-41.337 50.207-147.714 94.464-248.011-18.897 76.922 7.261 186.279 42.93 249.214 50.423 88.96 162.626 119.133 250.611 67.394 87.99-51.741 118.442-165.8 68.019-254.76-41.338-72.935-147.722-50.203-248.023-94.469 76.922 18.903 186.289-7.254 249.228-42.929z m-322.295 71.587c-38.175 0-69.122-30.945-69.122-69.12s30.947-69.12 69.122-69.12c38.173 0 69.12 30.945 69.12 69.12s-30.948 69.12-69.12 69.12z"  /></svg>

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
src/assets/icons/svg/fengsufengxiangyi.svg


Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 0
src/assets/icons/svg/inclination.svg


+ 1 - 0
src/assets/icons/svg/jiayouzhan.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M990.8224 231.2192l-77.1072-72.0896c-5.12-6.4512-13.1072-10.1376-21.9136-10.1376-8.704 0-17.3056 3.584-23.6544 9.9328-13.312 13.312-13.312 32.0512 0.1024 45.4656l77.4144 72.4992c8.8064 6.656 14.1312 18.1248 14.1312 30.72v466.2272c0 22.528-17.7152 40.2432-40.2432 40.2432-21.4016 0-40.2432-18.8416-40.2432-40.2432V457.216c0-60.3136-50.176-109.3632-111.8208-109.3632h-15.36V158.0032c0-74.0352-60.2112-134.2464-134.2464-134.2464H208.9984C135.0656 23.7568 74.752 83.968 74.752 158.0032V946.176H32.0512C13.2096 946.176 0 957.3376 0 973.2096s13.2096 27.0336 32.0512 27.0336h912.4864c18.8416 0 32.0512-11.1616 32.0512-27.0336 0-15.9744-13.2096-27.0336-32.0512-27.0336H752.128V411.9552h15.36c23.6544 0 45.2608 21.6064 45.2608 45.2608v314.1632c0 57.5488 47.9232 104.3456 106.8032 104.3456 29.5936 0 57.9584-11.9808 77.824-32.768 18.2272-19.0464 27.648-43.6224 26.4192-69.12V310.0672c0.1024-29.4912-11.5712-57.5488-32.9728-78.848zM208.9984 87.7568h408.8832c38.7072 0 70.144 31.5392 70.144 70.144v778.24H138.8544v-778.24c0-38.6048 31.5392-70.144 70.144-70.144zM527.2576 168.5504H299.7248c-52.736 0-95.6416 42.9056-95.6416 95.6416v62.6688c0 52.736 42.9056 95.6416 95.6416 95.6416h227.5328c52.736 0 95.6416-42.9056 95.6416-95.6416V264.192c0-52.8384-42.9056-95.6416-95.6416-95.6416z m31.8464 158.208c0 17.6128-14.336 31.8464-31.8464 31.8464H299.7248c-17.6128 0-31.8464-14.336-31.8464-31.8464V264.192c0-17.6128 14.336-31.8464 31.8464-31.8464h227.5328c17.6128 0 31.8464 14.336 31.8464 31.8464v62.5664z" /></svg>

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
src/assets/icons/svg/jiayouzhan_1.svg


+ 1 - 0
src/assets/icons/svg/route.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1719210370252" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13922" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M170.666667 293.546667h102.4v-68.266667H170.666667v68.266667z m204.8-68.266667v68.266667H853.333333v-68.266667H375.466667zM170.666667 532.48h102.4v-68.266667H170.666667v68.266667z m204.8 0H853.333333v-68.266667H375.466667v68.266667zM170.666667 771.413333h102.4v-68.266666H170.666667v68.266666z m204.8 0H853.333333v-68.266666H375.466667v68.266666z" p-id="13923"></path></svg>

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
src/assets/icons/svg/routePoints.svg


+ 1 - 0
src/assets/icons/svg/threeArrows.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1717471669709" class="icon" viewBox="0 0 1499 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20641" xmlns:xlink="http://www.w3.org/1999/xlink" width="292.7734375" height="200"><path d="M1470.171429 477.257143L1018.514286 25.6c-18.285714-18.285714-47.542857-18.285714-69.485715 0-18.285714 18.285714-18.285714 53.028571 0 69.485714L1364.114286 512 949.028571 927.085714c-18.285714 18.285714-18.285714 47.542857 0 69.485715 18.285714 18.285714 47.542857 18.285714 69.485715 0l449.828571-449.828572c10.971429-10.971429 18.285714-23.771429 10.971429-34.742857 7.314286-10.971429 1.828571-29.257143-9.142857-34.742857z" fill="#666666" opacity=".2" p-id="20642"></path><path d="M1031.314286 512c0-10.971429-5.485714-29.257143-10.971429-34.742857L568.685714 25.6c-18.285714-18.285714-47.542857-18.285714-69.485714 0-18.285714 18.285714-18.285714 53.028571 0 69.485714L914.285714 512 497.371429 927.085714c-18.285714 18.285714-18.285714 47.542857 0 69.485715 18.285714 18.285714 53.028571 18.285714 69.485714 0l449.828571-449.828572c7.314286-5.485714 14.628571-23.771429 14.628572-34.742857z" fill="#666666" opacity=".5" p-id="20643"></path><path d="M568.685714 512c0-10.971429-5.485714-29.257143-10.971428-34.742857L106.057143 25.6c-18.285714-18.285714-47.542857-18.285714-69.485714 0-18.285714 18.285714-18.285714 47.542857 0 71.314286L457.142857 512 42.057143 927.085714c-18.285714 18.285714-18.285714 47.542857 0 69.485715 18.285714 18.285714 53.028571 18.285714 69.485714 0l449.828572-449.828572c1.828571-5.485714 7.314286-23.771429 7.314285-34.742857z" fill="#666666" p-id="20644"></path></svg>

BIN
src/assets/images/20240529135050.png


BIN
src/assets/images/bigModa.png


BIN
src/assets/images/bigscree.png


BIN
src/assets/images/bigship_yh.png


BIN
src/assets/images/diancBg-black.png


BIN
src/assets/images/diancBg.png


BIN
src/assets/images/finish-icon.png


BIN
src/assets/images/gps.png


BIN
src/assets/images/icon.png


BIN
src/assets/images/login-background.jpg


BIN
src/assets/images/maozi.png


BIN
src/assets/images/maozi_no.png


BIN
src/assets/images/map-end.png


BIN
src/assets/images/map-start.png


BIN
src/assets/images/mask.jpg


BIN
src/assets/images/mask.png


BIN
src/assets/images/minscreen.png


BIN
src/assets/images/money-icon.png


BIN
src/assets/images/novideo.png


BIN
src/assets/images/offline.png


BIN
src/assets/images/oldbigship.png


BIN
src/assets/images/online.png


BIN
src/assets/images/profile.jpg


BIN
src/assets/images/psc.jfif


BIN
src/assets/images/ship-icon.png


BIN
src/assets/images/ship.png


BIN
src/assets/images/shipWhei.png


BIN
src/assets/images/ship_tblr.png


BIN
src/assets/images/ship_tblr_yh.png


BIN
src/assets/images/shipnum.png


BIN
src/assets/images/shipnumbg.png


BIN
src/assets/images/speed-bigship.png


BIN
src/assets/images/speed-ship.png


BIN
src/assets/images/stop-icon.png


BIN
src/assets/images/tabbg.png


BIN
src/assets/images/tabcenter.png


BIN
src/assets/images/tableft.png


BIN
src/assets/images/tabright.png


BIN
src/assets/images/time-icon.png


BIN
src/assets/images/warn-bigship.png


BIN
src/assets/images/warn-ship.png


BIN
src/assets/images/yhTitle.png


BIN
src/assets/logo/logo.jpg


BIN
src/assets/logo/logo.png


+ 252 - 0
src/assets/styles/login.css

@@ -0,0 +1,252 @@
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2) format('woff2');
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2) format('woff2');
+  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2) format('woff2');
+  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2) format('woff2');
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2) format('woff2');
+  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2) format('woff2');
+  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCRc4EsA.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fABc4EsA.woff2) format('woff2');
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCBc4EsA.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBxc4EsA.woff2) format('woff2');
+  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCxc4EsA.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fChc4EsA.woff2) format('woff2');
+  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBBc4.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2) format('woff2');
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2) format('woff2');
+  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2) format('woff2');
+  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}

+ 74 - 1
src/assets/styles/main.scss

@@ -15,6 +15,7 @@ page {
   --yellow: #e6a23c;
   --olive: #8dc63f;
   --green: #42b983;
+  --ngreen: #04e087;
   /* --green: #67c23a; */
   --cyan: #1cbbb4;
   --blue: #409eff;
@@ -4193,7 +4194,11 @@ scroll-view.ui-steps .ui-item {
 .lines-green {
   color: var(--green);
 }
-
+.text-ngreen,
+.line-ngreen,
+.lines-ngreen {
+  color: var(--ngreen);
+}
 .text-cyan,
 .line-cyan,
 .lines-cyan {
@@ -4283,3 +4288,71 @@ scroll-view.ui-steps .ui-item {
 #app.mobile{
   overflow-y: scroll;
 }
+.box-card.cardSty{
+	background-color: #092a45;
+	color:#fff;
+	border:2px solid #2f516c;
+}
+.box-card.blueCard{
+	background-color: #1768a3;
+	border-radius: 14px;
+	border:2px solid rgba(47,81,108,0.5);
+}
+.inblock{
+  display: inline-block;
+}
+.sTitleSty{
+	position: absolute;
+	// top: 50%;
+	left: 0;
+	height: 100%;
+	text-align: center;
+	color: #fff;
+	font-size: 0.9rem;
+	font-weight: bold;
+	// transform: translate(0, -50%);
+	writing-mode: vertical-rl;
+	letter-spacing: 6px;
+}
+.selfBtn{
+	font-size: 0.75rem;
+	padding: 5px 10px;
+	margin: 12% 0 10px;
+	border-radius: 4px;
+	font-weight: normal;
+	cursor: pointer;
+	background-color: #fff;
+	box-shadow: 0 0 8px 1px #ccc;
+	&.active{
+		background-color: #3b9a9c;
+		color: #fff;
+	}
+}
+.reportSty{
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	text-align: center;
+	border-radius: 10px;
+	height: calc(20vh - 60px);
+	width: calc(20vh - 60px);
+	background: linear-gradient(to bottom, #d369ee 40%, #74c4fe);
+	&>div{
+		position: relative;
+		height: 50%;
+		width: 50%;
+		border-radius: 50%;
+		font-size: 2rem;
+		background-color: #fff;
+		span{
+			position: absolute;
+			top: 50%;
+			left: 50%;
+			font-weight: bold;
+			transform: translate(-50%, -50%);
+			background: linear-gradient(to bottom, #d369ee, #74c4fe);
+			-webkit-background-clip: text;
+			color: transparent;
+		}
+	}
+}

+ 219 - 0
src/components/AlarmSetting/index.vue

@@ -0,0 +1,219 @@
+<template>
+	<div>
+		<el-drawer v-model="open" 
+			:title="`设备报警设置`" 
+			:before-close="handleClose" 
+			direction="rtl" 
+			class="demo-drawer"
+			modal-class="el-subscribe-drawer" 
+			size="50%">
+			<div class="margin-bottom-xs flex justify-between">
+				<el-button type="success" @click="handleNew">新增一行</el-button>
+				<div>
+					<el-button plain @click="handleClose">取 消</el-button>
+					<el-button :disabled="disabled" type="primary" @click="submitForm">提 交</el-button>
+				</div>
+			</div>
+			<el-form ref="formAlarmRefs" :rules="rules" :model="formAlarm">
+				<el-table :data="formAlarm.tableData" border>
+					<el-table-column label="序号" align="center" type="index" width="80" />
+					<el-table-column label="设备名称" align="center" prop="deviceName">
+						<template #default="scope">
+							<el-form-item :prop="`tableData.${scope.$index}.deviceName`" :rules="rules.deviceName" style="margin: 0;">
+								<span v-if="scope.row.alarmSetId">{{scope.row.deviceName}}</span>
+								<el-input v-else type="text" v-model="scope.row.deviceName" placeholder="输入设备名称"/>
+							</el-form-item>
+						</template>
+					</el-table-column>
+					<el-table-column label="内容" align="center" prop="content">
+						<template #default="scope">
+							<el-form-item :prop="`tableData.${scope.$index}.content`" :rules="rules.content" style="margin: 0;">
+								<span v-if="scope.row.alarmSetId">{{scope.row.content}}</span>
+								<el-input v-else type="text" v-model="scope.row.content" placeholder="输入内容"/>
+							</el-form-item>
+						</template>
+					</el-table-column>
+					<el-table-column label="最小值" align="center" prop="minValue">
+						<template #default="scope">
+							<el-form-item :prop="`tableData.${scope.$index}.minValue`" :rules="rules.minValue" style="margin: 0;">
+								<span v-if="scope.row.alarmSetId">{{scope.row.minValue}}</span>
+								<el-input v-else type="number" v-model="scope.row.minValue" placeholder="输入最小值"/>
+							</el-form-item>
+						</template>
+					</el-table-column>
+					<el-table-column label="最大值" align="center" prop="maxValue">
+						<template #default="scope">
+							<el-form-item :prop="`tableData.${scope.$index}.maxValue`" :rules="rules.maxValue" style="margin: 0;">
+								<span v-if="scope.row.alarmSetId">{{scope.row.maxValue}}</span>
+								<el-input v-else type="number" v-model="scope.row.maxValue" placeholder="输入最大值"/>
+							</el-form-item>
+						</template>
+					</el-table-column>
+					<el-table-column label="报警值" align="center" prop="alarmValue">
+						<template #default="scope">
+							<el-form-item :prop="`tableData.${scope.$index}.alarmValue`" :rules="rules.alarmValue" style="margin: 0;">
+								<span v-if="scope.row.alarmSetId">{{scope.row.alarmValue}}</span>
+								<el-input v-else type="number" v-model="scope.row.alarmValue" placeholder="输入报警值"/>
+							</el-form-item>
+						</template>
+					</el-table-column>
+					<el-table-column width="80" align="center">
+						<template #default="scope">
+							<div v-if="scope.row.alarmSetId">
+								<elIcon class="margin-right-sm" @click="handleEdit(scope.row)"><Edit class="text-green pointer"/></elIcon>
+								<elIcon @click="handleDelete(scope.row)"><Delete class="text-red pointer"/></elIcon>
+							</div>
+							<elIcon v-else @click="handleDel(scope.$index)"><Remove class="text-red pointer"/></elIcon>
+						</template>
+					</el-table-column>
+				</el-table>
+			</el-form>
+		</el-drawer>
+		<el-dialog
+		  title="修改报警设置数据"
+		  v-model="dialogVisible"
+		  width="30%">
+			<el-form ref="alarmFormRef" :rules="rules" :model="alarmForm" label-width="100px">
+				<el-form-item prop="deviceName" label="设备名称:">
+					<el-input type="text" v-model="alarmForm.deviceName" placeholder="输入设备名称"/>
+				</el-form-item>
+				<el-form-item prop="content" label="内容:">
+					<el-input type="text" v-model="alarmForm.content" placeholder="输入内容"/>
+				</el-form-item>
+				<el-form-item prop="minValue" label="最小值:">
+					<el-input type="number" v-model="alarmForm.minValue" placeholder="输入最小值"/>
+				</el-form-item>
+				<el-form-item prop="maxValue" label="最大值:">
+					<el-input type="number" v-model="alarmForm.maxValue" placeholder="输入最大值"/>
+				</el-form-item>
+				<el-form-item prop="alarmValue" label="报警值:">
+					<el-input type="number" v-model="alarmForm.alarmValue" placeholder="输入报警值"/>
+				</el-form-item>
+				<el-form-item label="">
+					<el-button @click="dialogVisible = false">取 消</el-button>
+					<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
+				</el-form-item>
+			</el-form>
+		</el-dialog>
+	</div>
+</template>
+
+<script setup>
+	const { proxy } = getCurrentInstance();
+	const open = ref(false);
+	const dialogVisible = ref(false);
+	const disabled = ref(true);
+	const data = reactive({
+		formAlarm: {
+			tableData: []
+		},
+		alarmForm: {},
+		rules: {
+			deviceName: [{
+				required: true,
+				message: "请输入设备名称",
+				trigger: "blur"
+			}],
+			content: [{
+				required: true,
+				message: "请输入内容",
+				trigger: "blur"
+			}],
+			maxValue: [{
+				required: true,
+				message: "请输入最大值",
+				trigger: "blur"
+			}],
+			minValue: [{
+				required: true,
+				message: "请输入最小值",
+				trigger: "blur"
+			}],
+			alarmValue: [{
+				required: true,
+				message: "请输入报警值",
+				trigger: "blur"
+			}]
+		}
+	})
+	
+	const { formAlarm, alarmForm, rules } = toRefs(data);
+	// 显示弹框
+	function show() {
+		open.value = true;
+		formAlarm.value.tableData = [{
+			alarmSetId: 124,
+			deviceName: "主机转速",
+			content: "主机转速过高",
+			maxValue: 3000,
+			minValue: 0,
+			alarmValue: 2500
+		}]
+	}
+	// 关闭按钮
+	function handleClose() {
+		formAlarm.value = {
+			tableData: []
+		}
+		open.value = false;
+		// emit("close");
+	}
+	/** 提交按钮 */
+	function submitForm() {
+		proxy.$refs["formAlarmRef"].validate(valid => {
+			if (valid) {
+				
+			}
+		})
+	}
+	// 新增一条数据
+	function handleNew(){
+		let _data = { 
+			deviceName: "",
+			content: "",
+			maxValue: 0,
+			minValue: 0,
+			alarmValue: 0
+		};
+		formAlarm.value.tableData.push(_data);
+	}
+	// 移除一条新增的数据
+	function handleDel(index){
+		formAlarm.value.tableData.splice(index, 1);
+	}
+	// 表单重置
+	function reset() {
+	    alarmForm.value = {
+			deviceName: null,
+			content: null,
+			maxValue: 0,
+			minValue: 0,
+			alarmValue: 0
+	    };
+	    proxy.resetForm("alarmFormRef");
+	}
+	// 编辑数据库里的数据
+	function handleEdit(row) {
+		reset();
+	    // getMaintenanceApply(maintenanceApplyId).then(response => {
+	        alarmForm.value = JSON.parse(JSON.stringify(row));
+	        dialogVisible.value = true;
+	    // });
+	}
+	// 删除数据库里的数据
+	function handleDelete(_row){
+		proxy.$modal.confirm('是否确认删除该报警设置数据"' + _row.deviceName + '"的数据项?').then(function () {
+		    // return delMaintenanceApply(_row.regionalId);
+		}).then(() => {
+		    // getList();
+		    proxy.$modal.msgSuccess("删除成功");
+		}).catch(() => { });
+	}
+	defineExpose({
+		show,
+		handleClose,
+	});
+</script>
+
+<style>
+</style>

+ 181 - 0
src/components/EcaRegional/index.vue

@@ -0,0 +1,181 @@
+<template>
+	<div>
+		<el-drawer v-model="open" 
+			:title="`添加ECA区域数据`" 
+			:before-close="handleClose" 
+			direction="rtl" 
+			class="demo-drawer"
+			modal-class="el-subscribe-drawer" 
+			size="50%">
+			<div class="margin-bottom-xs flex justify-between">
+				<el-button type="success" @click="handleNew">新增一行</el-button>
+				<div>
+					<el-button plain @click="handleClose">取 消</el-button>
+					<el-button :disabled="disabled" type="primary" @click="submitForm">提 交</el-button>
+				</div>
+			</div>
+			<el-form ref="formRegionalRefs" :rules="rules" :model="formRegional">
+				<el-table :data="formRegional.tableData" border>
+					<el-table-column label="序号" align="center" type="index" width="80" />
+					<el-table-column label="名称" align="center" prop="regionalName">
+						<template #default="scope">
+							<el-form-item :prop="`tableData.${scope.$index}.regionalName`" :rules="rules.regionalName" style="margin: 0;">
+								<span v-if="scope.row.regionalId">{{scope.row.regionalName}}</span>
+								<el-input v-else type="text" v-model="scope.row.regionalName" placeholder="输入名称"/>
+							</el-form-item>
+						</template>
+					</el-table-column>
+					<el-table-column label="经度" align="center" prop="longitude">
+						<template #default="scope">
+							<el-form-item :prop="`tableData.${scope.$index}.longitude`" :rules="rules.longitude" style="margin: 0;">
+								<span v-if="scope.row.regionalId">{{scope.row.longitude}}</span>
+								<el-input v-else type="text" v-model="scope.row.longitude" placeholder="输入经度"/>
+							</el-form-item>
+						</template>
+					</el-table-column>
+					<el-table-column label="纬度" align="center" prop="latitude">
+						<template #default="scope">
+							<el-form-item :prop="`tableData.${scope.$index}.latitude`" :rules="rules.latitude" style="margin: 0;">
+								<span v-if="scope.row.regionalId">{{scope.row.latitude}}</span>
+								<el-input v-else type="text" v-model="scope.row.latitude" placeholder="输入纬度"/>
+							</el-form-item>
+						</template>
+					</el-table-column>
+					<el-table-column align="center">
+						<template #default="scope">
+							<div v-if="scope.row.regionalId">
+								<elIcon class="margin-right-sm" @click="handleEdit(scope.row)"><Edit class="text-green pointer"/></elIcon>
+								<elIcon @click="handleDelete(scope.row)"><Delete class="text-red pointer"/></elIcon>
+							</div>
+							<elIcon v-else @click="handleDel(scope.$index)"><Remove class="text-red pointer"/></elIcon>
+						</template>
+					</el-table-column>
+				</el-table>
+			</el-form>
+		</el-drawer>
+		<el-dialog
+		  title="修改区域数据"
+		  v-model="dialogVisible"
+		  width="30%">
+			<el-form ref="regionalFormRef" :rules="rules" :model="regionalForm" label-width="100px">
+				<el-form-item prop="regionalName" label="名称:">
+					<el-input type="text" v-model="regionalForm.regionalName" placeholder="输入名称"/>
+				</el-form-item>
+				<el-form-item prop="longitude" label="经度:">
+					<el-input type="text" v-model="regionalForm.longitude" placeholder="输入经度"/>
+				</el-form-item>
+				<el-form-item prop="latitude" label="纬度:">
+					<el-input type="text" v-model="regionalForm.latitude" placeholder="输入纬度"/>
+				</el-form-item>
+				<el-form-item label="">
+					<el-button @click="dialogVisible = false">取 消</el-button>
+					<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
+				</el-form-item>
+			</el-form>
+		</el-dialog>
+	</div>
+</template>
+
+<script setup>
+	const { proxy } = getCurrentInstance();
+	const open = ref(false);
+	const dialogVisible = ref(false);
+	const disabled = ref(true);
+	const data = reactive({
+		formRegional: {
+			tableData: []
+		},
+		regionalForm: {},
+		rules: {
+			regionalName: [{
+				required: true,
+				message: "请输入名称",
+				trigger: "blur"
+			}],
+			longitude: [{
+				required: true,
+				message: "请输入经度",
+				trigger: "blur"
+			}],
+			latitude: [{
+				required: true,
+				message: "请输入纬度",
+				trigger: "blur"
+			}]
+		}
+	})
+	
+	const { formRegional, regionalForm, rules } = toRefs(data);
+	// 显示弹框
+	function show() {
+		open.value = true;
+		formRegional.value.tableData = [{
+			regionalId: 126,
+			regionalName: "加油记录-1",
+			longitude: "113.23656",
+			latitude: "23.64589"
+		}];
+	}
+	// 关闭按钮
+	function handleClose() {
+		formRegional.value = {
+			tableData: []
+		}
+		open.value = false;
+		// emit("close");
+	}
+	/** 提交按钮 */
+	function submitForm() {
+		proxy.$refs["formRegionalRef"].validate(valid => {
+			if (valid) {
+				
+			}
+		})
+	}
+	// 新增一条数据
+	function handleNew(){
+		let _data = { 
+			regionalName: "",
+			longitude: 0,
+			latitude: 0
+		};
+		formRegional.value.tableData.push(_data);
+	}
+	// 移除一条新增的数据
+	function handleDel(index){
+		formRegional.value.tableData.splice(index, 1);
+	}
+	// 表单重置
+	function reset() {
+	    regionalForm.value = {
+			regionalName: null,
+			longitude: null,
+			latitude: null
+	    };
+	    proxy.resetForm("regionalFormRef");
+	}
+	// 编辑数据库里的数据
+	function handleEdit(row) {
+		reset();
+	    // getMaintenanceApply(maintenanceApplyId).then(response => {
+	        regionalForm.value = JSON.parse(JSON.stringify(row));
+	        dialogVisible.value = true;
+	    // });
+	}
+	// 删除数据库里的数据
+	function handleDelete(_row){
+		proxy.$modal.confirm('是否确认删除该ECA区域数据"' + _row.regionalName + '"的数据项?').then(function () {
+		    // return delMaintenanceApply(_row.regionalId);
+		}).then(() => {
+		    // getList();
+		    proxy.$modal.msgSuccess("删除成功");
+		}).catch(() => { });
+	}
+	defineExpose({
+		show,
+		handleClose,
+	});
+</script>
+
+<style>
+</style>

+ 123 - 0
src/components/Echarts/BarChart/index.vue

@@ -0,0 +1,123 @@
+<template>
+	<div>
+		<div :class="name" :style="{ 'height': height }" />
+	</div>
+</template>
+
+<script setup>
+	import * as echarts from "echarts";
+	import useResize from "@/hooks/useResize";
+	const { proxy } = getCurrentInstance();
+	var echartInstance = null;
+	const props = defineProps({
+		height: {
+			type: String,
+			default: '100%'
+		},
+		name: {
+			type: String,
+			default: 'echart'
+		},
+		data: {
+		  type: Object,
+		  default: () => {
+		    return {
+				name: "",
+				xAxis: [],
+				data: [],
+				unit: ""
+		    }
+		  }
+		}
+	});
+	const { height, name, data } = toRefs(props);
+	watch(data, (newValue) => {
+			if(echartInstance != null){
+				echartInstance.setOption(getOption(newValue));
+			}
+		},{
+			deep: true
+		},
+	);
+	const getOption = function(_data){
+		let option = {
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'cross',
+				},
+				textStyle:{
+					fontSize: 10
+				}
+			},
+			legend: {
+				show: true,
+				bottom: '1%',
+				itemWidth: 22,
+				itemHeight: 10,
+				textStyle: {
+					 color: "#000",
+					 fontSize: 10
+				}
+			},
+			color: ['#0493ee', '#3ee5fd', '#ee6666', '#fac858', '#fc8452'],
+			grid: {
+				top: '6%',
+				left: _data.name.length?'40':'2%',
+				right: '2%',
+				bottom: '16%',
+				containLabel: true
+			},
+			xAxis: {
+				type: 'category',
+				axisLabel: {
+					color: '#000',
+					fontSize: 10,
+					showMaxLabel: true
+				},
+				data:  _data.xAxis
+			},
+			yAxis: {
+				type: 'value',
+				axisLabel: {
+					fontSize: 10,
+					color:"#000",
+					showMaxLabel: true
+				},
+				axisLine: {
+					show: false,
+					lineStyle: {
+						color: ['#fff']
+					}
+				},
+				splitLine: {
+					show: true,
+					lineStyle: {
+						color: ['#d9d9d9'],
+						type: "dashed"
+					}
+				}
+			},
+			series: _data.data
+		};
+		return option;
+	};
+	onMounted(() => {
+		nextTick(()=>{
+			echartInstance = echarts.init(document.getElementsByClassName(name.value)[0]);
+			echartInstance.setOption(getOption(data.value));
+			echartInstance.resize();
+		})
+	})
+	function resize() {
+		echartInstance.resize();
+	}
+	// 暴露函数 (供hook调用)
+	defineExpose({
+	  resize,
+	});
+	useResize();
+</script>
+
+<style lang='scss' scoped>
+</style>

+ 125 - 0
src/components/Echarts/LineChart/index.vue

@@ -0,0 +1,125 @@
+<template>
+	<div>
+		<div :class="name" :style="{ 'height': height }" />
+	</div>
+</template>
+
+<script setup>
+	import * as echarts from "echarts";
+	import useResize from "@/hooks/useResize";
+	const { proxy } = getCurrentInstance();
+	var echartInstance = null;
+	const props = defineProps({
+		height: {
+			type: String,
+			default: '100%'
+		},
+		name: {
+			type: String,
+			default: 'echart'
+		},
+		data: {
+		  type: Object,
+		  default: () => {
+		    return {
+				name: "",
+				xAxis: [],
+				data: [],
+				unit: ""
+		    }
+		  }
+		}
+	});
+	const { height, name, data } = toRefs(props);
+	watch(data, (newValue) => {
+			if(echartInstance != null){
+				echartInstance.setOption(getOption(newValue));
+			}
+		},{
+			deep: true
+		},
+	);
+	const getOption = function(_data){
+		let option = {
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'cross',
+				},
+				textStyle:{
+					fontSize: 11
+				}
+			},
+			legend: {
+				show: true,
+				bottom: '1%',
+				itemWidth: 22,
+				itemHeight: 10,
+				textStyle: {
+					 color: "#fff",
+					 fontSize: 11
+				}
+			},
+			color: ['#0493ee', '#3ee5fd', '#ee6666', '#fac858', '#fc8452'],
+			grid: {
+				top: '6%',
+				left: _data.name.length?'40':'2%',
+				right: '2%',
+				bottom: '16%',
+				containLabel: true
+			},
+			xAxis: {
+				type: 'category',
+				boundaryGap: false, //X轴贴边false不贴边true
+				axisLabel: {
+					color: '#fff',
+					fontSize: 11,
+					showMaxLabel: true
+				},
+				data:  _data.xAxis
+			},
+			yAxis: {
+				// name: "(" + _data.unit + ")",
+				type: 'value',
+				axisLabel: {
+					fontSize: 11,
+					color:"#fff",
+					showMaxLabel: true
+				},
+				axisLine: {
+					show: false,
+					lineStyle: {
+						color: ['#fff']
+					}
+				},
+				splitLine: {
+					show: true,
+					lineStyle: {
+						color: ['#368e8f'],
+						type: "dashed"
+					}
+				}
+			},
+			series: _data.data
+		};
+		return option;
+	};
+	onMounted(() => {
+		nextTick(()=>{
+			echartInstance = echarts.init(document.getElementsByClassName(name.value)[0]);
+			echartInstance.setOption(getOption(data.value));
+			echartInstance.resize();
+		})
+	})
+	function resize() {
+		echartInstance.resize();
+	}
+	// 暴露函数 (供hook调用)
+	defineExpose({
+	  resize,
+	});
+	useResize();
+</script>
+
+<style lang='scss' scoped>
+</style>

+ 124 - 0
src/components/Echarts/annularChart/index.vue

@@ -0,0 +1,124 @@
+<template>
+	<div>
+		<div :class="name" :style="{ 'height': height }" />
+	</div>
+</template>
+
+<script setup>
+	import * as echarts from "echarts";
+	import useResize from "@/hooks/useResize";
+	const {
+		proxy
+	} = getCurrentInstance();
+	var echartInstance = null;
+	const props = defineProps({
+		height: {
+			type: String,
+			default: '100%'
+		},
+		name: {
+			type: String,
+			default: 'echart'
+		},
+		data: {
+			type: Object,
+			default: {
+				title: "重油总量",
+				name: "heavyOil",
+				value: 85.36,
+				unit: "L"
+			}
+		}
+	});
+	const {
+		height,
+		name,
+		data
+	} = toRefs(props);
+	watch(data, (newValue) => {
+		if (echartInstance != null) {
+			echartInstance.setOption(getOption(newValue));
+		}
+	}, {
+		deep: true
+	});
+	const getOption = function(_data) {
+		let option = {
+			series: [{
+				type: 'gauge',
+				axisShadow: true,
+				startAngle: 90,
+				endAngle: -270,
+				pointer: {
+					show: false
+				},
+				progress: {
+					show: true,
+					overlap: false,
+					roundCap: true,
+					clip: false,
+					itemStyle: {
+						shadowColor: 'rgba(255, 162, 81, 0.8)',
+						shadowBlur: 10,
+						color: new echarts.graphic.LinearGradient(
+							0, 0, 1, 0,
+							[{
+								offset: 0,
+								color: '#ffa251'
+							},
+							{
+								offset: 1,
+								color: '#ff7c7c'
+							}]
+						)
+					}
+				},
+				axisLine: {
+					lineStyle: {
+						width: 16,
+						shadowColor: 'rgba(219, 229, 245, 0.8)',
+						shadowBlur: 10,
+						color: [[1, "#dde7f6"]]
+					}
+				},
+				splitLine: {
+					show: false
+				},
+				axisTick: {
+					show: false
+				},
+				axisLabel: {
+					show: false
+				},
+				title: {
+					show: false
+				},
+				detail: {
+					fontSize: (data.value.value+"").length>6?16:((data.value.value+"").length>4?20:26),
+					offsetCenter: ['0%', '4%']
+				},
+				data: [data.value]
+			}]
+		};
+		return option;
+	};
+	onMounted(() => {
+		nextTick(() => {
+			echartInstance = echarts.init(document.getElementsByClassName(name.value)[0]);
+			echartInstance.setOption(getOption(data.value));
+			echartInstance.resize();
+		})
+	})
+
+	function resize() {
+		echartInstance.resize();
+	}
+	// 暴露函数 (供hook调用)
+	defineExpose({
+		resize,
+	});
+	useResize();
+</script>
+
+<style lang='scss' scoped>
+</style>

+ 3 - 3
src/components/Echarts/barDataColor/index.vue

@@ -16,9 +16,9 @@ const props = defineProps({
   data: {
     type: Array,
     default: [
-      { value: 0, name: "data 1" },
-      { value: 0, name: "data 2" },
-      { value: 0, name: "data 3" },
+      { data: 10, name: "data 1" },
+      { value: 30, name: "data 2" },
+      { value: 40, name: "data 3" },
     ],
   },
   // 高度

+ 143 - 0
src/components/Echarts/gaugeChart/index.vue

@@ -0,0 +1,143 @@
+<template>
+	<div>
+		<div :class="name" :style="{ 'height': height }" />
+	</div>
+</template>
+
+<script setup>
+	import * as echarts from "echarts";
+	import useResize from "@/hooks/useResize";
+	const {
+		proxy
+	} = getCurrentInstance();
+	var echartInstance = null;
+	const props = defineProps({
+		height: {
+			type: String,
+			default: '100%'
+		},
+		name: {
+			type: String,
+			default: 'gaugeEchart'
+		},
+		data: {
+			type: Object,
+			default: () => {
+				return {
+					name: "",
+					value: 0,
+					min: 0,
+					max: 100,
+					unit: "KN*m"
+				}
+			}
+		}
+	});
+	const {
+		height,
+		name,
+		data
+	} = toRefs(props);
+	watch(data, (newValue) => {
+		if (echartInstance != null) {
+			echartInstance.setOption(getOption(newValue));
+		}
+	}, {
+		deep: true
+	}, );
+	const getOption = function(_data) {
+		let option = {
+			series: [{
+				type: 'gauge',
+				// splitNumber: 12,
+				min: data.value.min,
+				max: data.value.max,
+				radius: '95%',
+				progress: {
+					show: true,
+					width: 8,
+					color: "#fff"
+				},
+				itemStyle: {
+				    color: '#009dff',
+				},
+				pointer: {
+					length: '45%',
+					width: 3,
+				},
+				axisLine: {
+					lineStyle: {
+						width: 8
+					}
+				},
+				axisTick: {
+					distance: 1,
+					lineStyle: {
+						width: 1,
+						color: '#999'
+					}
+				},
+				splitLine: {
+					length: 10,
+					distance: 1,
+					lineStyle: {
+						width: 1,
+						color: '#999'
+					}
+				},
+				axisLabel: {
+					distance: 8,
+					color: '#fff',
+					fontSize: 8
+				},
+				title: {
+					show: false
+				},
+				detail: {
+					valueAnimation: true,
+					fontSize: 20,
+					offsetCenter: [0, '92%'],
+					color: 'inherit',
+					formatter: function (value) {
+						return '{value|' + data.value.value + '}{unit|' + data.value.unit + '}';
+					},
+					rich: {
+						value: {
+							fontSize: 20,
+							fontWeight: 'bolder',
+							color: '#04e088'
+						},
+						unit: {
+							fontSize: 12,
+							color: '#04e088',
+							padding: [0, 0, 0, 5]
+						}
+					}
+				},
+				data: [{
+					value: data.value.value
+				}]
+			}]
+		};
+		return option;
+	};
+	onMounted(() => {
+		nextTick(() => {
+			echartInstance = echarts.init(document.getElementsByClassName(name.value)[0]);
+			echartInstance.setOption(getOption(data.value));
+			echartInstance.resize();
+		})
+	})
+
+	function resize() {
+		echartInstance.resize();
+	}
+	// 暴露函数 (供hook调用)
+	defineExpose({
+		resize,
+	});
+	useResize();
+</script>
+
+<style lang='scss' scoped>
+</style>

+ 0 - 116
src/components/Echarts/newChart/DashChart.vue

@@ -1,116 +0,0 @@
-<template>
-	<div>
-		<div :class="name" :style="'height:'+height+';width:'+width" style="margin: auto;" />
-	</div>
-</template>
-
-<script setup>
-	import * as echarts from 'echarts';
-	const store = useStore();
-	const { proxy } = getCurrentInstance();
-	import { reactive, ref } from '@vue/reactivity';
-	import { onMounted, onBeforeUnmount } from 'vue';
-	var eChart = null;
-	const gutter = ref(5);
-	const fontS = ref(16);
-	const props = defineProps({
-		height: {
-			type: String,
-			default: '100%'
-		},
-		width: {
-			type: String,
-			default: '100%'
-		},
-		name: {
-			type: String,
-			default: 'echart'
-		},
-		data: {
-		  type: Object,
-		  default: () => {
-		    return {
-				name: "name",
-				max: 1500,
-				value: 0
-		    }
-		  }
-		}
-	});
-	const { height, name, data } = toRefs(props);
-	watch(data, (newValue) => {
-			if(eChart != null){
-				eChart.setOption(getOption(newValue));
-				eChart.resize();
-			}
-		},{
-			deep: true
-		},
-	);
-	const getOption = function(_data){
-		let option = {
-			series: [{
-				name: '实时数据',
-				min: 0,
-				max: 1500,
-				splitNumber: 10,
-				type: 'gauge',
-				center: ['50%', '55%'],
-				radius: '90%',
-				detail: {
-					show: false,
-				},
-				data: [{
-					value: _data.value,
-				}],
-				axisLine: {
-					lineStyle: {
-						color: [
-							[0.09, 'lime'],
-							[0.82, '#1e90ff'],
-							[1, '#ff4500']
-						],
-						width: gutter.value
-					}
-				},
-				axisTick: {
-					distance: -(gutter.value*0.67),
-					length: gutter.value,
-					lineStyle: {
-						color: '#fff',
-					}
-				},
-				pointer: {
-					width: gutter.value*0.67,
-					length: "60%",
-				},
-				splitLine: {
-					distance: -(gutter.value*0.67),
-					length: gutter.value,
-					lineStyle: {
-						width: gutter.value*0.2,
-						color: '#fff',
-					}
-				},
-				axisLabel: {
-					color: '#fff',
-					fontSize: gutter.value*0.67>10?gutter.value*0.67:6,
-					distance: gutter.value
-				},
-				title: {
-					color: '#fff',
-				},
-			}]  
-		};
-		return option;
-	};
-	onMounted(() => {
-		let screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
-		gutter.value = Math.ceil(screenWidth / 320);
-		eChart = echarts.init(document.getElementsByClassName(name.value)[0]);
-		eChart.setOption(getOption({}));
-	})
-</script>
-
-<style lang='scss' scoped>
-</style>

+ 0 - 117
src/components/Echarts/newChart/GaugeChart.vue

@@ -1,117 +0,0 @@
-<template>
-	<div>
-		<div :class="name" :style="'height:'+height+';width:'+width" style="margin: auto;" />
-	</div>
-</template>
-
-<script setup>
-	import * as echarts from 'echarts';
-	const store = useStore();
-	const { proxy } = getCurrentInstance();
-	import { reactive, ref } from '@vue/reactivity';
-	import { onMounted, onBeforeUnmount,nextTick } from 'vue';
-	var eChart;
-	const gutter = ref(5);
-	const props = defineProps({
-		height: {
-			type: String,
-			default: '100%'
-		},
-		width: {
-			type: String,
-			default: '100%'
-		},
-		name: {
-			type: String,
-			default: 'echart'
-		},
-		data: {
-		  type: Object,
-		  default: () => {
-		    return {
-				name:"name",
-				data:[{name: "", value: 0},
-					 {name: "", value: 0},
-					 {name: "", value: 0},
-					 {name: "", value: 0},
-					 {name: "", value: 0}]
-		    }
-		  }
-		}
-	});
-	const { height, name, data } = toRefs(props);
-	watch(data, (newValue) => {
-			if(eChart != null){
-				eChart.setOption(getOption(newValue));
-				eChart.resize();
-			}
-		},{
-			deep: true
-		},
-	);
-	const getOption = function(_data){
-		let option = {
-			tooltip: {
-				trigger: "item",
-				formatter: "{a} <br/>{b} : {c}艘 ({d}%)",
-				textStyle:{
-					fontSize: gutter.value*1.2
-				}
-			},
-			legend: {
-				show: true,
-				itemWidth: gutter.value*0.8,
-				itemHeight: gutter.value*0.8,
-				right: '3%',
-				y: "center",
-				itemGap: gutter.value,
-				orient: 'vertical',
-				// data:Name,
-				textStyle: {
-					color: "#fff",
-					fontSize: gutter.value*0.86
-				}
-			},
-			color: ['#4f6dcd', '#fad972', '#f88582', '#3ae3bc', '#9299f3'],
-			series: [{
-			    name: _data.name,
-			    type: "pie",
-			    roseType: "radius",
-			    radius: ['50%', '60%'],
-				center: ['40%', '50%'],
-			    data: _data.data,
-			    animationEasing: "cubicInOut",
-			    animationDuration: 1000,
-				label:{  
-					normal:{
-						show:true,
-						textStyle : {
-							color:"#fff",
-							fontSize : gutter.value
-						},
-						formatter:'{d}%'
-					}
-				},
-				itemStyle: {
-					borderRadius: gutter.value*0.34,
-					borderWidth: gutter.value*0.14,
-					labelLine: {
-						show: true
-					}
-				}
-			}]
-		};
-		return option;
-	};
-	onMounted(() => {
-		let screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
-		gutter.value = Math.ceil(screenWidth / 320);
-		nextTick(()=>{
-			eChart = echarts.init(document.getElementsByClassName(name.value)[0]);
-			eChart.setOption(getOption(data.value));
-		})
-	})
-</script>
-
-<style lang='scss' scoped>
-</style>

+ 0 - 127
src/components/Echarts/newChart/LineChart.vue

@@ -1,127 +0,0 @@
-<template>
-	<div>
-		<div v-if="data.name.length" class="text-bold text-center text-blue text-sm">
-		  {{data.name}}
-		</div>
-		<div :class="name" :style="'height:'+height" style="min-width: 200px;margin: auto;" />
-	</div>
-</template>
-
-<script setup>
-	import * as echarts from 'echarts';
-	const store = useStore();
-	const { proxy } = getCurrentInstance();
-	import { reactive, ref } from '@vue/reactivity';
-	import { onMounted, onBeforeUnmount } from 'vue';
-	var eChart = null;
-	const props = defineProps({
-		height: {
-			type: String,
-			default: '100%'
-		},
-		name: {
-			type: String,
-			default: 'echart'
-		},
-		data: {
-		  type: Object,
-		  default: () => {
-		    return {
-				name: "",
-				xAxis: [],
-				value: [],
-				unit: "%"
-		    }
-		  }
-		}
-	});
-	const { height, name, data } = toRefs(props);
-	watch(data, (newValue) => {
-			if(eChart != null){
-				eChart.setOption(getOption(newValue));
-			}
-		},{
-			deep: true
-		},
-	);
-	const getOption = function(_data){
-		let option = {
-			tooltip: {
-				trigger: 'axis',
-				axisPointer: {
-					type: 'cross',
-				},
-				textStyle:{
-					fontSize: 16
-				}
-			},
-			grid: {
-				top: '14%',
-				left: '1%',
-				right: '2%',
-				bottom: '1%',
-				containLabel: true
-			},
-			xAxis: {
-				type: 'category',
-				boundaryGap: false,
-				axisLabel: {
-					color: '#000',
-					fontSize: 12,
-					showMaxLabel: true
-				},
-				data:  _data.xAxis
-			},
-			yAxis: {
-				name: "(" + _data.unit + ")",
-				type: 'value',
-				axisLabel: {
-					fontSize: 12,
-					color:"#5f6ee1",
-					showMaxLabel: true
-				},
-				axisLine: {
-					show: true,
-					lineStyle: {
-						color: ['#5f6ee1']
-					}
-				},
-				splitLine: {
-					show: true,
-					lineStyle: {
-						color: ['#29437c']
-					}
-				}
-			},
-			series: [{
-				name: _data.name,
-				data: _data.value,
-				type: 'line',
-				markPoint: {
-					data: [{
-						name:"最大值",
-						type: "max"
-					}]
-				}
-			}]
-		};
-		return option;
-	};
-	onMounted(() => {
-		nextTick(()=>{
-			eChart = echarts.init(document.getElementsByClassName(name.value)[0]);
-			eChart.setOption(getOption(data.value));
-			eChart.resize();
-			window.addEventListener("resize",function(){
-				eChart.resize();
-			})
-		})
-	})
-	onBeforeUnmount(() => {
-		window.removeEventListener("resize",function(){
-		})
-	})
-</script>
-
-<style lang='scss' scoped>
-</style>

+ 0 - 134
src/components/Echarts/newChart/exLineChart.vue

@@ -1,134 +0,0 @@
-<template>
-	<div>
-		<div :class="name" :style="'height:'+height" style="margin: auto;" />
-	</div>
-</template>
-
-<script setup>
-	import * as echarts from 'echarts';
-	const store = useStore();
-	const { proxy } = getCurrentInstance();
-	import { reactive, ref } from '@vue/reactivity';
-	import { onMounted, onBeforeUnmount, nextTick } from 'vue';
-	var eChart = null;
-	const gutter = ref(5);
-	const fontS = ref(16);
-	const props = defineProps({
-		height: {
-			type: String,
-			default: '100%'
-		},
-		name: {
-			type: String,
-			default: 'echart'
-		},
-		data: {
-		  type: Object,
-		  default: () => {
-		    return {
-				name: "name",
-				xAxis: [1,2,2,3],
-				value: [4,5,6,8],
-				unit: "%"
-		    }
-		  }
-		}
-	});
-	const { height, name, data } = toRefs(props);
-	watch([data,height], ([newValue,newHig]) => {
-			if(eChart != null){
-				eChart.setOption(getOption(newValue));
-				eChart.resize();
-			}
-		},{
-			deep: true
-		},
-	);
-	const getOption = function(_data){
-		let option = {
-			tooltip: {
-				trigger: 'axis',
-				axisPointer: {
-					type: 'cross',
-				},
-				formatter: "{b}年 : {c}艘",
-				textStyle:{
-					fontSize: gutter.value*1.2
-				}
-			},
-			grid: {
-				top: '7%',
-				left: '1%',
-				right: '2%',
-				bottom: '2%',
-				containLabel: true
-			},
-			xAxis: {
-				type: 'category',
-				boundaryGap: true,
-				splitLine: {
-					show: true,
-					lineStyle: {
-						color: '#29437c'
-					}
-				},
-				axisLabel: {
-					color: '#fff',
-					fontSize: gutter.value*1.2,
-					showMaxLabel: true
-				},
-				data: _data.xAxis
-			},
-			yAxis: {
-				type: 'value',
-				axisLabel: {
-					fontSize: gutter.value*1.2,
-					color:"#5f6ee1",
-					showMaxLabel: true
-				},
-				axisLine: {
-					show: true,
-					lineStyle: {
-						color: ['#5f6ee1']
-					}
-				},
-				splitLine: {
-					show: true,
-					lineStyle: {
-						color: ['#29437c']
-					}
-				}
-			},
-			series: [{
-				data: _data.value,
-				type: 'line',
-				label: {
-					show: true,
-					position: 'top',
-					fontSize: gutter.value*1.2,
-					color:"#fff"
-				},
-				symbolSize:  gutter.value*0.4,
-				itemStyle: {
-					color: '#5f6ee1',
-				},
-				lineStyle: {
-					width: gutter.value*0.2,
-					color: '#5f6ee1'
-				}
-			}]
-		};
-		return option;
-	};
-	onMounted(() => {
-		let screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
-		gutter.value = Math.ceil(screenWidth / 320);
-		nextTick(()=>{
-			eChart = echarts.init(document.getElementsByClassName(name.value)[0]);
-			eChart.setOption(getOption(data.value));
-		})
-	})
-</script>
-
-<style lang='scss' scoped>
-</style>

+ 0 - 148
src/components/Echarts/newChart/roundDashChart.vue

@@ -1,148 +0,0 @@
-<template>
-	<div>
-		<div :class="name" :style="'height:'+height+';width:'+height" style="margin: auto;" />
-	</div>
-</template>
-
-<script setup>
-	import * as echarts from 'echarts';
-	const store = useStore();
-	const { proxy } = getCurrentInstance();
-	import { reactive, ref } from '@vue/reactivity';
-	import { onMounted, onBeforeUnmount,nextTick } from 'vue';
-	var eChart;
-	const gutter = ref(5)
-	const props = defineProps({
-		height: {
-			type: String,
-			default: '100%'
-		},
-		width: {
-			type: String,
-			default: '100%'
-		},
-		name: {
-			type: String,
-			default: 'echart'
-		},
-		data: {
-		  type: Object,
-		  default: () => {
-		    return {
-				name: "name",
-				value: 0
-		    }
-		  }
-		}
-	});
-	const { height, name, data } = toRefs(props);
-	watch(data, (newValue) => {
-			if(eChart != null){
-				eChart.setOption(getOption(newValue));
-				eChart.resize();
-			}
-		},{
-			deep: true
-		},
-	);
-	const getOption = function(_data){
-		let option = {
-			series: [{
-				name: '实时数据',
-				min: 0,
-				max: 360,
-				splitNumber: 12,
-				type: 'gauge',
-				fontSize: 0,
-				center: ['50%', '50%'],
-				radius: '80%',
-				startAngle: 90,
-				endAngle: -269.999999,
-				detail: {
-					show: false
-				},
-				axisTick: {
-					distance: -(gutter.value*0.66),
-					length: gutter.value*0.66,
-					lineStyle: {
-						color: '#fff',
-					}
-				},
-				data: [{
-					value: _data.value
-				}],
-				axisLine: {
-					lineStyle: {
-						color: [
-							[1, '#1e90ff']
-						],
-						width: gutter.value*0.67
-					},
-					
-				},
-				axisLabel: {
-					color: '#fff',
-					fontSize: gutter.value*0.67,
-					distance: gutter.value,
-					formatter: function(e) {
-						switch (e + "") {
-							case "0":
-								return "0";
-							case "30":
-								return "30";
-							case "60":
-								return "60";
-							case "90":
-								return "90";
-							case "120":
-								return "120";
-							case "150":
-								return "150";
-							case "180":
-								return "180";
-							case "210":
-								return "210";
-							case "240":
-								return "240";
-							case "270":
-								return "270";
-							case "300":
-								return "300";
-							case "330":
-								return "330";
-							default:
-								return "";
-						}
-					}
-				},
-				pointer: {
-					width: gutter.value*0.67,
-					length: "60%",
-				},
-				splitLine: {
-					distance: -(gutter.value*0.67),
-					length: gutter.value,
-					lineStyle: {
-						width: gutter.value*0.2,
-						color: '#fff',
-					}
-				},
-				title: {
-					color: '#fff',
-				},
-			}]
-		};
-		return option;
-	};
-	let screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
-	gutter.value = Math.ceil(screenWidth / 320);
-	onMounted(() => {
-		nextTick(()=>{
-			eChart = echarts.init(document.getElementsByClassName(name.value)[0]);
-			eChart.setOption(getOption(data.value));
-		})
-	})
-</script>
-
-<style lang='scss' scoped>
-</style>

+ 99 - 0
src/components/Echarts/pieCircularChart/index.vue

@@ -0,0 +1,99 @@
+<template>
+	<div>
+		<div :class="name" :style="{ 'height': height }" />
+	</div>
+</template>
+
+<script setup>
+	import * as echarts from "echarts";
+	import useResize from "@/hooks/useResize";
+	const {
+		proxy
+	} = getCurrentInstance();
+	var echartInstance = null;
+	const props = defineProps({
+		height: {
+			type: String,
+			default: '100%'
+		},
+		name: {
+			type: String,
+			default: 'echart'
+		},
+		data: {
+			type: Array,
+			default: [{
+				value: 0,
+				name: "data 1"
+			}, {
+				value: 0,
+				name: "data 2"
+			}]
+		}
+	});
+	const {
+		height,
+		name,
+		data
+	} = toRefs(props);
+	watch(data, (newValue) => {
+		if (echartInstance != null) {
+			echartInstance.setOption(getOption(newValue));
+		}
+	}, {
+		deep: true
+	});
+	const getOption = function(_data) {
+		let option = {
+			legend: {
+				bottom: "3%",
+				itemWidth: 15,
+				itemHeight: 7,
+				itemGap: 5,
+				textStyle: {
+					color: "#000",
+					fontSize: 10
+				}
+			},
+			color: ["#009dff","#22e4ff","#3bffd0","#04e38a","#9dff86","#fee588","#fea844","#fe7044","#fe4444","#ff7c8c"],
+			toolbox: {
+				show: false
+			},
+			tooltip: {
+				trigger: "item",
+				formatter: "{b} : {c} ({d}%)",
+			},
+			series: [{
+				name: "Nightingale Chart",
+				type: "pie",
+				radius: ['40%', '60%'],
+				center: ["50%", "50%"],
+				label: {
+					formatter: '{d}%'
+				},
+				data: data.value,
+			}],
+		};
+		return option;
+	};
+	onMounted(() => {
+		nextTick(() => {
+			echartInstance = echarts.init(document.getElementsByClassName(name.value)[0]);
+			echartInstance.setOption(getOption(data.value));
+			echartInstance.resize();
+		})
+	})
+
+	function resize() {
+		echartInstance.resize();
+	}
+	// 暴露函数 (供hook调用)
+	defineExpose({
+		resize,
+	});
+	useResize();
+</script>
+
+<style lang='scss' scoped>
+</style>
+

+ 137 - 102
src/components/Echarts/pieRoseTypeSimple/index.vue

@@ -1,108 +1,143 @@
 <template>
-  <div ref="echart" :style="{ height: height, width: width }"></div>
+	<div>
+		<div :class="name" :style="{ 'height': height }" />
+	</div>
 </template>
 
 <script setup>
-import * as echarts from "echarts";
-import useResize from "@/hooks/useResize"; // hook
+	import * as echarts from "echarts";
+	import useResize from "@/hooks/useResize";
+	const {
+		proxy
+	} = getCurrentInstance();
+	var echartInstance = null;
+	const props = defineProps({
+		height: {
+			type: String,
+			default: '100%'
+		},
+		name: {
+			type: String,
+			default: 'gaugeEchart'
+		},
+		data: {
+			type: Object,
+			default: () => {
+				return {
+					name: "",
+					value: 0,
+					min: 0,
+					max: 100,
+					unit: "KN*m"
+				}
+			}
+		}
+	});
+	const {
+		height,
+		name,
+		data
+	} = toRefs(props);
+	watch(data, (newValue) => {
+		if (echartInstance != null) {
+			echartInstance.setOption(getOption(newValue));
+		}
+	}, {
+		deep: true
+	}, );
+	const getOption = function(_data) {
+		let option = {
+			series: [{
+				type: 'gauge',
+				// splitNumber: 12,
+				min: data.value.min,
+				max: data.value.max,
+				radius: '95%',
+				progress: {
+					show: true,
+					width: 8,
+					color: "#fff"
+				},
+				itemStyle: {
+				    color: '#009dff',
+				},
+				pointer: {
+					length: '45%',
+					width: 3,
+				},
+				axisLine: {
+					lineStyle: {
+						width: 8
+					}
+				},
+				axisTick: {
+					distance: 1,
+					lineStyle: {
+						width: 1,
+						color: '#999'
+					}
+				},
+				splitLine: {
+					length: 10,
+					distance: 1,
+					lineStyle: {
+						width: 1,
+						color: '#999'
+					}
+				},
+				axisLabel: {
+					distance: 8,
+					color: '#fff',
+					fontSize: 8
+				},
+				title: {
+					show: false
+				},
+				detail: {
+					valueAnimation: true,
+					fontSize: 20,
+					offsetCenter: [0, '92%'],
+					color: 'inherit',
+					formatter: function (value) {
+						return '{value|' + data.value.value + '}{unit|' + data.value.unit + '}';
+					},
+					rich: {
+						value: {
+							fontSize: 20,
+							fontWeight: 'bolder',
+							color: '#04e088'
+						},
+						unit: {
+							fontSize: 12,
+							color: '#04e088',
+							padding: [0, 0, 0, 5]
+						}
+					}
+				},
+				data: [{
+					value: data.value.value
+				}]
+			}]
+		};
+		return option;
+	};
+	onMounted(() => {
+		nextTick(() => {
+			echartInstance = echarts.init(document.getElementsByClassName(name.value)[0]);
+			echartInstance.setOption(getOption(data.value));
+			echartInstance.resize();
+		})
+	})
 
-const { proxy } = getCurrentInstance(); // 获取实例中的proxy
+	function resize() {
+		echartInstance.resize();
+	}
+	// 暴露函数 (供hook调用)
+	defineExpose({
+		resize,
+	});
+	useResize();
+</script>
 
-let echart;
-let echartInstance;
-
-const props = defineProps({
-  // 数据
-  data: {
-    type: Array,
-    default: [
-      { value: 0, name: "data 1" },
-      { value: 0, name: "data 2" },
-      { value: 0, name: "data 3" },
-    ],
-  },
-  // 高度
-  height: {
-    type: [Number, String],
-    default: "300px",
-  },
-  // 宽度
-  width: {
-    type: [Number, String],
-    default: "100%",
-  },
-});
-
-const { data } = toRefs(props);
-
-const data1 = reactive({
-  option: {
-    legend: {
-      top: "bottom",
-    },
-    toolbox: {
-      show: false,
-      feature: {
-        mark: { show: true },
-        dataView: { show: true, readOnly: false },
-        restore: { show: true },
-        saveAsImage: { show: true },
-      },
-    },
-    tooltip: {
-      trigger: "item",
-      formatter: "{b} : {c} ({d}%)",
-    },
-    series: [
-      {
-        name: "Nightingale Chart",
-        type: "pie",
-        radius: [10, 120],
-        center: ["50%", "45%"],
-        roseType: "area",
-        itemStyle: {
-          borderRadius: 8,
-        },
-        data: data.value,
-      },
-    ],
-  },
-});
-
-const { option } = toRefs(data1);
-
-// 观察 data ,重新绘制
-watch(
-  data,
-  (newValue) => {
-    option.value.series[0].data = newValue;
-  },
-  { deep: true }
-);
-watch(
-  option,
-  (newValue) => {
-    echartInstance.setOption(newValue, true);
-  },
-  { deep: true }
-);
-
-onMounted(() => {
-  echart = proxy.$refs.echart; // 获取的DOM根节点
-  echartInstance = echarts.init(echart, "macarons"); // 初始化 echart
-  echartInstance.setOption(option.value, true); // 绘制
-  // notMerge 可选。是否不跟之前设置的 option 进行合并。默认为 false。即表示合并。合并的规则,详见 组件合并模式。如果为 true,表示所有组件都会被删除,然后根据新 option 创建所有新组件。
-  // setOption 见 https://echarts.apache.org/zh/api.html#echartsInstance.setOption
-});
-
-function resize() {
-  echartInstance.resize();
-}
-
-// 暴露函数 (供hook调用)
-defineExpose({
-  resize,
-});
-
-useResize();
-</script>
+<style lang='scss' scoped>
+</style>

+ 136 - 0
src/components/Echarts/roundbDashChart/roundbDashChart.vue

@@ -0,0 +1,136 @@
+<template>
+  <div ref="echart" :class="name" :style="{ height: height, width: width }"></div>
+</template>
+
+<script setup>
+import * as echarts from "echarts";
+import useResize from "@/hooks/useResize"; // hook
+const store = useStore();
+const { proxy } = getCurrentInstance(); // 获取实例中的proxy
+
+let echart;
+let echartInstance;
+
+const props = defineProps({
+  // 数据
+  data: {
+    type: Object,
+    default: {
+		max: 3000,
+		value: 0,
+		name: "name",
+		show: false,
+		unit: ""
+	},
+  },
+  // 高度
+  height: {
+    type: [Number, String],
+    default: "300px",
+  },
+  // 宽度
+  width: {
+    type: [Number, String],
+    default: "100%",
+  },
+  name:  {
+  		type: String,
+  		default: 'echart'
+  	},
+});
+
+const { data, name } = toRefs(props);
+const data1 = reactive({
+	option: {
+		tooltip: {
+			formatter: '{a} <br/>{b} '+': {c}'+data.value.unit
+		},
+		series: [{
+			name: '实时数据',
+			type: 'gauge',
+			radius: data.value.scalc || '95%',
+			max: data.value.max || 1500,
+			data: [{
+				value: data.value.value,
+				name: data.value.name
+			}],
+			title: {
+				show:true,
+				fontSize: 10,
+				offsetCenter: [0, '20%'],
+			},
+			detail: {
+				fontSize: 14,
+				formatter: function (value) {
+					return '{value|' + value.toFixed(0) + '}{unit|'+data.value.unit+'}';
+				},
+				offsetCenter: [0, '50%'],
+				rich: {
+					unit: {
+						fontSize: 10,
+						color: '#000',
+						padding: [0,0,0,6]
+					}
+				}
+			},
+			axisTick: {
+				distance: 2,
+				length: 3,
+			},
+			pointer: {
+				width: 2,
+				length: "50%",
+			},
+			splitLine: {
+				length: 5,
+				distance: 2,
+				lineStyle: {
+					width: 1
+				}
+			},
+			axisLine: {
+				lineStyle: {
+					width: 4
+				}
+			},
+			axisLabel: {
+				distance: 8,
+				color: "#000",
+				fontSize: 8
+			}
+		}]
+	}
+});
+
+const { option } = toRefs(data1);
+
+// 观察 data ,重新绘制
+watch(data, (newValue) => {
+    option.value.series[0].data[0].value = newValue.value;
+  },{ deep: true }
+);
+watch(option, (newValue) => {
+    echartInstance.setOption(newValue, true);
+  },{ deep: true }
+);
+onMounted(() => {
+	// echart = proxy.$refs.echart;
+	// echartInstance = echarts.init(echart, "macarons");
+	// echartInstance.setOption(option.value, true);
+	nextTick(()=>{
+		echartInstance = echarts.init(document.getElementsByClassName(name.value)[0]);
+		echartInstance.setOption(option.value, true);
+	})
+});
+
+function resize() {
+	echartInstance.resize();
+}
+
+// 暴露函数 (供hook调用)
+defineExpose({
+  resize,
+});
+
+useResize();
+</script>

+ 222 - 0
src/components/FuelRecord/index.vue

@@ -0,0 +1,222 @@
+<template>
+	<el-drawer v-model="open" 
+		:title="`添加加油记录`" 
+		:before-close="handleClose" 
+		direction="rtl" 
+		class="demo-drawer"
+		modal-class="el-subscribe-drawer" 
+		size="80%">
+		<div class="margin-bottom-xs flex justify-between">
+			<el-button type="success" @click="handleNew">新增一行</el-button>
+			<div>
+				<el-button plain @click="handleClose">取 消</el-button>
+				<el-button :disabled="disabled" type="primary" @click="submitForm">提 交</el-button>
+			</div>
+		</div>
+		<el-form ref="formRecordRefs" :rules="rules" :model="formRecord">
+			<el-table :data="formRecord.tableData" border>
+				<el-table-column label="序号" align="center" type="index" width="80" />
+				<el-table-column label="名称" align="center" prop="oilName">
+					<template #default="scope">
+						<el-form-item :prop="`tableData.${scope.$index}.oilName`" :rules="rules.oilName" style="margin: 0;">
+							<el-input type="text" v-model="scope.row.oilName" placeholder="输入名称"/>
+						</el-form-item>
+					</template>
+				</el-table-column>
+				<el-table-column label="经度" align="center" prop="longitude">
+					<template #default="scope">
+						<el-form-item :prop="`tableData.${scope.$index}.longitude`" :rules="rules.longitude" style="margin: 0;">
+							<el-input type="text" v-model="scope.row.longitude" placeholder="输入经度"/>
+						</el-form-item>
+					</template>
+				</el-table-column>
+				<el-table-column label="纬度" align="center" prop="latitude">
+					<template #default="scope">
+						<el-form-item :prop="`tableData.${scope.$index}.latitude`" :rules="rules.latitude" style="margin: 0;">
+							<el-input type="text" v-model="scope.row.latitude" placeholder="输入纬度"/>
+						</el-form-item>
+					</template>
+				</el-table-column>
+				<el-table-column label="开始时间" align="center" prop="startTime" width="220">
+					<template #default="scope">
+						<el-form-item :prop="`tableData.${scope.$index}.startTime`" :rules="rules.startTime" style="margin: 0;">
+							<el-date-picker
+							  v-model="scope.row.startTime"
+							  type="datetime"
+							  placeholder="选择开始时间">
+							</el-date-picker>
+						</el-form-item>
+					</template>
+				</el-table-column>
+				<el-table-column label="结束时间" align="center" prop="endTime" width="220">
+					<template #default="scope">
+						<el-form-item :prop="`tableData.${scope.$index}.endTime`" :rules="rules.endTime" style="margin: 0;">
+							<el-date-picker
+							  v-model="scope.row.endTime"
+							  type="datetime"
+							  placeholder="选择结束时间">
+							</el-date-picker>
+						</el-form-item>
+					</template>
+				</el-table-column>
+				<el-table-column label="加油量" align="center" prop="oilsVolume">
+					<template #default="scope">
+						<el-form-item :prop="`tableData.${scope.$index}.oilsVolume`" :rules="rules.oilsVolume" style="margin: 0;">
+							<el-input type="text" v-model="scope.row.oilsVolume" placeholder="输入加油量"/>
+						</el-form-item>
+					</template>
+				</el-table-column>
+				<el-table-column label="加油类型" align="center" prop="oilsType">
+					<template #default="scope">
+						<el-form-item :prop="`tableData.${scope.$index}.oilsType`" :rules="rules.oilsType" style="margin: 0;">
+							<el-select v-model="scope.row.oilsType" placeholder="选择加油类型">
+							    <el-option
+							      v-for="item in oilsTypeOptions"
+							      :key="item.value"
+							      :label="item.label"
+							      :value="item.value">
+							    </el-option>
+							</el-select>
+						</el-form-item>
+					</template>
+				</el-table-column>
+				<el-table-column label="加油费用" align="center" prop="oilsMoney">
+					<template #default="scope">
+						<el-form-item :prop="`tableData.${scope.$index}.oilsMoney`" :rules="rules.oilsMoney" style="margin: 0;">
+							<el-input type="text" v-model="scope.row.oilsMoney" placeholder="输入费用"/>
+						</el-form-item>
+					</template>
+				</el-table-column>
+				<el-table-column label="负责人" align="center" prop="person">
+					<template #default="scope">
+						<el-form-item :prop="`tableData.${scope.$index}.person`" :rules="rules.person" style="margin: 0;">
+							<el-input type="text" v-model="scope.row.person" placeholder="输入负责人"/>
+						</el-form-item>
+					</template>
+				</el-table-column>
+				<el-table-column width="40">
+					<template #default="scope">
+						<elIcon @click="handleDel(scope.$index)"><Delete class="text-red pointer"/></elIcon>
+					</template>
+				</el-table-column>
+			</el-table>
+		</el-form>
+	</el-drawer>
+</template>
+
+<script setup>
+	const open = ref(false);
+	const disabled = ref(true);
+	const data = reactive({
+		formRecord: {
+			tableData: []
+		},
+		rules: {
+			oilName: [{
+				required: true,
+				message: "请输入名称",
+				trigger: "blur"
+			}],
+			longitude: [{
+				required: true,
+				message: "请输入经度",
+				trigger: "blur"
+			}],
+			latitude: [{
+				required: true,
+				message: "请输入纬度",
+				trigger: "blur"
+			}],
+			startTime: [{
+				required: true,
+				message: "请选择开始时间",
+				trigger: "blur"
+			}],
+			endTime: [{
+				required: true,
+				message: "请选择结束时间",
+				trigger: "blur"
+			}],
+			oilsVolume: [{
+				required: true,
+				message: "请输入加油量",
+				trigger: "blur"
+			}],
+			oilsType: [{
+				required: true,
+				message: "请选择油类型",
+				trigger: "blur"
+			}],
+			oilsMoney: [{
+				required: true,
+				message: "请输入费用",
+				trigger: "blur"
+			}],
+			person: [{
+				required: true,
+				message: "请输入负责人",
+				trigger: "blur"
+			}]
+		},
+		oilsTypeOptions: [{
+			value: 1,
+			label: "轻柴油"
+		},{
+			value: 2,
+			label: "重柴油"
+		},{
+			value: 3,
+			label: "燃料油"
+		},{
+			value: 4,
+			label: "渣油型燃料油"
+		}]
+	})
+	
+	const { formRecord, rules, oilsTypeOptions } = toRefs(data);
+	// 显示弹框
+	function show() {
+		open.value = true;
+		formRecord.value.tableData = []
+	}
+	// 关闭按钮
+	function handleClose() {
+		formRecord.value = {
+			tableData: []
+		}
+		open.value = false;
+		// emit("close");
+	}
+	/** 提交按钮 */
+	function submitForm() {
+		proxy.$refs["formRecordRef"].validate(valid => {
+			if (valid) {
+				
+			}
+		})
+	}
+	function handleNew(){
+		let _data = { 
+			oilName: "",
+			longitude: "",
+			latitude: "",
+			startTime: "",
+			endTime: "",
+			oilsVolume: "",
+			oilsType: "",
+			oilsMoney: "",
+			person: ""
+		};
+		formRecord.value.tableData.push(_data);
+	}
+	function handleDel(index){
+		formRecord.value.tableData.splice(index, 1);
+	}
+	defineExpose({
+		show,
+		handleClose,
+	});
+</script>
+
+<style>
+</style>

+ 52 - 0
src/components/Progress/index.vue

@@ -0,0 +1,52 @@
+<template>
+	<div class="flex">
+		<div style="width: calc(100% - 100px);" class="text-center">
+			<el-progress
+				:show-text="false" 
+				:color="data.color" 
+				style="width: 100%;" 
+				class="margin-bottom-sm"
+				:stroke-width="data.swid" 
+				:percentage="parseFloat(data.max)>100?(parseFloat(data.value)/parseFloat(data.max))*100:data.value">
+			</el-progress>
+			<span class="text-sm">{{data.name}}</span>
+		</div>
+		<div class="text-xxl margin-left-sm">{{data.value}}{{data.unit}}</div>
+	</div>
+</template>
+
+<script setup>
+	const props = defineProps({
+		data: {
+			type: Object,
+			default: {
+				max: 100,
+				value: 0,
+				name: "name",
+				unit: "",
+				color: "#009dff",
+				swid: 12
+			},
+		},
+		height: {
+			type: [Number, String],
+			default: "300px",
+		},
+		width: {
+			type: [Number, String],
+			default: "100%",
+		}
+	});
+	const {
+		data,
+		height,
+		width
+	} = toRefs(props);
+	watch(data, (newValue) => {
+	    console.log(newValue)
+	  },{ deep: true }
+	);
+</script>
+
+<style>
+</style>

+ 118 - 0
src/components/TimeZone/index.vue

@@ -0,0 +1,118 @@
+<template>
+	<div>
+		<el-form ref="form" :model="zoneForm" label-width="60px" class="custom-label">
+			<el-form-item label="时区:" style="margin: 0;">
+				<el-select v-model="zoneForm.zoneId" placeholder="请选择" 
+					style="width: 90px;" size="small" @change="handleSele">
+				    <el-option
+				      v-for="item in zoneOptions"
+				      :key="item.value"
+				      :label="item.label"
+				      :value="item.value">
+				    </el-option>
+				</el-select>
+				<span class="margin-left-sm margin-right text-sm">{{zoneForm.zoneTime}}</span>
+			</el-form-item>
+		</el-form>
+	</div>
+</template>
+
+<script setup name="">
+	const { proxy } = getCurrentInstance();
+	const data = reactive({
+		zoneForm: {
+			zoneId: 8,
+			zoneTime: ""
+		},
+		zoneOptions: [{
+			value: 1,
+			label: "东一区"
+		},{
+			value: 2,
+			label: "东二区"
+		},{
+			value: 3,
+			label: "东三区"
+		},{
+			value: 4,
+			label: "东四区"
+		},{
+			value: 5,
+			label: "东五区"
+		},{
+			value: 6,
+			label: "东六区"
+		},{
+			value: 7,
+			label: "东七区"
+		},{
+			value: 8,
+			label: "东八区"
+		},{
+			value: 9,
+			label: "东九区"
+		},{
+			value: 10,
+			label: "东十区"
+		},{
+			value: 11,
+			label: "东十一区"
+		},{
+			value: 12,
+			label: "东十二区"
+		},{
+			value: -1,
+			label: "西一区"
+		},{
+			value: -2,
+			label: "西二区"
+		},{
+			value: -3,
+			label: "西三区"
+		},{
+			value: -4,
+			label: "西四区"
+		},{
+			value: -5,
+			label: "西五区"
+		},{
+			value: -6,
+			label: "西六区"
+		},{
+			value: -7,
+			label: "西七区"
+		},{
+			value: -8,
+			label: "西八区"
+		},{
+			value: -9,
+			label: "西九区"
+		},{
+			value: -10,
+			label: "西十区"
+		},{
+			value: -11,
+			label: "西十一区"
+		},{
+			value: -12,
+			label: "西十二区"
+		}]
+	});
+	const { zoneForm, zoneOptions } = toRefs(data);
+	const handleSele = function(val){
+		var d = new Date();
+		var len = d.getTime();
+		var offset = d.getTimezoneOffset()*60000;
+		var utcTime = len + offset;
+		let _time = new Date(utcTime + 3600000*val)
+		zoneForm.value.zoneTime = proxy.parseTime(_time,`{y}-{m}-{d} {h}:{i}:{s}`);;
+	}
+	handleSele(8);
+	
+</script>
+
+<style lang='scss' scoped>
+	::v-deep .el-form-item__label {
+	  color: #fff;
+	}
+</style>

+ 1 - 1
src/layout/components/AppMain.vue

@@ -7,7 +7,7 @@
         </keep-alive>
       </transition>
 	   <keep-alive :include="cachedViews" v-else>
-          <component style="background-color: #000;height:calc(100vh - 84px);overflow-y: auto;" :is="Component" :key="route.path" />
+          <component style="height:calc(100vh - 84px);overflow-y: auto;" :is="Component" :key="route.path" />
         </keep-alive>
     </router-view>
   </section>

+ 136 - 173
src/layout/components/Navbar.vue

@@ -1,180 +1,143 @@
 <template>
-  <div class="navbar">
-    <hamburger id="hamburger-container" :is-active="getters.sidebar.opened" class="hamburger-container"
-      @toggleClick="toggleSideBar" />
-    <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!$store.state.settings.topNav" />
-    <top-nav id="topmenu-container" class="topmenu-container" v-if="$store.state.settings.topNav" />
-
-    <div class="right-menu">
-      <template v-if="getters.device !== 'mobile'">
-        <!-- <ShipSelect /> -->
-        <header-search id="header-search" class="right-menu-item" />
-        <screenfull id="screenfull" class="right-menu-item hover-effect" />
-      </template>
-      <div class="avatar-container">
-        <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
-          <div class="avatar-wrapper flex align-center">
-            <div class="margin-left-xs">
-              <div class="text-df text-bold">{{ $store.state.user.user.nickName }}</div>
-              <div class="text-sm">{{ $store.state.user.user.userName }}</div>
-            </div>
-          </div>
-          <template #dropdown>
-            <el-dropdown-menu>
-              <router-link to="/user/profile">
-                <el-dropdown-item>个人中心</el-dropdown-item>
-              </router-link>
-              <el-dropdown-item command="setLayout">
-                <span>布局设置</span>
-              </el-dropdown-item>
-              <el-dropdown-item divided command="logout">
-                <span>退出登录</span>
-              </el-dropdown-item>
-            </el-dropdown-menu>
-          </template>
-        </el-dropdown>
-      </div>
-    </div>
-  </div>
+	<div class="navbar">
+		<div class="left-menu">
+			<logo/>
+		</div>
+		<div class="left-menu" style="width:calc(100% - 734px);">
+			<sidebar/>
+		</div>
+		<div class="right-menu">
+			<time-zone/>
+			<div class="avatar-container">
+				<el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
+					<div class="avatar-wrapper flex align-center">
+						<div class="margin-left-xs">
+							<div class="text-df text-bold">{{ $store.state.user.user.nickName }}</div>
+							<div class="text-sm">{{ $store.state.user.user.userName }}</div>
+						</div>
+					</div>
+					<template #dropdown>
+						<el-dropdown-menu>
+							<router-link to="/user/profile">
+								<el-dropdown-item>个人中心</el-dropdown-item>
+							</router-link>
+							<el-dropdown-item command="setLayout">
+								<span>布局设置</span>
+							</el-dropdown-item>
+							<el-dropdown-item divided command="logout">
+								<span>退出登录</span>
+							</el-dropdown-item>
+						</el-dropdown-menu>
+					</template>
+				</el-dropdown>
+			</div>
+		</div>
+	</div>
 </template>
 
 <script setup>
-import modal from "@/plugins/modal";
-import Breadcrumb from "@/components/Breadcrumb";
-import TopNav from "@/components/TopNav";
-import Hamburger from "@/components/Hamburger";
-import Screenfull from "@/components/Screenfull";
-import SizeSelect from "@/components/SizeSelect";
-// import ShipSelect from "@/components/ShipSelect";
-import ToggleTheme from "@/components/ToggleTheme";
-
-const store = useStore();
-const getters = computed(() => store.getters);
-
-function toggleSideBar() {
-  store.dispatch("app/toggleSideBar");
-}
-
-function handleCommand(command) {
-  switch (command) {
-    case "setLayout":
-      setLayout();
-      break;
-    case "logout":
-      logout();
-      break;
-    default:
-      break;
-  }
-}
-
-function logout() {
-  modal
-    .confirm("确定注销并退出系统吗?")
-    .then(() => {
-      store.dispatch("LogOut").then(() => {
-        location.href = "./";
-      });
-    })
-    .catch(() => { });
-}
-
-const emits = defineEmits(["setLayout"]);
-function setLayout() {
-  emits("setLayout");
-}
-
-
-
-
+	import modal from "@/plugins/modal";
+	import Logo from './Sidebar/Logo.vue';
+	import Sidebar from "./Sidebar/index.vue";
+	import TimeZone from "@/components/TimeZone";
+	// import ShipSelect from "@/components/ShipSelect";
+	import ToggleTheme from "@/components/ToggleTheme";
+
+	const store = useStore();
+	const getters = computed(() => store.getters);
+
+	function toggleSideBar() {
+		store.dispatch("app/toggleSideBar");
+	}
+
+	function handleCommand(command) {
+		switch (command) {
+			case "setLayout":
+				setLayout();
+				break;
+			case "logout":
+				logout();
+				break;
+			default:
+				break;
+		}
+	}
+
+	function logout() {
+		modal
+			.confirm("确定注销并退出系统吗?")
+			.then(() => {
+				store.dispatch("LogOut").then(() => {
+					location.href = "./";
+				});
+			})
+			.catch(() => {});
+	}
+
+	const emits = defineEmits(["setLayout"]);
+
+	function setLayout() {
+		emits("setLayout");
+	}
 </script>
 
 <style lang='scss' scoped>
-.navbar {
-  height: 60px;
-  overflow: hidden;
-  position: relative;
-  background: #3b9a9c;
-  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
-
-  .hamburger-container {
-    line-height: 46px;
-    height: 100%;
-    float: left;
-    cursor: pointer;
-    transition: background 0.3s;
-    -webkit-tap-highlight-color: transparent;
-
-    &:hover {
-      background: rgba(0, 0, 0, 0.025);
-    }
-  }
-
-  .breadcrumb-container {
-    float: left;
-  }
-
-  .topmenu-container {
-    position: absolute;
-    left: 50px;
-  }
-
-  .errLog-container {
-    display: inline-block;
-    vertical-align: top;
-  }
-
-  .right-menu {
-    float: right;
-    height: 100%;
-    line-height: 50px;
-    display: flex;
-
-    &:focus {
-      outline: none;
-    }
-
-    .right-menu-item {
-      display: inline-block;
-      padding: 0 8px;
-      height: 100%;
-      font-size: 18px;
-      color: #5a5e66;
-      vertical-align: text-bottom;
-
-      &.hover-effect {
-        cursor: pointer;
-        transition: background 0.3s;
-
-        &:hover {
-          background: rgba(0, 0, 0, 0.025);
-        }
-      }
-    }
-
-    .avatar-container {
-      margin-right: 20px;
-
-      .avatar-wrapper {
-        margin-top: 5px;
-        position: relative;
-
-        .user-avatar {
-          cursor: pointer;
-          width: 40px;
-          height: 40px;
-          border-radius: 10px;
-        }
-
-        i {
-          cursor: pointer;
-          position: absolute;
-          right: -20px;
-          top: 25px;
-          font-size: 12px;
-        }
-      }
-    }
-  }
-}
-</style>
+	.navbar {
+		height: 60px;
+		overflow: hidden;
+		position: relative;
+		color: #fff;
+		background: #3b9a9c;
+		box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
+		.left-menu{
+			float: left;
+			padding: 0 8px;
+		}
+		.right-menu {
+			float: right;
+			height: 100%;
+			/* line-height: 60px; */
+			display: flex;
+			align-items: center;
+			&:focus {
+				outline: none;
+			}
+			.right-menu-item {
+				display: inline-block;
+				padding: 0 8px;
+				height: 100%;
+				font-size: 18px;
+				color: #5a5e66;
+				vertical-align: text-bottom;
+				&.hover-effect {
+					cursor: pointer;
+					transition: background 0.3s;
+
+					&:hover {
+						background: rgba(0, 0, 0, 0.025);
+					}
+				}
+			}
+			.avatar-container {
+				margin-right: 20px;
+				.avatar-wrapper {
+					margin-top: 5px;
+					position: relative;
+					.user-avatar {
+						cursor: pointer;
+						width: 40px;
+						height: 40px;
+						border-radius: 10px;
+					}
+					i {
+						cursor: pointer;
+						position: absolute;
+						right: -20px;
+						top: 25px;
+						font-size: 12px;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 56 - 66
src/layout/components/Sidebar/Logo.vue

@@ -1,81 +1,71 @@
 <template>
-  <!-- <div class="sidebar-logo-container" :class="{ 'collapse': collapse }" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"> -->
-	<div class="sidebar-logo-container" :class="{ 'collapse': collapse }" :style="{ backgroundColor: '#409eff' }">
-    <transition name="sidebarLogoFade">
-      <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
-        <el-image v-if="logo" :src="logo" class="sidebar-logo" fit="fill"/>
-        <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
-      </router-link>
-      <router-link v-else key="expand" class="sidebar-logo-link" to="/">
-        <el-image v-if="logo" :src="logo" class="sidebar-logo" fit="fill"/>
-        <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
-      </router-link>
-    </transition>
-  </div>
+	<div class="sidebar-logo-container">
+		<transition name="sidebarLogoFade">
+			<router-link key="collapse" class="sidebar-logo-link" to="/">
+				<el-image :src="logo" class="sidebar-logo" fit="fill" />
+				<h1 class="sidebar-title">
+					{{ title }}
+				</h1>
+			</router-link>
+		</transition>
+	</div>
 </template>
 
 <script setup>
-import variables from '@/assets/styles/variables.module.scss'
-import logo from '@/assets/logo/logo.jpg'
+	import variables from '@/assets/styles/variables.module.scss'
+	import logo from '@/assets/logo/logo.png'
 
-defineProps({
-  collapse: {
-    type: Boolean,
-    required: true
-  }
-})
-
-const title = ref('扬海船舶管理系统');
-const store = useStore();
-const sideTheme = computed(() => store.state.settings.sideTheme);
+	const title = ref('智能能效管理系统');
+	const store = useStore();
+	const sideTheme = computed(() => store.state.settings.sideTheme);
 </script>
 
 <style lang="scss" scoped>
-.sidebarLogoFade-enter-active {
-  transition: opacity 1.5s;
-}
+	.sidebarLogoFade-enter-active {
+		transition: opacity 1.5s;
+	}
 
-.sidebarLogoFade-enter,
-.sidebarLogoFade-leave-to {
-  opacity: 0;
-}
+	.sidebarLogoFade-enter,
+	.sidebarLogoFade-leave-to {
+		opacity: 0;
+	}
 
-.sidebar-logo-container {
-  position: relative;
-  width: 100%;
-  height: 50px;
-  line-height: 50px;
-  background: #2b2f3a;
-  text-align: center;
-  overflow: hidden;
+	.sidebar-logo-container {
+		position: relative;
+		// width: 100%;
+		height: 60px;
+		line-height: 60px;
+		// background: #2b2f3a;
+		text-align: center;
+		overflow: hidden;
 
-  & .sidebar-logo-link {
-    height: 100%;
-    width: 100%;
+		& .sidebar-logo-link {
+			height: 100%;
+			width: 100%;
 
-    & .sidebar-logo {
-      width: 42px;
-      height: 32px;
-      vertical-align: middle;
-      margin-right: 12px;
-    }
+			& .sidebar-logo {
+				height: 40px;
+				vertical-align: middle;
+				margin-right: 12px;
+			}
 
-    & .sidebar-title {
-      display: inline-block;
-      margin: 0;
-      color: #fff;
-      font-weight: 600;
-      line-height: 50px;
-      font-size: 14px;
-      font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
-      vertical-align: middle;
-    }
-  }
+			& .sidebar-title {
+				display: inline-block;
+				margin: 0;
+				color: #fff;
+				font-weight: 600;
+				line-height: 60px;
+				font-size: 22px;
+				transform: skewX(-10deg);
+				font-family: "黑体";
+				vertical-align: middle;
+			}
+		}
 
-  &.collapse {
-    .sidebar-logo {
-      margin-right: 0px;
-    }
-  }
-}
+		&.collapse {
+			.sidebar-logo {
+				margin-right: 0px;
+			}
+		}
+	}
 </style>

+ 4 - 7
src/layout/components/Sidebar/index.vue

@@ -1,7 +1,5 @@
 <template>
-  <div :class="{ 'has-logo': showLogo }" :style="{ backgroundColor: '#409eff' }">
-  <!-- <div :class="{ 'has-logo': showLogo }" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"> -->
-	<logo v-if="showLogo" :collapse="isCollapse" />
+  <div>
     <el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper">
       <el-menu
         :default-active="activeMenu"
@@ -10,11 +8,10 @@
         active-text-color="#000"
         :collapse-transition="false"
 		text-color="#fff"
-		background-color="#409eff"
-        mode="vertical"
+		background-color="#3b9a9c"
+        mode="horizontal"
+		class="justify-center"
       >
-       <!-- :background-color="sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
-        :text-color="sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor" -->
         <sidebar-item
           v-for="(route, index) in sidebarRouters"
           :key="route.path + index"

+ 53 - 0
src/layout/components/Sidebar/tabMeun.vue

@@ -0,0 +1,53 @@
+<template>
+	
+	<el-menu :default-active="activeIndex" 
+		class="el-menu-demo" 
+		mode="horizontal" 
+		text-color="#fff"
+		active-text-color="#fff"
+		background-color="#3b9a9c"
+		@select="handleSelect"
+		style="border: none;">
+		<template v-for="(item, index) in sidebarRouters">
+			<app-link v-if="item.meta" :to="resolvePath(item.path, item.query)">
+				<el-menu-item index="1">{{item.meta.title}}{{resolvePath(item.path, item.query)}}</el-menu-item>
+			</app-link>
+		</template>
+	</el-menu>
+	
+</template>
+
+<script setup>
+	import { isExternal } from '@/utils/validate';
+	import { getNormalPath } from '@/utils/ruoyi';
+	const store = useStore();
+	const route = useRoute();
+	const sidebarRouters =  computed(() => store.getters.sidebarRouters);
+	const activeIndex = computed(() => {
+	  const { meta, path } = route;
+	  if (meta.activeMenu) {
+	    return meta.activeMenu;
+	  }
+	  return path;
+	})
+	const handleSelect = function(){
+		
+	}
+	function resolvePath(routePath, routeQuery) {
+		console.log(routePath, routeQuery)
+	  if (isExternal(routePath)) {
+	    return routePath
+	  }
+	  if (isExternal(routePath)) {
+	    return routePath
+	  }
+	  if (routeQuery) {
+	    let query = JSON.parse(routeQuery);
+	    return { path: getNormalPath(routePath + '/' + routePath), query: query }
+	  }
+	  return getNormalPath(routePath + '/' + routePath)
+	}
+</script>
+
+<style>
+</style>

+ 3 - 5
src/layout/index.vue

@@ -13,7 +13,6 @@
 	import {
 		useWindowSize
 	} from "@vueuse/core";
-	import Sidebar from "./components/Sidebar/index.vue";
 	import {
 		AppMain,
 		Navbar,
@@ -37,7 +36,6 @@
 	let timer;
 
 	const classObj = computed(() => ({
-		hideSidebar: !sidebar.value.opened,
 		openSidebar: sidebar.value.opened,
 		withoutAnimation: sidebar.value.withoutAnimation,
 		mobile: device.value === "mobile",
@@ -62,7 +60,7 @@
 			});
 		}
 		if (width.value - 1 < WIDTH) {
-			toggleTheme("dark");
+			// toggleTheme("dark");
 			store.dispatch("app/toggleDevice", "mobile");
 			store.dispatch("app/closeSideBar", {
 				withoutAnimation: true
@@ -72,7 +70,7 @@
 			store.dispatch("app/toggleDevice", "desktop");
 		}
 	});
-	toggleTheme(store.state.app.device === "mobile" ? "dark" : "light");
+	// toggleTheme(store.state.app.device === "mobile" ? "dark" : "light");
 
 	function handleClickOutside() {
 		store.dispatch("app/closeSideBar", {
@@ -92,7 +90,7 @@
 			// value: "theme-dark",
 			value: store.state.app.device === "mobile" ? "theme-dark" : "theme-light"
 		});
-		toggleTheme(store.state.app.device === "mobile" ? "dark" : "light"); //dark
+		// toggleTheme(store.state.app.device === "mobile" ? "dark" : "light"); //dark
 		let messageHello = store.state.app.device === "mobile" ? "晚上好😀," : "";
 		proxy.$modal.notify(
 			messageHello + "请注意合理安排休息哦!",

+ 30 - 0
src/router/index.js

@@ -73,6 +73,36 @@ export const constantRoutes = [
       }
     }]
   },
+  {
+    path: '/efficiencyAnalysis',
+    component: Layout,
+    redirect: 'noredirect',
+    children: [{
+      path: 'efficiencyAnalysis',
+      component: () => import('@/views/efficiencyAnalysis/index'),
+      name: 'efficiencyAnalysis',
+      meta: {
+        title: '能效分析',
+        icon: 'home',
+        affix: true
+      }
+    }]
+  },
+  {
+    path: '/efficiencyMana',
+    component: Layout,
+    redirect: 'noredirect',
+    children: [{
+      path: 'efficiencyMana',
+      component: () => import('@/views/efficiencyMana/index'),
+      name: 'efficiencyMana',
+      meta: {
+        title: '能效管理',
+        icon: 'home',
+        affix: true
+      }
+    }]
+  },
   {
     path: '/user',
     component: Layout,

+ 5 - 12
src/views/desktop/index.vue

@@ -1,20 +1,13 @@
 <template>
 	<div>
-		<statistics />
+		<home-page />
 	</div>
 </template>
 
 <script setup name="Index">
-import statistics from "@/views/statistics/index.vue";
-const { proxy } = getCurrentInstance();
-function handleApplyDetailDialogOpen() {
-  proxy.$refs["applyDetailDialogRef"].show();
-}
-function handleUserInfoDialogOpen() {
-  proxy.$refs["userInfoDialogRef"].show();
-}
-function handleApplyDetailDrawerOpen() {
-  proxy.$refs["applyDetailDrawerRef"].show();
-}
+import homePage from "@/views/homePage/index.vue";
 </script>
+{"imageTime":1717667579000,"updateDate":0,"msgType":"wsjjc","dealState":"N","faceImg":"","msgTypeCn":"玩手机监测","msgLevel":"1","channelAlias":"驾驶室内左","areaId":0,"videoUrl":"/data/YBX/out_image/2024-06-06/20240606175259_004_playphone.jpeg","areaName":"","cameraId":0,"imageUrl":"http://127.0.0.1:8170/faceImg/businessFile/20240606/wsjjc/20240606175259_004_playphone.jpeg","id":0,"taskId":0,"createDate":1717667579000}
+
+{"imageTime":1717615506000,"updateDate":0,"msgType":"wsjjc","dealState":"N","faceImg":"","msgTypeCn":"玩手机监测","msgLevel":"1","channelAlias":"货控室","areaId":0,"videoUrl":"/data/YBX/out_image/2024-06-06/20240606032506_001_playphone.jpeg","areaName":"","cameraId":0,"imageUrl":"http://127.0.0.1:8170/faceImg/businessFile/20240606/wsjjc/20240606032506_001_playphone.jpeg","id":0,"taskId":0,"createDate":1717615506000}
 

+ 217 - 0
src/views/efficiencyAnalysis/contRast/index.vue

@@ -0,0 +1,217 @@
+<template>
+	<el-row :gutter="14">
+		<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+			<div style="max-height: calc(66.66vh - 90px);overflow: hidden;border-radius: 14px;">
+				<el-image style="width: 100%;" :src="engImg"></el-image>
+			</div>
+		</el-col>
+		<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+			<el-card class="box-card blueCard text-sm" :body-style="{ padding: '10px !important' }">
+				<div style="height: calc(14vh - 36px)" class="bg-white radius padding-xs">
+					<div class="text-bold">重油储存</div>
+					<div class="flex justify-around align-center text-center" style="height: calc(100% - 22px)">
+						<div v-for="(ztem, zndex) in 4" :key="zndex">
+							<div class="text-blue text-xxl text-bold">1222L</div>
+							<div>{{zndex+1}}号柜</div>
+						</div>
+					</div>
+				</div>
+				<div style="height: calc(14vh - 36px)" class="bg-white margin-tb-xs radius padding-xs">
+					<div class="text-bold">轻油储存</div>
+					<div class="flex justify-around align-center text-center" style="height: calc(100% - 22px)">
+						<div v-for="(qtem, qndex) in 4" :key="qndex">
+							<div class="text-blue text-xxl text-bold">1222L</div>
+							<div>{{qndex+1}}号柜</div>
+						</div>
+					</div>
+				</div>
+				<div class="flex">
+					<div style="width: 70%;">
+						<line-chart name="HostPressure" :data="oilsData" height="calc(38.66vh - 51px)"/>
+					</div>
+					<div style="width: 30%;padding: 0 2%;" class="text-white">
+						<el-form ref="oilsFormRef" :model="oilsForm" label-width="0px">
+							<el-form-item style="margin-bottom: 8px;">
+								<div>时间单位:</div>
+								<el-select v-model="oilsForm.timeUnit" placeholder="请选择" size="small" style="width: 100%;">
+									<el-option
+									  v-for="item in timeUnitOptions"
+									  :key="item.value"
+									  :label="item.label"
+									  :value="item.value">
+									</el-option>
+								</el-select>
+							</el-form-item>
+							<el-form-item style="margin-bottom: 8px;">
+								<div>开始时间:</div>
+								<el-date-picker
+								  v-model="oilsForm.startTime"
+								  type="date"
+								  size="small"
+								  style="width: 100%;"
+								  start-placeholder="开始日期">
+								</el-date-picker>
+							</el-form-item>
+							<el-form-item style="margin-bottom: 15px;">
+								<div>结束时间:</div>
+								<el-date-picker
+								  v-model="oilsForm.endTime"
+								  type="date"
+								  size="small"
+								  style="width: 100%;"
+								  end-placeholder="结束日期">
+								</el-date-picker>
+							</el-form-item>
+							<el-form-item style="margin-bottom: 0;">
+								<el-button style="width: 100%;" type="primary" size="small">查询</el-button>
+							</el-form-item>
+						</el-form>
+					</div>
+				</div>
+			</el-card>
+		</el-col>
+		<el-col :span="24" :xs="24">
+			<el-card class="box-card blueCard margin-top-sm" :body-style="{ padding: '10px !important' }">
+				<el-row :gutter="20">
+					<template v-for="(item,index) in consumeData" :key="index">
+						<el-col :xl="6" :lg="6" :md="6" :sm="12" :xs="24" style="position: relative;">
+							<pie-rose :name="item.name" :data="item.data" height="calc(33.33vh - 90px)"/>
+							<div class="text-sm text-white" style="position: absolute;bottom: 0;left: 36%;transform: translate(-50%, 0);">{{item.title}}</div>
+						</el-col>
+					</template>
+				</el-row>
+			</el-card>
+		</el-col>
+	</el-row>
+	<!--  -->
+</template>
+
+<script setup>
+	import pieRose from "@/components/Echarts/pieRoseTypeSimple";
+	import lineChart from "@/components/Echarts/LineChart";
+	import engImg from "@/assets/images/20240529135050.png";
+	const timeUnitOptions = ref([]);
+	const data = reactive({
+		oilsData: {
+			name: "",
+			xAxis: ["2024/5/1", "2024/5/2", "2024/5/3", "2024/5/4", "2024/5/5", "2024/5/6"],
+			data: [{
+				name: '进机温度',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				areaStyle: {},
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '出口温度',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				areaStyle: {},
+				data: [10, 14, 18, 19, 13, 10]
+			}],
+		},
+		consumeData: [{
+			title: "初级能量消耗端能量",
+			name: "primaryCons",
+			data: [{
+				value: 10,
+				name: "主机"
+			},{
+				value: 20,
+				name: "辅机"
+			},{
+				value: 30,
+				name: "燃油锅炉"
+			},{
+				value: 80,
+				name: "初级耗能装置"
+			}]
+		},{
+			title: "有效做功能量分布图",
+			name: "effectWork",
+			data: [{
+				value: 40,
+				name: "推进做功"
+			},{
+				value: 70,
+				name: "电力做功"
+			},{
+				value: 14,
+				name: "蒸汽做功"
+			},{
+				value: 16,
+				name: "其他做功"
+			}]
+		},{
+			title: "能量损失分布图",
+			name: "energyLoss",
+			data: [{
+				value: 10,
+				name: "排烟损失"
+			},{
+				value: 30,
+				name: "冷却损失"
+			},{
+				value: 78,
+				name: "推进损失"
+			},{
+				value: 65,
+				name: "主机其他损失"
+			},{
+				value: 45,
+				name: "传动损失"
+			},{
+				value: 37,
+				name: "辅机其他损失"
+			},{
+				value: 17,
+				name: "锅炉热损失"
+			}]
+		},{
+			title: "全船能量分布图",
+			name: "totalEnergy",
+			data: [{
+				value: 68,
+				name: "推进做功"
+			},{
+				value: 44,
+				name: "推进损失"
+			},{
+				value: 87,
+				name: "排烟损失"
+			},{
+				value: 53,
+				name: "冷却损失"
+			},{
+				value: 12,
+				name: "主机其他损失"
+			},{
+				value: 75,
+				name: "电力做功"
+			},{
+				value: 78,
+				name: "蒸汽做功"
+			},{
+				value: 35,
+				name: "辅机其他损失"
+			},{
+				value: 57,
+				name: "项锅炉热损失"
+			},{
+				value: 34,
+				name: "其他做功"
+			}]
+		}],
+		oilsForm: {
+			timeUnit: null,
+			startTime: null,
+			endTime: null
+		}
+	});
+	const { consumeData, oilsData, oilsForm } = toRefs(data);
+</script>
+
+<style>
+</style>

+ 288 - 0
src/views/efficiencyAnalysis/distriBution/index.vue

@@ -0,0 +1,288 @@
+<template>
+	<el-row :gutter="14">
+		<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+			<el-card class="box-card blueCard text-sm" :body-style="{ padding: '10px !important' }">
+				<div class="flex" :class="undex == 0?'margin-bottom':''" 
+					v-for="(utem,undex) in unitConsData" :key="undex">
+					<div style="width: 70%;position: relative;">
+						<div class="sTitleSty" style="letter-spacing: 2px;">{{utem.name}}</div>
+						<line-chart :name="utem.className" :data="utem" height="calc(30vh - 65px)"/>
+					</div>
+					<div style="width: 30%;padding: 0 2%;" class="text-white">
+						<el-form ref="oilsFormRef" :model="oilsForm" label-width="0px">
+							<el-form-item style="margin-bottom: 0px;">
+								<div>开始时间:</div>
+								<el-date-picker
+								  v-model="oilsForm.startTime"
+								  type="date"
+								  size="small"
+								  style="width: 100%;"
+								  start-placeholder="开始日期">
+								</el-date-picker>
+							</el-form-item>
+							<el-form-item style="margin-bottom: 8px;">
+								<div>结束时间:</div>
+								<el-date-picker
+								  v-model="oilsForm.endTime"
+								  type="date"
+								  size="small"
+								  style="width: 100%;"
+								  end-placeholder="结束日期">
+								</el-date-picker>
+							</el-form-item>
+							<el-form-item style="margin-bottom: 0;">
+								<el-button style="width: 100%;" type="primary" size="small">查询</el-button>
+							</el-form-item>
+						</el-form>
+					</div>
+				</div>
+			</el-card>
+		</el-col>
+		<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+			<el-card class="box-card blueCard text-sm" :body-style="{ padding: '10px !important' }">
+				<div class="flex" :class="sndex == 0?'margin-bottom':''" 
+					v-for="(stem,sndex) in timeConsData" :key="sndex">
+					<div style="width: 70%;position: relative;">
+						<div class="sTitleSty" style="letter-spacing: 2px;">{{stem.name}}</div>
+						<line-chart :name="stem.className" :data="stem" height="calc(30vh - 65px)"/>
+					</div>
+					<div style="width: 30%;padding: 0 2%;" class="text-white">
+						<el-form ref="oilsFormRef" :model="oilsForm" label-width="0px">
+							<el-form-item style="margin-bottom: 0px;">
+								<div>开始时间:</div>
+								<el-date-picker
+								  v-model="oilsForm.startTime"
+								  type="date"
+								  size="small"
+								  style="width: 100%;"
+								  start-placeholder="开始日期">
+								</el-date-picker>
+							</el-form-item>
+							<el-form-item style="margin-bottom: 8px;">
+								<div>结束时间:</div>
+								<el-date-picker
+								  v-model="oilsForm.endTime"
+								  type="date"
+								  size="small"
+								  style="width: 100%;"
+								  end-placeholder="结束日期">
+								</el-date-picker>
+							</el-form-item>
+							<el-form-item style="margin-bottom: 0;">
+								<el-button style="width: 100%;" type="primary" size="small">查询</el-button>
+							</el-form-item>
+						</el-form>
+					</div>
+				</div>
+			</el-card>
+		</el-col>
+		<el-col :span="24" :xs="24">
+			<el-card class="box-card blueCard margin-top-sm" :body-style="{ padding: '10px !important' }">
+				<el-row :gutter="20">
+					<template v-for="(item,index) in linesData" :key="index">
+						<el-col :xl="8" :lg="8" :md="8" :sm="24" :xs="24">
+							<div style="position: relative;">
+								<div class="sTitleSty" style="letter-spacing: 2px;">{{item.name}}</div>
+								<line-chart :name="item.className" :data="item" height="calc(40vh - 88px)"/>
+							</div>
+							<div></div>
+						</el-col>
+					</template>
+				</el-row>
+			</el-card>
+		</el-col>
+	</el-row>
+</template>
+
+<script setup>
+	import lineChart from "@/components/Echarts/LineChart";
+	const timeUnitOptions = ref([]);
+	const data = reactive({
+		unitConsData: [{
+			name: "单位航行距离燃油消耗量",
+			className: "distanceCons",
+			xAxis: ["5月1日", "5月2日", "5月3日", "5月4日", "5月5日", "5月6日", "5月7日", "5月8日", "5月9日", "5月10日"],
+			data: [{
+				name: '主机',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '辅机',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [120, 104, 118, 119, 103, 106, 158, 129, 133, 140]
+			},{
+				name: '锅炉',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10, 18, 19, 13, 10]
+			}]
+		},{
+			name: "单位运输功燃油消耗量",
+			className: "transportCons",
+			xAxis: ["5月1日", "5月2日", "5月3日", "5月4日", "5月5日", "5月6日", "5月7日", "5月8日", "5月9日", "5月10日"],
+			data: [{
+				name: '主机',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '辅机',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [120, 104, 118, 119, 103, 106, 158, 129, 133, 140]
+			},{
+				name: '锅炉',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10, 18, 19, 13, 10]
+			}]
+		}],
+		timeConsData: [{
+			name: "燃油小时消耗量",
+			className: "hourCons",
+			xAxis: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
+			data: [{
+				name: '主机',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				areaStyle: {},
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '辅机',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				areaStyle: {},
+				data: [120, 104, 118, 119, 103, 106, 158, 129, 133, 140]
+			},{
+				name: '锅炉',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				areaStyle: {},
+				data: [10, 14, 18, 19, 13, 10, 18, 19, 13, 10]
+			}]
+		},{
+			name: "燃油日消耗量",
+			className: "dayCons",
+			xAxis: ["5月1日", "5月2日", "5月3日", "5月4日", "5月5日", "5月6日", "5月7日", "5月8日", "5月9日", "5月10日"],
+			data: [{
+				name: '主机',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '辅机',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [120, 104, 118, 119, 103, 106, 158, 129, 133, 140]
+			},{
+				name: '锅炉',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10, 18, 19, 13, 10]
+			}]
+		}],
+		linesData: [{
+			name: "燃油航次消耗量",
+			className: "VoyageCons",
+			xAxis: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
+			data: [{
+				name: '青岛-广州',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '上海-唐山',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10, 18, 19, 13, 10]
+			},{
+				name: '唐山-福州',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [120, 104, 118, 119, 103, 106, 158, 129, 133, 140]
+			}]
+		},{
+			name: "CO2排放指标",
+			className: "CoDischarge",
+			xAxis: ["5月1日", "5月2日", "5月3日", "5月4日", "5月5日", "5月6日", "5月7日", "5月8日", "5月9日", "5月10日"],
+			data: [{
+				name: '主机',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '辅机',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [120, 104, 118, 119, 103, 106, 158, 129, 133, 140]
+			},{
+				name: '锅炉',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10, 18, 19, 13, 10]
+			}]
+		},{
+			name: "EEOI排放指标",
+			className: "EeoioDischarge",
+			xAxis: ["5月1日", "5月2日", "5月3日", "5月4日", "5月5日", "5月6日", "5月7日", "5月8日", "5月9日", "5月10日"],
+			data: [{
+				name: '主机',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '辅机',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [120, 104, 118, 119, 103, 106, 158, 129, 133, 140]
+			},{
+				name: '锅炉',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10, 18, 19, 13, 10]
+			}]
+		}],
+		oilsForm: {
+			timeUnit: null,
+			startTime: null,
+			endTime: null
+		}
+	});
+	const { linesData, oilsForm, timeConsData, unitConsData } = toRefs(data);
+</script>
+
+<style scoped lang="scss">
+	.sTitleSty{
+		font-size: 0.8rem;
+	}
+</style>

+ 242 - 0
src/views/efficiencyAnalysis/historyPage/index.vue

@@ -0,0 +1,242 @@
+<template>
+	<div class="margin-bottom">
+		<el-row :gutter="14">
+			<el-col :span="12" :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+				<el-card class="box-card blueCard" :body-style="{ padding: '10px !important' }">
+					<el-form ref="systemFormRef" :model="systemForm" label-width="100px" class="grid">
+						<el-form-item label="系统选择:" class="flex-twice" style="margin-bottom: 8px;">
+							<el-select v-model="systemForm.systemId" placeholder="请选择" size="small" style="width: 100%;">
+								<el-option
+								  v-for="item in systemOptions"
+								  :key="item.value"
+								  :label="item.label"
+								  :value="item.value">
+								</el-option>
+							</el-select>
+						</el-form-item>
+						<el-form-item label="时间范围:" class="flex-treble" style="margin-bottom: 8px;">
+							<el-date-picker
+							  v-model="systemForm.sendTime"
+							  type="daterange"
+							  size="small"
+							   style="width: 100%;"
+							  range-separator=" - "
+							  start-placeholder="开始日期"
+							  end-placeholder="结束日期">
+							</el-date-picker>
+						</el-form-item>
+						<div class="flex-sub padding-left">
+							<el-button type="primary" size="small">查询</el-button>
+						</div>
+					</el-form>
+					<div style="position: relative;">
+						<div class="sTitleSty text-sm">温度</div>
+						<line-chart name="HostTempl" :data="templData" height="calc(33.33vh - 88px)"/>
+					</div>
+					<div class="margin-tb" style="position: relative;">
+						<div class="sTitleSty">压力</div>
+						<line-chart name="HostPressure" :data="pressureData" height="calc(33.33vh - 88px)"/>
+					</div>
+					<div style="position: relative;">
+						<div class="sTitleSty">轴转速</div>
+						<line-chart name="HostSpeed" :data="speedData" height="calc(33.33vh - 89px)"/>
+					</div>
+					<div class="margin-top-xs text-white text-bold">主机</div>
+				</el-card>
+			</el-col>
+			<el-col :span="12" :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+				<el-card class="box-card blueCard" :body-style="{ padding: '10px !important' }">
+					<el-form ref="equipFormRef" :model="equipForm" label-width="100px" class="grid">
+						<el-form-item label="设备选择:" class="flex-twice" style="margin-bottom: 8px;">
+							<el-select v-model="equipForm.equipId" placeholder="请选择" size="small" style="width: 100%;">
+								<el-option
+								  v-for="item in equipOptions"
+								  :key="item.value"
+								  :label="item.label"
+								  :value="item.value">
+								</el-option>
+							</el-select>
+						</el-form-item>
+						<el-form-item label="时间范围:" class="flex-treble" style="margin-bottom: 8px;">
+							<el-date-picker
+							  v-model="equipForm.sendTime"
+							  type="daterange"
+							  size="small"
+							   style="width: 100%;"
+							  range-separator=" - "
+							  start-placeholder="开始日期"
+							  end-placeholder="结束日期">
+							</el-date-picker>
+						</el-form-item>
+						<div class="flex-sub padding-left">
+							<el-button type="primary" size="small">查询</el-button>
+						</div>
+					</el-form>
+					<div style="position: relative;">
+						<div class="sTitleSty">温度</div>
+						<line-chart name="EngiTempl" :data="eTemplData" height="calc(33.33vh - 88px)"/>
+					</div>
+					<div class="margin-tb" style="position: relative;">
+						<div class="sTitleSty">压力</div>
+						<line-chart name="EngiPressure" :data="ePressureData" height="calc(33.33vh - 88px)"/>
+					</div>
+					<div style="position: relative;">
+						<div class="sTitleSty">功率</div>
+						<line-chart name="EngiPower" :data="powerData" height="calc(33.33vh - 89px)"/>
+					</div>
+					<div class="margin-top-xs text-white text-bold">辅机</div>
+				</el-card>
+			</el-col>
+		</el-row>
+	</div>
+</template>
+
+<script setup>
+	import lineChart from "@/components/Echarts/LineChart"
+	const systemOptions = ref([]);
+	const equipOptions = ref([]);
+	const data = reactive({
+		systemForm: {
+			systemId: 1
+		},
+		equipForm: {
+			equipId: 1
+		},
+		templData: {
+			name: "温度",
+			xAxis: ["一月", "二月", "三月", "四月", "五月", "六月"],
+			data: [{
+				name: '主机缸套冷却水进机温度',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '主机X号气打冷却水出口温度',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10]
+			},{
+				name: '主机活塞冷却油进口温度',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [50, 10, 14, 13, 11, 12]
+			},{
+				name: '主机X号活塞冷却油出口温度',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 12, 14, 13, 12, 11]
+			}]
+		},
+		pressureData: {
+			name: "压力",
+			xAxis: ["一月", "二月", "三月", "四月", "五月", "六月"],
+			data: [{
+				name: '主机缸套冷却水进机压力',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '主机活塞冷却油进口压力',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10]
+			}]
+		},
+		speedData: {
+			name: "轴转速",
+			xAxis: ["一月", "二月", "三月", "四月", "五月", "六月"],
+			data: [{
+				name: '主机缸套冷却水进机温度',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '主机X号气打冷却水出口温度',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10]
+			}]
+		},
+		ePressureData: {
+			name: "压力",
+			xAxis: ["一月", "二月", "三月", "四月", "五月", "六月"],
+			data: [{
+				name: '数据1',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '数据2',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10]
+			}]
+		},
+		eTemplData: {
+			name: "温度",
+			xAxis: ["一月", "二月", "三月", "四月", "五月", "六月"],
+			data: [{
+				name: '数据1',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '数据2',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10]
+			}]
+		},
+		powerData: {
+			name: "数据",
+			xAxis: ["一月", "二月", "三月", "四月", "五月", "六月"],
+			data: [{
+				name: '数据1',
+				type: 'line',
+				stack: 'Total',
+				unit: "℃",
+				smooth: true,
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '数据2',
+				type: 'line',
+				stack: 'Total',
+				smooth: true,
+				data: [10, 14, 18, 19, 13, 10]
+			}]
+		}
+	});
+	const { systemForm, 
+			equipForm, 
+			templData, 
+			pressureData, 
+			speedData,
+			eTemplData,
+			ePressureData,
+			powerData
+	} = toRefs(data);
+</script>
+
+<style scoped lang="scss">
+	::v-deep .el-form-item__label {
+	  color: #fff;
+	}
+	
+</style>

+ 84 - 0
src/views/efficiencyAnalysis/index.vue

@@ -0,0 +1,84 @@
+<template>
+	<div class="text-white padding">
+		<div class="margin-bottom">
+			<history-page v-if="tabPosition == 'history'"/>
+			<cont-rast v-if="tabPosition == 'contrast'"/>
+			<distri-bution v-if="tabPosition == 'distribution'"/>
+		</div>
+		<el-row>
+			<el-col :xl="4" :lg="4" :md="4" :sm="12" :xs="12"><progress-bar :data="oilList.heavyOil"/></el-col>
+			<el-col :xl="4" :lg="4" :md="4" :sm="12" :xs="12"><progress-bar :data="oilList.lightOil"/></el-col>
+			<el-col :xl="8" :lg="8" :md="8" :sm="24" :xs="24" class="text-center text-sm">
+				<el-radio-group v-model="tabPosition" style="border-radius: 40px;overflow: hidden;">
+				    <el-radio-button label="history">历史数据查询</el-radio-button>
+				    <el-radio-button style="border-left: 1px solid #2f516c;border-right: 1px solid #2f516c;" label="contrast">能效指标对比分析</el-radio-button>
+				    <el-radio-button label="distribution">能效分布分析</el-radio-button>
+				</el-radio-group>
+			</el-col>
+			<el-col :xl="4" :lg="4" :md="4" :sm="12" :xs="12"><progress-bar :data="oilList.lubricatOil"/></el-col>
+			<el-col :xl="4" :lg="4" :md="4" :sm="12" :xs="12"><progress-bar :data="oilList.totalOil"/></el-col>
+		</el-row>
+	</div>
+</template>
+
+<script setup>
+	import ProgressBar from "@/components/Progress";
+	import historyPage from "./historyPage/index.vue";
+	import contRast from "./contRast/index.vue";
+	import distriBution from "./distriBution/index.vue";
+	
+	const tabPosition = ref("history");
+	const data = reactive({
+		oilList: {
+			heavyOil: {
+				max: 100,
+				value: 14.3,
+				name: "当前重油总量",
+				unit: "L",
+				color: "#009dff",
+				swid: 10
+			},
+			lightOil: {
+				max: 100,
+				value: 89.63,
+				name: "当前轻油总量",
+				unit: "L",
+				color: "#009dff",
+				swid: 10
+			},
+			lubricatOil: {
+				max: 100,
+				value: 50.37,
+				name: "当前滑油总量",
+				unit: "L",
+				color: "#009dff",
+				swid: 10
+			},
+			totalOil: {
+				max: 200,
+				value: 164.3,
+				name: "当前总量",
+				unit: "L",
+				color: "#009dff",
+				swid: 10
+			}
+		}
+		
+	});
+	const { oilList } = toRefs(data);
+</script>
+
+<style scoped lang="scss">
+	::v-deep .el-radio-button__inner{
+		background-color: #2091de;
+		border: none;
+		color: #fff;
+		font-size: 0.75rem;
+	}
+	::v-deep .el-radio-button__original-radio:checked+.el-radio-button__inner{
+		background-color: #3b9a9c;
+	}
+	::v-deep .el-radio-button:first-child .el-radio-button__inner{
+		border: none;
+	}
+</style>

+ 225 - 0
src/views/efficiencyMana/AlarmMana/index.vue

@@ -0,0 +1,225 @@
+<template>
+	<div>
+		<el-row :gutter="14">
+			<el-col :xl="10" :lg="10" :md="10" :sm="24" :xs="24">
+				<el-row :gutter="20">
+					<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+						<el-card class="box-card" :body-style="{ padding: '10px !important' }">
+							<div class="flex align-center justify-around" style="position: relative;padding-left: 40px;height: calc(36vh - 100px);">
+								<div class="sTitleSty" style="font-size: 1.2rem;letter-spacing: 4px;color: #000;">报警管理</div>
+								<div>
+									<div class="reportSty"><div><span>9</span></div></div>
+									<div class="text-center text-bold margin-top-sm">警告总数</div>
+								</div>
+								<div class="text-sm">
+									<div v-for="(items,indexs) in tabEquipment" :key="indexs" 
+										class="margin-bottom" @click="handleChange(items.type)">
+										<el-button circle type="primary" :plain="equipmentType != items.type">
+											<svg-icon :icon-class="items.type"/>
+										</el-button>
+										<span class="margin-left-xs">{{ items.name }}</span>
+									</div>
+								</div>
+							</div> 
+						</el-card>
+					</el-col>
+					<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+						<el-card class="box-card" :body-style="{ padding: '10px !important' }">
+							<div style="position: relative;padding-left: 40px;">
+								<div class="sTitleSty" style="font-size: 1.2rem;letter-spacing: 4px;color: #000;">{{alarmProportion.title}}</div>
+								<pie-circular-chart :name="alarmProportion.name" :data="alarmProportion.data" height="calc(36vh - 100px)"/>
+							</div>
+						</el-card>
+					</el-col>
+				</el-row>
+				<el-card class="box-card margin-top" :body-style="{ padding: '10px !important' }">
+					<div class="text-center margin-bottom-sm text-xl text-bold">{{alarmRepoData.name}}</div>
+					<bar-chart name="HostPressure" :data="alarmRepoData" height="calc(64vh - 127px)"/>
+				</el-card>
+			</el-col>
+			<el-col :xl="14" :lg="14" :md="14" :sm="24" :xs="24">
+				<el-form ref="refuelRecordsRef" :model="refuelForm" label-width="0">
+					<el-row>
+						<el-col :xl="16" :lg="16" :md="16" :sm="24" :xs="24">
+							<div class="flex text-xs">
+								<div v-for="(item,index) in tabEquipment" :key="index" 
+									class="margin-right" @click="handleChange(item.type)">
+									<el-button circle type="primary" :plain="equipmentType != item.type">
+										<svg-icon :icon-class="item.type"/>
+									</el-button>
+									<span class="margin-left-xs">{{ item.name }}</span>
+								</div>
+								<el-form-item label="" class="margin-right">
+									<el-date-picker
+										v-model="refuelForm.compilationDate"
+										type="daterange"
+										range-separator="~"
+										start-placeholder="开始日期"
+										end-placeholder="结束日期">
+									</el-date-picker>
+								</el-form-item>
+								<el-button type="primary">查询</el-button>
+							</div>
+						</el-col>
+						<el-col :xl="8" :lg="8" :md="8" :sm="24" :xs="24">
+							<div class="flex justify-end text-xs">
+								<div>
+									<el-button circle><elIcon><RefreshRight/></elIcon></el-button>
+									<span class="margin-left-xs">刷新</span>
+								</div>
+								<div class="margin-lr">
+									<el-button circle type="primary"><elIcon><Download/></elIcon></el-button>
+									<span class="margin-left-xs">导出</span>
+								</div>	
+								<div @click="handleAddSet">
+									<el-button circle type="success"><elIcon><Setting/></elIcon></el-button>
+									<span class="margin-left-xs">设置</span>
+								</div>
+							</div>
+						</el-col>
+					</el-row>
+				</el-form>
+				<el-table :data="alarmLogData" stripe style="width: 100%"
+					height="calc(100vh - 190px)"
+					:cell-style="{ fontSize: '0.75rem' }"
+					:header-cell-style="{ backgroundColor: '#a9cbe2' }">
+					<el-table-column label="id" width="80" align="center">
+						<template #default="scope">
+							<span style="color: #0672fc;" class="text-bold text-sm">{{scope.$index}}</span>
+						</template>
+					</el-table-column>
+					<el-table-column align="center" prop="deviceName" label="设备名称"></el-table-column>
+					<el-table-column align="center" prop="content" label="内容"></el-table-column>
+					<el-table-column align="center" prop="alarmValue" label="数值"></el-table-column>
+					<el-table-column align="center" prop="alarmTime" label="报警时间"></el-table-column>
+					<el-table-column align="center" prop="alarmPosi" label="报警位置"></el-table-column>
+				</el-table>
+			</el-col>
+		</el-row>
+		<alarm-set-drawer ref="AlarmSetDrawerRef"/>
+	</div>
+</template>
+
+<script setup>
+	import { reactive } from "vue";
+	const { proxy } = getCurrentInstance();
+	import AlarmSetDrawer from "@/components/AlarmSetting"
+	import BarChart from "@/components/Echarts/BarChart";
+	import pieCircularChart from "@/components/Echarts/pieCircularChart";
+	import engImg from "@/assets/images/20240529135050.png";
+	const equipmentType = ref('engineRoom');
+	const data = reactive({
+		tabEquipment: [{
+			name: "机舱",
+			type: "engineRoom"
+		},{
+			name: "发电机",
+			type: "alternator"
+		},{
+			name: "锅炉",
+			type: "boiler"
+		}],
+		refuelForm: {},
+		alarmRepoData: {
+			name: "报警统计",
+			xAxis: ["一月", "二月", "三月", "四月", "五月", "六月"],
+			data: [{
+				name: '主机',
+				type: 'bar',
+				color: "#ffa300",
+				data: [15.3, 26.1, 14.1, 16.1, 13.1, 16.4]
+			},{
+				name: '发电机',
+				type: 'bar',
+				color: "#0672fc",
+				data: [10, 14, 18, 19, 13, 10]
+			},{
+				name: '锅炉',
+				type: 'bar',
+				color: "#00ffd9",
+				data: [15.28, 42.4, 31.8, 21.9, 11.3, 10.6]
+			}],
+		},
+		alarmProportion: {
+			title: "报警占比",
+			name: "alarmPropCons",
+			data: [{
+				value: 10,
+				name: "主机"
+			},{
+				value: 20,
+				name: "辅机"
+			},{
+				value: 30,
+				name: "锅炉"
+			}]
+		},
+		alarmLogData: [{
+			deviceName: "主机转速",
+			content: "主机转速过高",
+			alarmTime: "2024-06-20 15:35:36",
+			alarmPosi: "",
+			alarmValue: "2999"
+		},{
+			deviceName: "机油温度",
+			content: "机油温度过高",
+			alarmTime: "2024-06-02 09:16:36",
+			alarmPosi: "",
+			alarmValue: "106"
+		},{
+			deviceName: "主机转速",
+			content: "主机转速过高",
+			alarmTime: "2024-06-20 15:35:36",
+			alarmPosi: "",
+			alarmValue: "2999"
+		},{
+			deviceName: "主机转速",
+			content: "主机转速过高",
+			alarmTime: "2024-06-20 15:35:36",
+			alarmPosi: "",
+			alarmValue: "2999"
+		},{
+			deviceName: "主机转速",
+			content: "主机转速过高",
+			alarmTime: "2024-06-20 15:35:36",
+			alarmPosi: "",
+			alarmValue: "2999"
+		},{
+			deviceName: "主机转速",
+			content: "主机转速过高",
+			alarmTime: "2024-06-20 15:35:36",
+			alarmPosi: "",
+			alarmValue: "2999"
+		},{
+			deviceName: "主机转速",
+			content: "主机转速过高",
+			alarmTime: "2024-06-20 15:35:36",
+			alarmPosi: "",
+			alarmValue: "2999"
+		},{
+			deviceName: "主机转速",
+			content: "主机转速过高",
+			alarmTime: "2024-06-20 15:35:36",
+			alarmPosi: "",
+			alarmValue: "2999"
+		}]
+	});
+	const { alarmLogData, refuelForm, alarmProportion, alarmRepoData, tabEquipment } = toRefs(data);
+	const handleChange = function(val){
+		equipmentType.value = val;
+	}
+	const handleAddSet = function(){
+		proxy.$refs["AlarmSetDrawerRef"].show()
+	}
+</script>
+
+
+<style scoped lang="scss">
+	.box-card{
+		border-radius: 16px;
+		box-shadow: 0 0 4px 1px #ccc;
+	}
+	::v-deep .el-table__body tr.el-table__row--striped td.el-table__cell{
+		background-color: #a9cbe2;
+	}
+</style>

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff