Browse Source

提交大屏内容

luogang 9 months ago
parent
commit
e2cd5c10bb
100 changed files with 4287 additions and 13 deletions
  1. 1 1
      demo/ny_code/src/views/net/right.vue
  2. 1 0
      ems-ui/package.json
  3. BIN
      ems-ui/src/assets/images/center.jpg
  4. BIN
      ems-ui/src/assets/images/device/l1-pie_bg.png
  5. BIN
      ems-ui/src/assets/images/device/l2-item1_bg.png
  6. BIN
      ems-ui/src/assets/images/device/l2-item2_bg.png
  7. BIN
      ems-ui/src/assets/images/device/l2-item3_bg.png
  8. BIN
      ems-ui/src/assets/images/device/l2-top_bg.png
  9. BIN
      ems-ui/src/assets/images/device/l3-item_bg.png
  10. BIN
      ems-ui/src/assets/images/device/r1-alarm.png
  11. 1 0
      ems-ui/src/assets/images/home/cost.svg
  12. 1 0
      ems-ui/src/assets/images/home/down-arrow.svg
  13. BIN
      ems-ui/src/assets/images/home/icon1.png
  14. BIN
      ems-ui/src/assets/images/home/icon2.png
  15. BIN
      ems-ui/src/assets/images/home/icon3.png
  16. BIN
      ems-ui/src/assets/images/home/icon4.png
  17. BIN
      ems-ui/src/assets/images/home/l1_item_bg.png
  18. BIN
      ems-ui/src/assets/images/home/l2-top_bg.png
  19. BIN
      ems-ui/src/assets/images/home/l2-top_center.png
  20. BIN
      ems-ui/src/assets/images/home/l2-top_center_.png
  21. BIN
      ems-ui/src/assets/images/home/l2_item_bg.png
  22. BIN
      ems-ui/src/assets/images/home/r1-left_bg.png
  23. BIN
      ems-ui/src/assets/images/home/r1-pie_bg.png
  24. BIN
      ems-ui/src/assets/images/home/r1-right_item1.png
  25. BIN
      ems-ui/src/assets/images/home/r1-right_item2.png
  26. BIN
      ems-ui/src/assets/images/home/r1-top_center.png
  27. 0 0
      ems-ui/src/assets/images/home/tianqi.svg
  28. 1 0
      ems-ui/src/assets/images/home/up-arrow.svg
  29. 0 0
      ems-ui/src/assets/images/home/water.svg
  30. BIN
      ems-ui/src/assets/images/layout/footer.png
  31. BIN
      ems-ui/src/assets/images/layout/footer/center.png
  32. BIN
      ems-ui/src/assets/images/layout/footer/center_.png
  33. BIN
      ems-ui/src/assets/images/layout/footer/item.png
  34. BIN
      ems-ui/src/assets/images/layout/footer/iteml.png
  35. BIN
      ems-ui/src/assets/images/layout/footer/iteml_.png
  36. BIN
      ems-ui/src/assets/images/layout/footer/itemr.png
  37. BIN
      ems-ui/src/assets/images/layout/footer/itemr_.png
  38. BIN
      ems-ui/src/assets/images/layout/footer/itemr___.png
  39. BIN
      ems-ui/src/assets/images/layout/head.png
  40. BIN
      ems-ui/src/assets/images/layout/left.png
  41. BIN
      ems-ui/src/assets/images/layout/left_top.png
  42. BIN
      ems-ui/src/assets/images/layout/left_top2.png
  43. BIN
      ems-ui/src/assets/images/layout/right.png
  44. BIN
      ems-ui/src/assets/images/layout/right_top.png
  45. BIN
      ems-ui/src/assets/images/layout/right_top2.png
  46. BIN
      ems-ui/src/assets/images/net/l1-item_bg.png
  47. 1 0
      ems-ui/src/assets/images/net/price1.svg
  48. 0 0
      ems-ui/src/assets/images/net/price2.svg
  49. 0 0
      ems-ui/src/assets/images/net/price3.svg
  50. 0 0
      ems-ui/src/assets/images/net/price4.svg
  51. BIN
      ems-ui/src/assets/images/net/r1-item_bg.png
  52. BIN
      ems-ui/src/assets/images/net/r1-top.png
  53. BIN
      ems-ui/src/assets/images/net/r2-top_bg.png
  54. BIN
      ems-ui/src/assets/images/soc/item1.png
  55. BIN
      ems-ui/src/assets/images/soc/item2.png
  56. BIN
      ems-ui/src/assets/images/soc/item3.png
  57. BIN
      ems-ui/src/assets/images/soc/l-item1.png
  58. BIN
      ems-ui/src/assets/images/soc/l-item2.png
  59. BIN
      ems-ui/src/assets/images/soc/l-item3.png
  60. BIN
      ems-ui/src/assets/images/soc/l1_bg.png
  61. BIN
      ems-ui/src/assets/images/soc/l2-pie_bg.png
  62. BIN
      ems-ui/src/assets/images/soc/r2-list.png
  63. 1 0
      ems-ui/src/assets/images/source/elec1.svg
  64. 0 0
      ems-ui/src/assets/images/source/elec2.svg
  65. 0 0
      ems-ui/src/assets/images/source/elec3.svg
  66. 0 0
      ems-ui/src/assets/images/source/elec4.svg
  67. BIN
      ems-ui/src/assets/images/source/item_bg1.png
  68. BIN
      ems-ui/src/assets/images/source/item_bg3.png
  69. BIN
      ems-ui/src/assets/images/source/item_bg4.png
  70. BIN
      ems-ui/src/assets/images/source/l1-item1.png
  71. BIN
      ems-ui/src/assets/images/source/l1-item2.png
  72. BIN
      ems-ui/src/assets/images/source/l1-item3.png
  73. BIN
      ems-ui/src/assets/images/source/l1-top.png
  74. BIN
      ems-ui/src/assets/images/storage/item1.png
  75. BIN
      ems-ui/src/assets/images/storage/item2.png
  76. BIN
      ems-ui/src/assets/images/storage/item3.png
  77. 1 0
      ems-ui/src/assets/images/title/dec.svg
  78. BIN
      ems-ui/src/assets/images/title/dian.png
  79. BIN
      ems-ui/src/assets/images/title/index.png
  80. 1 0
      ems-ui/src/assets/images/title/title.svg
  81. 1 0
      ems-ui/src/assets/images/title/title1.svg
  82. 12 0
      ems-ui/src/layout/components/Navbar.vue
  83. 93 12
      ems-ui/src/router/index.js
  84. 27 0
      ems-ui/src/views/largeScreen/center.vue
  85. 82 0
      ems-ui/src/views/largeScreen/components/AppLink.vue
  86. 54 0
      ems-ui/src/views/largeScreen/components/CusModule.vue
  87. 173 0
      ems-ui/src/views/largeScreen/components/CusProgress.vue
  88. 61 0
      ems-ui/src/views/largeScreen/components/CusTabs.vue
  89. 340 0
      ems-ui/src/views/largeScreen/device/left.vue
  90. 381 0
      ems-ui/src/views/largeScreen/device/right.vue
  91. 165 0
      ems-ui/src/views/largeScreen/footer.vue
  92. 383 0
      ems-ui/src/views/largeScreen/home/left.vue
  93. 381 0
      ems-ui/src/views/largeScreen/home/right.vue
  94. 8 0
      ems-ui/src/views/largeScreen/index.scss
  95. 230 0
      ems-ui/src/views/largeScreen/index.vue
  96. 394 0
      ems-ui/src/views/largeScreen/net/left.vue
  97. 413 0
      ems-ui/src/views/largeScreen/net/right.vue
  98. 355 0
      ems-ui/src/views/largeScreen/soc/left.vue
  99. 439 0
      ems-ui/src/views/largeScreen/soc/right.vue
  100. 286 0
      ems-ui/src/views/largeScreen/source/left.vue

+ 1 - 1
demo/ny_code/src/views/net/right.vue

@@ -10,7 +10,7 @@ const { lineOption, itemList } = useRight();
       <div
         class="h-[90px] bg-[url('assets/images/net/r1-top.png')] bg-center flex items-center justify-center"
       >
-        <span class="text-[#B3E3E8] text-xs">保护:</span>
+        <span class="text-[#B3E3E8] text-xs ">保护:</span>
         <span class="value">正常</span>
       </div>
       <div class="flex justify-between">

+ 1 - 0
ems-ui/package.json

@@ -40,6 +40,7 @@
   "dependencies": {
     "@antv/x6": "^2.18.1",
     "@riophae/vue-treeselect": "^0.4.0",
+    "autofit.js": "^3.1.3",
     "axios": "0.24.0",
     "clipboard": "2.0.8",
     "core-js": "^3.25.3",

BIN
ems-ui/src/assets/images/center.jpg


BIN
ems-ui/src/assets/images/device/l1-pie_bg.png


BIN
ems-ui/src/assets/images/device/l2-item1_bg.png


BIN
ems-ui/src/assets/images/device/l2-item2_bg.png


BIN
ems-ui/src/assets/images/device/l2-item3_bg.png


BIN
ems-ui/src/assets/images/device/l2-top_bg.png


BIN
ems-ui/src/assets/images/device/l3-item_bg.png


BIN
ems-ui/src/assets/images/device/r1-alarm.png


+ 1 - 0
ems-ui/src/assets/images/home/cost.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="1728635985572" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="76396" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M326.523 138.551a11.328 11.328 0 0 1-0.5-3.226c0 4.717-0.54 5.2 0.54 3.33-0.001-0.034-0.04-0.069-0.04-0.104z m-0.347 4.786l78 91.315H619.9s116.109-91.766 61.619-110.91c0 0-54.876-28.23-184.9-27.745-142.084 0.52-166.323 36.242-170.061 42.658 0.269 0.867 0.539 1.734 0.809 2.566zM619.9 262.4H404.173C235.193 314.489 96 485.883 96 644.1 96 835.089 218.93 928 512 928s416-92.911 416-283.9c0.034-158.217-139.119-329.611-308.1-381.7z m20.5 337.483v55.455h-92.447v27.745H640.4v55.455l-92.448-0.624v56.114H486.3v-56.567l-92.411-0.658v-53.722H486.3v-27.745h-92.416v-55.455h79.154l-79.154-138.656H455.5l61.621 138.656 61.657-138.656H640.4l-76.724 138.656H640.4z" fill="#C2F4FF" p-id="76397"></path></svg>

+ 1 - 0
ems-ui/src/assets/images/home/down-arrow.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="1728635651065" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="73665" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M573.056 752l308.8-404.608A76.8 76.8 0 0 0 820.736 224H203.232a76.8 76.8 0 0 0-61.056 123.392l308.8 404.608a76.8 76.8 0 0 0 122.08 0z" fill="#00C852" p-id="73666"></path></svg>

BIN
ems-ui/src/assets/images/home/icon1.png


BIN
ems-ui/src/assets/images/home/icon2.png


BIN
ems-ui/src/assets/images/home/icon3.png


BIN
ems-ui/src/assets/images/home/icon4.png


BIN
ems-ui/src/assets/images/home/l1_item_bg.png


BIN
ems-ui/src/assets/images/home/l2-top_bg.png


BIN
ems-ui/src/assets/images/home/l2-top_center.png


BIN
ems-ui/src/assets/images/home/l2-top_center_.png


BIN
ems-ui/src/assets/images/home/l2_item_bg.png


BIN
ems-ui/src/assets/images/home/r1-left_bg.png


BIN
ems-ui/src/assets/images/home/r1-pie_bg.png


BIN
ems-ui/src/assets/images/home/r1-right_item1.png


BIN
ems-ui/src/assets/images/home/r1-right_item2.png


BIN
ems-ui/src/assets/images/home/r1-top_center.png


File diff suppressed because it is too large
+ 0 - 0
ems-ui/src/assets/images/home/tianqi.svg


+ 1 - 0
ems-ui/src/assets/images/home/up-arrow.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="1728635680397" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="73903" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M573.056 272l308.8 404.608A76.8 76.8 0 0 1 820.736 800H203.232a76.8 76.8 0 0 1-61.056-123.392L450.976 272a76.8 76.8 0 0 1 122.08 0z" fill="#d81e06" p-id="73904"></path></svg>

File diff suppressed because it is too large
+ 0 - 0
ems-ui/src/assets/images/home/water.svg


BIN
ems-ui/src/assets/images/layout/footer.png


BIN
ems-ui/src/assets/images/layout/footer/center.png


BIN
ems-ui/src/assets/images/layout/footer/center_.png


BIN
ems-ui/src/assets/images/layout/footer/item.png


BIN
ems-ui/src/assets/images/layout/footer/iteml.png


BIN
ems-ui/src/assets/images/layout/footer/iteml_.png


BIN
ems-ui/src/assets/images/layout/footer/itemr.png


BIN
ems-ui/src/assets/images/layout/footer/itemr_.png


BIN
ems-ui/src/assets/images/layout/footer/itemr___.png


BIN
ems-ui/src/assets/images/layout/head.png


BIN
ems-ui/src/assets/images/layout/left.png


BIN
ems-ui/src/assets/images/layout/left_top.png


BIN
ems-ui/src/assets/images/layout/left_top2.png


BIN
ems-ui/src/assets/images/layout/right.png


BIN
ems-ui/src/assets/images/layout/right_top.png


BIN
ems-ui/src/assets/images/layout/right_top2.png


BIN
ems-ui/src/assets/images/net/l1-item_bg.png


+ 1 - 0
ems-ui/src/assets/images/net/price1.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="1728890547978" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3789" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M512 0L51.2 281.6v460.8L512 1024l460.8-281.6v-460.8L512 0z m204.8 512h-153.6v51.2h153.6v102.4h-153.6v153.6H460.8v-153.6H307.2v-102.4h153.6v-51.2H307.2V409.6h153.6L358.4 307.2l51.2-51.2 102.4 102.4 102.4-102.4 51.2 51.2-102.4 102.4h153.6v102.4z" fill="#B3E3E8" p-id="3790"></path></svg>

File diff suppressed because it is too large
+ 0 - 0
ems-ui/src/assets/images/net/price2.svg


File diff suppressed because it is too large
+ 0 - 0
ems-ui/src/assets/images/net/price3.svg


File diff suppressed because it is too large
+ 0 - 0
ems-ui/src/assets/images/net/price4.svg


BIN
ems-ui/src/assets/images/net/r1-item_bg.png


BIN
ems-ui/src/assets/images/net/r1-top.png


BIN
ems-ui/src/assets/images/net/r2-top_bg.png


BIN
ems-ui/src/assets/images/soc/item1.png


BIN
ems-ui/src/assets/images/soc/item2.png


BIN
ems-ui/src/assets/images/soc/item3.png


BIN
ems-ui/src/assets/images/soc/l-item1.png


BIN
ems-ui/src/assets/images/soc/l-item2.png


BIN
ems-ui/src/assets/images/soc/l-item3.png


BIN
ems-ui/src/assets/images/soc/l1_bg.png


BIN
ems-ui/src/assets/images/soc/l2-pie_bg.png


BIN
ems-ui/src/assets/images/soc/r2-list.png


+ 1 - 0
ems-ui/src/assets/images/source/elec1.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="1728716516438" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="80901" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M910.29248 0H113.705813A57.173333 57.173333 0 0 0 56.959147 56.746667V853.333333a56.746667 56.746667 0 0 0 56.746666 56.746667h85.333334V1024H312.959147v-113.92h144.64V1024h115.2v-113.92h138.24V1024H824.959147v-113.92h85.333333A56.32 56.32 0 0 0 967.039147 853.333333V56.746667A56.746667 56.746667 0 0 0 910.29248 0z m6.4 810.666667A50.346667 50.346667 0 0 1 867.625813 862.72H158.079147A50.346667 50.346667 0 0 1 107.305813 810.666667V104.106667a50.346667 50.346667 0 0 1 50.773334-50.346667H867.625813a50.346667 50.346667 0 0 1 50.773334 50.346667z" p-id="80902" fill="#B3E3E8"></path><path d="M621.01248 184.32L205.01248 512h252.16l-113.493333 226.986667 416-327.68h-252.16l113.493333-226.986667z" p-id="80903" fill="#B3E3E8"></path></svg>

File diff suppressed because it is too large
+ 0 - 0
ems-ui/src/assets/images/source/elec2.svg


File diff suppressed because it is too large
+ 0 - 0
ems-ui/src/assets/images/source/elec3.svg


File diff suppressed because it is too large
+ 0 - 0
ems-ui/src/assets/images/source/elec4.svg


BIN
ems-ui/src/assets/images/source/item_bg1.png


BIN
ems-ui/src/assets/images/source/item_bg3.png


BIN
ems-ui/src/assets/images/source/item_bg4.png


BIN
ems-ui/src/assets/images/source/l1-item1.png


BIN
ems-ui/src/assets/images/source/l1-item2.png


BIN
ems-ui/src/assets/images/source/l1-item3.png


BIN
ems-ui/src/assets/images/source/l1-top.png


BIN
ems-ui/src/assets/images/storage/item1.png


BIN
ems-ui/src/assets/images/storage/item2.png


BIN
ems-ui/src/assets/images/storage/item3.png


+ 1 - 0
ems-ui/src/assets/images/title/dec.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="1728608573065" class="icon" viewBox="0 0 38103 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="57618" xmlns:xlink="http://www.w3.org/1999/xlink" width="1190.71875" height="32"><path d="M1024 29.789091h18432l1210.181818 930.909091H0L1024 29.789091zM24732.392727 1024h-1057.512727l-744.727273-930.909091h1057.512728l744.727272 930.909091z" fill="#1396DB" p-id="57619"></path><path d="M24732.392727 930.909091h-1057.512727l-744.727273-930.909091h1057.512728l744.727272 930.909091zM27405.963636 930.909091h-1053.789091l-744.727272-930.909091h1053.789091l744.727272 930.909091zM30079.534545 930.909091h-1053.78909l-744.727273-930.909091h1053.789091l744.727272 930.909091zM32756.829091 930.909091h-1057.512727l-744.727273-930.909091h1057.512727l744.727273 930.909091zM35430.4 930.909091h-1053.789091l-744.727273-930.909091h1053.789091l744.727273 930.909091zM38103.970909 930.909091H37050.181818l-744.727273-930.909091h1053.789091l744.727273 930.909091z" fill="#1396DB" p-id="57620"></path></svg>

BIN
ems-ui/src/assets/images/title/dian.png


BIN
ems-ui/src/assets/images/title/index.png


+ 1 - 0
ems-ui/src/assets/images/title/title.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="1728559473057" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="43703" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M447.226703 147.463062L550.841379 251.077738 289.919117 512 550.841379 772.922262l-103.614676 103.614676a28.248276 28.248276 0 0 1-39.943062 0l-344.558344-344.558345a28.248276 28.248276 0 0 1 0-39.950124l344.558344-344.558345a28.248276 28.248276 0 0 1 39.943062 0z m247.172414 74.907366l269.658042 269.658041a28.248276 28.248276 0 0 1 0 39.943062l-269.658042 269.658041a28.248276 28.248276 0 0 1-39.943062 0L384.798014 531.971531a28.248276 28.248276 0 0 1 0-39.943062l269.658041-269.658041a28.248276 28.248276 0 0 1 39.943062 0z" p-id="43704" fill="#22A7DB"></path></svg>

+ 1 - 0
ems-ui/src/assets/images/title/title1.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="1728608480738" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="49247" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M928 512l-529.472 512V0z" fill="#194A75" p-id="49248"></path><path d="M625.472 512L96 1024V0z" fill="#33D9FB" p-id="49249"></path></svg>

+ 12 - 0
ems-ui/src/layout/components/Navbar.vue

@@ -7,6 +7,7 @@
 
     <div class="right-menu">
       <template v-if="device!=='mobile'">
+        <div class="large-screen" @click="toLarge">监控大屏</div>
         <search id="header-search" class="right-menu-item" />
 
         <el-tooltip content="源码地址" effect="dark" placement="bottom">
@@ -105,6 +106,9 @@ export default {
           location.href = '/index';
         })
       }).catch(() => {});
+    },
+    toLarge () {
+      window.open('/largeScreen')
     }
   }
 }
@@ -149,6 +153,14 @@ export default {
     float: right;
     height: 100%;
     line-height: 50px;
+    .large-screen{
+      display: inline-block;
+      color: #409EFF;
+      position: relative;
+      top: -15px;
+      margin-right: 50px;
+      cursor: pointer;
+    }
 
     &:focus {
       outline: none;

+ 93 - 12
ems-ui/src/router/index.js

@@ -1,11 +1,11 @@
-import Vue from 'vue'
-import Router from 'vue-router'
+import Vue from 'vue';
+import Router from 'vue-router';
 
-Vue.use(Router)
+Vue.use(Router);
 
 /* Layout */
-import Layout from '@/layout'
-
+import Layout from '@/layout';
+import LargeScreen from '@/views/largeScreen/index.vue'
 /**
  * Note: 路由配置项
  *
@@ -61,6 +61,87 @@ export const constantRoutes = [
     component: () => import('@/views/error/401'),
     hidden: true
   },
+  //智慧园区管理平台
+  {
+    path: '/largeScreen',
+    name: 'largeScreen',
+    redirect: { name: 'soc' },
+    component: LargeScreen,
+    children: [
+      {
+        path: 'home',
+        name: 'home',
+        meta: {
+          title: '首页'
+        },
+        components: {
+          default:() => import('@/views/largeScreen/center.vue'),
+          left: () => import('@/views/largeScreen/home/left.vue'),
+          right: () => import('@/views/largeScreen/home/right.vue')
+        }
+      },
+      {
+        path: 'source',
+        name: 'source',
+        meta: {
+          title: '源'
+        },
+        components: {
+          default:() => import('@/views/largeScreen/center.vue'),
+          left: () => import('@/views/largeScreen/source/left.vue'),
+          right: () => import('@/views/largeScreen/source/right.vue')
+        }
+      },
+      {
+        path: 'storage',
+        name: 'storage',
+        meta: {
+          title: '储'
+        },
+        components: {
+          default:() => import('@/views/largeScreen/center.vue'),
+          left: () => import('@/views/largeScreen/storage/left.vue'),
+          right: () => import('@/views/largeScreen/storage/right.vue')
+        }
+      },
+      {
+        path: 'soc',
+        name: 'soc',
+        meta: {
+          title: '荷'
+        },
+        components: {
+          default:() => import('@/views/largeScreen/center.vue'),
+          left: () => import('@/views/largeScreen/soc/left.vue'),
+          right: () => import('@/views/largeScreen/soc/right.vue')
+        }
+      },
+      {
+        path: 'net',
+        name: 'net',
+        meta: {
+          title: '网'
+        },
+        components: {
+          default:() => import('@/views/largeScreen/center.vue'),
+          left: () => import('@/views/largeScreen/net/left.vue'),
+          right: () => import('@/views/largeScreen/net/right.vue')
+        }
+      },
+      {
+        path: 'device',
+        name: 'device',
+        meta: {
+          title: '设备'
+        },
+        components: {
+          default:() => import('@/views/largeScreen/center.vue'),
+          left: () => import('@/views/largeScreen/device/left.vue'),
+          right: () => import('@/views/largeScreen/device/right.vue')
+        }
+      }
+    ]
+  },
   {
     path: '',
     component: Layout,
@@ -88,7 +169,7 @@ export const constantRoutes = [
       }
     ]
   }
-]
+];
 
 // 动态路由,基于用户权限动态去加载
 export const dynamicRoutes = [
@@ -162,22 +243,22 @@ export const dynamicRoutes = [
       }
     ]
   }
-]
+];
 
 // 防止连续点击多次路由报错
 let routerPush = Router.prototype.push;
 let routerReplace = Router.prototype.replace;
 // push
 Router.prototype.push = function push(location) {
-  return routerPush.call(this, location).catch(err => err)
-}
+  return routerPush.call(this, location).catch(err => err);
+};
 // replace
 Router.prototype.replace = function push(location) {
-  return routerReplace.call(this, location).catch(err => err)
-}
+  return routerReplace.call(this, location).catch(err => err);
+};
 
 export default new Router({
   mode: 'history', // 去掉url中的#
   scrollBehavior: () => ({ y: 0 }),
   routes: constantRoutes
-})
+});

+ 27 - 0
ems-ui/src/views/largeScreen/center.vue

@@ -0,0 +1,27 @@
+<template>
+  <div class="center">
+    <!-- <img src="@/assets/images/center.jpg" alt=""> -->
+  </div>
+</template>
+<script>
+export default {
+name: 'index',
+  data () {
+    return {
+    };
+  },
+  components: {},
+  computed: {},
+  mounted(){},
+  methods: {}
+}
+</script>
+<style lang='scss' scoped>
+.center{
+  background: url("~@/assets/images/center.jpg") no-repeat;
+  background-size:cover ;
+  width: calc(100% - 806px);
+  margin:auto auto 0;
+  height: calc(100% - 90px);
+}
+</style>

+ 82 - 0
ems-ui/src/views/largeScreen/components/AppLink.vue

@@ -0,0 +1,82 @@
+<template>
+  <a v-if="isExternalLink" v-bind="$attrs" :href="to" target="_blank">
+    <slot />
+  </a>
+  <router-link
+    v-else
+    v-bind="$attrs"
+    :to="to"
+    :exact="exact"
+    :active-class="activeClass"
+  >
+    <a
+      v-bind="$attrs"
+      :href="to"
+      @click="handleClick"
+      :class="isActive ? activeClass : inactiveClass"
+    >
+      <slot />
+    </a>
+  </router-link>
+</template>
+
+<script>
+
+export default {
+  name: 'AppLink',
+  inheritAttrs: false,
+
+  props: {
+    to: {
+      type: [String, Object],
+      required: true,
+    },
+    exact: {
+      type: Boolean,
+      default: false,
+    },
+    activeClass: {
+      type: String,
+      default: 'router-link-active',
+    },
+    inactiveClass: {
+      type: String,
+      default: '',
+    },
+  },
+
+  data() {
+    return {
+      isActive: false,
+    };
+  },
+
+  watch: {
+    '$route.path': function(newPath) {
+      this.isActive = this.isActiveRoute(newPath);
+    },
+  },
+  computed: {
+    isExternalLink() {
+      return typeof this.to === 'string' && this.to.startsWith('http');
+    },
+  },
+  created() {
+    this.isActive = this.isActiveRoute(this.$route.path);
+  },
+
+  methods: {
+    isActiveRoute(path) {
+      if (this.exact) {
+        return path === this.to;
+      } else {
+        return path.startsWith(this.to);
+      }
+    },
+
+    handleClick () {
+      this.$router.push(this.to)
+    },
+  },
+};
+</script>

+ 54 - 0
ems-ui/src/views/largeScreen/components/CusModule.vue

@@ -0,0 +1,54 @@
+<template>
+  <div class="module">
+    <div class="title">
+      <div class="title-name">
+        <img src="@/assets/images/title/title1.svg" alt="">
+        <span>{{ title }}</span>
+      </div>
+      <slot name="title-right"></slot>
+    </div>
+    <div class="content">
+      <slot></slot>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  name: 'CustomModule',
+  props: ['title'],
+  data () {
+    return {
+    };
+  },
+  mounted () { },
+  methods: {}
+}
+</script>
+<style lang='scss' scoped>
+.module {
+  padding: 0 15px 0 10px;
+}
+.title {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  .title-name {
+    display: flex;
+    align-items: center;
+    img {
+      height: 22px;
+    }
+
+    span {
+      font-size: 20px;
+      font-weight: bold;
+      color: #C1D8E3;
+      text-shadow: 0px 2px 2px #333333;
+      margin-left: 5px;
+    }
+  }
+}
+.content {
+  margin-top: 5px;
+}
+</style>

+ 173 - 0
ems-ui/src/views/largeScreen/components/CusProgress.vue

@@ -0,0 +1,173 @@
+<template>
+  <div class="Progress-wrapper" v-bind="$attrs">
+    <template v-if="isMore">
+      <div class="more-item" v-for="(value, index) in values" :key="index" :style="{
+        width: `${widthPercent(value)}%`,
+        backgroundColor: colors[index],
+        height: `${addUnit(strokeWidth)}`
+      }"></div>
+    </template>
+    <template v-else>
+      <div class="wrapper" :style="{
+        height: `${addUnit(strokeWidth)}`
+      }">
+        <div :style="{
+          background: `linear-gradient(90deg, ${gradient})`,
+          width: `${Progress}%`,
+          height: `${addUnit(strokeWidth)}`
+        }"></div>
+      </div>
+      <div class="label" :style="{ width: addUnit(labelWidth) }" v-if="showLabel || showPercent">
+        <span v-if="showLabel">
+          <span class="value">{{ numToStr(value, 0) }}&nbsp;</span>
+          <span class="unit text-xs">{{ unit }}</span>
+        </span>
+        <span v-if="showPercent" class="unit"> {{ Progress }}%</span>
+      </div>
+    </template>
+  </div>
+</template>
+<script>
+export default {
+  name: 'zh-progress',
+  props: {
+    total: {
+      type: Number,
+      default: 100
+    },
+    value: {
+      type: Number,
+      default: 0
+    },
+    color: {
+      type: String,
+      default: '#17caf8'
+    },
+    showLabel: {
+      type: Boolean,
+      default: false
+    },
+    showPercent: {
+      type: Boolean,
+      default: false
+    },
+    unit: {
+      type: String
+    },
+    values: {
+      type: Array,
+      default () {
+        return [1, 2];
+      }
+    },
+    colors: {
+      type: Array,
+      default () {
+        return ['#14b6df', '#06b869'];
+      }
+    },
+    isMore: {
+      type: Boolean,
+      default: false
+    },
+    labelWidth: {
+      type: [Number, String],
+      default: 70
+    },
+    strokeWidth: {
+      type: [Number, String],
+      default: 6
+    }
+  },
+  data () {
+    return {};
+  },
+  computed: {
+    gradient () {
+      return this.hex2Rgba(this.color, 0) + ',' + this.color;
+    },
+    Progress () {
+      return this.getPercent(this.value, this.total, 1);
+    },
+    sum () {
+      return this.values.reduce((sum, value) => sum + Number(value || 0), 0);
+    }
+  },
+  methods: {
+    hex2Rgba (bgColor, alpha = 1) {
+      let color = bgColor.slice(1); // 去掉'#'号
+      let rgba = [
+        parseInt("0x" + color.slice(0, 2)),
+        parseInt("0x" + color.slice(2, 4)),
+        parseInt("0x" + color.slice(4, 6)),
+        alpha,
+      ];
+      return "rgba(" + rgba.toString() + ")";
+    },
+    getPercent (value, total, fixed) {
+      return total && Number(((value / total) * 100).toFixed(fixed));
+    },
+    numToStr (num, fixed = 2) {
+      const million = 10000; // 一万
+      const billion = 100000000; // 一亿
+      let unit = "";
+      let result = Number(num);
+      if (num >= billion) {
+        unit = "亿";
+        result = num / billion;
+      } else if (num >= million) {
+        unit = "万";
+        result = num / million;
+      }
+      return result.toFixed(fixed) + unit;
+    },
+    addUnit (value, defaultUnit = "px") {
+      if (!value) return "";
+      if (typeof (value) == "string") {
+        return value;
+      } else if (typeof (value) == "number") {
+        return `${value}${defaultUnit}`;
+      }
+    },
+    widthPercent (v) {
+      return this.getPercent(v, Number(this.sum), 2);
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+.Progress-wrapper {
+  width: 100%;
+  display: flex;
+  align-items: baseline;
+  .more-item {
+    // height: 10px;
+    border-radius: 8px;
+    margin-right: 2px;
+    &:last-of-type {
+      margin-right: 0;
+    }
+  }
+  .wrapper {
+    width: 100%;
+    // height: 10px;
+    border-radius: 10px;
+    background-color: rgba(9, 67, 119, 1);
+    // overflow: hidden;
+    div {
+      position: relative;
+      height: 100%;
+      border-radius: 10px;
+      z-index: 1;
+    }
+  }
+  .label {
+    display: flex;
+    flex-direction: column;
+    > span {
+      font-size: 14px;
+      margin-left: 10px;
+    }
+  }
+}
+</style>

+ 61 - 0
ems-ui/src/views/largeScreen/components/CusTabs.vue

@@ -0,0 +1,61 @@
+<template>
+  <div class="tabs">
+    <div :class="{ 'tab-selected': active == item.value }" v-for="item in tabs" :key="item.value"
+      @click="tabClick(item)">{{ item.name }}</div>
+  </div>
+</template>
+<script>
+export default {
+  name: 'CustomTabs',
+  props: {
+    tabs: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    active: {
+      type: String | Number,
+      default:null
+    }
+  },
+  data () {
+    return {
+    };
+  },
+  mounted () { },
+  methods: {
+    tabClick (item) {
+      this.$emit('update:active', item.value)
+      this.$emit('tab-click', item)
+    }
+  }
+}
+</script>
+<style lang='scss' scoped>
+.tabs {
+  display: flex;
+
+  >div {
+    padding: 2px 8px;
+    background: #184770;
+    color: #C1D8E3;
+    cursor: pointer;
+    border: none;
+    font-size: 16px;
+    &:first-of-type {
+      border-radius: 4px 0 0 4px;
+    }
+
+    &:last-of-type {
+      border-radius: 0 4px 4px 0;
+    }
+  }
+
+  .tab-selected {
+    background: #fff;
+    color: #000;
+    border-radius: 4px !important;
+  }
+}
+</style>

+ 340 - 0
ems-ui/src/views/largeScreen/device/left.vue

@@ -0,0 +1,340 @@
+<template>
+  <div>
+    <CusModule title="产能情况">
+      <CusTabs slot="title-right" :tabs="dateTabs" :active.sync="dateType" @tab-click="dateTabClick" />
+      <div class="production">
+        <div v-for="i in productionList" :key="i.id" class="production-item"
+          :style="{ backgroundImage: `url(${i.image})` }">
+          <div class="item-value">
+            <span class="value">{{ i.value }}</span>
+            <span class="unit">{{ i.unit }}</span>
+          </div>
+          <div class="item-name">{{ i.name }}</div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="用能情况">
+      <CusTabs slot="title-right" :tabs="buildingTabs" :active.sync="buildingType" />
+      <BaseChart width="100%" height="300px" :option="usePieOptions"></BaseChart>
+    </CusModule>
+    <CusModule class="module-top" title="储能数据">
+      <div class="storage-container">
+        <div class="center-spinner"></div>
+        <div class="percentage-display">
+          <span class="value">100</span><span class="unit">%</span>
+        </div>
+        <div class="charge-status">
+          实时充电量
+        </div>
+      </div>
+      <div class="storage-grid">
+        <div class="grid-item" v-for="i in storageData" :key="i.name">
+          <div class="image-container">
+            <img :src="i.image" alt="" />
+          </div>
+          <div class="item-details">
+            <div class="item-value">
+              <span class="value">{{ i.value }}</span>
+              <span class="unit">{{ i.unit }}</span>
+            </div>
+            <div class="item-name">{{ i.name }}</div>
+          </div>
+        </div>
+      </div>
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusTabs from '../components/CusTabs.vue';
+import CusModule from '../components/CusModule.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+
+export default {
+  name:'HomeLeft',
+  data () {
+    return {
+      dateType: '1',
+      dateTabs: [{name: '当日', value: '1'}, {name: '本周', value: '2'}, {name: '本月', value: '3'}, {name: '本年', value: '4'}],
+      productionList: [
+        {
+          name: "装机容量",
+          value: 100,
+          unit: "kW",
+          image: require("@/assets/images/source/item_bg1.png"),
+        },
+        {
+          name: "光伏发电量",
+          value: 86.3,
+          unit: "kWh",
+          image: require("@/assets/images/source/item_bg1.png"),
+        },
+        {
+          name: "负荷消耗",
+          value: 82.1,
+          unit: "kWh",
+          image: require("@/assets/images/source/item_bg3.png"),
+        },
+        {
+          name: "入网",
+          value: 78.09,
+          unit: "kWh",
+          image: require("@/assets/images/source/item_bg4.png"),
+        },
+      ],
+      buildingType: '1',
+      buildingTabs: [{name: '按建筑', value: '1'}, {name: '按设施', value: '2'}],
+      useStorage: [
+        {
+          name: "配电泵房",
+          value: 100
+        },
+        {
+          name: "北区综合楼",
+          value: 500
+        },
+        {
+          name: "南区综合楼",
+          value: 300
+        },
+        {
+          name: "北区加油站",
+          value: 200
+        },
+        {
+          name: "南区加油站",
+          value: 100
+        },
+        {
+          name: "北区停车场",
+          value: 100
+        },
+        {
+          name: "南区停车场",
+          value: 80
+        },
+      ],
+      storageData: [
+        {
+          name: "今日充电",
+          image: require("@/assets/images/home/icon1.png"),
+          value: 250,
+          unit: "kWh",
+        },
+        {
+          name: "今日放电",
+          image: require("@/assets/images/home/icon2.png"),
+          value: 58,
+          unit: "kWh",
+        },
+        {
+          name: "电池温度",
+          image: require("@/assets/images/home/icon3.png"),
+          value: 36,
+          unit: "°C",
+        },
+        {
+          name: "累计充电次数",
+          image: require("@/assets/images/home/icon4.png"),
+          value: 289,
+          unit: "次",
+        },
+      ]
+    };
+  },
+  components: {
+    CusModule,
+    CusTabs,
+    BaseChart
+  },
+  computed: {
+    usePieOptions () {
+      return {
+        calculable: true,
+        tooltip: {
+          trigger: 'item',
+          formatter: (params) => {
+            const {name, value, percent, seriesName} = params
+            if (seriesName != '透明圆圈') {
+              return `${name} : ${value} (${percent}%)`
+            }
+            return ''
+          }
+        },
+        series: [
+          {
+            name: '',
+            type: 'pie',
+            clockWise: false,
+            radius: ['10%', '70%'],
+            center: ['50%', '50%'],
+            roseType: 'area',
+            data: this.useStorage,
+            label: {
+              color: '#fff',
+              formatter: "{b} : {d}%",
+              padding: [0, -75]
+            },
+            labelLine: {
+              normal: {
+                show: true,
+                length: 10,
+                length2: 20,
+              }
+            },
+          },
+          {
+            name: '透明圆圈',
+            type: 'pie',
+            radius: [10, 27],
+            center: ['50%', '50%'],
+            itemStyle: {
+              color: 'rgba(250, 250, 250, 0.3)',
+            },
+            data: [
+              {value: 10, name: ''}
+            ]
+          },
+          {
+            name: '透明圆圈',
+            type: 'pie',
+            radius: [10, 35],
+            center: ['50%', '50%'],
+            itemStyle: {
+              color: 'rgba(250, 250, 250, 0.3)',
+            },
+            data: [
+              {value: 10, name: ''}
+            ]
+          }
+        ]
+
+      };
+
+    }
+  },
+  mounted () { },
+  methods: {
+    dateTabClick () { }
+  }
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+.production {
+  display: flex;
+  flex-wrap: wrap;
+
+  .production-item {
+    height: 51px;
+    flex-basis: 50%;
+    background-repeat: no-repeat;
+    display: flex;
+    flex-direction: column;
+    padding-left: 70px;
+    padding-top: 10px;
+    margin-top: 15px;
+
+    .item-name {
+      font-size: 12px;
+    }
+
+    .item-value {
+      .value {
+        color: #07e3f9;
+        font-weight: bold;
+        font-size: 20px;
+      }
+
+      .unit {
+        color: #768f95;
+        font-size: 12px;
+        margin-left: 2px;
+      }
+    }
+  }
+}
+.storage-container {
+  position: relative;
+  margin-top: 8px;
+  width: 335px;
+  height: 172px;
+  background-image: url('~@/assets/images/home/l2-top_bg.png');
+
+  .center-spinner {
+    position: absolute;
+    animation: spin 10s linear infinite;
+    left: calc(50% - 61.5px);
+    top: 0;
+    width: 123px;
+    height: 123px;
+    background-image: url('~@/assets/images/home/l2-top_center.png');
+  }
+  .percentage-display {
+    position: absolute;
+    left: 50%;
+    top: 44px;
+    transform: translateX(-50%);
+    span.value {
+      font-size: 36px;
+    }
+    span.unit {
+      font-size: inherit;
+    }
+  }
+
+  .charge-status {
+    position: absolute;
+    bottom: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+    color: #B3E3E8;
+    font-size: 14px;
+  }
+}
+
+.storage-grid {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.grid-item {
+  flex-basis: 50%;
+  height: 62px;
+  display: flex;
+  background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
+  &:nth-child(n+3){
+    margin-top: 10px;
+  }
+  .image-container {
+    width: 90px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .item-details {
+    width: calc(100% - 22px);
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    margin-left: 5px;
+    color: #B3E3E8;
+
+    .item-value {
+      span.value {
+        font-size: 20px;
+        font-weight: bold;
+      }
+      span.unit {
+        color: #768f95;
+        font-size: 12px;
+        margin-left: 2px;
+      }
+    }
+
+    .item-name {
+      font-size: 12px;
+    }
+  }
+}
+</style>

+ 381 - 0
ems-ui/src/views/largeScreen/device/right.vue

@@ -0,0 +1,381 @@
+<template>
+  <div>
+    <CusModule title="节能分析">
+      <div class="grid-container">
+        <div class="left-panel">
+          <div class="spinner"></div>
+          <div class="value-display">
+            <span class="value">2589</span>
+            <span class="unit">度</span>
+          </div>
+          <div class="description">
+            <span class="text">本月用电量</span>
+            <div class="rate">
+              <span>环比</span>
+              <img src="@/assets/images/home/down-arrow.svg" alt="">
+              <span>12%</span>
+            </div>
+          </div>
+        </div>
+        <div class="right-panel ">
+          <div class="panel-content">
+            <div class="image-container">
+              <img src="@/assets/images/home/water.svg" alt="">
+            </div>
+            <div class="whitespace-pre">
+              <span class="value">989</span>
+              <span class="unit">吨</span>
+              <div class="label">本月用水量</div>
+              <div class="rate">
+                <span>环比</span>
+                <img src="@/assets/images/home/down-arrow.svg" alt="">
+                <span>12%</span>
+              </div>
+            </div>
+          </div>
+          <div class="panel-content">
+            <div class="image-container">
+              <img src="@/assets/images/home/cost.svg" alt="">
+            </div>
+            <div class="whitespace-pre">
+              <span class="value">4892</span>
+              <span class="unit">元</span>
+              <div class="label">本月用能费用</div>
+              <div class="rate">
+                <span>环比</span>
+                <img src="@/assets/images/home/down-arrow.svg" alt="">
+                <span>12%</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="设备设施">
+      <div class="equip">
+        <div v-for="item in equipment" :style="{ 'color': item.color }" class="equip-item" :key="item.name">
+          <div><span>{{ item.value }}</span> <span class="unit">{{ item.unit }}</span></div>
+          <div>{{ item.name }}</div>
+        </div>
+      </div>
+      <div class="pie-chart">
+        <BaseChart height="100%" width="100%" :option="pieOptions" />
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="告警信息">
+      <div class="seamless-header">
+        <div>告警内容</div>
+        <div>告警设备</div>
+        <div>告警时间</div>
+      </div>
+      <vue-seamless-scroll :data="listData" class="seamless-warp" :class-option="classOption">
+        <div class="seamless-item" v-for="(item, index) in listData" :key="index">
+          <div>{{ item.name }}</div>
+          <div>{{ item.type }}</div>
+          <div>{{ item.createTime }}</div>
+        </div>
+      </vue-seamless-scroll>
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusModule from '../components/CusModule.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+import vueSeamlessScroll from 'vue-seamless-scroll'
+export default {
+  name: 'HomeRight',
+  data () {
+    return {
+      equipment: [{name: '设备总数', value: '2024', unit: '个', color: '#01A7F0'},
+      {name: '在线设备', value: '1800', unit: '个', color: '#B3E3E8'},
+      {name: '离线设备', value: '200', unit: '个', color: '#fff'},
+      {name: '故障设备', value: '24', unit: '个', color: '#EB808D'}],
+      classOption: {
+        step: 0.3, // 数值越大速度滚动越快
+        limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
+        hoverStop: true, // 是否开启鼠标悬停stop
+        direction: 1, // 0向下 1向上 2向左 3向右
+        openWatch: true, // 开启数据实时监控刷新dom
+        singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
+        singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
+        waitTime: 1000 // 单步运动停止
+      },
+      listData: [
+        {
+          name: '温度超阈值上限',
+          type: '温湿度01',
+          createTime: '2024-10-07 12:15:46'
+        },
+        {
+          name: '制冷压力超阈值上限',
+          type: '精密空调',
+          createTime: '2024-10-08 11:11:41'
+        },
+        {
+          name: '检测到有水',
+          type: '水浸',
+          createTime: '2024-10-09 15:15:46'
+        },
+        {
+          name: '开门时间异常',
+          type: '东门门禁',
+          createTime: '2024-10-10 09:15:46'
+        },
+        {
+          name: '设备离线',
+          type: '摄像机1',
+          createTime: '2024-10-10 12:33:40'
+        },
+        {
+          name: '检测到有人',
+          type: '红外1',
+          createTime: '2024-10-10 12:35:40'
+        }
+      ]
+
+    }
+  },
+  components: {
+    CusModule,
+    BaseChart,
+    vueSeamlessScroll
+  },
+  computed: {
+    pieOptions () {
+      return {
+        legend: {
+          show: false,
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: (params) => {
+            const {name, value, percent, } = params
+            return `${name} : ${value}个 (${percent}%)`
+          }
+        },
+        color: ["#3FA7FD", "#8AC540", "#F9AF39", "#82D8F9"],
+        series: [
+          {
+            name: "类别统计",
+            type: "pie",
+            radius: ["40%", "55%"],
+            center: ["50%", "39%"],
+            emphasis: {
+              label: {
+                show: true,
+              },
+            },
+            data: [
+              {value: 123, name: "照明设备", },
+              {value: 96, name: "暖通设备"},
+              {value: 43, name: "电气设备"},
+              {value: 21, name: "安防设备"},
+            ],
+            label: {
+              color: "#fff",
+              alignTo: "edge",
+              fontSize: 14,
+              minMargin: 5,
+              edgeDistance: 20,
+              lineHeight: 20,
+              formatter: "{name|{b}}\n{value|{c}个}",
+              rich: {
+                name: {
+                  color: "#B3E3E8",
+                },
+                value: {
+                  color: "#07E3F9",
+                },
+              },
+            },
+            labelLine: {
+              length: 5,
+              length2: 3,
+              smooth: true,
+            },
+          },
+        ],
+      }
+    }
+  },
+  mounted () { },
+  methods: {}
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+
+.grid-container {
+  display: flex;
+  margin-top: 20px;
+  .left-panel {
+    position: relative;
+    text-align: center;
+    margin-left: 20px;
+    width: 111px;
+    background: url('~@/assets/images/home/r1-left_bg.png') no-repeat;
+    background-size: 100% 100%;
+
+    .spinner {
+      position: absolute;
+      animation: spin 10s linear infinite;
+      top: 40px;
+      left: 25px;
+      width: 63px;
+      height: 63px;
+      background-image: url('~@/assets/images/home/r1-top_center.png');
+    }
+
+    .value-display {
+      margin-top: 10px;
+
+      span.value {
+        font-size: 18px;
+        font-weight: bold;
+      }
+    }
+
+    .description {
+      position: absolute;
+      bottom: 8px;
+      width: 100%;
+      text-align: center;
+
+      span.text {
+        color: #B3E3E8;
+        font-size: 14px;
+      }
+
+      .rate {
+        justify-content: center;
+      }
+    }
+  }
+
+  .rate {
+    color: #00C852;
+    font-size: 12px;
+    display: flex;
+    align-items: center;
+
+    img {
+      margin-left: 3px;
+    }
+  }
+
+  .right-panel {
+    padding-left: 20px;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+
+    .panel-content {
+      width: 200px;
+      height: 75px;
+      color: #B3E3E8;
+      background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
+      background-size: 100% 100%;
+      display: flex;
+
+      .whitespace-pre {
+        margin-top: 5px;
+        margin-left: 20px;
+
+        span.value {
+          font-size: 18px;
+          font-weight: bold;
+        }
+      }
+
+      .label {
+        font-size: 14px;
+      }
+
+      .image-container {
+        width: 70px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+        img {
+          height: 24px;
+          margin-bottom: 5px;
+        }
+      }
+    }
+  }
+}
+
+.equip {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 20px;
+  .equip-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    background: #1B4A64;
+    color: #B3E3E8;
+    border-radius: 4px;
+    padding: 5px 13px;
+    font-size: 14px;
+
+    >div:first-of-type {
+      span:first-of-type {
+        font-size: 18px;
+        font-weight: bold;
+      }
+    }
+  }
+}
+
+.pie-chart {
+  margin: 30px;
+  height: 201px;
+  background: url("~@/assets/images/device/l1-pie_bg.png") no-repeat;
+  background-position: center;
+}
+
+.seamless-header {
+  margin-top: 20px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 5px 10px;
+  color: #7DBAFF;
+  background: #1B4A64;
+  font-size: 16px;
+
+  >div:first-of-type,
+  >div:last-of-type {
+    flex-basis: 35%;
+  }
+
+  >div {
+    text-align: center;
+  }
+}
+
+.seamless-warp {
+  overflow: hidden;
+  height: 200px;
+
+  .seamless-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 5px 0;
+    &:nth-child(odd){
+      background: #000;
+    }
+    >div:first-of-type,
+    >div:last-of-type {
+      flex-basis: 38%;
+    }
+    >div {
+      text-align: center;
+      font-size: 13px;
+    }
+  }
+}
+</style>

+ 165 - 0
ems-ui/src/views/largeScreen/footer.vue

@@ -0,0 +1,165 @@
+<template>
+  <div class="footer-menu">
+    <AppLink v-for="item in menuList" :key="item.name" :to="{ name: item.routeName }" tag="div" class="app-link"
+      :class="setClass(item)" >
+      <div v-if="item.routeName === 'home'" class="home-icon" :style="{
+        backgroundImage:
+          activeRoute == item.routeName
+            ? `url(${require('@/assets/images/layout/footer/center_.png')})`
+            : `url(${require('@/assets/images/layout/footer/center.png')})`,
+      }"></div>
+      <div class="relative-text">
+        {{ item.name }}
+      </div>
+    </AppLink>
+  </div>
+</template>
+
+<script>
+import AppLink from './components/AppLink.vue';
+
+export default {
+  name: 'FooterMenu',
+  components: {
+    AppLink,
+  },
+  data () {
+    return {
+      menuList: [
+        {
+          name: '源',
+          routeName: 'source',
+          className: 'leftC',
+          activeClass: 'leftC-active',
+        },
+        // {
+        //   name: '储',
+        //   routeName: 'storage',
+        //   images: require('@/assets/images/layout/footer/iteml.png'),
+        //   imagesActive: require('@/assets/images/layout/footer/iteml_.png'),
+        // },
+        {
+          name: '荷',
+          routeName: 'soc',
+          className: 'leftC',
+          activeClass: 'leftC-active',
+        },
+        {
+          name: '首页',
+          routeName: 'home',
+          className:'home',
+        },
+        {
+          name: '网',
+          routeName: 'net',
+          className: 'rightC',
+          activeClass: 'rightC-active',
+        },
+        {
+          name: '设备',
+          routeName: 'device',
+          className: 'net-device rightC',
+          activeClass: 'rightC-active',
+        },
+      ],
+    };
+  },
+  computed: {
+    activeRoute () {
+      return this.$route.name;
+    },
+  },
+  methods: {
+    setClass (item) {
+        return this.activeRoute===item.routeName?`${item.className} ${item.activeClass||''}`:`${item.className}`
+    }
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+$footer-height: 60px;
+.footer-menu {
+  width: calc(40% + 10px);
+  height: $footer-height;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding-top: 2px;
+  padding-left: 10px;
+  padding-right: 14px;
+  pointer-events: auto;
+
+  .app-link {
+    position: relative;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    font-size: large;
+    ::v-deep a{
+      width: 100%;
+      text-align: center;
+    }
+
+    &.home {
+      width: 121px;
+      height: 37px;
+      margin-top: 1px;
+      background-repeat: no-repeat;
+    }
+    &.net-device {
+      padding-left: 20px;
+
+    }
+    &.leftC{
+      width: 103px;
+      height: 37px;
+      padding-right: 20px;
+      background: url("~@/assets/images/layout/footer/iteml.png") no-repeat;
+      background-size:100%;
+    }
+    &.leftC-active{
+      background: url("~@/assets/images/layout/footer/iteml_.png") no-repeat;
+      background-size:100%;
+    }
+    &.rightC{
+      width: 103px;
+      height: 37px;
+      background: url("~@/assets/images/layout/footer/itemr.png") no-repeat;
+      background-size:100% 100%;
+    }
+    &.rightC-active{
+      background: url("~@/assets/images/layout/footer/itemr_.png") no-repeat;
+      background-size:100% 100%;
+    }
+    .home-icon {
+      content: "";
+      position: absolute;
+      width: 77px;
+      height: 77px;
+      animation: spin-slow infinite 4s linear;
+      top: -20px;
+      left: 21px;
+      background-position: center;
+      background-size: cover;
+      z-index: 10;
+    }
+
+    .relative-text {
+      position: relative;
+      color: #fff;
+      z-index: 10;
+    }
+  }
+}
+
+@keyframes spin-slow {
+  from {
+    transform: rotate(0deg);
+  }
+
+  to {
+    transform: rotate(360deg);
+  }
+}
+</style>

+ 383 - 0
ems-ui/src/views/largeScreen/home/left.vue

@@ -0,0 +1,383 @@
+<template>
+  <div>
+    <CusModule title="产能情况">
+      <CusTabs slot="title-right" :tabs="dateTabs" :active.sync="dateType" @tab-click="dateTabClick" />
+      <div class="production">
+        <div v-for="i in productionList" :key="i.id" class="production-item"
+          :style="{ backgroundImage: `url(${i.image})` }">
+          <div class="item-value">
+            <span class="value">{{ i.value }}</span>
+            <span class="unit">{{ i.unit }}</span>
+          </div>
+          <div class="item-name">{{ i.name }}</div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="用能情况">
+      <CusTabs slot="title-right" :tabs="buildingTabs" :active.sync="buildingType" />
+      <BaseChart width="100%" height="300px" :option="usePieOptions"></BaseChart>
+    </CusModule>
+    <CusModule class="module-top" title="储能数据">
+      <div class="storage-container">
+        <div class="center-spinner"></div>
+        <div class="percentage-display">
+          <span class="value">100</span><span class="unit">%</span>
+        </div>
+        <div class="charge-status">
+          实时充电量
+        </div>
+      </div>
+      <div class="storage-grid">
+        <div class="grid-item" v-for="i in storageData" :key="i.name">
+          <div class="image-container">
+            <img :src="i.image" alt="" />
+          </div>
+          <div class="item-details">
+            <div class="item-value">
+              <span class="value">{{ i.value }}</span>
+              <span class="unit">{{ i.unit }}</span>
+            </div>
+            <div class="item-name">{{ i.name }}</div>
+          </div>
+        </div>
+      </div>
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusTabs from '../components/CusTabs.vue';
+import CusModule from '../components/CusModule.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+
+export default {
+  name: 'HomeLeft',
+  data () {
+    return {
+      dateType: '1',
+      dateTabs: [{name: '当日', value: '1'}, {name: '本周', value: '2'}, {name: '本月', value: '3'}, {name: '本年', value: '4'}],
+      productionList: [
+        {
+          name: "装机容量",
+          value: 100,
+          unit: "kW",
+          image: require("@/assets/images/source/item_bg1.png"),
+        },
+        {
+          name: "光伏发电量",
+          value: 86.3,
+          unit: "kWh",
+          image: require("@/assets/images/source/item_bg1.png"),
+        },
+        {
+          name: "负荷消耗",
+          value: 82.1,
+          unit: "kWh",
+          image: require("@/assets/images/source/item_bg3.png"),
+        },
+        {
+          name: "入网",
+          value: 78.09,
+          unit: "kWh",
+          image: require("@/assets/images/source/item_bg4.png"),
+        },
+      ],
+      buildingType: '1',
+      buildingTabs: [{name: '按建筑', value: '1'}, {name: '按设施', value: '2'}],
+      useStorage: [
+        {
+          name: "配电泵房",
+          value: 100
+        },
+        {
+          name: "北区综合楼",
+          value: 500
+        },
+        {
+          name: "南区综合楼",
+          value: 300
+        },
+        {
+          name: "北区加油站",
+          value: 200
+        },
+        {
+          name: "南区加油站",
+          value: 100
+        },
+        {
+          name: "北区停车场",
+          value: 100
+        },
+        {
+          name: "南区停车场",
+          value: 80
+        },
+      ],
+      facStorage: [
+        {
+          name: "北区-供电网",
+          value: 500
+        },
+        {
+          name: "南区-供电网",
+          value: 600
+        },
+        {
+          name: "南区-空调设施",
+          value: 200
+        },
+        {
+          name: "北区-空调设施",
+          value: 400
+        },
+        {
+          name: "南区-公共设施",
+          value: 300
+        },
+        {
+          name: "北区-室外照明",
+          value: 100
+        },
+        {
+          name: "北区-公共设施",
+          value: 80
+        },
+      ],
+      storageData: [
+        {
+          name: "今日充电",
+          image: require("@/assets/images/home/icon1.png"),
+          value: 250,
+          unit: "kWh",
+        },
+        {
+          name: "今日放电",
+          image: require("@/assets/images/home/icon2.png"),
+          value: 58,
+          unit: "kWh",
+        },
+        {
+          name: "电池温度",
+          image: require("@/assets/images/home/icon3.png"),
+          value: 36,
+          unit: "°C",
+        },
+        {
+          name: "累计充电次数",
+          image: require("@/assets/images/home/icon4.png"),
+          value: 289,
+          unit: "次",
+        },
+      ]
+    };
+  },
+  components: {
+    CusModule,
+    CusTabs,
+    BaseChart
+  },
+  computed: {
+    usePieOptions () {
+      return {
+        calculable: true,
+        tooltip: {
+          trigger: 'item',
+          formatter: (params) => {
+            const {name, value, percent, seriesName} = params
+            if (seriesName != '透明圆圈') {
+              return `${name} : ${value} (${percent}%)`
+            }
+            return ''
+          }
+        },
+        series: [
+          {
+            name: '',
+            type: 'pie',
+            clockWise: false,
+            radius: ['10%', '70%'],
+            center: ['50%', '50%'],
+            roseType: 'area',
+            data:this.buildingType==='1'? this.useStorage:this.facStorage,
+            label: {
+              color: '#fff',
+              formatter: "{b} : {d}%",
+              padding: [0, -75]
+            },
+            labelLine: {
+              normal: {
+                show: true,
+                length: 10,
+                length2: 20,
+              }
+            },
+          },
+          {
+            name: '透明圆圈',
+            type: 'pie',
+            radius: [10, 27],
+            center: ['50%', '50%'],
+            itemStyle: {
+              color: 'rgba(250, 250, 250, 0.3)',
+            },
+            data: [
+              {value: 10, name: ''}
+            ]
+          },
+          {
+            name: '透明圆圈',
+            type: 'pie',
+            radius: [10, 35],
+            center: ['50%', '50%'],
+            itemStyle: {
+              color: 'rgba(250, 250, 250, 0.3)',
+            },
+            data: [
+              {value: 10, name: ''}
+            ]
+          }
+        ]
+
+      };
+
+    }
+  },
+  mounted () { },
+  methods: {
+    dateTabClick () {
+      this.productionList = this.productionList.map(item => ({
+        ...item,
+        value: parseFloat((Math.random() * 100+(Number(this.dateType)*100)).toFixed(1)),
+      }));
+    }
+  }
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+
+.production {
+  display: flex;
+  flex-wrap: wrap;
+
+  .production-item {
+    height: 51px;
+    flex-basis: 50%;
+    background-repeat: no-repeat;
+    display: flex;
+    flex-direction: column;
+    padding-left: 70px;
+    padding-top: 10px;
+    margin-top: 15px;
+
+    .item-name {
+      font-size: 12px;
+    }
+
+    .item-value {
+      .value {
+        color: #07e3f9;
+        font-weight: bold;
+        font-size: 20px;
+      }
+
+      .unit {
+        color: #768f95;
+        font-size: 12px;
+        margin-left: 2px;
+      }
+    }
+  }
+}
+
+.storage-container {
+  position: relative;
+  margin-top: 8px;
+  width: 335px;
+  height: 172px;
+  background-image: url('~@/assets/images/home/l2-top_bg.png');
+
+  .center-spinner {
+    position: absolute;
+    animation: spin 10s linear infinite;
+    left: calc(50% - 61.5px);
+    top: 0;
+    width: 123px;
+    height: 123px;
+    background-image: url('~@/assets/images/home/l2-top_center.png');
+  }
+
+  .percentage-display {
+    position: absolute;
+    left: 50%;
+    top: 44px;
+    transform: translateX(-50%);
+
+    span.value {
+      font-size: 36px;
+    }
+
+    span.unit {
+      font-size: inherit;
+    }
+  }
+
+  .charge-status {
+    position: absolute;
+    bottom: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+    color: #B3E3E8;
+    font-size: 14px;
+  }
+}
+
+.storage-grid {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.grid-item {
+  flex-basis: 50%;
+  height: 62px;
+  display: flex;
+  background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
+
+  &:nth-child(n+3) {
+    margin-top: 10px;
+  }
+
+  .image-container {
+    width: 90px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .item-details {
+    width: calc(100% - 22px);
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    margin-left: 5px;
+    color: #B3E3E8;
+
+    .item-value {
+      span.value {
+        font-size: 20px;
+        font-weight: bold;
+      }
+
+      span.unit {
+        color: #768f95;
+        font-size: 12px;
+        margin-left: 2px;
+      }
+    }
+
+    .item-name {
+      font-size: 12px;
+    }
+  }
+}
+</style>

+ 381 - 0
ems-ui/src/views/largeScreen/home/right.vue

@@ -0,0 +1,381 @@
+<template>
+  <div>
+    <CusModule title="节能分析">
+      <div class="grid-container">
+        <div class="left-panel">
+          <div class="spinner"></div>
+          <div class="value-display">
+            <span class="value">2589</span>
+            <span class="unit">度</span>
+          </div>
+          <div class="description">
+            <span class="text">本月用电量</span>
+            <div class="rate">
+              <span>环比</span>
+              <img src="@/assets/images/home/down-arrow.svg" alt="">
+              <span>12%</span>
+            </div>
+          </div>
+        </div>
+        <div class="right-panel ">
+          <div class="panel-content">
+            <div class="image-container">
+              <img src="@/assets/images/home/water.svg" alt="">
+            </div>
+            <div class="whitespace-pre">
+              <span class="value">989</span>
+              <span class="unit">吨</span>
+              <div class="label">本月用水量</div>
+              <div class="rate">
+                <span>环比</span>
+                <img src="@/assets/images/home/down-arrow.svg" alt="">
+                <span>10%</span>
+              </div>
+            </div>
+          </div>
+          <div class="panel-content">
+            <div class="image-container">
+              <img src="@/assets/images/home/cost.svg" alt="">
+            </div>
+            <div class="whitespace-pre">
+              <span class="value">4892</span>
+              <span class="unit">元</span>
+              <div class="label">本月用能费用</div>
+              <div class="rate">
+                <span>环比</span>
+                <img src="@/assets/images/home/down-arrow.svg" alt="">
+                <span>9%</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="设备设施">
+      <div class="equip">
+        <div v-for="item in equipment" :style="{ 'color': item.color }" class="equip-item" :key="item.name">
+          <div><span>{{ item.value }}</span> <span class="unit">{{ item.unit }}</span></div>
+          <div>{{ item.name }}</div>
+        </div>
+      </div>
+      <div class="pie-chart">
+        <BaseChart height="100%" width="100%" :option="pieOptions" />
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="告警信息">
+      <div class="seamless-header">
+        <div>告警内容</div>
+        <div>告警设备</div>
+        <div>告警时间</div>
+      </div>
+      <vue-seamless-scroll :data="listData" class="seamless-warp" :class-option="classOption">
+        <div class="seamless-item" v-for="(item, index) in listData" :key="index">
+          <div>{{ item.name }}</div>
+          <div>{{ item.type }}</div>
+          <div>{{ item.createTime }}</div>
+        </div>
+      </vue-seamless-scroll>
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusModule from '../components/CusModule.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+import vueSeamlessScroll from 'vue-seamless-scroll'
+export default {
+  name: 'HomeRight',
+  data () {
+    return {
+      equipment: [{name: '设备总数', value: '2024', unit: '个', color: '#01A7F0'},
+      {name: '在线设备', value: '1800', unit: '个', color: '#B3E3E8'},
+      {name: '离线设备', value: '200', unit: '个', color: '#fff'},
+      {name: '故障设备', value: '24', unit: '个', color: '#EB808D'}],
+      classOption: {
+        step: 0.3, // 数值越大速度滚动越快
+        limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
+        hoverStop: true, // 是否开启鼠标悬停stop
+        direction: 1, // 0向下 1向上 2向左 3向右
+        openWatch: true, // 开启数据实时监控刷新dom
+        singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
+        singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
+        waitTime: 1000 // 单步运动停止
+      },
+      listData: [
+        {
+          name: '温度超阈值上限',
+          type: '温湿度01',
+          createTime: '2024-10-07 12:15:46'
+        },
+        {
+          name: '制冷压力超阈值上限',
+          type: '精密空调',
+          createTime: '2024-10-08 11:11:41'
+        },
+        {
+          name: '检测到有水',
+          type: '水浸',
+          createTime: '2024-10-09 15:15:46'
+        },
+        {
+          name: '开门时间异常',
+          type: '东门门禁',
+          createTime: '2024-10-10 09:15:46'
+        },
+        {
+          name: '设备离线',
+          type: '摄像机1',
+          createTime: '2024-10-10 12:33:40'
+        },
+        {
+          name: '检测到有人',
+          type: '红外1',
+          createTime: '2024-10-10 12:35:40'
+        }
+      ]
+
+    }
+  },
+  components: {
+    CusModule,
+    BaseChart,
+    vueSeamlessScroll
+  },
+  computed: {
+    pieOptions () {
+      return {
+        legend: {
+          show: false,
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: (params) => {
+            const {name, value, percent, } = params
+            return `${name} : ${value}个 (${percent}%)`
+          }
+        },
+        color: ["#3FA7FD", "#8AC540", "#F9AF39", "#82D8F9"],
+        series: [
+          {
+            name: "类别统计",
+            type: "pie",
+            radius: ["40%", "55%"],
+            center: ["50%", "39%"],
+            emphasis: {
+              label: {
+                show: true,
+              },
+            },
+            data: [
+              {value: 123, name: "照明设备", },
+              {value: 96, name: "暖通设备"},
+              {value: 43, name: "电气设备"},
+              {value: 21, name: "安防设备"},
+            ],
+            label: {
+              color: "#fff",
+              alignTo: "edge",
+              fontSize: 14,
+              minMargin: 5,
+              edgeDistance: 20,
+              lineHeight: 20,
+              formatter: "{name|{b}}\n{value|{c}个}",
+              rich: {
+                name: {
+                  color: "#B3E3E8",
+                },
+                value: {
+                  color: "#07E3F9",
+                },
+              },
+            },
+            labelLine: {
+              length: 5,
+              length2: 3,
+              smooth: true,
+            },
+          },
+        ],
+      }
+    }
+  },
+  mounted () { },
+  methods: {}
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+
+.grid-container {
+  display: flex;
+  margin-top: 20px;
+  .left-panel {
+    position: relative;
+    text-align: center;
+    margin-left: 20px;
+    width: 111px;
+    background: url('~@/assets/images/home/r1-left_bg.png') no-repeat;
+    background-size: 100% 100%;
+
+    .spinner {
+      position: absolute;
+      animation: spin 10s linear infinite;
+      top: 40px;
+      left: 25px;
+      width: 63px;
+      height: 63px;
+      background-image: url('~@/assets/images/home/r1-top_center.png');
+    }
+
+    .value-display {
+      margin-top: 10px;
+
+      span.value {
+        font-size: 18px;
+        font-weight: bold;
+      }
+    }
+
+    .description {
+      position: absolute;
+      bottom: 8px;
+      width: 100%;
+      text-align: center;
+
+      span.text {
+        color: #B3E3E8;
+        font-size: 14px;
+      }
+
+      .rate {
+        justify-content: center;
+      }
+    }
+  }
+
+  .rate {
+    color: #00C852;
+    font-size: 12px;
+    display: flex;
+    align-items: center;
+
+    img {
+      margin-left: 3px;
+    }
+  }
+
+  .right-panel {
+    padding-left: 20px;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+
+    .panel-content {
+      width: 200px;
+      height: 75px;
+      color: #B3E3E8;
+      background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
+      background-size: 100% 100%;
+      display: flex;
+
+      .whitespace-pre {
+        margin-top: 5px;
+        margin-left: 20px;
+
+        span.value {
+          font-size: 18px;
+          font-weight: bold;
+        }
+      }
+
+      .label {
+        font-size: 14px;
+      }
+
+      .image-container {
+        width: 70px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+        img {
+          height: 24px;
+          margin-bottom: 5px;
+        }
+      }
+    }
+  }
+}
+
+.equip {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 20px;
+  .equip-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    background: #1B4A64;
+    color: #B3E3E8;
+    border-radius: 4px;
+    padding: 5px 13px;
+    font-size: 14px;
+
+    >div:first-of-type {
+      span:first-of-type {
+        font-size: 18px;
+        font-weight: bold;
+      }
+    }
+  }
+}
+
+.pie-chart {
+  margin: 30px;
+  height: 201px;
+  background: url("~@/assets/images/device/l1-pie_bg.png") no-repeat;
+  background-position: center;
+}
+
+.seamless-header {
+  margin-top: 20px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 5px 10px;
+  color: #7DBAFF;
+  background: #1B4A64;
+  font-size: 16px;
+
+  >div:first-of-type,
+  >div:last-of-type {
+    flex-basis: 35%;
+  }
+
+  >div {
+    text-align: center;
+  }
+}
+
+.seamless-warp {
+  overflow: hidden;
+  height: 200px;
+
+  .seamless-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 5px 0;
+    &:nth-child(odd){
+      background: #000;
+    }
+    >div:first-of-type,
+    >div:last-of-type {
+      flex-basis: 38%;
+    }
+    >div {
+      text-align: center;
+      font-size: 13px;
+    }
+  }
+}
+</style>

+ 8 - 0
ems-ui/src/views/largeScreen/index.scss

@@ -0,0 +1,8 @@
+.module-top {
+  margin-top: 30px;
+}
+.unit {
+  font-size: 14px;
+  margin-left: 2px;
+  color: #768f95;
+}

+ 230 - 0
ems-ui/src/views/largeScreen/index.vue

@@ -0,0 +1,230 @@
+<template>
+  <div class="large-screen" id="largeScreen">
+    <div class="header">
+      <span class="header-name">常泰大桥服务区智慧能源管理平台</span>
+    </div>
+    <div class="left-sidebar-container">
+      <div class="top-info-area">
+        <div class="info-block">
+          <img src="@/assets/images/home/tianqi.svg" alt="">
+          <span>晴转多云</span>
+          <span>4°C~20°C</span>
+        </div>
+      </div>
+      <router-view class="sidebar-router-view" name="left"></router-view>
+    </div>
+    <router-view class="center"></router-view>
+    <div class="right-sidebar-container">
+      <div class="top-info-area">
+        <div class="info-block ">
+          <span class="date-info">
+            <span>{{nowDay.currentTime}}</span>
+            <span>{{nowDay.week}}</span>
+          </span>
+        </div>
+      </div>
+      <router-view class="sidebar-router-view" name="right"></router-view>
+    </div>
+    <div class="footer-container">
+      <Footer></Footer>
+    </div>
+
+  </div>
+</template>
+<script>
+import autofit from 'autofit.js'
+import Footer from './footer.vue';
+import { dateFormat} from '@/utils/index.js'
+export default {
+  name: 'LargeScreen',
+  data () {
+    return {
+      nowDay: {
+        currentTime: '',
+        week: '',
+      },
+      timer:null
+    };
+  },
+  components: {
+    Footer
+  },
+  computed: {},
+  mounted () {
+    autofit.init({
+      designHeight: 1080,
+      designWidth: 1920,
+      renderDom: "#largeScreen",
+      resize: true
+    })
+    this.getDate();
+    this.timer = setInterval(() => {
+      this.getDate();
+    }, 1000);
+  },
+  beforeDestroy () {
+    clearInterval(this.timer)
+    this.timer=null
+  },
+  methods: {
+    getDate () {
+      let nowTime = new Date();
+      this.nowDay.week = "星期" + "日一二三四五六".charAt(nowTime.getDay());
+      this.nowDay.currentTime =dateFormat(nowTime,'yyyy-MM-dd HH:mm:ss')
+    },
+  }
+}
+</script>
+<style lang='scss' scoped>
+.large-screen {
+  background: #000;
+  width: 100%;
+  height: 100%;
+  color: #fff;
+  font-size: 18px;
+  display: flex;
+}
+
+.header {
+  width: 100%;
+  z-index: 40;
+  position: absolute;
+  top: 0;
+  height: 230px;
+  text-align: center;
+  background-image: url('~@/assets/images/layout/head.png');
+  background-position: center;
+  background-repeat: no-repeat;
+
+  .header-name {
+    font-size: 32px;
+    font-weight: bold;
+    letter-spacing: 0.1em;
+    background-clip: text;
+    color: transparent;
+    line-height: 70px;
+    background-image: linear-gradient(to bottom,
+        white 30%,
+        #75bfe9 100%);
+  }
+
+}
+
+// 左侧栏的容器样式
+.left-sidebar-container {
+  position: absolute;
+  z-index: 50;
+  top: 0;
+  left: 0;
+  width: 403px;
+  height: 1081px;
+  background-image: url('~@/assets/images/layout/left.png');
+  background-repeat: no-repeat;
+  padding-left: 7px;
+  padding-right: 6px;
+  padding-top: 4px;
+  padding-bottom: 20px;
+  pointer-events: auto;
+
+  // 顶部信息区域样式
+  .top-info-area {
+    height: 10%;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    font-size: 18px;
+  }
+
+  // 信息块样式
+  .info-block {
+    display: flex;
+    align-items: center;
+    padding-left: 25px;
+    color: #B3E3E8;
+    margin-top: 8px;
+    height: 38px;
+
+    img {
+      height: 24px;
+      margin-right: 5px;
+    }
+
+    span {
+      margin-right: 5px;
+    }
+  }
+
+  // 路由视图容器样式
+  .sidebar-router-view {
+    height: 90%;
+  }
+}
+
+// 右侧栏的容器样式
+.right-sidebar-container {
+  position: absolute;
+  z-index: 40;
+  top: 0;
+  right: 0;
+  width: 403px;
+  height: 1081px;
+  background-image: url('~@/assets/images/layout/right.png');
+  background-repeat: no-repeat;
+  padding-left: 6px;
+  padding-right: 7px;
+  padding-top: 4px;
+  padding-bottom: 20px;
+  pointer-events: auto;
+
+  // 顶部信息区域样式
+  .top-info-area {
+    height: 10%;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    text-align: right;
+  }
+
+  // 信息块样式
+  .info-block {
+    display: flex;
+    align-items: center;
+    height: 38px;
+    background-repeat: no-repeat;
+    justify-content: flex-end;
+    padding-right: 25px;
+    margin-top: 8px;
+  }
+
+  // 日期数据样式
+  .date-info {
+    color: #B3E3E8;
+    display: flex;
+    align-items: center;
+
+    span {
+      margin-left: 5px;
+    }
+  }
+
+  // 路由视图容器样式
+  .sidebar-router-view {
+    height: 90%;
+  }
+}
+
+// 底部栏的容器样式
+.footer-container {
+  display: flex;
+  align-items: flex-end;
+  justify-content: center;
+  width: 100%;
+  position: absolute;
+  bottom: 0;
+  height: 230px;
+  pointer-events: none;
+  background-image: url('~@/assets/images/layout/footer.png');
+  background-position: center;
+  background-repeat: no-repeat;
+}
+</style>

+ 394 - 0
ems-ui/src/views/largeScreen/net/left.vue

@@ -0,0 +1,394 @@
+<template>
+  <div>
+    <CusModule title="上网电量">
+      <div class="net-flex">
+        <div v-for="i in energyList" class="net-item" :key="i.name">
+          <div class="net-value">
+            <span class="value">{{ i.value }}</span><span class="unit">{{ i.unit }}</span>
+          </div>
+          <div class="net-name">
+            {{ i.name }}
+          </div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="光伏上网电量">
+      <BaseChart style="margin-top: 20px" width="100%" height="300px" :option="lineOptions"></BaseChart>
+    </CusModule>
+    <CusModule class="module-top" title="上网电量预测">
+      <BaseChart height="300px" width="100%" :option="netlineOptions" />
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusModule from '../components/CusModule.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+import * as echarts from 'echarts'
+import { dateFormat} from '@/utils'
+export default {
+  name: 'NetLeft',
+  data () {
+    return {
+      energyList: [
+        {
+          name: "今日上网电量",
+          value: 321,
+          unit: "kWh",
+        },
+        {
+          name: "本月上网电量",
+          value: 9521,
+          unit: "kWh",
+        },
+        {
+          name: "今年上网电量",
+          value: 12342,
+          unit: "kWh",
+        },
+      ],
+      lineData: [],
+      netlineData:[],
+    };
+  },
+  components: {
+    CusModule,
+    BaseChart
+  },
+  computed: {
+    lineOptions () {
+      return {
+        grid: {
+          top: "10%",
+          right:'12%',
+          bottom: "10%",//也可设置left和right设置距离来控制图表的大小
+          contain: true
+        },
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            type: "shadow",
+            label: {
+              show: true
+            }
+          }
+        },
+        legend: {
+          data: ["光伏上网电量", "环比增长"],
+          textStyle: {
+            color: "#ffffff"
+          }
+        },
+        xAxis: {
+          data: this.lineData.map(item => item.xData),
+          axisLine: {
+            show: true, //隐藏X轴轴线
+          },
+          axisTick: {
+            show: true //隐藏X轴刻度
+          },
+          axisLabel: {
+            show: true,
+          },
+
+        },
+        yAxis: [{
+          type: "value",
+          name: "kWh",
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#334E5E'
+            }
+          },
+        },
+        {
+          type: "value",
+          name: "%",
+          position: "right",
+          splitLine: {
+            show: false
+          },
+          axisLabel: {
+            show: true,
+            formatter: "{value} %", //右侧Y轴文字显示
+          }
+        },
+        ],
+        series: [
+          {
+            name: "光伏上网电量",
+            type: "bar",
+            barWidth: 15,
+            itemStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: "#21C3E8"
+                },
+                {
+                  offset: 0.7,
+                  color: "#1484A1"
+                },
+                {
+                  offset: 1,
+                  color: "#0B2B38"
+                }
+                ])
+              }
+            },
+            data: this.lineData.map(item => item.yData1)
+          },
+          {
+            name: "环比增长",
+            type: "line",
+            yAxisIndex: 1, //使用的 y 轴的 index,在单个图表实例中存在多个 y轴的时候有用
+            smooth: true, //平滑曲线显示
+            itemStyle: {
+              color: "#F5D6AD",
+              borderColor: "#fff",
+              borderWidth: 3
+            },
+            lineStyle: {
+              color: "#F5D6AD"
+            },
+            areaStyle: {
+              color:new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: "#A18C74"
+                },
+                {
+                  offset: 1,
+                  color: "transparent"
+                }
+                ])
+            },
+            data: this.lineData.map(item => item.yData2)
+          },
+        ]
+      }
+    },
+    netlineOptions () {
+      return {
+        legend: {
+          show: false,
+        },
+        grid: {
+          top:'10%'
+        },
+        tooltip: {
+          trigger: "axis",
+        },
+        yAxis: {
+          name: "kWh",
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#334E5E'
+            }
+          },
+        },
+        xAxis: {
+          splitLine: {
+            show: false,
+          },
+          data: this.netlineData.map(item=>item.xData),
+        },
+        series: [
+          {
+            type: 'line',
+            name: "上网电量",
+            smooth: true,
+            lineStyle: {
+              normal: {
+                color: "#80DBE1", // 线条颜色
+              },
+            },
+            itemStyle: {
+              color: "#80DBE1",
+              borderColor: "#fff",
+              borderWidth: 3
+            },
+            areaStyle: { //区域填充样式
+              normal: {
+                //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: "rgba(81, 139, 152,0.8)"
+                },
+                {
+                  offset: 1,
+                  color: "rgba(81, 139, 152, 0)"
+                }
+                ], false),
+                shadowColor: 'rgba(81, 139, 152, 0.5)', //阴影颜色
+                shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
+              }
+            },
+            data: this.netlineData.map(item=>item.yData),
+          },
+        ],
+      }
+    }
+  },
+  mounted () {
+    this.lineData = this.getDatesOfLastTenDays()
+    this.netlineData =this.getLatestDays()
+   },
+  methods: {
+    getDatesOfLastTenDays () {
+      var dates = [];
+      var today = new Date();
+      for (var i = 1; i < 11; i++) {
+        var pastDate = new Date(today);
+        pastDate.setDate(today.getDate() + i); // 减去i天
+        var formattedDate = dateFormat(pastDate, 'MM-dd');
+        dates.push(formattedDate);
+      }
+      return dates.map(item => ({
+        xData: item,
+        yData1: parseFloat(((Math.random() * 100 + 200)).toFixed(1)),
+        yData2: parseFloat(((Math.random() * 100)).toFixed(1))
+      }));
+    },
+    getLatestDays () {
+      var dates = [];
+      var today = new Date();
+      for (var i = 1; i < 11; i++) {
+        var pastDate = new Date(today);
+        pastDate.setDate(today.getDate() + i); // 减去i天
+        var formattedDate = dateFormat(pastDate, 'MM-dd');
+        dates.push(formattedDate);
+      }
+      return dates.map(item => ({
+        xData: item,
+        yData: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
+      }));
+    },
+  }
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+
+.net-flex {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 20px;
+  .net-item {
+    position: relative;
+    width: 104px;
+    height: 146px;
+    background-image: url('~@/assets/images/net/l1-item_bg.png');
+    background-repeat: no-repeat;
+
+    .net-value {
+      position: absolute;
+      bottom: 72px;
+      width: 100%;
+      text-align: center;
+      color: #06E3F9;
+      font-size: 18px;
+    }
+
+    .net-name {
+      position: absolute;
+      bottom: 20px;
+      width: 100%;
+      text-align: center;
+      color: #B3E3E8;
+      font-size: 12px;
+    }
+  }
+}
+
+.storage-container {
+  position: relative;
+  margin-top: 8px;
+  width: 335px;
+  height: 172px;
+  background-image: url('~@/assets/images/home/l2-top_bg.png');
+
+  .center-spinner {
+    position: absolute;
+    animation: spin 10s linear infinite;
+    left: calc(50% - 61.5px);
+    top: 0;
+    width: 123px;
+    height: 123px;
+    background-image: url('~@/assets/images/home/l2-top_center.png');
+  }
+
+  .percentage-display {
+    position: absolute;
+    left: 50%;
+    top: 44px;
+    transform: translateX(-50%);
+
+    span.value {
+      font-size: 36px;
+    }
+
+    span.unit {
+      font-size: inherit;
+    }
+  }
+
+  .charge-status {
+    position: absolute;
+    bottom: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+    color: #B3E3E8;
+    font-size: 14px;
+  }
+}
+
+.storage-grid {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.grid-item {
+  flex-basis: 50%;
+  height: 62px;
+  display: flex;
+  background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
+
+  &:nth-child(n+3) {
+    margin-top: 10px;
+  }
+
+  .image-container {
+    width: 90px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .item-details {
+    width: calc(100% - 22px);
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    margin-left: 5px;
+    color: #B3E3E8;
+
+    .item-value {
+      span.value {
+        font-size: 20px;
+        font-weight: bold;
+      }
+
+      span.unit {
+        color: #768f95;
+        font-size: 12px;
+        margin-left: 2px;
+      }
+    }
+
+    .item-name {
+      font-size: 12px;
+    }
+  }
+}
+</style>

+ 413 - 0
ems-ui/src/views/largeScreen/net/right.vue

@@ -0,0 +1,413 @@
+<template>
+  <div>
+    <CusModule title="上网电价">
+      <div class="elec-index">
+        <div class="panel-content" v-for="item, index in priceList" :key="index">
+          <div class="image-container">
+            <img :src="require(`@/assets/images/net/price${index + 1}.svg`)" alt="">
+          </div>
+          <div class="whitespace-pre">
+            <span class="value">{{ item.value }}</span>
+            <span class="unit">{{ item.unit }}</span>
+            <div class="label">{{ item.name }}</div>
+          </div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="上网收益">
+      <BaseChart height="300px" width="100%" :option="barOptions" />
+    </CusModule>
+    <CusModule class="module-top" title="今年购电费用">
+      <BaseChart height="300px" width="100%" :option="lineOptions" />
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusModule from '../components/CusModule.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+import vueSeamlessScroll from 'vue-seamless-scroll'
+import {dateFormat} from '@/utils';
+import * as echarts from 'echarts'
+export default {
+  name: 'NetRight',
+  data () {
+    return {
+      priceList: [
+        {
+          name: "余电上网电价",
+          value: 0.92,
+          unit: "元/度",
+        },
+        {
+          name: "脱硫煤电价",
+          value: 0.378,
+          unit: "元/度",
+        },
+        {
+          name: "国家补贴",
+          value: 0.42,
+          unit: "元/度",
+        },
+        {
+          name: "地方补贴",
+          value: 0.12,
+          unit: "元/度",
+        },
+      ],
+      barData: [],
+      lineData:[]
+    }
+  },
+  components: {
+    CusModule,
+    BaseChart,
+    vueSeamlessScroll
+  },
+  computed: {
+    barOptions () {
+      const xData = this.barData.map(item => item.xData)
+      const line = this.barData.map(item => item.yData);
+      return {
+        tooltip: {
+          trigger: 'item',
+        },
+        grid: {
+          left: '5%',
+          top: '10%',
+          right: '5%',
+          bottom: 0,
+          containLabel: true
+        },
+        legend: {
+          show: false,
+        },
+        xAxis: {
+          data: xData,
+          axisLabel: {
+            interval: 0,
+            margin: 10, //刻度标签与轴线之间的距离。
+          },
+          axisLine: {
+            show: false //不显示x轴
+          },
+          axisTick: {
+            show: false //不显示刻度
+          },
+          boundaryGap: true,
+          splitLine: {
+            show: false,
+          }
+        },
+        yAxis: [{
+          name: '万元',
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#334E5E'
+            }
+          },
+          axisTick: {
+            show: false
+          },
+          axisLine: {
+            show: false
+          },
+          axisLabel: {
+            textStyle: {
+              color: '#888'
+            },
+          }
+        }],
+        series: [
+          {//柱底圆片
+            name: "",
+            type: "pictorialBar",
+            symbolSize: [20, 15],
+            symbolOffset: [0, 5],
+            z: 12,
+            itemStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: "rgba(89,211,255,1)"
+                },
+                {
+                  offset: 1,
+                  color: "rgba(23,237,194,1)"
+                }
+                ])
+              }
+            },
+            data: line
+          },
+
+          //柱体
+          {
+            name: '',
+            type: 'bar',
+            barWidth: 20,
+            barGap: '0%',
+            itemStyle: {
+              normal: {
+                color: {
+                  x: 0,
+                  y: 0,
+                  x2: 0,
+                  y2: 1,
+                  type: "linear",
+                  global: false,
+                  colorStops: [{//第一节下面
+                    offset: 0,
+                    color: "rgba(0,255,245,0.5)"
+                  }, {
+                    offset: 1,
+                    color: "#43bafe"
+                  }]
+                }
+              }
+            },
+
+            data: line
+          },
+          //柱顶圆片
+          {
+            name: "",
+            type: "pictorialBar",
+            symbolSize: [20, 15],
+            symbolOffset: [0, -5],
+            z: 12,
+            symbolPosition: "end",
+            itemStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1,
+                  [{
+                    offset: 0,
+                    color: "rgba(89,211,255,1)"
+                  },
+                  {
+                    offset: 1,
+                    color: "rgba(23,237,194,1)"
+                  }
+                  ],
+                  false
+                ),
+              }
+            },
+            data: line
+          }
+        ]
+      };
+    },
+    lineOptions () {
+      return {
+        legend: {
+          show: false,
+        },
+        grid: {
+          top: '10%'
+        },
+        tooltip: {
+          trigger: "axis",
+        },
+        yAxis: {
+          name: "万元",
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#334E5E'
+            }
+          },
+        },
+        xAxis: {
+          axisLabel: {
+            interval: 0,
+          },
+          splitLine: {
+            show: false,
+          },
+          data: this.lineData.map(item => item.xData),
+        },
+        series: [
+          {
+            type: 'line',
+            name: "费用",
+            smooth: true,
+            lineStyle: {
+              normal: {
+                color: "#80DBE1", // 线条颜色
+              },
+            },
+            itemStyle: {
+              color: "#80DBE1",
+              borderColor: "#fff",
+              borderWidth: 3
+            },
+            areaStyle: { //区域填充样式
+              normal: {
+                //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: "rgba(81, 139, 152,0.8)"
+                },
+                {
+                  offset: 1,
+                  color: "rgba(81, 139, 152, 0)"
+                }
+                ], false),
+                shadowColor: 'rgba(81, 139, 152, 0.5)', //阴影颜色
+                shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
+              }
+            },
+            data: this.lineData.map(item => item.yData),
+          },
+        ],
+      }
+
+    }
+  },
+  mounted () {
+    this.barData = this.getMonthsOfLastTenMonths()
+    this.lineData = this.getMonthsOfLastTenMonths()
+  },
+  methods: {
+    getMonthsOfLastTenMonths () {
+      var months = [];
+      var today = new Date();
+      for (var i = 0; i < 10; i++) {
+        var pastMonth = new Date(today);
+        pastMonth.setMonth(today.getMonth() - i); // 减去i个月
+        var formattedMonth = `${dateFormat(pastMonth, 'M')}月`;
+        months.push(formattedMonth);
+      }
+      return months.reverse().map(item => ({
+        xData: item,
+        yData: parseFloat(((Math.random() * 100)).toFixed(1)),
+      }));
+    }
+  }
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+
+.elec-index {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  padding: 10px 0 0;
+
+  .panel-content {
+    margin-top: 12px;
+    flex-basis: 48%;
+    height: 75px;
+    color: #B3E3E8;
+    background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
+    background-size: 100% 100%;
+    display: flex;
+
+    .whitespace-pre {
+      margin-top: 15px;
+      margin-left: 10px;
+
+      span.value {
+        font-size: 18px;
+        font-weight: bold;
+      }
+    }
+
+    .label {
+      margin-top: 5px;
+      font-size: 14px;
+    }
+
+    .image-container {
+      width: 65px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      img {
+        height: 24px;
+        margin-bottom: 5px;
+      }
+    }
+  }
+}
+
+.equip {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 20px;
+
+  .equip-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    background: #1B4A64;
+    color: #B3E3E8;
+    border-radius: 4px;
+    padding: 5px 13px;
+    font-size: 14px;
+
+    >div:first-of-type {
+      span:first-of-type {
+        font-size: 18px;
+        font-weight: bold;
+      }
+    }
+  }
+}
+
+.pie-chart {
+  margin: 30px;
+  height: 201px;
+  background: url("~@/assets/images/device/l1-pie_bg.png") no-repeat;
+  background-position: center;
+}
+
+.seamless-header {
+  margin-top: 20px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 5px 10px;
+  color: #7DBAFF;
+  background: #1B4A64;
+  font-size: 16px;
+
+  >div:first-of-type,
+  >div:last-of-type {
+    flex-basis: 35%;
+  }
+
+  >div {
+    text-align: center;
+  }
+}
+
+.seamless-warp {
+  overflow: hidden;
+  height: 200px;
+
+  .seamless-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 5px 0;
+
+    &:nth-child(odd) {
+      background: #000;
+    }
+
+    >div:first-of-type,
+    >div:last-of-type {
+      flex-basis: 38%;
+    }
+
+    >div {
+      text-align: center;
+      font-size: 13px;
+    }
+  }
+}
+</style>

+ 355 - 0
ems-ui/src/views/largeScreen/soc/left.vue

@@ -0,0 +1,355 @@
+<template>
+  <div>
+    <CusModule title="抄表采集率">
+      <div class="soc-container">
+        <div class="soc-data-point soc-left-data">
+          <div>
+            <span class="soc-value">45</span>
+            <span class="unit">个</span>
+          </div>
+          <div class="soc-description">实采数据</div>
+        </div>
+        <div class="soc-central-data">
+          <span class="soc-value">50</span>
+          <span class="unit">%</span>
+        </div>
+        <div class="soc-data-point soc-right-data">
+          <div>
+            <span class="soc-failure">5</span>
+            <span class="soc-failure unit">个</span>
+          </div>
+          <div class="soc-description">失败数据</div>
+        </div>
+        <div class="soc-bottom-data">
+          <div>
+            <span class="soc-value">50</span>
+            <span class="unit">个</span>
+          </div>
+          <div class="soc-description">应采数据</div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="用能情况">
+      <div class="soc-pie-chart-container">
+        <BaseChart width="100%" height="100%" :option="pieOptions"></BaseChart>
+        <div class="soc-chart-label soc-top-left">
+          <div class="soc-chart-label-text">空调</div>
+          <div>
+            <span class="soc-chart-value">24.5</span>
+            <span class="unit">kw.h</span>
+          </div>
+        </div>
+        <div class="soc-chart-label soc-top-right">
+          <div class="soc-chart-label-text">照明</div>
+          <span class="soc-chart-value">26.7</span>
+          <span class="unit">kw.h</span>
+        </div>
+        <div class="soc-chart-label soc-bottom-left">
+          <div class="soc-chart-label-text">电梯</div>
+          <span class="soc-chart-value">25.5</span>
+          <span class="unit">kw.h</span>
+        </div>
+        <div class="soc-chart-label soc-bottom-right">
+          <div class="soc-chart-label-text">其他</div>
+          <span class="soc-chart-value">23.3</span>
+          <span class="unit">kw.h</span>
+        </div>
+      </div>
+
+    </CusModule>
+    <CusModule class="module-top" title="新能源消纳情况">
+      <BaseChart height="350px" width="100%" :option="lineOptions" />
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusModule from '../components/CusModule.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+import {dateFormat} from '@/utils';
+import * as echarts from 'echarts'
+export default {
+  name: 'SocLeft',
+  data () {
+    return {
+      lineData:[]
+    };
+  },
+  components: {
+    CusModule,
+    BaseChart
+  },
+  computed: {
+    pieOptions () {
+      return {
+        legend: {
+          show: false,
+        },
+        color: ["#3FA7FD", "#8AC540", "#F9AF39", "#82D8F9"],
+        grid: {
+          top:'20%'
+        },
+        series: [
+          {
+            name: "类别统计",
+            type: "pie",
+            radius: ["40%", "55%"],
+            center: ["50%", "50%"],
+            data: [
+              {value: 123, name: "照明设备", },
+              {value: 96, name: "暖通设备"},
+              {value: 43, name: "电气设备"},
+              {value: 21, name: "安防设备"},
+            ],
+            label: {
+              show:false,
+            },
+          },
+        ],
+      }
+    },
+    lineOptions () {
+      return {
+        legend: {
+          show: false,
+        },
+        tooltip: {
+          trigger: "axis",
+        },
+        yAxis: {
+          name: "kWh",
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#334E5E'
+            }
+          },
+        },
+        xAxis: {
+          splitLine: {
+            show: false,
+          },
+          data: this.lineData.map(item=>item.xData),
+        },
+        series: [
+          {
+            type: 'line',
+            name: "",
+            smooth: true,
+            lineStyle: {
+              normal: {
+                color: "#80DBE1", // 线条颜色
+              },
+            },
+            itemStyle: {
+              color: "#80DBE1",
+              borderColor: "#fff",
+              borderWidth: 3
+            },
+            areaStyle: { //区域填充样式
+              normal: {
+                //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: "rgba(81, 139, 152,0.8)"
+                },
+                {
+                  offset: 1,
+                  color: "rgba(81, 139, 152, 0)"
+                }
+                ], false),
+                shadowColor: 'rgba(81, 139, 152, 0.5)', //阴影颜色
+                shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
+              }
+            },
+            data: this.lineData.map(item=>item.yData),
+          },
+        ],
+      }
+    }
+  },
+  mounted () {
+    this.lineData = this.getDatesOfLastTenDays()
+  },
+  methods: {
+    getDatesOfLastTenDays () {
+      var dates = [];
+      var today = new Date();
+      for (var i = 0; i < 10; i++) {
+        var pastDate = new Date(today);
+        pastDate.setDate(today.getDate() - i); // 减去i天
+        var formattedDate = dateFormat(pastDate, 'MM-dd');
+        dates.push(formattedDate);
+      }
+      return dates.reverse().map(item => ({
+        xData: item,
+        yData: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
+      }));
+    },
+
+  }
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+
+.soc-container {
+  margin-top: 20px;
+  width: 100%;
+  height: 203px;
+  background-image: url('~@/assets/images/soc/l1_bg.png');
+  background-repeat: no-repeat;
+  background-position: center;
+  position: relative;
+  text-align: center;
+
+  .soc-data-point {
+    position: absolute;
+    top: 60px;
+
+    .soc-value {
+      color: #06E3F9;
+      font-size: 18px;
+    }
+
+    .soc-description {
+      color: #B3E3E8;
+      font-size: 14px;
+    }
+  }
+
+  .soc-left-data {
+    left: 45px;
+  }
+
+  .soc-right-data {
+    right: 35px;
+  }
+
+  .soc-central-data {
+    position: absolute;
+    left: 50%;
+    top: 20px;
+    transform: translateX(-50%);
+
+    .soc-value {
+      color: #06E3F9;
+      font-size: 32px;
+    }
+  }
+
+  .soc-bottom-data {
+    position: absolute;
+    left: 50%;
+    bottom: 62px;
+    transform: translateX(-50%);
+
+    .soc-value {
+      color: #06E3F9;
+      font-size: 18px;
+    }
+
+    .soc-description {
+      color: #B3E3E8;
+      font-size: 14px;
+    }
+  }
+
+  .soc-failure {
+    color: #F05050;
+    font-size: 18px;
+
+    &.unit {
+      font-size: 14px;
+    }
+  }
+}
+
+.soc-pie-chart-container {
+  margin-top: 20px;
+  width: 369px;
+  height: 178px;
+  padding-bottom: 2px;
+  padding-right: 17px;
+  position: relative;
+  background-image: url('~@/assets/images/soc/l2-pie_bg.png');
+  .soc-chart-label {
+    position: absolute;
+    text-align: center;
+    .soc-chart-label-text {
+      color: #B3E3E8;
+      font-size: 14px;
+    }
+
+    .soc-chart-value {
+      font-size: 18px;
+      font-weight: bold;
+      color: #06E3F9;
+    }
+  }
+  .soc-top-left {
+    top: 12px;
+    left: 20px;
+  }
+  .soc-top-right {
+    top: 12px;
+    right: 35px;
+  }
+  .soc-bottom-left {
+    bottom:32px;
+    left: 20px;
+  }
+  .soc-bottom-right {
+    bottom:32px;
+    right: 35px;
+  }
+}
+
+.storage-grid {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.grid-item {
+  flex-basis: 50%;
+  height: 62px;
+  display: flex;
+  background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
+
+  &:nth-child(n+3) {
+    margin-top: 10px;
+  }
+
+  .image-container {
+    width: 90px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .item-details {
+    width: calc(100% - 22px);
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    margin-left: 5px;
+    color: #B3E3E8;
+
+    .item-value {
+      span.value {
+        font-size: 20px;
+        font-weight: bold;
+      }
+
+      span.unit {
+        color: #768f95;
+        font-size: 12px;
+        margin-left: 2px;
+      }
+    }
+
+    .item-name {
+      font-size: 12px;
+    }
+  }
+}
+</style>

+ 439 - 0
ems-ui/src/views/largeScreen/soc/right.vue

@@ -0,0 +1,439 @@
+<template>
+  <div>
+    <CusModule title="能耗统计">
+      <div class="soc-stats-container">
+        <div v-for="i in socList" :key="i.name" class="soc-stats-item" :style="{ backgroundImage: `url(${i.image})` }">
+          <div class="soc-stats-info">
+            <div class="mb-1">
+              <span class="soc-stats-value">{{ i.value }}</span>
+              <span class="unit">{{ i.unit }}</span>
+            </div>
+            <div class="soc-stats-label">
+              {{ i.name }}
+            </div>
+          </div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="用能排名">
+      <div class="soc-lst">
+        <div v-for="(item, index) in ranking" :key="item.name" class="soc-itm">
+          <div class="soc-num">
+            {{ index + 1 }}
+          </div>
+          <div class="soc-dtl">
+            <div class="txt-sm">
+              {{ item.name }}
+            </div>
+            <CusProgress :value="item.value" :total="ranking.reduce((a, b) => a + b.value, 0)" :color="item.color"
+              :labelWidth="95" unit="kw.h" showLabel></CusProgress>
+          </div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="用能趋势预测">
+      <BaseChart height="350px" width="100%" :option="lineOptions" />
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusModule from '../components/CusModule.vue';
+import CusProgress from '../components/CusProgress.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+import * as echarts from 'echarts'
+import {dateFormat} from '@/utils'
+export default {
+  name: 'HomeRight',
+  data () {
+    return {
+      socList: [
+        {
+          name: "电",
+          image: require("@/assets/images/soc/item1.png"),
+          value: 345,
+          unit: "kWh",
+        },
+        {
+          name: "燃气",
+          image: require("@/assets/images/soc/item2.png"),
+          value: 7945,
+          unit: "kg",
+        },
+        {
+          name: "水",
+          image: require("@/assets/images/soc/item3.png"),
+          value: 8541,
+          unit: "吨",
+        },
+      ],
+      ranking: [
+        {
+          name: "公共设施",
+          color: "#14c5f2",
+          value: 500,
+        },
+        {
+          name: "空调",
+          color: "#14c5f2",
+          value: 400,
+        },
+        {
+          name: "照明",
+          color: "#14c5f2",
+          value: 300,
+        },
+        {
+          name: "电梯",
+          color: "#14c5f2",
+          value: 100,
+        },
+        {
+          name: "其他",
+          color: "#14c5f2",
+          value: 100,
+        },
+      ],
+      lineData: []
+
+    }
+  },
+  components: {
+    CusModule,
+    CusProgress,
+    BaseChart,
+  },
+  computed: {
+    pieOptions () {
+      return {
+        legend: {
+          show: false,
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: (params) => {
+            const {name, value, percent, } = params
+            return `${name} : ${value}个 (${percent}%)`
+          }
+        },
+        color: ["#3FA7FD", "#8AC540", "#F9AF39", "#82D8F9"],
+        series: [
+          {
+            name: "类别统计",
+            type: "pie",
+            radius: ["40%", "55%"],
+            center: ["50%", "39%"],
+            emphasis: {
+              label: {
+                show: true,
+              },
+            },
+            data: [
+              {value: 123, name: "照明设备", },
+              {value: 96, name: "暖通设备"},
+              {value: 43, name: "电气设备"},
+              {value: 21, name: "安防设备"},
+            ],
+            label: {
+              color: "#fff",
+              alignTo: "edge",
+              fontSize: 14,
+              minMargin: 5,
+              edgeDistance: 20,
+              lineHeight: 20,
+              formatter: "{name|{b}}\n{value|{c}个}",
+              rich: {
+                name: {
+                  color: "#B3E3E8",
+                },
+                value: {
+                  color: "#07E3F9",
+                },
+              },
+            },
+            labelLine: {
+              length: 5,
+              length2: 3,
+              smooth: true,
+            },
+          },
+        ],
+      }
+    },
+    lineOptions () {
+      return {
+        grid: {
+          top: "10%",
+          bottom: "10%",//也可设置left和right设置距离来控制图表的大小
+          contain: true
+        },
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            type: "shadow",
+            label: {
+              show: true
+            }
+          }
+        },
+        legend: {
+          data: ["用电量", "当日最高负荷"],
+          textStyle: {
+            color: "#ffffff"
+          }
+        },
+        xAxis: {
+          data: this.lineData.map(item => item.xData),
+          axisLine: {
+            show: true, //隐藏X轴轴线
+          },
+          axisTick: {
+            show: true //隐藏X轴刻度
+          },
+          axisLabel: {
+            show: true,
+          },
+
+        },
+        yAxis: [{
+          type: "value",
+          name: "kWh",
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#334E5E'
+            }
+          },
+        },
+        {
+          type: "value",
+          name: "kW",
+          position: "right",
+          splitLine: {
+            show: false
+          },
+        }
+        ],
+        series: [
+          {
+            name: "用电量",
+            type: "bar",
+            barWidth: 15,
+            itemStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: "#21C3E8"
+                },
+                {
+                  offset: 0.7,
+                  color: "#1484A1"
+                },
+                {
+                  offset: 1,
+                  color: "#0B2B38"
+                }
+                ])
+              }
+            },
+            data: this.lineData.map(item => item.yData1)
+          },
+          {
+            name: "当日最高负荷",
+            type: "line",
+            yAxisIndex: 1, //使用的 y 轴的 index,在单个图表实例中存在多个 y轴的时候有用
+            smooth: true, //平滑曲线显示
+            itemStyle: {
+              color: "#F5D6AD",
+              borderColor: "#fff",
+              borderWidth: 3
+            },
+            lineStyle: {
+              color: "#F5D6AD"
+            },
+            areaStyle: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: "#A18C74"
+              },
+              {
+                offset: 1,
+                color: "transparent"
+              }
+              ])
+            },
+            markLine: {
+              symbol: 'none',
+              silent: true,
+              lineStyle: {normal: {type: 'dashed'}},
+              label: {position: 'start'},
+              data: [
+                {
+                  yAxis: 190,
+                  lineStyle: {width: 1.656, color: '#ff6367'},
+                  label: {show: false}
+                },
+              ]
+            },
+            markPoint: {
+              silent: true,
+              data: [
+                {
+                  yAxis: 190,
+                  x: '100%',
+                  symbolSize: 0.1,
+                  label: {
+                    textStyle: {color: '#F59A23'},
+                    fontSize: 12,
+                    position: 'left',
+                    formatter: '历史最高负荷'
+                  }
+                },
+              ]
+            },
+            data: this.lineData.map(item => item.yData2)
+          },
+        ]
+      }
+    }
+  },
+  mounted () {
+    this.lineData = this.getDatesOfLastTenDays()
+  },
+  methods: {
+    getDatesOfLastTenDays () {
+      var dates = [];
+      var today = new Date();
+      for (var i = 1; i < 11; i++) {
+        var pastDate = new Date(today);
+        pastDate.setDate(today.getDate() + i); // 减去i天
+        var formattedDate = dateFormat(pastDate, 'MM-dd');
+        dates.push(formattedDate);
+      }
+      return dates.map(item => ({
+        xData: item,
+        yData1: parseFloat(((Math.random() * 100 + 200)).toFixed(1)),
+        yData2: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
+      }));
+    },
+  }
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+
+.soc-stats-container {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 20px;
+
+  .soc-stats-item {
+    position: relative;
+    width: 100px;
+    height: 138px;
+    background-size: cover;
+
+    .soc-stats-info {
+      position: absolute;
+      bottom: 15px;
+      width: 100%;
+      text-align: center;
+
+      .soc-stats-value {
+        font-size: 18px;
+        font-weight: bold;
+        color: #06E3F9;
+      }
+
+      .soc-stats-label {
+        color: #B3E3E8;
+        font-size: 14px;
+        margin-top: 2px;
+      }
+    }
+  }
+}
+
+.soc-lst {
+  height: 100%;
+  padding-top: 6px;
+  padding-bottom: 6px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  overflow-y: auto;
+
+  .soc-itm {
+    width: 332px;
+    height: 45px;
+    background-image: url('~@/assets/images/soc/r2-list.png');
+    background-repeat: no-repeat;
+    display: flex;
+    align-items: center;
+
+    .soc-num {
+      width: 53px;
+      margin-right: 16px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+
+    .soc-dtl {
+      padding-right: 2px;
+      width: 100%;
+
+      .txt-sm {
+        color: #B3E3E8;
+        font-size: 12px;
+        margin-bottom: 5px;
+      }
+    }
+  }
+}
+
+.seamless-header {
+  margin-top: 20px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 5px 10px;
+  color: #7DBAFF;
+  background: #1B4A64;
+  font-size: 16px;
+
+  >div:first-of-type,
+  >div:last-of-type {
+    flex-basis: 35%;
+  }
+
+  >div {
+    text-align: center;
+  }
+}
+
+.seamless-warp {
+  overflow: hidden;
+  height: 200px;
+
+  .seamless-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 5px 0;
+
+    &:nth-child(odd) {
+      background: #000;
+    }
+
+    >div:first-of-type,
+    >div:last-of-type {
+      flex-basis: 38%;
+    }
+
+    >div {
+      text-align: center;
+      font-size: 13px;
+    }
+  }
+}
+</style>

+ 286 - 0
ems-ui/src/views/largeScreen/source/left.vue

@@ -0,0 +1,286 @@
+<template>
+  <div>
+    <CusModule title="光伏发电量">
+      <div class="elec-top-bar">
+        <span class="elec-content">
+          今日发电量<span class="elec-value">321</span><span class="unit"> kWh</span>
+        </span>
+      </div>
+      <div class="elec-items-container">
+        <div v-for="i in elecList" :key="i.name" class="elec-item" :style="{ backgroundImage: `url(${i.image})` }">
+          <div class="elec-item-content">
+            <div class="elec-item-value">{{ i.value }}</div>
+            <div class="unit">{{ i.unit }}</div>
+          </div>
+          <div class="elec-item-label">
+            {{ i.name }}
+          </div>
+        </div>
+        <div></div>
+        <div></div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="光伏发电指标">
+      <div class="elec-index">
+        <div class="panel-content" v-for="item, index in elecIndexList" :key="index">
+          <div class="image-container">
+            <img :src="require(`@/assets/images/source/elec${index + 1}.svg`)" alt="">
+          </div>
+          <div class="whitespace-pre">
+            <span class="value">{{ item.value }}</span>
+            <span class="unit">{{ item.unit }}</span>
+            <div class="label">{{ item.name }}</div>
+          </div>
+        </div>
+      </div>
+    </CusModule>
+    <CusModule class="module-top" title="历史发电量">
+      <BaseChart height="350px" width="100%" :option="lineOptions" />
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusModule from '../components/CusModule.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+import {dateFormat} from '@/utils';
+import * as echarts from 'echarts'
+export default {
+  name: 'SourceLeft',
+  data () {
+    return {
+      elecList: [
+        {
+          name: "本月发电量",
+          value: 9431,
+          unit: "kw.h",
+          image: require("@/assets/images/source/l1-item1.png"),
+        },
+        {
+          name: "今年发电量",
+          value: 12034,
+          unit: "kWh",
+          image: require("@/assets/images/source/l1-item2.png"),
+        },
+        {
+          name: "累计发电量",
+          value: 95312,
+          unit: "kWh",
+          image: require("@/assets/images/source/l1-item3.png"),
+        },
+      ],
+      elecIndexList: [
+        {
+          name: "逆变器输入电量",
+          value: 120,
+          unit: "kW",
+        },
+        {
+          name: "逆变器转换效率",
+          value: 86.3,
+          unit: "%",
+        },
+        {
+          name: "光电转换效率",
+          value: 82.1,
+          unit: "%",
+        },
+        {
+          name: "电站性能比",
+          value: 78.09,
+          unit: "",
+        },
+      ],
+      lineData:[]
+    };
+  },
+  components: {
+    CusModule,
+    BaseChart
+  },
+  computed: {
+    lineOptions () {
+      return {
+        legend: {
+          show: false,
+        },
+        tooltip: {
+          trigger: "axis",
+        },
+        yAxis: {
+          name: "kWh",
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#334E5E'
+            }
+          },
+        },
+        xAxis: {
+          splitLine: {
+            show: false,
+          },
+          data: this.lineData.map(item=>item.xData),
+        },
+        series: [
+          {
+            type: 'line',
+            name: "发电量",
+            smooth: true,
+            lineStyle: {
+              normal: {
+                color: "#80DBE1", // 线条颜色
+              },
+            },
+            itemStyle: {
+              color: "#80DBE1",
+              borderColor: "#fff",
+              borderWidth: 3
+            },
+            areaStyle: { //区域填充样式
+              normal: {
+                //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: "rgba(81, 139, 152,0.8)"
+                },
+                {
+                  offset: 1,
+                  color: "rgba(81, 139, 152, 0)"
+                }
+                ], false),
+                shadowColor: 'rgba(81, 139, 152, 0.5)', //阴影颜色
+                shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
+              }
+            },
+            data: this.lineData.map(item=>item.yData),
+          },
+        ],
+      }
+    }
+  },
+  mounted () {
+    this.lineData = this.getDatesOfLastTenDays()
+  },
+  methods: {
+    getDatesOfLastTenDays () {
+      var dates = [];
+      var today = new Date();
+      for (var i = 0; i < 10; i++) {
+        var pastDate = new Date(today);
+        pastDate.setDate(today.getDate() - i); // 减去i天
+        var formattedDate = dateFormat(pastDate, 'MM-dd');
+        dates.push(formattedDate);
+      }
+      return dates.reverse().map(item => ({
+        xData: item,
+        yData: parseFloat(((Math.random() * 100 + 100)).toFixed(1))
+      }));
+    },
+
+  }
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+
+.elec-top-bar {
+  width: 100%;
+  height: 90px;
+  background-image: url('~@/assets/images/source/l1-top.png');
+  background-repeat: no-repeat;
+  display: flex;
+  align-items: center;
+  padding-left: 14px;
+
+  .elec-content {
+    color: #B3E3E8;
+    font-size: 14px;
+    letter-spacing: 1px;
+    white-space: pre;
+
+    .elec-value {
+      font-size: 20px;
+      font-weight: bold;
+      color: #06E3F9;
+    }
+
+  }
+}
+
+.elec-items-container {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 2px;
+
+  .elec-item {
+    width: 108px;
+    height: 134px;
+    position: relative;
+    background-size: cover;
+
+    .elec-item-content {
+      text-align: center;
+      margin-top: 1px;
+
+      .elec-item-value {
+        font-weight: bold;
+        font-size: 20px;
+        color: #06E3F9;
+      }
+    }
+
+    .elec-item-label {
+      position: absolute;
+      bottom: 16px;
+      width: 100%;
+      color: #B3E3E8;
+      font-size: 14px;
+      text-align: center;
+    }
+  }
+}
+
+.elec-index {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  padding: 10px 0 0;
+
+  .panel-content {
+    margin-top: 12px;
+    flex-basis: 48%;
+    height: 75px;
+    color: #B3E3E8;
+    background: url('~@/assets/images/home/l2_item_bg.png') no-repeat;
+    background-size: 100% 100%;
+    display: flex;
+
+    .whitespace-pre {
+      margin-top: 15px;
+      margin-left: 10px;
+
+      span.value {
+        font-size: 18px;
+        font-weight: bold;
+      }
+    }
+
+    .label {
+      margin-top: 5px;
+      font-size: 14px;
+    }
+
+    .image-container {
+      width: 60px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      img {
+        height: 24px;
+        margin-bottom: 5px;
+      }
+    }
+  }
+}
+</style>

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