lining 3 anos atrás
pai
commit
9fd9765262
100 arquivos alterados com 83763 adições e 16745 exclusões
  1. 0 0
      .env
  2. 8 0
      .env.development
  3. 4 0
      .env.eapi
  4. 10 0
      .env.production
  5. 1 6
      .gitignore
  6. 1 6
      README.md
  7. 2848 2171
      package-lock.json
  8. 25 42
      package.json
  9. BIN
      public/img/icons/android-chrome-192x192.png
  10. BIN
      public/img/icons/android-chrome-512x512.png
  11. BIN
      public/img/icons/android-chrome-maskable-192x192.png
  12. BIN
      public/img/icons/android-chrome-maskable-512x512.png
  13. BIN
      public/img/icons/apple-touch-icon-120x120.png
  14. BIN
      public/img/icons/apple-touch-icon-152x152.png
  15. BIN
      public/img/icons/apple-touch-icon-180x180.png
  16. BIN
      public/img/icons/apple-touch-icon-60x60.png
  17. BIN
      public/img/icons/apple-touch-icon-76x76.png
  18. BIN
      public/img/icons/apple-touch-icon.png
  19. BIN
      public/img/icons/favicon-16x16.png
  20. BIN
      public/img/icons/favicon-32x32.png
  21. BIN
      public/img/icons/msapplication-icon-144x144.png
  22. BIN
      public/img/icons/mstile-150x150.png
  23. 3 0
      public/img/icons/safari-pinned-tab.svg
  24. 2 0
      public/robots.txt
  25. 113 56
      src/App.vue
  26. 173 0
      src/api/index.js
  27. BIN
      src/assets/img/RecommendedArea/background.png
  28. BIN
      src/assets/img/controlcenter/daraTrue.png
  29. BIN
      src/assets/img/controlcenter/dataFalse.png
  30. BIN
      src/assets/img/logo.png
  31. BIN
      src/assets/img/type/down.png
  32. BIN
      src/assets/img/type/electricityRestrictions.png
  33. BIN
      src/assets/img/type/lock.png
  34. BIN
      src/assets/img/type/none.png
  35. BIN
      src/assets/img/type/up.png
  36. BIN
      src/assets/logo.png
  37. 0 2067
      src/assets/script/BoosterStation.js
  38. 0 125
      src/assets/script/MessageBridge.js
  39. 0 8005
      src/assets/script/UniformCodes.js
  40. 25 4
      src/assets/style/main.css
  41. 5 4
      src/background.js
  42. 1253 0
      src/components/BasicInformationDetail.vue
  43. 5930 0
      src/components/BoosterStation/dwk.vue
  44. 4944 0
      src/components/BoosterStation/hzj.vue
  45. 2844 0
      src/components/BoosterStation/mch.vue
  46. 9139 0
      src/components/BoosterStation/mhs.vue
  47. 5432 0
      src/components/BoosterStation/nss.vue
  48. 5304 0
      src/components/BoosterStation/pl1.vue
  49. 3617 0
      src/components/BoosterStation/pl2.vue
  50. 722 0
      src/components/BoosterStation/previewPicture.vue
  51. 4050 0
      src/components/BoosterStation/qs.vue
  52. 2502 0
      src/components/BoosterStation/sbdl.vue
  53. 4403 0
      src/components/BoosterStation/sbq.vue
  54. 12163 0
      src/components/BoosterStation/xh.vue
  55. 10411 0
      src/components/BoosterStation/xs.vue
  56. 0 120
      src/components/CenterPage.vue
  57. 431 0
      src/components/StandAloneImg.vue
  58. 0 366
      src/components/StatusBar.vue
  59. 0 513
      src/components/TitleBar.vue
  60. 0 0
      src/components/TitleBarCard.vue
  61. 252 0
      src/components/WindturbineDetailPages.vue
  62. 0 210
      src/components/area/AlarmArea.vue
  63. 0 6
      src/components/area/CheckArea.vue
  64. 0 399
      src/components/area/ControlArea.vue
  65. 0 64
      src/components/area/LabelArea.vue
  66. 0 147
      src/components/area/ProblemArea.vue
  67. 0 66
      src/components/area/RecommendedArea.vue
  68. 0 383
      src/components/area/gy-card.vue
  69. 0 6
      src/components/area/index.js
  70. 0 252
      src/components/area/windturbine/BasicInformationDetail.vue
  71. 0 62
      src/components/area/windturbine/MatrixCard.vue
  72. 0 175
      src/components/area/windturbine/WindturbineDetailPages.vue
  73. 0 341
      src/components/area/windturbine/WindturbineMinCard.vue
  74. 0 99
      src/components/area/windturbine/YawDetail.vue
  75. 0 457
      src/components/area/windturbine/control/ControlMatrixCard.vue
  76. 0 448
      src/components/area/windturbine/problem/ProblemMatrixCard.vue
  77. 0 143
      src/components/area/windturbine/warning.vue
  78. 0 2
      src/components/area/wtbDetailPages.js
  79. 731 0
      src/components/areaCard.vue
  80. 438 0
      src/components/basicDataDetails.vue
  81. 180 0
      src/components/boxSelect.vue
  82. 186 0
      src/components/check/areaCard.vue
  83. 33 0
      src/components/check/checkArea.vue
  84. 393 0
      src/components/check/operationRecords.vue
  85. 853 0
      src/components/control/areaCard.vue
  86. 867 0
      src/components/control/controlAllArea.vue
  87. 45 0
      src/components/control/controlArea.vue
  88. 145 0
      src/components/dataDetails.vue
  89. 264 0
      src/components/focus/PhotoelectricDetailPages.vue
  90. 220 0
      src/components/focus/agcDetails.vue
  91. 394 0
      src/components/focus/dataDetails.vue
  92. 155 0
      src/components/focus/detailsCharts.vue
  93. 101 0
      src/components/focus/focusArea.vue
  94. 272 0
      src/components/focus/focusCard.vue
  95. 125 0
      src/components/focus/multiple-line-chart.vue
  96. 723 0
      src/components/matrixBlock.vue
  97. 408 0
      src/components/modeControl/detailPages.vue
  98. 576 0
      src/components/modeControl/modeControl.vue
  99. 39 0
      src/components/problem/ProblemArea.vue
  100. 0 0
      src/components/problem/ProblemMatrixCard.vue

src/components/area/windturbine/problem/FaultInfoDetail.vue → .env


+ 8 - 0
.env.development

@@ -0,0 +1,8 @@
+VUE_APP_API=http://192.168.10.18:8099
+VUE_APP_WARNING=http://192.168.10.18:8070
+VUE_APP_SHARDINGURL=http://192.168.10.18:8075
+VUE_APP_ADAPTERURL=http://192.168.10.18:8011
+VUE_APP_APIS=192.168.10.18:8099
+VUE_APP_SHARDINGURLS=192.168.10.18:8075
+VUE_APP_ADAPTERURLS=192.168.10.18:8011
+VUE_APP_WARNINGS=92.168.10.18:8070

+ 4 - 0
.env.eapi

@@ -0,0 +1,4 @@
+NODE_ENV=eapi
+VUE_APP_API=https://eapi.nxgqt.org
+VUE_APP_IMAGE=https://eapi.nxgqt.org
+VUE_APP_MAP_KEY=df6LUP4BcbGgSGjZLf8sOBSB6a0fktrb

+ 10 - 0
.env.production

@@ -0,0 +1,10 @@
+# VUE_APP_API=http://18.6.30.53:8075
+# VUE_APP_IMAGE=http://18.6.30.53:8075
+VUE_APP_API=http://18.6.30.63:8099
+VUE_APP_WARNING=http://18.6.30.63:8070
+VUE_APP_SHARDINGURL=http://18.6.30.53:8075
+VUE_APP_ADAPTERURL=http://18.6.30.63:8011
+VUE_APP_APIS=18.6.30.63:8099
+VUE_APP_SHARDINGURLS=18.6.30.53:8075
+VUE_APP_ADAPTERURLS=18.6.30.63:8011
+VUE_APP_WARNINGS=18.6.30.63:8070

+ 1 - 6
.gitignore

@@ -21,11 +21,6 @@ pnpm-debug.log*
 *.njsproj
 *.sln
 *.sw?
-node_modules
 
 #Electron-builder output
-/dist_electron
-/out
-
-#vs
-.vs
+/dist_electron

+ 1 - 6
README.md

@@ -1,4 +1,4 @@
-# neic
+# newneic
 
 ## Project setup
 ```
@@ -15,10 +15,5 @@ npm run serve
 npm run build
 ```
 
-### Lints and fixes files
-```
-npm run lint
-```
-
 ### Customize configuration
 See [Configuration Reference](https://cli.vuejs.org/config/).

Diferenças do arquivo suprimidas por serem muito extensas
+ 2848 - 2171
package-lock.json


+ 25 - 42
package.json

@@ -1,65 +1,48 @@
 {
-  "name": "neic",
+  "name": "newneic",
   "version": "0.1.0",
   "private": true,
-  "description": "新能源智能发电集中控制系统",
-  "author": "gyee",
   "scripts": {
     "serve": "vue-cli-service serve",
     "build": "vue-cli-service build",
-    "lint": "vue-cli-service lint",
-    "dist": "electron-builder",
-    "dist-linux": "electron-builder --linux",
-    "dist-mac": "electron-builder --mac",
-    "dist-win": "electron-builder --win --ia32",
-    "dist-win64": "electron-builder --win --x64",
     "electron:build": "vue-cli-service electron:build",
     "electron:serve": "vue-cli-service electron:serve",
-    "pack": "electron-builder --dir",
     "postinstall": "electron-builder install-app-deps",
     "postuninstall": "electron-builder install-app-deps"
   },
   "main": "background.js",
   "dependencies": {
     "axios": "^0.21.1",
-    "core-js": "^3.15.2",
-    "electron-squirrel-startup": "^1.0.0",
-    "element-plus": "^1.0.2-beta.54",
+    "core-js": "^3.6.5",
+    "dayjs": "^1.10.6",
+    "echarts": "^5.1.2",
+    "element-plus": "^1.0.2-beta.55",
+    "element-ui": "^2.15.3",
+    "register-service-worker": "^1.7.1",
     "stompjs": "^2.3.3",
-    "vue": "^3.1.4",
-    "vue-router": "^3.5.2",
-    "vuex": "^4.0.2"
+    "vue": "^3.0.0",
+    "vue-router": "^4.0.0-0",
+    "vuex": "^4.0.0-0",
+    "xlsx": "^0.17.1"
   },
   "devDependencies": {
-    "@vue/cli-plugin-babel": "~4.5.13",
-    "@vue/cli-plugin-eslint": "~4.5.13",
-    "@vue/cli-service": "~4.5.13",
-    "@vue/compiler-sfc": "^3.1.4",
-    "babel-eslint": "^10.1.0",
-    "electron": "^13.1.5",
-    "electron-devtools-installer": "^3.2.0",
-    "eslint": "^7.30.0",
-    "eslint-plugin-vue": "^7.12.1",
-    "vue-cli-plugin-electron-builder": "^2.1.1"
-  },
-  "eslintConfig": {
-    "root": true,
-    "env": {
-      "node": true
-    },
-    "extends": [
-      "plugin:vue/vue3-essential",
-      "eslint:recommended"
-    ],
-    "parserOptions": {
-      "parser": "babel-eslint"
-    },
-    "rules": {}
+    "@vue/cli-plugin-babel": "~4.5.0",
+    "@vue/cli-plugin-pwa": "~4.5.0",
+    "@vue/cli-plugin-router": "~4.5.0",
+    "@vue/cli-plugin-vuex": "~4.5.0",
+    "@vue/cli-service": "~4.5.0",
+    "@vue/compiler-sfc": "^3.0.0",
+    "electron": "^13.0.0",
+    "electron-devtools-installer": "^3.1.0",
+    "less": "^3.0.4",
+    "less-loader": "^5.0.0",
+    "node-sass": "^4.12.0",
+    "sass-loader": "^8.0.2",
+    "vue-cli-plugin-electron-builder": "~2.1.1"
   },
   "browserslist": [
     "> 1%",
     "last 2 versions",
     "not dead"
-  ],
-  "config": {}
+  ]
 }

BIN
public/img/icons/android-chrome-192x192.png


BIN
public/img/icons/android-chrome-512x512.png


BIN
public/img/icons/android-chrome-maskable-192x192.png


BIN
public/img/icons/android-chrome-maskable-512x512.png


BIN
public/img/icons/apple-touch-icon-120x120.png


BIN
public/img/icons/apple-touch-icon-152x152.png


BIN
public/img/icons/apple-touch-icon-180x180.png


BIN
public/img/icons/apple-touch-icon-60x60.png


BIN
public/img/icons/apple-touch-icon-76x76.png


BIN
public/img/icons/apple-touch-icon.png


BIN
public/img/icons/favicon-16x16.png


BIN
public/img/icons/favicon-32x32.png


BIN
public/img/icons/msapplication-icon-144x144.png


BIN
public/img/icons/mstile-150x150.png


+ 3 - 0
public/img/icons/safari-pinned-tab.svg

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.00251 14.9297L0 1.07422H6.14651L8.00251 4.27503L9.84583 1.07422H16L8.00251 14.9297Z" fill="black"/>
+</svg>

+ 2 - 0
public/robots.txt

@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:

+ 113 - 56
src/App.vue

@@ -1,63 +1,120 @@
-<template>
-  <TitleBar />
-  <CenterPage/>
-  <StatusBar />
+<template class="app">
+  <TitleBar class="titleBar" />
+  <div class="right">
+    <el-col>
+      <el-row>
+        <el-col>
+          <ModeControl ref="modeControl" :current="current" @clicks="handleClick"></ModeControl>
+        </el-col>
+      </el-row>
+      <el-row>
+        <el-col>
+          <FocusArea />
+        </el-col>
+      </el-row>
+      <el-row>
+        <el-col>
+          <WarningArea></WarningArea>
+        </el-col>
+      </el-row>
+    </el-col>
+  </div>
+  <StatusBar class="statusBar" />
+  <router-view />
 </template>
-
 <script>
-import TitleBar from "./components/TitleBar.vue";
-import CenterPage from "./components/CenterPage.vue";
-import StatusBar from "./components/StatusBar.vue";
-
-import MessageBridge from "./assets/script/MessageBridge";
-
-export default {
-  name: "App",
-  components: {
-    TitleBar,
-    CenterPage,
-    StatusBar,
-  },
-  props:{
-    
-  },
-  created: function () {
-    this.initData()
-  },
-  methods: {
-    initData: function () {
-      var mb = MessageBridge.getInstance();
-      var vs = [{ key: "/topic/windturbine", action: this.windturbineMessage }];
-      mb.register(vs);
+  import TitleBar from 'views/TitleBar.vue'
+  import StatusBar from 'views/StatusBar.vue'
+  import MessageBridge from 'utils/MessageBridge'
+  import ModeControl from "components/modeControl/modeControl.vue";
+  import FocusArea from "components/focus/focusArea.vue";
+  import WarningArea from "components/warning/warningArea.vue";
+  export default {
+    components: {
+      TitleBar,
+      StatusBar,
+      ModeControl,
+      FocusArea,
+      WarningArea
+    },
+    created: function () {
+      this.initData()
+      this.subscribe()
     },
-    windturbineMessage(msg) {
-      var json = JSON.parse(msg);
-      this.$store.commit('windturbinelist', json)
+    methods: {
+      initData: function () {
+        let mb = MessageBridge.getInstance();
+        let windturbine = [{ key: "/topic/windturbine", action: this.windturbineMessage }];
+        let popup = [{ key: "/topic/fault-popup", action: this.faultMessage }];
+        let title = [{ key: "/topic/title-info", action: this.titleInfos }];
+        // var heartbeat = [{ key: "/topic/heartbeat-data", action: this.heartbeat }];
+        // mb.register(heartbeat);
+        mb.register(title);
+        mb.register(windturbine);
+        mb.register(popup);
+      },
+      windturbineMessage(msg) {
+        let json = JSON.parse(msg);
+        this.$store.commit('windturbinelist', json)
+      },
+      faultMessage(msg) {
+        let json = JSON.parse(msg);
+        this.$store.commit('warning', json)
+      },
+      // heartbeat(msg){
+      //   console.log(msg);
+      // },
+      subscribe() {
+        setTimeout(() => {
+          this.subscribe()
+        }, 20000);
+        if (!this.$store.state.observers) {
+          let mb = MessageBridge.getInstance();
+          let windturbine = [{ key: "/topic/windturbine", action: this.windturbineMessage }];
+          let popup = [{ key: "/topic/fault-popup", action: this.faultMessage }];
+          let title = [{ key: "/topic/title-info", action: this.titleInfos }];
+          let suggestion = [{ key: "/topic/suggestion", action: this.suggestion }];
+          mb.register(suggestion);
+          mb.register(title);
+          mb.register(windturbine);
+          mb.register(popup);
+          this.$store.commit('observers', true)
+        }
+      }
     },
-  },
-};
+  }
 </script>
-
 <style>
-@import "./assets/style/main.css";
-/*#app {
-   font-family: Avenir, Helvetica, Arial, sans-serif;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  text-align: center;
-  color: #2c3e50;
-  margin-top: 60px; 
-  background-color: coral;
-  padding: 0;
-  margin: 0;
-  border: none;
-} */
+  @import "../src/assets/styles/main.css";
+  body {
+    /* 设置内容不可选中 */
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+  }
+
+  /* .app{
+    background-color: #000000;
+  } */
+  .right {
+    width: 32%;
+    position: absolute;
+    right: 20px;
+    z-index: 99;
+  }
+
+  .statusBar {
+    width: 100%;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+  }
 
-body {
-  /* 设置内容不可选中 */
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-}
-</style>
+  .titleBar {
+    width: 100%;
+    position: relative;
+    top: 0;
+    left: 0;
+  }
+</style>

+ 173 - 0
src/api/index.js

@@ -0,0 +1,173 @@
+import request from "../utils/request";
+//登陆
+const login = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_API,
+        url: `/user/login`,
+        method: "post",
+        data:data,
+    });
+};
+//刷新报警信息
+const getSnap = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_SHARDINGURL,
+        url: `/alarm/snap/page?pagenum=${data.pagenum}&pagesize=${data.pagesize}&category1=${data.category1}&isopened=${data.isopened}&starttime=${data.starttime}&endtime=${data.endtime}`,
+        method: "get",
+    });
+};
+//数据刷新
+const refreshData = (keys) => {
+    return request({
+        baseURL:process.env.VUE_APP_ADAPTERURL,
+        url: `/ts/latest?keys=${keys}`,
+        method: "get",
+    });
+};
+//风机控制
+const windturbControl = (pairs) => {
+    return request({
+        baseURL:process.env.VUE_APP_API,
+        url: `/api/control/`,
+        method: "post",
+        data:pairs
+    });
+};
+//风机控制
+const windturbControlLock = (pairs) => {
+    return request({
+        baseURL:process.env.VUE_APP_API,
+        url: `/api/control/lock`,
+        method: "post",
+        data:pairs
+    });
+};
+//获取风机详情页面数据
+const nitWinturbineBaseData = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_ADAPTERURL,
+        url: `/ts/latest?thingType=${data.thingType}&thingId=${data.thingId}&uniformCodes=${data.uniformCodes}`,
+        method: "get",
+    });
+};
+const getOverview = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_API,
+        url: `/api/windturbine/overview`,
+        method: "get",
+    });
+};
+const sendWarning = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_API,
+        url: `/alarm/confirm?snapID=${data.snapID}&faultID=${data.faultID}&userName=${data.userName}`,
+        method: "get",
+    });
+};
+const sendRecommend = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_API,
+        url: `api/voice-control/addvoicetask`,
+        method: "post",
+        data:data
+    });
+};
+const getPower = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_ADAPTERURL,
+        url: `/ts/history/snap?tagName=${data.tagName}&startTs=${data.startTs}&endTs=${data.endTs}&interval=${data.interval}`,
+        method: "get",
+    });
+};
+const getOriginalPower = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_ADAPTERURL,
+        url: `/ts/history/raw?tagName=${data.tagName}&startTs=${data.startTs}&endTs=${data.endTs}`,
+        method: "get",
+    });
+};
+const getWindturbinePower = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_ADAPTERURL,
+        url: `/ts/history/snap?thingId=${data.thingId}&uniformCode=${data.uniformCode}&startTs=${data.startTs}&endTs=${data.endTs}&thingType=${data.thingType}&interval=${data.interval}`,
+        method: "get",
+    });
+};
+const getOriginalWindturbinePower = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_ADAPTERURL,
+        url: `/ts/history/raw?thingId=${data.thingId}&uniformCode=${data.uniformCode}&startTs=${data.startTs}&endTs=${data.endTs}&thingType=${data.thingType}`,
+        method: "get",
+    });
+};
+const getWindWarning = (data,pageIndex,pageSize) => {
+    return request({
+        baseURL:process.env.VUE_APP_API,
+        url: `/alarm/real-time-alarm?objectId=${data}&pageIndex=${pageIndex}&pageSize=${pageSize}`,
+        method: "get"
+    });
+};
+const getHealthDate=(stid,wtid)=>{
+    return request({
+        baseURL:process.env.VUE_APP_WARNING,
+        url:`/alarm/statistic?stId=${stid}&wtId=${wtid}`,
+        method:"get"
+    })
+}
+const getDetial=(data)=>{
+    return request({
+        baseURL:process.env.VUE_APP_API,
+        url:`/api/windturbine/${data}`,
+        method:"get"
+    })
+}
+const getWarning=(data,wtid,pt)=>{
+    return request({
+        baseURL:process.env.VUE_APP_WARNING,
+        url:`/alarm/list?stId=${data}&wtId=${wtid}&widget=${pt}`,
+        method:"get"
+    })
+}
+const getCustomerLock=()=>{
+    return request({
+        baseURL: process.env.VUE_APP_API,
+        url:`/api/windturbine/customer-lock`,
+        method:"get"
+    })
+}
+const controlRecord = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_API,
+        url: `/control-record/search?stationId=${data.stationId}&userName=${data.userName}&windturbineId=${data.windturbineId}&startTime=${data.startTime}&endTime=${data.endTime}&pageSize=${data.pageSize}&pageIndex=${data.pageIndex}`,
+        method: "get",
+    });
+};
+const getLatest = (data) => {
+    return request({
+        baseURL:process.env.VUE_APP_ADAPTERURL,
+        url: `/ts/latest?keys=${data}`,
+        method: "get",
+    });
+};
+export default {
+    login,
+    getSnap,
+    refreshData,
+    windturbControl,
+    windturbControlLock,
+    nitWinturbineBaseData,
+    getOverview,
+    sendWarning,
+    sendRecommend,
+    getPower,
+    getOriginalPower,
+    getWindWarning,
+    getHealthDate,
+    getDetial,
+    getWarning,
+    getCustomerLock,
+    getWindturbinePower,
+    getOriginalWindturbinePower,
+    controlRecord,
+    getLatest,
+};

BIN
src/assets/img/RecommendedArea/background.png


BIN
src/assets/img/controlcenter/daraTrue.png


BIN
src/assets/img/controlcenter/dataFalse.png


BIN
src/assets/img/logo.png


BIN
src/assets/img/type/down.png


BIN
src/assets/img/type/electricityRestrictions.png


BIN
src/assets/img/type/lock.png


BIN
src/assets/img/type/none.png


BIN
src/assets/img/type/up.png


BIN
src/assets/logo.png


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 2067
src/assets/script/BoosterStation.js


+ 0 - 125
src/assets/script/MessageBridge.js

@@ -1,125 +0,0 @@
-import Stomp from 'stompjs'
-import {config} from '../../config';
-
-export default class MessageBridge {
-  observers;// 观察者
-
-  calcSocket;// 后台websocket
-  adapterSocket;// 适配器websocket
-
-  constructor() {
-    this.register = this.register.bind(this);
-    this.unregister = this.unregister.bind(this);
-    this.onmessage = this.onmessage.bind(this);
-    this.getActions = this.getActions.bind(this);
-
-    this.observers = new Array();
-
-    this.calcSocket = new WebSocket(`ws://${config.calcUrl}/wisdom_service`, this.onmessage, ["/topic/suggestion", "/topic/sync-command-result", "/topic/fault-count",
-      "/topic/alarm-count", "/topic/fault-popup", "/topic/popup-remove", "/topic/heartbeat-data"]);
-    this.adapterSocket = new WebSocket(`ws://${config.adapterUrl}/wisdom`, this.onmessage, ["/topic/windturbine", "/topic/pv"]);
-  }
-
-  /* 单例 */
-  static getInstance() {
-    if (!MessageBridge.instance) {
-      MessageBridge.instance = new MessageBridge();
-    }
-    return MessageBridge.instance;
-  }
-
-  /* 获得消息 */
-  onmessage(msg) {
-    if(msg.headers["data-type"] && msg.headers["data-type"]=="heartbeat"){
-      console.log("获得心跳包!");
-      return;
-    }
-    if (msg.command != "MESSAGE" || !msg.headers.destination) return;
-    var os = this.getActions(msg.headers.destination);
-    for (var id in os) {
-      try{
-        os[id].action(msg.body,msg.headers);
-      }catch(e){console.log(e);}
-    }
-  }
-
-  getActions(destination){
-    var list = new Array();
-    for(var i in this.observers){
-      if(this.observers[i].key==destination){
-        list.push(this.observers[i]);
-      }
-    }
-    return list;
-  }
-
-  /* 注册消息 */
-  register(msgs) {
-    for(var i in msgs){
-      this.observers.push(msgs[i]);
-    }
-  }
-
-  /* 取消注册消息 */
-  unregister(msgs) {
-    this.observers.remove(msgs);
-  }
-}
-
-class WebSocket {
-  onmessage;
-  url;
-  settings;
-  client;
-  constructor(url, onmessage, settings) {
-    this.onerror = this.onerror.bind(this);
-    this.connectCallBackSubscribe = this.connectCallBackSubscribe.bind(this);
-    this.send = this.send.bind(this);
-    this.connect=this.connect.bind(this);
-
-    this.onmessage = onmessage;
-    this.url = url;
-    this.settings = settings;
-    try {
-      this.connect();
-    } catch (e) {
-      console.log("websocket连接错误:\n" + e);
-    }
-
-    console.log("websocket");
-  }
-
-  /* 连接 */
-  connect() {
-    console.log(`正在连接websocket [${this.url}]`)
-    this.client = Stomp.client(this.url);
-    this.client.connect("", "", this.connectCallBackSubscribe, this.onerror);
-  }
-
-  /* 检测连接是否正常 */
-  protector() {
-
-  }
-
-  /* 注册 */
-  connectCallBackSubscribe() {
-    console.log(`注册消息${this.settings}`)
-    for (var index in this.settings) {
-      this.client.subscribe(this.settings[index], frame => this.onmessage(frame));
-    }
-  }
-
-  /* 发送 */
-  send(destination, headers, body) {
-    if (this.client.connected) {
-      this.client.send(destination, headers, body);
-    }
-  }
-
-  /* 发生错误 */
-  onerror(error) {
-    console.log(`websocket [${this.url}] 连接出现错误:\n${error.message}`);
-    // TODO 断线重连还有问题
-    setTimeout(this.connect(), 5000);
-  }
-}

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 8005
src/assets/script/UniformCodes.js


+ 25 - 4
src/assets/style/main.css

@@ -41,15 +41,24 @@ body,
 .el-dialog__title{
   color: rgb(220, 220, 220) !important;
 }
+.inputs .el-input__inner{
+  background-color: #000000 !important;
+  color: rgb(220, 220, 220) !important;
+}
 .el-input__inner{
-  background-color: rgb(100,100,100) !important;
+  /* background-color: rgb(100,100,100) !important; */
   color: rgb(220, 220, 220) !important;
+  border: 1px solid rgba(77, 77, 77, 1) !important;
 }
 .el-tabs{
   background-color: black !important;
   border: none !important;
   color: rgb(220,220,220) !important;
 }
+.el-table__empty-block{
+  background-color: #141414;
+  border: none;
+}
 .el-tabs__item{
   background-color: #363636 !important;
   color: rgb(220,220,220) !important;
@@ -87,9 +96,21 @@ body,
     border-right:1px solid rgb(36,36,36);
   
   }
-  .el-table__body-wrapper{
-    background-color: black;
-  }
+  
   .el-table__empty-text{
     color: black;
+  }
+
+  .el-tree-node:focus>.el-tree-node__content {
+    background-color: #000000 !important;
+  }
+
+  .el-tree-node__content:hover {
+    background-color: #000000 !important;
+  }
+  .el-notification .el-icon-success{
+    color: #67C23A !important;
+  }
+  .el-notification .el-icon-warning {
+    color: #E6A23C !important;
   }

+ 5 - 4
src/background.js

@@ -3,7 +3,6 @@
 import { app, protocol, BrowserWindow } from 'electron'
 import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
 import installExtension, { VUEJS3_DEVTOOLS } from 'electron-devtools-installer'
-
 const isDevelopment = process.env.NODE_ENV !== 'production'
 
 // Scheme must be registered before the app is ready
@@ -19,12 +18,14 @@ async function createWindow() {
     frame:false,
     fullscreen:true,
     webPreferences: {
-
+      
       // Use pluginOptions.nodeIntegration, leave this alone
       // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
+      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
+      contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
       nodeIntegration: true,
       contextIsolation: false,
-      enableRemoteModule: true
+      enableRemoteModule: true,   // 打开remote模块
     }
   })
 
@@ -61,7 +62,7 @@ app.on('ready', async () => {
   if (isDevelopment && !process.env.IS_TEST) {
     // Install Vue Devtools
     try {
-      await installExtension(VUEJS_DEVTOOLS)
+      await installExtension(VUEJS3_DEVTOOLS)
     } catch (e) {
       console.error('Vue Devtools failed to install:', e.toString())
     }

Diferenças do arquivo suprimidas por serem muito extensas
+ 1253 - 0
src/components/BasicInformationDetail.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 5930 - 0
src/components/BoosterStation/dwk.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 4944 - 0
src/components/BoosterStation/hzj.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 2844 - 0
src/components/BoosterStation/mch.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 9139 - 0
src/components/BoosterStation/mhs.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 5432 - 0
src/components/BoosterStation/nss.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 5304 - 0
src/components/BoosterStation/pl1.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 3617 - 0
src/components/BoosterStation/pl2.vue


+ 722 - 0
src/components/BoosterStation/previewPicture.vue

@@ -0,0 +1,722 @@
+<template>
+  <div class="pop-up-main">
+    <div class="paln-box">
+      <div
+        class="movableItem"
+        :style="{ width: width, height: height }"
+        @mousewheel="rollImg($event)"
+        @mousedown="drag($event, 1)"
+        ref="bigImage"
+      >
+        <!-- 图片不可选中 或不可拖拽到新标签打开-->
+        <slot
+          name="svg"
+          oncontextmenu="return false;"
+          onselectstart="return false;"
+          draggable="false"
+        ></slot>
+        <template v-if="isEdit && iconWidth">
+          <img
+            ref="signImage"
+            :src="iconImgUrl"
+            @mousedown="dragSign($event, key)"
+            v-for="(item, key) in equipment"
+            :key="key"
+            :style="{
+              top: equipment[key].top + '%',
+              left: equipment[key].left + '%',
+              width: iconWidth,
+              height: iconHeight,
+            }"
+            class="equipment"
+          />
+        </template>
+        <el-popover
+          width="200"
+          placement="bottom-start"
+          trigger="hover"
+          :close-delay="100"
+          content="暂无描述"
+          v-else-if="!isEdit && iconWidth && arrIcon.length == equipment.length"
+          v-for="(item, key) in equipment"
+          :key="key"
+          popper-class="preview-popover"
+        >
+          <!-- &&arrIcon.length==equipment.length -->
+          <template>
+            <div v-if="equipment[key].describe" class="describe">
+              <p class="describe-top">
+                {{ equipment[key].describe.deviceName }}
+              </p>
+              <p class="describe-center">
+                {{ equipment[key].describe.remark }}
+              </p>
+              <p class="describe-bottom">
+                {{ equipment[key].describe.location }}
+              </p>
+            </div>
+          </template>
+          <!-- <img oncontextmenu="return false;" onselectstart="return false;" draggable="false" slot="reference"
+						ref="signImage" :src="$baseUrl + equipment[key].iconImgUrl"
+						:style="{top:equipment[key].top+'%',left:equipment[key].left+'%',width:arrIcon[key].iconWidth,height:arrIcon[key].iconHeight}"
+						class="equipment" /> -->
+        </el-popover>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  props: {
+    equipment: {
+      type: Array,
+      default: () => {
+        return [
+          {
+            iconImgUrl: "",
+            top: 0,
+            left: 0,
+          },
+        ];
+      },
+    },
+    isEdit: {
+      default: false,
+    },
+    imgUrl: {},
+  },
+
+  data() {
+    return {
+      // 定时器
+      timer: "",
+      // 图片加载失败
+      imgOnerror: false,
+      imgIndex: 0,
+      isChange: true,
+      // 图片显示默认大小
+      width: "1200px",
+      height: "800px",
+      // 可缩小倍数,为空则可无限缩小
+      minification: 3,
+      // 可放大倍数 为空则可无限放大
+      magnification: "",
+      bigMaxWidth: 1100,
+      bigMaxHeight: 800,
+
+      // 小图标信息
+      iconImgUrl: "",
+      iconWidth: "",
+      // 存储每个小图标处理好的宽高
+      iconHeight: "",
+      arrIcon: [],
+      iconMaxWidth: 32,
+      iconMaxHeight: 32,
+      tog: 1,
+    };
+  },
+  methods: {
+    // 获取图片大小
+    getImgInfo(
+      imgUrl,
+      MaxWidth,
+      MaxHeight,
+      StrWidth,
+      StrHeight,
+      Array = false,
+      arr,
+      num = 0
+    ) {
+      let img = new Image();
+
+      // img.src = imgUrl;
+      img = document.getElementsByClassName("svg");
+      let _this = this;
+      img.onerror = () => {
+        // console.log("加载失败!!", _this.arrIcon.length);
+        // console.log(imgUrl, MaxWidth, MaxHeight, StrWidth, StrHeight);
+        _this.imgOnerror = true;
+        _this.imgIndex =
+          _this.arrIcon.length - 1 < 0 ? 0 : _this.arrIcon.length - 1;
+        this.timer = setTimeout(() => {
+          if (num <= 5) {
+            _this.getImgInfo(
+              imgUrl,
+              MaxWidth,
+              MaxHeight,
+              StrWidth,
+              StrHeight,
+              Array,
+              arr,
+              num + 1
+            );
+          }
+          clearInterval(this.timer);
+        }, 2000);
+      };
+      img.onload = function (e) {
+        //  显示时 初始 最大宽度
+        let maxWidth = MaxWidth;
+        //  显示时 初始 最大高度
+        let maxHeight = MaxHeight;
+        if (
+          e.path[0].naturalWidth <= maxWidth &&
+          e.path[0].naturalHeight <= maxHeight
+        ) {
+          _this[StrWidth] = e.path[0].naturalWidth + "px";
+          _this[StrHeight] = e.path[0].naturalHeight + "px";
+        } else {
+          _this[StrWidth] = e.path[0].naturalWidth + "px";
+          _this[StrHeight] = e.path[0].naturalHeight + "px";
+          if (
+            e.path[0].naturalWidth > maxWidth &&
+            e.path[0].naturalHeight <= maxHeight
+          ) {
+            let ratio = e.path[0].naturalWidth / e.path[0].naturalHeight;
+            _this[StrWidth] = "1600px";
+            _this[StrHeight] = maxWidth / ratio + "px";
+          } else if (
+            e.path[0].naturalWidth <= maxWidth &&
+            e.path[0].naturalHeight > maxHeight
+          ) {
+            let ratio = e.path[0].naturalWidth / e.path[0].naturalHeight;
+            _this[StrWidth] = maxHeight * ratio + "px";
+            _this[StrHeight] = "800px";
+          } else if (
+            e.path[0].naturalWidth > maxWidth &&
+            e.path[0].naturalHeight > maxHeight
+          ) {
+            let ratio = e.path[0].naturalWidth / e.path[0].naturalHeight;
+            let w = maxWidth;
+            let h = w / ratio;
+            if (h > maxHeight) {
+              let ratio2 = w / h;
+              h = maxHeight;
+              w = h * ratio2;
+            }
+            _this[StrWidth] = w + "px";
+            _this[StrHeight] = h + "px";
+          }
+        }
+        if (Array) {
+          _this[arr].push({
+            iconWidth: _this[StrWidth],
+            iconHeight: _this[StrHeight],
+          });
+          // console.log(
+          // 	"tow#################################arrIcon",
+          // 	_this[arr].length
+          // );
+        }
+        // _this[StrWidth] = `${e.path[0].naturalWidth}px`;
+        // _this[StrHeight] = `${e.path[0].naturalHeight}px`;
+        // vm.$set(vm.imgInfo, "width", img.width);
+        // vm.$set(vm.imgInfo, "height", img.height);
+        // console.log("打印图片信息", imgUrl, _this[StrWidth], _this[StrHeight]); // 打印图片信息
+
+        // console.log("打印图片信息", e.path[0].naturalHeight); // 打印图片信息
+        // console.log("打印图片信息", e); // 打印图片信息
+        // console.log("打印图片信息this.width", _this[StrWidth]); // 打印图片信息
+        // console.log("打印图片信息this.height", _this[StrHeight]); // 打印图片信息
+      };
+    },
+    // 缩放
+    rollImg() {
+      let that = this;
+      // let oImg = document.getElementsByClassName("movableItem")[0];
+      let oImg = this.$refs.bigImage;
+      // console.log(
+      // 	"length",
+      // 	document.getElementsByClassName("movableItem").length
+      // );
+      // console.log("oImg", oImg);
+      let _this = this;
+
+      function fnWheel(obj, fncc) {
+        obj.onmousewheel = fn;
+        if (obj.addEventListener) {
+          obj.addEventListener("DOMMouseScroll", fn, false);
+        }
+
+        function fn(ev) {
+          let oEvent = ev || window.event;
+          let down = true;
+          if (oEvent.detail) {
+            down = oEvent.detail > 0;
+          } else {
+            down = oEvent.wheelDelta < 0;
+          }
+          if (fncc) {
+            fncc.call(this, down, oEvent);
+          }
+          if (oEvent.preventDefault) {
+            oEvent.preventDefault();
+          }
+          return false;
+        }
+      }
+      fnWheel(oImg, function (down, oEvent) {
+        let oldWidth = this.offsetWidth;
+        let oldHeight = this.offsetHeight;
+        let oldLeft = this.offsetLeft;
+        let oldTop = this.offsetTop;
+        let parent = oEvent.path[2];
+        // 获取父元素距离页面可视区域的位置
+        let parentLeft = parent.getBoundingClientRect().left;
+        let parentTop = parent.getBoundingClientRect().top;
+        // 比例 = (点击位置距离可视窗口位置 - 父元素距离可视窗口位置 - 相对定位的left)/ 本身宽度
+        let scaleX = (oEvent.clientX - parentLeft - oldLeft) / oldWidth; //比例
+        let scaleY = (oEvent.clientY - parentTop - oldTop) / oldHeight;
+
+        let nowWidth = this.style.width.split("p")[0];
+        let initWidth = _this.width.split("p")[0];
+        let initHeight = _this.height.split("p")[0];
+
+        let miniFlag = true;
+        let magniFlag = true;
+        if (_this.minification) {
+          // 限制缩小范围
+          if (nowWidth <= parseInt(initWidth / _this.minification)) {
+            miniFlag = false;
+            // console.log("限制缩小范围");
+            // console.log(
+            // 	"限制缩小范围",
+            // 	nowWidth,
+            // 	parseInt(initWidth / _this.minification)
+            // );
+            this.style.width = parseInt(initWidth / _this.minification) + "px";
+            this.style.height =
+              parseInt(initHeight / _this.minification) + "px";
+          }
+          if (_this.magnification) {
+            // 限制放大范围
+            if (nowWidth >= parseInt(initWidth * _this.magnification)) {
+              magniFlag = false;
+              // console.log("限制放大范围");
+              this.style.width =
+                parseInt(initWidth * _this.magnification) + "px";
+              this.style.height =
+                parseInt(initHeight * _this.magnification) + "px";
+            }
+          }
+        }
+
+        if (down && miniFlag) {
+          this.style.width = parseInt(this.offsetWidth * 0.9) + "px";
+          this.style.height = parseInt(this.offsetHeight * 0.9) + "px";
+
+          that.width = parseInt(this.offsetWidth * 0.9) + "px";
+          that.height = parseInt(this.offsetHeight * 0.9) + "px";
+        } else if (!down && magniFlag) {
+          // console.log("放大");
+          this.style.width = parseInt(this.offsetWidth * 1.1) + "px";
+          this.style.height = parseInt(this.offsetHeight * 1.1) + "px";
+          that.width = parseInt(this.offsetWidth * 1.1) + "px";
+          that.height = parseInt(this.offsetHeight * 1.1) + "px";
+        }
+        let newWidth = this.offsetWidth;
+        let newHeight = this.offsetHeight;
+
+        // 新的相对位置left = 原先的相对位置left - 比例 *(本身新的宽度-旧的宽度)
+        this.style.left =
+          Math.round(this.offsetLeft - scaleX * (newWidth - oldWidth)) + "px";
+        this.style.top =
+          Math.round(this.offsetTop - scaleY * (newHeight - oldHeight)) + "px";
+      });
+      // console.log(that.width)
+    },
+    // },
+    //拖拽
+    drag(ev) {
+      // let ie = document.all;
+      let nn6 = document.getElementById && !document.all;
+      let isdrag = false;
+      let y, x;
+      let nTY, nTX;
+      let oDragObj;
+
+      function moveMouse(e) {
+        if (isdrag) {
+          oDragObj.style.top =
+            (nn6 ? nTY + e.clientY - y : nTY + event.clientY - y) + "px";
+          oDragObj.style.left =
+            (nn6 ? nTX + e.clientX - x : nTX + event.clientX - x) + "px";
+          return false;
+        }
+      }
+
+      function initDrag(e) {
+        // console.log("点击图片initDrag");
+        let oDragHandle = nn6 ? e.target : event.srcElement;
+        let topElement = "HTML";
+        while (
+          oDragHandle.tagName != topElement &&
+          oDragHandle.className != "movableItem"
+        ) {
+          oDragHandle = nn6
+            ? oDragHandle.parentNode
+            : oDragHandle.parentElement;
+        }
+        if (oDragHandle.className == "movableItem") {
+          isdrag = true;
+          oDragObj = oDragHandle;
+          // 父元素宽高
+          let width = e.path[2].offsetWidth;
+          let height = e.path[2].offsetHeight;
+          // 这里判断第一次获取不到style 样式 默认为 居中50%
+          if (oDragObj.style.top == "") {
+            nTY = 0;
+            nTX = parseInt((50 * width) / 100 + 0);
+          } else {
+            nTY = parseInt(oDragObj.style.top + 0);
+            nTX = parseInt(oDragObj.style.left + 0);
+          }
+          y = nn6 ? e.clientY : event.clientY;
+          x = nn6 ? e.clientX : event.clientX;
+          oDragObj.style.cursor = "move";
+          document.onmousemove = moveMouse;
+          return false;
+        }
+      }
+      document.onmousemove = initDrag;
+      // document.onmouseup = new Function("isdrag=false");
+      document.onmouseup = function (e) {
+        isdrag = false;
+        document.onmousemove = null;
+        document.onmouseup = null;
+        let oDragHandle = nn6 ? e.target : event.srcElement;
+        let topElement = "HTML";
+        while (
+          oDragHandle.tagName != topElement &&
+          oDragHandle.className != "movableItem"
+        ) {
+          oDragHandle = nn6
+            ? oDragHandle.parentNode
+            : oDragHandle.parentElement;
+        }
+        if (oDragHandle.className == "movableItem") {
+          oDragObj = oDragHandle;
+          oDragObj.style.cursor = "Default";
+        }
+      };
+      ev = event || window.event;
+
+      // 取消事件冒泡行为
+      // window.event ? (window.event.cancelBubble = true) : ev.stopPropagation();
+    },
+    // 拖拽标记
+    // eslint-disable-next-line no-unused-lets
+    dragSign(ev, key) {
+      let nn6 = document.getElementById && !document.all;
+      let isdrag = false;
+      let y, x;
+      let nTY, nTX;
+      let oDragObj;
+      let _this = this;
+
+      function moveMouse(e) {
+        if (isdrag) {
+          this.equipmentKey = key;
+          // console.log("thisequipmentKey", this.equipmentKey);
+
+          let widthItem = e.path[1].style.width.split("p");
+          let heightItem = e.path[1].style.height.split("p");
+          let width = widthItem[0];
+          // eslint-disable-next-line no-unused-lets
+          let height = heightItem[0];
+          let top =
+            ((nn6
+              ? (nTY / 100) * height + e.clientY - y
+              : (nTY / 100) * height + event.clientY - y) /
+              height) *
+            100;
+          let left =
+            ((nn6
+              ? (nTX / 100) * width + e.clientX - x
+              : (nTX / 100) * width + event.clientX - x) /
+              width) *
+            100;
+
+          if (top >= 0 && top <= 100) {
+            _this.equipment[key].top = top;
+          }
+          if (left >= 0 && left <= 100) {
+            _this.equipment[key].left = left;
+          }
+
+          return false;
+        }
+      }
+      // eslint-disable-next-line no-unused-vars
+      function initDrag(e) {
+        // console.log("_this", _this);
+        let oDragHandle = nn6 ? e.target : event.srcElement;
+        let topElement = "HTML";
+        while (
+          oDragHandle.tagName != topElement &&
+          oDragHandle.className.indexOf("equipment") == -1
+        ) {
+          oDragHandle = nn6
+            ? oDragHandle.parentNode
+            : oDragHandle.parentElement;
+        }
+        if (oDragHandle.className.indexOf("equipment") != -1) {
+          isdrag = true;
+          oDragObj = oDragHandle;
+          // 父元素宽高
+          let width = e.path[1].offsetWidth;
+          // let height = e.path[1].offsetHeight;
+          // console.log(width, height);
+          // console.log("oDragObj.style", oDragObj.style);
+          // 这里判断第一次获取不到style 样式 默认为 居中50%
+          if (oDragObj.style.top == "") {
+            // nTY = parseInt((50 * height) / 100 + 0);
+            nTY = 0;
+            nTX = parseInt((50 * width) / 100 + 0);
+          } else if (oDragObj.style.top.indexOf("%") != -1) {
+            nTY = oDragObj.style.top.split("%")[0];
+            nTX = oDragObj.style.left.split("%")[0];
+          } else {
+            nTY = parseInt(oDragObj.style.top + 0);
+            nTX = parseInt(oDragObj.style.left + 0);
+          }
+          y = nn6 ? e.clientY : event.clientY;
+          x = nn6 ? e.clientX : event.clientX;
+
+          oDragObj.style.cursor = "move";
+          document.onmousemove = moveMouse;
+          return false;
+        }
+      }
+
+      // document.onmousedown = initDrag;
+      document.onmousemove = initDrag;
+
+      document.onmouseup = function (e) {
+        isdrag = false;
+        document.onmousemove = null;
+        document.onmouseup = null;
+        let oDragHandle = nn6 ? e.target : event.srcElement;
+        let topElement = "HTML";
+        while (
+          oDragHandle.tagName != topElement &&
+          oDragHandle.className != "equipment"
+        ) {
+          oDragHandle = nn6
+            ? oDragHandle.parentNode
+            : oDragHandle.parentElement;
+        }
+        if (oDragHandle.className == "equipment") {
+          oDragObj = oDragHandle;
+          oDragObj.style.cursor = "Default";
+        }
+      };
+
+      // _this.equipmentKey = key;
+      // _this.equipment[_this.equipmentKey].left = l;
+      // _this.equipment[_this.equipmentKey].top = t;
+      ev = event || window.event;
+
+      // 取消事件冒泡行为
+      window.event ? (window.event.cancelBubble = true) : ev.stopPropagation();
+    },
+  },
+
+  watch: {
+    equipment() {
+      if (this.equipment.length != 0) {
+        this.arrIcon = [];
+        let finish = true;
+        this.equipment.filter((item) => {
+          if (!item.iconImgUrl) {
+            finish = false;
+          }
+          return true;
+        });
+        // console.log("finish", finish);
+        if (finish) {
+          this.equipment.filter((item, index) => {
+            if (index >= this.imgIndex) {
+              console.log("iconImgUrl", this.equipment[index].iconImgUrl);
+              this.getImgInfo(
+                this.$baseUrl + item.iconImgUrl,
+                this.iconMaxWidth,
+                this.iconMaxHeight,
+                "iconWidth",
+                "iconHeight",
+                true,
+                "arrIcon"
+              );
+            }
+            console.log("22filter", index);
+            return true;
+          });
+        }
+      }
+    },
+  },
+  created() {
+    this.getImgInfo(
+      this.imgUrl,
+      this.bigMaxWidth,
+      this.bigMaxHeight,
+      "width",
+      "height"
+    );
+    if (this.equipment.length != 0) {
+      this.arrIcon = [];
+      let finish = true;
+      this.equipment.filter((item) => {
+        if (!item.iconImgUrl) {
+          finish = false;
+        }
+        return true;
+      });
+      // console.log("finish", finish);
+      if (finish) {
+        this.equipment.filter((item, index) => {
+          if (index >= this.imgIndex) {
+            // console.log("iconImgUrl", this.equipment[index].iconImgUrl);
+            this.getImgInfo(
+              this.$baseUrl + item.iconImgUrl,
+              this.iconMaxWidth,
+              this.iconMaxHeight,
+              "iconWidth",
+              "iconHeight",
+              true,
+              "arrIcon"
+            );
+          }
+          // console.log("22filter", index);
+          return true;
+        });
+      }
+    }
+
+    this.iconImgUrl = JSON.parse(
+      JSON.stringify(this.$baseUrl + this.equipment[0].iconImgUrl)
+    );
+    // console.log("imgUrl", this.imgUrl);
+    // console.log("equipment", this.equipment);
+    // //禁止鼠标右键
+    // document.oncontextmenu = function() {
+    //   return false;
+    // };
+  },
+};
+</script>
+<style lang="less">
+.preview-popover {
+  background-color: #d3edf7dd;
+  padding: 12px;
+
+  .popper__arrow::after {
+    border-bottom-color: #d3edf7dd !important;
+  }
+
+  .describe {
+    p {
+      padding-bottom: 5px;
+
+      &:last-child {
+        padding-bottom: 0px;
+      }
+    }
+
+    .describe-top {
+      // color: sandybrown;
+      // color: red;
+      color: rgb(21, 110, 110);
+    }
+
+    .describe-center {
+      color: rgb(79, 21, 206);
+    }
+
+    .describe-bottom {
+      color: rgb(30, 31, 29);
+    }
+  }
+}
+</style>
+<style lang="less" scoped>
+.pop-up-main {
+		width: 100%;
+		height: calc(100vh - 32vh);
+		overflow-y:hidden ;
+
+		.paln-box {
+			width: 100%;
+			height: 100%;
+			position: relative;
+
+			.movableItem {
+				position: absolute;
+				// top: 75%;
+				left: 50%;
+				transform: translate(-50%, -15%);
+
+				img,
+				.svg {
+					z-index: 1;
+					width: 100%;
+					height: 100%;
+				}
+
+				.equipment {
+					position: absolute;
+					top: 0;
+					left: 0;
+					transform: translate(-50%, -50%);
+					z-index: 2;
+					font-size: 40px;
+					// color: red;
+					// background: blue;
+					zoom: 1;
+				}
+			}
+
+			.shuaxin {
+				position: absolute;
+				z-index: 2;
+				font-size: 40px;
+				top: 20px;
+				left: 20px;
+				cursor: pointer;
+
+				&:hover {
+					color: yellowgreen;
+				}
+			}
+
+			.equipment {
+				color: white;
+			}
+
+			&/deep/.el-button {
+				z-index: 2;
+				position: absolute;
+				bottom: 60px;
+				right: 20px;
+				width: 60px;
+				height: 35px;
+
+				span {
+					display: inline-block;
+					position: absolute;
+					top: 50%;
+					left: 50%;
+					transform: translate(-50%, -50%);
+				}
+
+				i {
+					display: inline-block;
+					position: absolute;
+					top: 50%;
+					left: 25%;
+					transform: translate(-50%, -50%);
+				}
+			}
+		}
+	}
+</style>

Diferenças do arquivo suprimidas por serem muito extensas
+ 4050 - 0
src/components/BoosterStation/qs.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 2502 - 0
src/components/BoosterStation/sbdl.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 4403 - 0
src/components/BoosterStation/sbq.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 12163 - 0
src/components/BoosterStation/xh.vue


Diferenças do arquivo suprimidas por serem muito extensas
+ 10411 - 0
src/components/BoosterStation/xs.vue


+ 0 - 120
src/components/CenterPage.vue

@@ -1,120 +0,0 @@
-/* 中间页面 */
-<template>
-  <div class="center-bar">
-    <el-row :gutter="10">
-      <el-col :span="8">
-        <ProblemArea ref="problempg" :problems="problems" />
-      </el-col>
-      <el-col :span="8">
-        <el-row>
-          <el-col :span="24">
-            <ControlArea />
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <CheckArea />
-          </el-col>
-        </el-row>
-      </el-col>
-      <el-col :span="8">
-        <el-row>
-          <el-col :span="24">
-            <RecommendedArea />
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <LabelArea />
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <AlarmArea />
-          </el-col>
-        </el-row>
-      </el-col>
-    </el-row>
-  <WindturbineDetailPages v-model="dialogVisible"></WindturbineDetailPages>
-  </div>
-</template>
-<script>
-import AlarmArea from "./area/AlarmArea.vue";
-import CheckArea from "./area/CheckArea.vue";
-import ControlArea from "./area/ControlArea.vue";
-import LabelArea from "./area/LabelArea.vue";
-import ProblemArea from "./area/ProblemArea.vue";
-import RecommendedArea from "./area/RecommendedArea.vue";
-import WindturbineDetailPages from "./area/windturbine/WindturbineDetailPages.vue"
-/* import wtbdp from './area/wtbDetailPages'; */
-
-export default {
-  data(){
-    return{
-      dialogVisible:false
-    }
-  },
-  mounted(){
-    /* var self=this;
-    wtbdp.$on("evnt",function(){
-      self.dialogVisible=true;
-    }); */
-  },
-  components: {
-    AlarmArea,
-    CheckArea,
-    ControlArea,
-    LabelArea,
-    ProblemArea,
-    RecommendedArea,
-    WindturbineDetailPages
-  },
-  props: {
-    /* temp: {
-      type: Onject | Array,
-      default: [],
-    }, */
-  },
-  created: function () {
-      
-  },
-  computed: {
-    problems: {
-      get: function () {
-        return this.datas;
-      },
-      set: function (params) {
-        this.datas = params;
-        this.$refs.problempg.problems = params;
-      },
-    },
-  },
-  methods: {
-
-  },
-  watch: {
-    /* temp(res) {
-      this.mapData = res;
-    }, */
-  },
-};
-</script>
-
-<style scoped>
-.center-bar {
-  position: relative;
-  box-sizing: border-box;
-  height: 90vh;
-  background-color: #000000;
-  padding-top: 10px;
-  padding-left: 5px;
-  padding-right: 5px;
-  padding-bottom: 5px;
-  margin-top: 0;
-  margin-right: 0;
-  margin-bottom: 3px;
-  margin-left: 0;
-  display: flex;
-  flex-direction: column;
-}
-</style>

Diferenças do arquivo suprimidas por serem muito extensas
+ 431 - 0
src/components/StandAloneImg.vue


+ 0 - 366
src/components/StatusBar.vue

@@ -1,366 +0,0 @@
-/* 状态栏 */
-<template>
-  <div class="status-bar" onselectstart="return false">
-    <el-row>
-      <el-col :span="18" style="margin-top: 8px">
-        <span style="color: white; margin-left: 20px">系统时间:</span>
-        <span style="color: white">{{ currentTime }}</span>
-      </el-col>
-      <el-col :span="6" style="margin-top: 8px">
-        <el-popover
-          placement="top-start"
-          :width="521"
-          trigger="hover"
-          class="popoverBack"
-          :show-arrow="false"
-        >
-          <template #reference>
-            <div class="status-list">
-              <img
-                class="status-img"
-                src="../assets/img/statusbar/hidden_danger.png"
-              />
-              <span class="status-label hidden-danger">隐患</span>
-              <span>{{ hiddenDangerNum }}</span>
-            </div>
-          </template>
-          <el-scrollbar>
-            <el-table
-              :data="hiddenDangerData"
-              border
-              border-color="rgb(36,36,36)"
-              max-height="650px"
-              :header-cell-style="{
-                background: 'Black',
-                color: 'rgb(220,220,220)',
-                'border-bottom':'solid 1px rgb(36,36,36)'
-              }"
-              :cell-style="{ background: 'Black', color: 'rgb(220,220,220)' }"
-            >
-              <el-table-column
-                width="160"
-                property="lastUpdateTime"
-                label="时间"
-                align="center"
-              ></el-table-column>
-              <el-table-column
-                width="110"
-                property="windturbineId"
-                label="设备"
-                align="center"
-              ></el-table-column>
-              <el-table-column
-                width="250"
-                property="alertText"
-                label="故障信息"
-                align="center"
-              ></el-table-column>
-            </el-table>
-          </el-scrollbar>
-        </el-popover>
-        <el-popover
-          placement="top-start"
-          :width="521"
-          trigger="hover"
-          class="popoverBack"
-          :show-arrow="false"
-        >
-          <template #reference>
-            <div class="status-list">
-              <img
-                class="status-img"
-                src="../assets/img/statusbar/defect.png"
-              />
-              <span class="status-label defect">缺陷</span>
-              <span>{{ defectNum }}</span>
-            </div>
-          </template>
-          <el-scrollbar>
-          <el-table
-            :data="defectData"
-            border
-            border-color="rgb(36,36,36)"
-            max-height="650px"
-            :header-cell-style="{
-              background: 'Black',
-              color: 'rgb(220,220,220)',
-                'border-bottom':'solid 1px rgb(36,36,36)'
-            }"
-            :cell-style="{ background: 'Black', color: 'rgb(220,220,220)' }"
-          >
-            <el-table-column
-              width="160"
-              property="lastUpdateTime"
-              label="时间"
-              align="center"
-            ></el-table-column>
-            <el-table-column
-              width="110"
-              property="windturbineId"
-              label="设备"
-              align="center"
-            ></el-table-column>
-            <el-table-column
-              width="250"
-              property="alertText"
-              label="故障信息"
-              align="center"
-            ></el-table-column>
-          </el-table>
-          </el-scrollbar>
-        </el-popover>
-        <el-popover
-          placement="top-start"
-          :width="521"
-          trigger="hover"
-          class="popoverBack"
-          :show-arrow="false"
-        >
-          <template #reference>
-            <div class="status-list">
-              <img
-                class="status-img"
-                src="../assets/img/statusbar/malfunction.png"
-              />
-              <span class="status-label malfunction">故障</span>
-              <span>{{ malfunctionNum }}</span>
-            </div>
-          </template>
-          <el-scrollbar>
-          <el-table
-            :data="malfunctionData"
-            border
-            border-color="rgb(36,36,36)"
-            max-height="650px"
-            :header-cell-style="{
-              background: 'Black',
-              color: 'rgb(220,220,220)',
-                'border-bottom':'solid 1px rgb(36,36,36)'
-            }"
-            :cell-style="{ background: 'Black', color: 'rgb(220,220,220)' }"
-          >
-            <el-table-column
-              width="160"
-              property="lastUpdateTime"
-              label="时间"
-              align="center"
-            ></el-table-column>
-            <el-table-column
-              width="110"
-              property="stationName"
-              label="设备"
-              align="center"
-            ></el-table-column>
-            <el-table-column
-              width="250"
-              property="alertText"
-              label="故障信息"
-              align="center"
-            ></el-table-column>
-          </el-table>
-          </el-scrollbar>
-        </el-popover>
-        <el-popover
-          placement="top-start"
-          :width="521"
-          trigger="hover"
-          class="popoverBack"
-          :show-arrow="false"
-        >
-          <template #reference>
-            <div class="status-list">
-              <img
-                class="status-img"
-                src="../assets/img/statusbar/accident.png"
-              />
-              <span class="status-label accident">事故</span>
-              <span>{{ accidentNum }}</span>
-            </div>
-          </template>
-          <el-scrollbar>
-          <el-table
-            :data="accidentData"
-            border
-            border-color="rgb(36,36,36)"
-            max-height="650px"
-            :header-cell-style="{
-              background: 'Black',
-              color: 'rgb(220,220,220)',
-                'border-bottom':'solid 1px rgb(36,36,36)'
-            }"
-            :cell-style="{ background: 'Black', color: 'rgb(220,220,220)' }"
-          >
-            <el-table-column
-              width="160"
-              property="lastUpdateTime"
-              label="时间"
-              align="center"
-            ></el-table-column>
-            <el-table-column
-              width="110"
-              property="stationName"
-              label="设备"
-              align="center"
-            ></el-table-column>
-            <el-table-column
-              width="250"
-              property="alertText"
-              label="故障信息"
-              align="center"
-            ></el-table-column>
-          </el-table>
-          </el-scrollbar>
-        </el-popover>
-      </el-col>
-    </el-row>
-  </div>
-</template>
-
-<script>
-import BackgroundData from "../assets/script/BackgroundData";
-export default {
-  data() {
-    return {
-      hiddenDangerNum: 0,
-      defectNum: 0,
-      malfunctionNum: 0,
-      accidentNum: 0,
-      statusTimer: "",
-      currentTime: "",
-
-      hiddenDangerData: new Array(),
-      defectData: new Array(),
-      malfunctionData: new Array(),
-      accidentData: new Array(),
-    };
-  },
-  mounted() {
-    let that = this;
-    this.statusTimer = setInterval(function () {
-      that.currentTime =
-        new Date().getFullYear() +
-        "-" +
-        that.appendZero(new Date().getMonth() + 1) +
-        "-" +
-        that.appendZero(new Date().getDate()) +
-        " " +
-        that.appendZero(new Date().getHours()) +
-        ":" +
-        that.appendZero(new Date().getMinutes()) +
-        ": " +
-        that.appendZero(new Date().getSeconds());
-    }, 1000);
-  },
-  beforeDestory() {
-    clearInterval(this.statusTimer);
-    this.statusTimer = null;
-  },
-  created() {
-    this.refreshTimer = setInterval(this.refreshData, 2000);
-  },
-  methods: {
-    appendZero(obj) {
-      if (obj < 10) {
-        return "0" + obj;
-      } else {
-        return obj;
-      }
-    },
-    refreshData() {
-      var bd = BackgroundData.getInstance();
-      this.hiddenDangerNum = bd.HiddenProblems.length;
-      this.defectNum = bd.Defects.length;
-      this.malfunctionNum = bd.Failure.length;
-      this.accidentNum = bd.Accidents.length;
-
-      this.hiddenDangerData = bd.HiddenProblems;
-      this.defectData = bd.Defects;
-      this.malfunctionData = bd.Failure;
-      this.accidentData = bd.Accidents;
-/*       if (this.accidentData.length <= 0) {
-        this.accidentData = [
-          { lastUpdateTime: "-", stationName: "-", alertText: "-" },
-        ];
-      }
-      if (this.hiddenDangerData.length <= 0) {
-        this.hiddenDangerData = [
-          { lastUpdateTime: "-", windturbineId: "-", alertText: "-" },
-        ];
-      }
-      if (this.defectData.length <= 0) {
-        this.defectData = [
-          { lastUpdateTime: "-", windturbineId: "-", alertText: "-" },
-        ];
-      }
-      if (this.malfunctionData.length <= 0) {
-        this.malfunctionData = [
-          { lastUpdateTime: "-", stationName: "-", alertText: "-" },
-        ];
-      } */
-
-    },
-  },
-};
-</script>
-
-<style scoped>
-:deep(.el-table__body-wrapper::-webkit-scrollbar) {
-  width: 8px;
-  background-color: black;
-}
-
-:deep(.el-table__body-wrapper::-webkit-scrollbar-thumb) {
-  background-color: #292929;
-  border-radius: 6px;
-}
-:deep(.el-table td,.el-table th){
-border-bottom:1px solid rgb(36,36,36);
-}
-span {
-  font-size: 13px;
-}
-
-.status-bar {
-  height: 4vh;
-  background-color: #191919;
-
-  margin-bottom: 0;
-  margin-left: 0;
-  margin-right: 0;
-}
-
-.status-list {
-  position: relative;
-  display: inline-block;
-  box-sizing: border-box;
-  color: white;
-}
-
-.status-label {
-  margin-left: 10px;
-  margin-right: 10px;
-}
-
-.status-img {
-  position: relative;
-  top: 4px;
-  margin-left: 20px;
-  width: 20px;
-}
-
-.status-label.hidden-danger {
-  color: #e6d541;
-}
-
-.status-label.defect {
-  color: #e69641;
-}
-
-.status-label.malfunction {
-  color: #d541e6;
-}
-
-.status-label.accident {
-  color: #af3e3d;
-}
-</style>

+ 0 - 513
src/components/TitleBar.vue

@@ -1,513 +0,0 @@
-/* 标题栏 */
-<template>
-  <div class="title-bar" onselectstart="return false">
-    <el-row>
-      <el-col :span="2">
-        <img
-          class="logo"
-          src="../assets/img/main_window/logo.png"
-          sytle="align-items"
-        />
-      </el-col>
-      <el-col :span="1">
-        <div>
-          <el-dialog
-            title="用户登录"
-            v-model="dialogVisible"
-            width="21%"
-            :before-close="handleClose"
-            :show-close="false"
-          >
-            <el-form :model="form">
-              <el-form-item :label="loginMessage"> </el-form-item>
-              <el-form-item label="用户名:" :label-width="formLabelWidth">
-                <el-input
-                  v-model="form.name"
-                  autocomplete="off"
-                  type="text"
-                  placeholder="用户名"
-                  style="width: 80%"
-                ></el-input>
-              </el-form-item>
-              <el-form-item label="密&emsp;码:" :label-width="formLabelWidth">
-                <el-input
-                  v-model="form.psd"
-                  autocomplete="off"
-                  type="text"
-                  placeholder="密&emsp;码"
-                  style="width: 80%"
-                  show-password
-                ></el-input>
-              </el-form-item>
-              <el-form-item
-                label="验证码:"
-                :label-width="formLabelWidth"
-                style="display: none"
-              >
-                <el-input
-                  v-model="form.name"
-                  autocomplete="off"
-                  type="text"
-                  placeholder="验证码"
-                  style="width: 80%"
-                  ><template #append
-                    ><img
-                      src="../../src\assets\logo.png"
-                      style="width: 50px; height: 20px" /></template
-                ></el-input>
-              </el-form-item>
-            </el-form>
-            <template #footer>
-              <span class="dialog-footer">
-                <el-button
-                  @click="dialogVisible = false"
-                  style="
-                    background-color: rgb(100, 100, 100);
-                    color: rgb(220, 220, 220);
-                  "
-                  >取 消</el-button
-                >
-                <el-button type="primary" @click="login">登 录</el-button>
-              </span>
-            </template>
-          </el-dialog>
-        </div>
-      </el-col>
-
-      <el-col :span="19">
-            <!-- <el-popover
-          placement="bottom"
-          :width="1416"
-          trigger="hover"
-          :show-arrow="false"
-          offset="0"
-        >
-          <template #reference> -->
-            <div class="titleinfoall">
-              <div class="titleinfo">
-                <ul>
-                  <li>
-                    <TitleBarCard
-                      title="装机容量"
-                      unit="MW"
-                      :value="installedCapacity"
-                    ></TitleBarCard>
-                  </li>
-                </ul>
-              </div>
-              <div class="titleinfo">
-                <ul>
-                  <li>
-                    <TitleBarCard
-                      title="实时功率"
-                      unit="MW"
-                      :value="totalPower"
-                    ></TitleBarCard>
-                  </li>
-                </ul>
-              </div>
-              <div class="titleinfo">
-                <ul>
-                  <li>
-                    <TitleBarCard
-                      title="日发电量"
-                      unit="kWh"
-                      :value="dailyPowerGeneration"
-                    ></TitleBarCard>
-                  </li>
-                </ul>
-              </div>
-              <div class="titleinfo">
-                <ul>
-                  <li>
-                    <TitleBarCard
-                      title="上网电量"
-                      unit="kWh"
-                      :value="gridPower"
-                    ></TitleBarCard>
-                  </li>
-                </ul>
-              </div>
-              <div class="titleinfo">
-                <ul>
-                  <li>
-                    <TitleBarCard
-                      title="月发电量"
-                      unit="kWh"
-                      :value="monthlyPowerGeneration"
-                    ></TitleBarCard>
-                  </li>
-                </ul>
-              </div>
-              <div class="titleinfo">
-                <ul>
-                  <li>
-                    <TitleBarCard
-                      title="年发电量"
-                      unit="kWh"
-                      :value="annualPowerGeneration"
-                    ></TitleBarCard>
-                  </li>
-                </ul>
-              </div>
-              <div class="titleinfo">
-                <ul>
-                  <li>
-                    <TitleBarCard
-                      title="月利用小时"
-                      unit="小时"
-                      :value="monthlyUtilizationHours"
-                    ></TitleBarCard>
-                  </li>
-                </ul>
-              </div>
-              <div class="titleinfo">
-                <ul>
-                  <li>
-                    <TitleBarCard
-                      title="年利用小时"
-                      unit="小时"
-                      :value="annualUtilizationHours"
-                    ></TitleBarCard>
-                  </li>
-                </ul>
-              </div>
-            </div>
-          <!-- </template>
-
-          <el-table
-            :data="tableData"
-            border
-            border-color="rgb(36,36,36)"
-            :header-cell-style="{
-              background: 'Black',
-              color: 'rgb(220,220,220)',
-              'border-bottom':'solid 1px rgb(36,36,36)',
-              fontSize:'14px',
-              'padding-top':'7px',
-              'padding-bottom':'7px'
-            }"
-            :cell-style="{ background: 'Black', color: 'rgb(220,220,220)','border-bottom':'solid 1px rgb(36,36,36)',fontSize:'14px','padding-top':'5px','padding-bottom':'5px'}"
-            >
-        <el-table-column
-              align="center"
-              prop="station"
-              label="站点"
-              width="80px">
-          </el-table-column>
-        <el-table-column
-              align="center"
-              prop="date"
-              label="运行指标"
-              width="120px">
-            <el-table-column
-              align="center"
-              prop="date"
-              label="日发电量(万kwh)"
-              width="135px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="name"
-              label="&ensp;平均风速(m/s)&ensp;日照强度(w/m²)"
-              width="130px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="address"
-              label="实时功率(MW)"
-              width="120px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="name"
-              label="AGC有功设定(MW)"
-              width="150px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="name"
-              label="理论功率(MW)"
-              width="120px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="name"
-              label="预测功率(MW)"
-              width="120px">
-            </el-table-column>
-        </el-table-column>
-        
-        <el-table-column
-              align="center"
-              prop="date"
-              label="发电设备状态汇总"
-              width="80px">
-            <el-table-column
-              align="center"
-              prop="date"
-              label="接入"
-              width="80px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="name"
-              label="运行"
-              width="80px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="address"
-              label="待机"
-              width="80px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="name"
-              label="维护"
-              width="80px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="name"
-              label="故障"
-              width="80px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="name"
-              label="限电"
-              width="80px">
-            </el-table-column>
-            <el-table-column
-              align="center"
-              prop="name"
-              label="离线"
-              width="80px">
-            </el-table-column>
-        </el-table-column>
-          </el-table> 
-
-        </el-popover> -->
-      </el-col>
-      
-
-      <el-col :span="1">
-        <el-popover  placement="bottom" :width="150" trigger="hover" :show-arrow="false">
-          <template #reference>
-            <el-button @click="userClick" style="top: 10px; right: 70px; color: #ffffff; position: absolute;background-color:black;border:none;font-size:16px;">{{usreName}}</el-button>
-          </template>
-          <div style="background-color: #363636;">
-            <!-- <el-button class="loginoption">编&emsp;辑</el-button>
-            <br> -->
-            <el-button v-if="!isLogin" class="loginoption" @click="userClick">登&emsp;录</el-button>
-            <br v-if="!isLogin">
-            <el-button v-if="isLogin" class="loginoption" @click="logout">注&emsp;销</el-button>
-          </div>
-        </el-popover>
-
-        <!-- <div @click="userClick" style="top: 18px; right: 100px; color: #ffffff; position: absolute">{{usreName}}</div> -->
-
-        <!-- <el-button
-          v-popover:loginref
-          type="text"
-          @click="dialogVisible = true"
-          style="top:9px;right: 85px;color: #ffffff;position: absolute;">管理员</el-button> -->
-      </el-col>
-
-      <el-col :span="1">
-        <div style="margin-top: 7px; position: absolute; right: 10px">
-          <button class="closeButton" v-on:click="mainClose">×</button>
-        </div>
-      </el-col>
-    </el-row>
-  </div>
-</template>
-
-<script>
-import TitleBarCard from "./area/mainwindow/TitleBarCard.vue";
-import BackgroundData from "../assets/script/BackgroundData";
-
-export default {
-  name: "TitleBar",
-  components: {
-    TitleBarCard
-  },
-  data() {
-    return {
-      dialogVisible: false,
-      dialogFormVisible: false,
-      isLogin:false,
-      form: {
-        name: "",
-        psd: "",
-      },
-      usreName: "未登录...",
-      loginMessage: "", // 登录提示
-      formLabelWidth: "120px",
-      totalPower: 0, // 实时功率
-      dailyPowerGeneration: 0, // 日发电量
-      gridPower: 0, // 上网电量
-      monthlyPowerGeneration: 0, // 月发电量
-      annualPowerGeneration: 0, // 年发电量
-      installedCapacity: 734, // 装机容量
-      tableData: [{
-            station:'麻黄山',
-          }, {
-            station:'牛首山',
-          }, {
-            station:'青山',
-          }, {
-            station:'石板泉',
-          }, {
-            station:'香山',
-          }, {
-            station:'风场汇总',
-          }, {
-            station:'大武口',
-          }, {
-            station:'平罗',
-          }, {
-            station:'宣和',
-          }, {
-            station:'马场湖',
-          }, {
-            station:'海子井',
-          }, {
-            station:'光伏汇总',
-          }
-          ]
-    };
-  },
-  computed: {
-    monthlyUtilizationHours: function () {
-      // 月利用小时数
-      return (
-        (this.monthlyPowerGeneration * 10) /
-        this.installedCapacity
-      ).toFixed(2);
-    },
-    annualUtilizationHours: function () {
-      // 年利用小时数
-      return (
-        (this.annualPowerGeneration * 10) /
-        this.installedCapacity
-      ).toFixed(2);
-    },
-  },
-  created() {
-    this.refreshTimer = setInterval(this.refreshData, 2000);
-  },
-  methods: {
-    handleClose(done) {
-      done();
-    },
-    mainClose() {
-      const { remote } = require("electron");
-      remote.getCurrentWindow().destroy();
-    },
-    refreshData() {
-      // todo 计算发电量的时候没有考虑光伏的,后续完善
-      var bd = BackgroundData.getInstance();
-      var val = bd.TopPoint;
-      for (var v in val) {
-        var pt = val[v];
-        if (pt.pointName == "TotalPower") {
-          this.totalPower = pt.value.toFixed(2);
-        } else if (pt.pointName == "DailyPowerGeneration") {
-          this.dailyPowerGeneration = pt.value.toFixed(2);
-        } else if (pt.pointName == "GridPower") {
-          this.gridPower = pt.value.toFixed(2);
-        } else if (pt.pointName == "MonthlyPowerGeneration") {
-          this.monthlyPowerGeneration = pt.value.toFixed(2);
-        } else if (pt.pointName == "AnnualPowerGeneration") {
-          this.annualPowerGeneration = pt.value.toFixed(2);
-        }
-      }
-    },
-
-    /* 登录 */
-    login() {
-      var bd = BackgroundData.getInstance();
-        this.loginMessage='正在登录...';
-      bd.login(this.form.name,this.form.psd,this.onLoged);
-    },
-
-    onLoged(msg){
-      if(!msg.data){
-        this.loginMessage=msg;
-        return;
-      }
-      var user = msg.data;
-      if (!user.isValid) {
-        this.loginMessage = user.message;
-        return;
-      }
-      BackgroundData.getInstance().LoginUser = user;
-      this.usreName = user.name;
-      this.dialogVisible = false;
-      this.loginMessage = "";
-      this.form.name = this.form.psd = "";
-
-      this.isLogin=true;
-    },
-
-    /* 用户点击 */
-    userClick() {
-      this.dialogVisible = true;
-    },
-
-    /* 用户注销 */
-    logout(){
-      BackgroundData.getInstance().LoginUser=null;
-      this.usreName = '未登录...';
-      this.isLogin=false;
-    }
-  },
-};
-</script>
-
-
-<style scoped>
-.loginoption{
-  font-size:16px;
-  width:150px;
-  background-color: #292929;
-  border:none;
-  color:rgb(220,220,220);
-}
-.title-bar {
-  height: 5vh;
-  background-color: #000000;
-  margin-top: 0;
-  margin-right: 0;
-  margin-left: 0;
-}
-.logo {
-  position: relative;
-  top: 32%;
-  margin-left: 10px;
-}
-.titleinfo {
-  background-color: rgb(20, 20, 20);
-  height: auto;
-  padding: 13px;
-  border-radius: 6px;
-  margin-top: 5px;
-  margin-bottom: 5px;
-  margin-left: -9px;
-}
-
-.closeButton {
-  font-size: 30px;
-  color: white;
-  background: rgb(41, 41, 41);
-  width: 44px;
-  height: 44px;
-  border-radius: 8px;
-  border: none;
-}
-.titleinfoall{
-  display: flex;;
-}
-</style>

src/components/area/mainwindow/TitleBarCard.vue → src/components/TitleBarCard.vue


+ 252 - 0
src/components/WindturbineDetailPages.vue

@@ -0,0 +1,252 @@
+<template>
+	<el-dialog width="75%" @opened="opened()" @closed="closed()" :show-close="false" class="my-info-dialog">
+		<template #title>
+			<div style="margin-top:-10px;color: #FFFFFF;">风机详情</div>
+		</template>
+		<div class="body">
+			<div class="titleList">
+				<div class="chunkdiv">
+					<div class="title">风机号:&emsp;</div>
+					<div>{{ windturbine.windturbineId }}</div>
+				</div>
+				<div class="chunkdiv" @dblclick="dbClicks(baseDate.windSpeed)">
+					<div class="title">{{baseDate.windSpeed.name}}:&emsp;</div>
+					<div>{{baseDate.windSpeed.value}}{{baseDate.windSpeed.unit}}</div>
+				</div>
+				<div class="chunkdiv" @dblclick="dbClicks({code: 'YDPJFS5M',name: '五分钟平均风速'})">
+					<div class="title">五分钟平均风速:&emsp;</div>
+					<div>{{healthInfo?.averageWindSpeed5?.toFixed(2)}}m/s</div>
+				</div>
+				<div class="chunkdiv" @dblclick="dbClicks(theoreticalPower)">
+					<div class="title">理论功率:&emsp;</div>
+					<div>{{healthInfo?.theoreticalPower?.toFixed(2)}}Kw</div>
+				</div>
+				<div class="chunkdiv" @dblclick="dbClicks(baseDate.power)">
+					<div class="title">{{baseDate.power.name}}:&emsp;</div>
+					<div>{{baseDate.power.value}}{{baseDate.power.unit}}</div>
+				</div>
+				<div class="chunkdiv" @dblclick="dbClicks(baseDate.generatorSpeed)">
+					<div class="title">{{baseDate.generatorSpeed.name}}:&emsp;</div>
+					<div>{{baseDate.generatorSpeed.value}}{{baseDate.generatorSpeed.unit}}</div>
+				</div>
+			</div>
+			<BasicInformationDetail ref="BasicInfo" :types="types" @health-click="handleHealth" :windturbine="windturbine"></BasicInformationDetail>
+		</div>
+	</el-dialog>
+</template>
+
+<script>
+	// import YawDetail from "./YawDetail.vue";
+	import api from "api/index";
+	import BasicInformationDetail from "./BasicInformationDetail.vue";
+	import UniformCodes from "utils/UniformCodes";
+	import BackgroundData from 'utils/BackgroundData'
+	// import Worning from "./warning.vue"
+	export default {
+		components: {
+			BasicInformationDetail,
+		},
+		props: {
+			windturbine: Object,
+		},
+		data() {
+			return {
+				BasicInfo: {},
+				healthInfo: {},
+				line: "",
+				alarmTime: "",
+				alarmContent: "",
+				alarms: [],
+				count: false,
+				theoreticalPower:{
+					code: "LLGL",
+					name: "理论功率"
+				},
+				typeList: [{
+					type: 0,
+					name: '已经停机',
+				},
+				{
+					type: 1,
+					name: '上电',
+				},
+				{
+					type: 2,
+					name: '待机',
+				},
+				{
+					type: 3,
+					name: '启动',
+				},
+				{
+					type: 4,
+					name: '并网',
+				},
+				{
+					type: 5,
+					name: '故障',
+				},
+				{
+					type: 6,
+					name: '维护',
+				},
+				{
+					type: 7,
+					name: '离线',
+				},
+				],
+				baseDate: {
+					windSpeed: {
+						name: '',
+						num: '',
+						unit: ''
+					},
+					power: {
+						name: '',
+						num: '',
+						unit: ''
+					},
+					generatorSpeed: {
+						name: '',
+						num: '',
+						unit: ''
+					},
+				},
+				types: null,
+			};
+		},
+		created() {
+			this.UniformCodes = new UniformCodes();
+		},
+
+		methods: {
+			opened() {
+				this.line = "";
+					this.alarmTime = "";
+					this.alarmContent = "";
+					this.BasicInfo = this.UniformCodes.getStationInfos(this.windturbine);
+					this.BasicInfo.windturbineId = this.windturbine.windturbineId;
+					// this.dateDeal(this.BasicInfo)
+					this.$refs.BasicInfo.start(this.BasicInfo);
+					this.initData();
+					this.refreshData();
+					this.refreshTimer = setInterval(this.refreshData, 100)
+			},
+			closed() {
+				// todo 切换页面的时候应该让上一个页面停止刷新数据(调用end方法)
+				// this.$refs.svgRef.closed();
+				// this.$refs.BasicInfo.end();
+				// this.$refs.BasicInfo.labelChange();
+				this.$emit('close');
+				//clearInterval(this.refreshTimer);
+			},
+			dateDeal(BasicInfo) {
+				let showInf = {}
+				showInf = BasicInfo.BasicInfo.filter(item => item.tag === "基本信息")[0]
+				this.baseDate.windSpeed = showInf.param.filter(item => item.name === "风速")[0]
+				this.baseDate.power = showInf.param.filter(item => item.name === "有功功率")[0]
+				this.baseDate.generatorSpeed = showInf.param.filter(item => item.name === "发电机转速")[0]
+				this.baseDate.type = showInf.param.filter(item => item.name === "状态")[0].value ? this.typeList.filter(
+					status => status.type === Number(showInf.param.filter(item => item.name === "状态")[0].value))[0]
+					.name : ''
+				console.log(this.baseDate.generatorSpeed.name);
+				this.types = Number(showInf.param.filter(item => item.name === "状态")[0].value)
+				console.log(this.types)
+			},
+			refreshData() {
+				let bg = BackgroundData.getInstance();
+				bg.initWinturbineBaseData(this.BasicInfo, this.onMessage);
+				this.dateDeal(this.BasicInfo)
+				clearInterval(this.refreshTimer);
+				this.refreshTimer = setInterval(this.refreshData, 5000)
+			},
+			initData() {
+				// axiios.get(`http://${config.calcUrl}/windturbine/line/${this.windturbine.windturbineId}`)
+				//   .then(msg => this.line = msg.data);
+				api.getWindWarning(this.windturbine.windturbineId, '1', '50').then(msg => {
+					let vs = msg.data;
+					if (vs.length <= 0) return;
+					this.alarmTime = BackgroundData.getInstance().formatDate(vs[0].lastUpdateTime);
+					this.alarmContent = vs[0].alertText;
+					this.alarms = msg.data;
+					this.$refs.BasicInfo.alarmd(this.alarms);
+					console.log(this.alarms)
+				})
+					.catch(err => {
+						console.log(err);
+					});
+			},
+			dbClicks(value) {
+				this.$refs.BasicInfo.dbClicks(value, this.windturbine.windturbineId)
+			},
+			handleHealth(value){
+				this.healthInfo = value
+			}
+		},
+		watch: {
+			'windturbine': {
+				handler: function (json) {
+					if (json) {
+						this.initData()
+					}
+				}
+			}
+		}
+	};
+</script>
+<style scoped>
+	.my-info-dialog {
+		box-shadow: 0px 0px 10px #05bb4c;
+	}
+
+	.body {
+		background-color: black;
+		margin-top: -30px;
+		margin-left: -10px;
+		margin-right: -10px;
+		margin-bottom: -30px;
+		border-bottom: 20px solid rgb(36, 36, 36);
+	}
+
+	.chunkdiv {
+		display: flex;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		width: 17%;
+		background-color: #363636;
+		margin: 1px;
+		padding: 4px 0px;
+		font-size: 12px;
+		color: #FFFFFF;
+		overflow: hidden;
+		white-space: nowrap;
+	}
+
+	.title {
+		font-size: 12px;
+		color: #B3B3B3;
+	}
+
+	table {
+		margin-left: 2px;
+		margin-right: 2px;
+	}
+
+	/* td {
+		width: 20%;
+	} */
+
+	el-tabs {
+		background-color: black;
+	}
+
+	.svg {
+		height: 67vh;
+	}
+	.titleList{
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+	}
+</style>

+ 0 - 210
src/components/area/AlarmArea.vue

@@ -1,210 +0,0 @@
-/* 告警区 */
-<template>
-  <gy-card
-    title="告警区"
-    area-style="alarm"
-    circle-style="green"
-    content-style="25"
-  >
-    <div style="padding-left: 5px; padding-right: 5px">
-      <el-table
-        :data="values"
-        height="219px"
-        :header-cell-style="{
-          background: 'Black',
-          color: 'rgb(220,220,220)',
-          padding: '4px',
-          fontSize: '14px',
-          'border-bottom': 'solid 1px black',
-        }"
-        :cell-style="{
-          background: '#1e1e1e',
-          color: 'rgb(220,220,220)',
-          padding: '3px',
-          fontSize: '12px',
-        }"
-        @row-dblclick="itemDblclick"
-      >
-        <el-table-column
-          prop="lastUpdateTime"
-          align="center"
-          label="时间"
-          width="150"
-        >
-        </el-table-column>
-        <el-table-column
-          prop="alertText"
-          align="center"
-          label="描述"
-          width="380"
-        >
-        </el-table-column>
-        <el-table-column prop="isSelected" align="center" label="确认">
-          <template v-slot="scope">
-            <!-- <el-checkbox v-model="scope.row.isSelected" @click="itemChecked(scope.row)"></el-checkbox> -->
-            <input
-              type="checkbox"
-              v-model="scope.row.isSelected"
-              @click="itemChecked(scope.row)"
-            />
-          </template>
-          <!-- <el-checkbox v-model="isSelected"></el-checkbox> -->
-          <!-- <input type="checkbox"/> -->
-        </el-table-column>
-      </el-table>
-    </div>
-  </gy-card>
-  <WindturbineDetailPages
-    v-model="dialogVisible"
-    :windturbine="currentWindturbine"
-  ></WindturbineDetailPages>
-</template>
-
-<script>
-import MessageBridge from "../../assets/script/MessageBridge";
-import WindturbineDetailPages from "../area/windturbine/WindturbineDetailPages.vue";
-import BackgroundData from "../../assets/script/BackgroundData";
-import axios from "axios";
-import { config } from "../../config";
-
-export default {
-  name: "AlarmArea",
-  components: {
-    WindturbineDetailPages,
-  },
-  created: function () {
-    this.initData();
-  },
-  props: {},
-  data() {
-    return {
-
-      values: new Array(),
-      dialogVisible:false,
-      currentWindturbine: {},
-    };
-  },
-  methods: {
-    initData() {
-      var mb = MessageBridge.getInstance();
-      var vs = [{ key: "/topic/fault-popup", action: this.faultMessage }];
-      mb.register(vs);
-    },
-    faultMessage(msg) {
-      var val = JSON.parse(msg);
-      var sleected = {};
-      this.values.forEach((it) => {
-        if (it.isSelected) {
-          sleected[it.id] = 0;
-        }
-      });
-      this.values = new Array();
-      for (var v in val) {
-        var vl = val[v];
-        if (vl.stationId != "QS_FDC" && vl.category1 == "FJ") {
-          vl.alertText = vl.windturbineName + "-" + vl.alertText;
-        }
-        if (sleected[vl.id] == 0 && BackgroundData.getInstance().LoginUser) {
-          vl.isSelected = true;
-        }
-        this.values.push(vl);
-      }
-      console.log(val);
-    },
-    /* 行双击 */
-    itemDblclick(row) {
-      if (row.category1 != "FJ") return;
-      this.dialogVisible = true;
-      this.currentWindturbine = row;
-    },
-    /* 报警确认 */
-    itemChecked(row) {
-      if (row.isSelected == true) {
-        row.isSelected = false;
-        return;
-      }
-      var bd = BackgroundData.getInstance();
-      if (!bd.LoginUser) {
-        this.$notify({
-          title: "请登录",
-          message: "确认报警需要先登录!",
-          type: "warning",
-          position: "bottom-right",
-          offset: 60,
-        });
-        row.isSelected = false;
-        return;
-      }
-      row.isSelected = true;
-      this.confirm(row);
-      console.log(row);
-    },
-    confirm(item) {
-      var url = `http://${config.calcUrl}/alarm/confirm?snapID=${item.snapIDString}&faultID=${item.idString}&userName=${BackgroundData.getInstance().LoginUser.name}`;
-      axios
-        .get(url)
-        .then((msg) => {
-          var mms = msg.data > 0 ? "报警确认成功!" : "报警确认出现错误!";
-          var tp = msg.data > 0 ? "success" : "error";
-          this.$notify({
-            title: "报警",
-            message: mms,
-            type: tp,
-            position: "bottom-right",
-            offset: 60,
-          });
-        })
-        .catch((err) => {
-          this.$notify({
-            title: "报警",
-            message: `报警确认出现错误:${err.message},请重试`,
-            type: "error",
-            position: "bottom-right",
-            offset: 60,
-          });
-        });
-    },
-  },
-};
-</script>
-<style scoped>
-:deep(.el-table__body-wrapper::-webkit-scrollbar) {
-  width: 8px;
-  height: 0px;
-  background-color: black;
-}
-
-:deep(.el-table__body-wrapper::-webkit-scrollbar-thumb) {
-  background-color: #292929;
-  border-radius: 6px;
-}
-:deep(.el-table td, .el-table th) {
-  border-bottom: 2px solid black;
-}
-tr {
-  line-height: 1.5;
-  background: #1e1e1e;
-  margin-bottom: 2px;
-  border-radius: 5px;
-}
-/* .ToolBar {
-  position: absolute;
-  right: 12px;
-  width: 586px;
-  text-align: center;
-  z-index: 2;
-  font-size: 14px;
-  height: 28px;
-  margin: 5px;
-  background: #1e1e1e;
-} */
-.table-main {
-  font-size: 14px;
-  width: 600px;
-  text-align: center;
-  background: #000000;
-  margin: 5px;
-  border-collapse: separate;
-  border-spacing: 0px 5px;
-}
-</style>

+ 0 - 6
src/components/area/CheckArea.vue

@@ -1,6 +0,0 @@
-/* 校验区 */
-<template>
-    <gy-card title="校验区" area-style="check" circle-style="green" content-style="44">
-        <div></div>
-    </gy-card>
-</template>

+ 0 - 399
src/components/area/ControlArea.vue

@@ -1,399 +0,0 @@
-/* 控制区 */
-<template>
-  <gy-card
-    title="控制区"
-    area-style="control"
-    circle-style="green"
-    content-style="44"
-    @contextmenu="contextmenu"
-  >
-    <ControlMatrixCard
-      title="待启动"
-      :datas="ls.start"
-      :operateStyle="1"
-      ref="start"
-    ></ControlMatrixCard>
-    <ControlMatrixCard
-      title="待停机"
-      :datas="ls.stop"
-      :operateStyle="2"
-      ref="stop"
-    ></ControlMatrixCard>
-    <ControlMatrixCard
-      title="待维护"
-      :datas="ls.maintain"
-      :operateStyle="6"
-      ref="maintain"
-    ></ControlMatrixCard>
-    <ControlMatrixCard
-      title="待取消维护"
-      :datas="ls.unmaintain"
-      :operateStyle="8"
-      ref="unmaintain"
-    ></ControlMatrixCard>
-    <ControlMatrixCard
-      title="待复位"
-      :datas="ls.reset"
-      :operateStyle="5"
-      ref="reset"
-    ></ControlMatrixCard>
-    <el-button
-      style="
-        z-index: 2;
-        position: absolute;
-        bottom: 10px;
-        right: 10px;
-        background: #292929;
-        font-size: 15px;
-        width: 90px;
-        border: none;
-        color: rgb(220, 220, 220);
-      "
-      size="small"
-      @click="menuClicked({ type: 'send' })"
-      >发送</el-button
-    >
-  </gy-card>
-  <el-button-group
-    style="z-index: 3; position: absolute; top: 6px; left: 120px"
-  >
-    <el-button :class="buttonLeftStyle" size="mini" @click="controlClick(false)"
-      >手动</el-button
-    >
-    <el-button :class="buttonRightStyle" size="mini" @click="controlClick(true)"
-      >自动</el-button
-    >
-  </el-button-group>
-</template>
-
-<script>
-import ControlMatrixCard from "./windturbine/control/ControlMatrixCard.vue";
-import MessageBridge from "../../assets/script/MessageBridge";
-import BackgroundData from "../../assets/script/BackgroundData";
-
-export default {
-  name: "ControlArea",
-  components: {
-    ControlMatrixCard,
-  },
-  props: {},
-  computed: {
-    buttonLeftStyle: function () {
-      return this.IsAutoControl ? "button-unselected" : "button-selected";
-    },
-    buttonRightStyle: function () {
-      return this.IsAutoControl ? "button-selected" : "button-unselected";
-    },
-  },
-  created: function () {
-    this.initData();
-  },
-  data() {
-    return {
-      ls: {
-        start: { key: "待启动", value: [] },
-        stop: { key: "待停机", value: [] },
-        maintain: { key: "待维护", value: [] },
-        unmaintain: { key: "待取消维护", value: [] },
-        reset: { key: "待复位", value: [] },
-      },
-      IsAutoControl: false,
-      controlErorCodes:[
-        "控制成功",
-        "控制命令发送失败",
-        "无效的控制地址",
-        "被控设备异常",
-        "网络连接错误,检查场站通信",
-        "控制结果读取超时",
-        "未知错误",
-        "控制命令错误",
-        "收到无法识别数据",
-        "未读取到数据包",
-        "未知错误",
-        "风机操作过频繁",
-        "风机被挂牌",
-        "风机操作与风机状态不符",
-        "需要登录",
-      ],
-    };
-  },
-  methods: {
-    initData: function () {
-      var mb = MessageBridge.getInstance();
-      var vs = [{ key: "/topic/suggestion", action: this.suggestion }];
-      mb.register(vs);
-    },
-    suggestion(msg, headers) {
-      var val = JSON.parse(msg);
-      var tp = headers["operate-type"];
-      if (tp == "UnMaintain") {
-        this.updateSuggestion(this.ls.unmaintain.value, val);
-      } else if (tp == "Start") {
-        //推荐启动
-        this.updateSuggestion(this.ls.start.value, val);
-      } else if (tp == "Stop") {
-        // 推荐停机
-        this.updateSuggestion(this.ls.stop.value, val);
-      } else if (tp == "Reset") {
-        // 推荐复位
-        this.updateSuggestion(this.ls.reset.value, val);
-      } else if (tp == "Maintain") {
-        // 推荐维护
-        this.updateSuggestion(this.ls.maintain.value, val);
-      }
-    },
-
-    /* 获取推荐类型 */
-    getSuggestionType(val) {
-      if (typeof val === "undefined") return null;
-      for (var v in val) {
-        return val[v].adviceOperateStyle;
-      }
-      return null;
-    },
-
-    /* 更新推荐数据 */
-    updateSuggestion(ll, val) {
-      var lls = new Array();
-      for (var v1 in ll) {
-        var v2 = val[ll[v1]];
-        if (typeof v2 === "undefined") {
-          lls.push(v1);
-        }
-      }
-      for (var v3 in lls) {
-        ll.splice(v3, 1);
-      }
-      for (var v in val) {
-        var vl = val[v];
-        if (!ll.includes(vl.windturbineId)) {
-          ll.push(vl.windturbineId);
-        }
-      }
-    },
-
-    /* 右键菜单 */
-    contextmenu() {
-      const { remote } = require("electron");
-      var that = this;
-      const menuTemplate = [
-        {
-          label: "发送",
-          click() {
-            that.menuClicked({ type: "send" });
-          },
-        },
-        {
-          label: "挂牌",
-          submenu: [
-            {
-              label: "检修",
-              click() {
-                that.menuClicked({ type: "lock", value: "CheckLock" });
-              },
-            },
-            {
-              label: "故障维修",
-              click() {
-                that.menuClicked({ type: "lock", value: "FaultLock" });
-              },
-            },
-            {
-              label: "场内受累检修",
-              click() {
-                that.menuClicked({ type: "lock", value: "StationCheckLock" });
-              },
-            },
-            {
-              label: "场内受累故障",
-              click() {
-                that.menuClicked({ type: "lock", value: "StationFaulLock" });
-              },
-            },
-            {
-              label: "场外受累电网",
-              click() {
-                that.menuClicked({
-                  type: "lock",
-                  value: "StationPowerLineLock",
-                });
-              },
-            },
-            {
-              label: "场外受累天气",
-              click() {
-                that.menuClicked({ type: "lock", value: "StationWeatherLock" });
-              },
-            },
-          ],
-        },
-        {
-          label: "标注",
-          click() {
-            that.menuClicked({ type: "marking" });
-          },
-        },
-      ];
-      const menu = remote.Menu.buildFromTemplate(menuTemplate);
-
-      menu.popup(remote.getCurrentWindow());
-    },
-
-    menuClicked(msg) {
-      var bd = BackgroundData.getInstance();
-      if (!bd.LoginUser) {
-        this.$notify({
-          title: "请登录",
-          message: "控制风机需要先登录!",
-          type: "warning",
-          position: "bottom-right",
-          offset: 60,
-        });
-        return;
-      }
-      if (msg.type == "lock") {
-        // 挂牌
-        var los = this.getSelectedItems();
-        for (var id in los) {
-          los[id].lockType = msg.value;
-        }
-        bd.windturbineControl(
-          los,
-          true,
-          this.controlSuccess,
-          this.controlError
-        );
-      } else if (msg.type == "send") {
-        // 发送
-        var vs = this.getSelectedItems(true);
-        bd.windturbineControl(
-          vs,
-          false,
-          this.controlSuccess,
-          this.controlError
-        );
-      } else if (msg.type == "marking") {
-        // 标注
-        var vvs = this.getSelectedItems();
-        bd.marking(vvs);
-      }
-      this.clearSelected();
-    },
-
-    /* 控制成功 */
-    controlSuccess(msg) {
-      console.log(msg);
-      var mss = '';     // 信息
-      var iserror=false;// 是否有控制错误的风机
-      for(var v in msg.data){
-        var val = msg.data[v];
-        if(val.errorCode>0){
-          iserror=true;
-          mss+=`${val.windturbineId}  ${this.controlErorCodes[val.errorCode]}\n`;
-        }
-      }
-      var tp = iserror?"warning":"success";
-      var dt = iserror?0:4500;
-      if(!iserror){
-        mss="控制成功";
-      }
-
-      this.$notify({
-          title: "控制",
-          message: mss,
-          type: tp,
-          position: "bottom-right",
-          offset: 60,
-          duration: dt,
-        });
-    },
-
-    /* 控制失败 */
-    controlError(err) {
-      this.$notify({
-        title: "控制出现错误",
-        message: err.message,
-        type: "warning",
-        position: "bottom-right",
-        offset: 60,
-      });
-    },
-
-    /* 获取选中的项目,isControl:是否是控制 */
-    getSelectedItems(isControl) {
-      var ls = new Array();
-      this.$refs.start.outputSelectedItems(ls);
-      this.$refs.stop.outputSelectedItems(ls);
-      if (isControl) return ls;
-      this.$refs.maintain.outputSelectedItems(ls);
-      this.$refs.unmaintain.outputSelectedItems(ls);
-      this.$refs.reset.outputSelectedItems(ls);
-      return ls;
-    },
-
-    /* 清除所有选择 */
-    clearSelected() {
-      this.$refs.start.clearSelected();
-      this.$refs.stop.clearSelected();
-      this.$refs.maintain.clearSelected();
-      this.$refs.unmaintain.clearSelected();
-      this.$refs.reset.clearSelected();
-    },
-
-    controlClick(isAuto) {
-      var bd = BackgroundData.getInstance();
-      if (isAuto) {
-        if (!bd.LoginUser) {
-          this.$notify({
-            title: "请登录",
-            message: "切换为自动控制需要先登录!",
-            type: "warning",
-            position: "bottom-right",
-            offset: 60,
-          });
-          return;
-        }
-        this.AutoSendTimer = setInterval(this.AutoSend, 60000);
-        /* this.$message({
-          message: "已切换为自动控制",
-          type: "success",
-        }); */
-      } else {
-        /* this.$message({
-          message: "已切换为手动控制",
-          type: "success",
-        }); */
-        clearInterval(this.AutoSendTimer);
-      }
-      this.IsAutoControl = isAuto;
-    },
-
-    /* 自动发送命令 */
-    AutoSend() {
-      var ls = new Array();
-      this.$refs.start.outputAllItems(ls);
-      this.$refs.stop.outputAllItems(ls);
-      console.log("自动发送命令 " + ls.length);
-      if (ls.length <= 0) return;
-      var bd = BackgroundData.getInstance();
-      bd.windturbineControlSystem(ls, false);
-    },
-  },
-};
-</script>
-<style scoped>
-.button-selected {
-  background: black;
-  font-size: 14px;
-  width: 80px;
-  border: none;
-  color: rgb(220, 220, 220);
-}
-.button-unselected {
-  background: #202020;
-  font-size: 14px;
-  width: 80px;
-  border: none;
-  color: rgb(220, 220, 220);
-}
-</style>

+ 0 - 64
src/components/area/LabelArea.vue

@@ -1,64 +0,0 @@
-/* 标注区 */
-<template>
-    <gy-card title="标注区" area-style="label" circle-style="yellow" content-style="25">
-        <div v-for="mk in values" :key="mk" @contextmenu="contextmenu(mk)" style="width:110px;margin-left:10px;margin-top:10px;display: inline-block;">
-            <img src="../../assets/img/LabelArea/flag.png" style="float:left;margin-top:5px;margin-left:18px;"/>
-            <div style="text-align:center;font-size:12px;float:right;margin-right:18px;">{{mk.title}}</div>
-            <input v-model="mk.value" style="font-size:12px;border:none;background-color:#292929;height:26px;border-radius:6px;text-align:center;outline:none;width:110px;color:rgb(220,220,220);"/>
-        </div>
-    </gy-card>
-</template>
-
-<script>
-import BackgroundData from "../../assets/script/BackgroundData";
-
-export default {
-  name: "LabelArea",
-  data() {
-    return {
-      values: new Array(),
-    };
-  },
-  created() {
-    this.refreshTimer = setInterval(this.refreshData, 1000);
-  },
-  methods: {
-    refreshData() {
-      this.values = new Array();
-      this.values = BackgroundData.getInstance().Marks;
-    },
-
-    contextmenu(mk) {
-      const { remote } = require("electron");
-      var that = this;
-      const menuTemplate = [
-        {
-          label: "删除",
-          click() {
-            that.remove(mk);
-          },
-        },
-      ];
-      const menu = remote.Menu.buildFromTemplate(menuTemplate);
-
-      menu.popup(remote.getCurrentWindow());
-    },
-
-    remove(mk) {
-      var indx = -1;
-      for (var ind in this.values) {
-        if (this.values[ind].id == mk.id) {
-          indx = ind;
-          break;
-        }
-      }
-      if (indx < 0) return;
-      this.values.splice(indx, 1);
-      BackgroundData.getInstance().removeMarked(mk);
-    },
-  },
-};
-</script>
-
-<style scoped>
-</style>

+ 0 - 147
src/components/area/ProblemArea.vue

@@ -1,147 +0,0 @@
-/* 问题区 */
-<template>
-  <gy-card
-    title="问题区"
-    area-style="problem"
-    circle-style="green"
-    content-style="89"
-    @parentRun="run"
-    @contextmenu="contextmenu"
-  >
-    <ProblemMatrixCard title="故障" :type="5" ref="malfunction"></ProblemMatrixCard>
-    <ProblemMatrixCard title="维护" :type="6" ref="maintain"></ProblemMatrixCard>
-    <ProblemMatrixCard title="离线" :type="7" ref="offline"></ProblemMatrixCard>
-    <ProblemMatrixCard title="挂牌" :type="-1" ref="lock"></ProblemMatrixCard>
-  </gy-card>
-</template>
-
-<script>
-import ProblemMatrixCard from "./windturbine/problem/ProblemMatrixCard.vue";
-import BackgroundData from "../../assets/script/BackgroundData";
-
-export default {
-  name: "ProblemArea",
-  components: {
-    ProblemMatrixCard,
-  },
-  props: {},
-  data() {
-    return {
-      ls: {
-        maintain: { key: "维护", value: [] },
-        malfunction: { key: "故障", value: [] },
-        offline: { key: "离线", value: [] },
-        lockd: { key: "挂牌", value: [] },
-      },
-    };
-  },
-  computed: {},
-  created: function () {
-    
-  },
-  methods: {
-    /* 右键菜单 */
-    contextmenu() {
-      const { remote } = require("electron");
-      var that = this;
-      const menuTemplate = [
-        {
-          label: "标注",
-          click() {
-            that.menuClicked({ type: "marking" });
-          },
-        },
-        {
-          label: "挂牌",
-          submenu: [
-            {
-              label: "检修",
-              click() {
-                that.menuClicked({ type: "lock", value: "CheckLock" });
-              },
-            },
-            {
-              label: "故障维修",
-              click() {
-                that.menuClicked({ type: "lock", value: "FaultLock" });
-              },
-            },
-            {
-              label: "场内受累检修",
-              click() {
-                that.menuClicked({ type: "lock", value: "StationCheckLock" });
-              },
-            },
-            {
-              label: "场内受累故障",
-              click() {
-                that.menuClicked({ type: "lock", value: "StationFaulLock" });
-              },
-            },
-            {
-              label: "场外受累电网",
-              click() {
-                that.menuClicked({ type: "lock", value: "StationPowerLineLock" });
-              },
-            },
-            {
-              label: "场外受累天气",
-              click() {
-                that.menuClicked({ type: "lock", value: "StationWeatherLock" });
-              },
-            },
-          ],
-        },
-        {
-          label: "取消挂牌",
-          click() {
-            that.menuClicked({ type: "lock",value:"UnLock" });
-          },
-        },
-      ];
-      const menu = remote.Menu.buildFromTemplate(menuTemplate);
-
-      menu.popup(remote.getCurrentWindow());
-    },
-
-    menuClicked(msg) {
-      var bd = BackgroundData.getInstance();
-      if (!bd.LoginUser) {
-        bd.showdialog("提示", "请登录:", "在控制之前需要先登录!");
-        return;
-      }
-      if (msg.type == "lock") {
-        // 挂牌
-        var los = this.getSelectedItems();
-        for(var id in los){
-          los[id].lockType=msg.value;
-        }
-        bd.windturbineControl(los,true);
-      } else if (msg.type == "marking") {
-        // 标注
-        var vs = this.getSelectedItems();
-        bd.marking(vs);
-      }
-      this.clearSelected();
-    },
-
-    /* 获取选中的项目 */
-    getSelectedItems(){
-      var ls = new Array();
-      this.$refs.malfunction.outputSelectedItems(ls);
-      this.$refs.maintain.outputSelectedItems(ls);
-      this.$refs.offline.outputSelectedItems(ls);
-      this.$refs.lock.outputSelectedItems(ls);
-      return ls;
-    },
-    
-    /* 清除所有选择 */
-    clearSelected(){
-      this.$refs.malfunction.clearSelected();
-      this.$refs.maintain.clearSelected();
-      this.$refs.offline.clearSelected();
-      this.$refs.lock.clearSelected();
-    },
-  },
-};
-</script>

+ 0 - 66
src/components/area/RecommendedArea.vue

@@ -1,66 +0,0 @@
-/* 推荐区 */
-<template>
-  <gy-card
-    title="推荐区"
-    area-style="recommended"
-    circle-style="green"
-    content-style="37"
-  >
-  <div style="display: flex;justify-content: flex-start;flex-wrap: wrap;">
-  <table v-for="vl in values" :key="vl">
-      <tr>{{vl.stationName}}</tr>
-      <tr>{{vl.content}}</tr>
-      <tr>{{vl.createTime}}</tr>
-  </table>  
-  </div>
-  </gy-card>
-</template>
-
-<script>
-import BackgroundData from "../../assets/script/BackgroundData";
-export default {
-  name: "RecommendedArea",
-  props: ["datas"],
-  data() {
-    return {
-      values: new Array(),
-    };
-  },
-  created() {
-    this.initData();
-  },
-  mounted() {},
-  watch: {},
-  methods: {
-    initData() {
-      setInterval(this.refreshData, 2000);
-    },
-    refreshData() {
-      var bd = BackgroundData.getInstance();
-      var ll = new Array();
-      for (var v in bd.Recommends) {
-        if (bd.Recommends[v].isActive) {
-          ll.push(bd.Recommends[v]);
-        }
-      }
-      this.values = ll;
-    },
-  },
-};
-</script>
-<style scoped>
-table{
-  background-image: url("../../assets/img/RecommendedArea/guznzhu_bg_01.png");
-  text-align: center;
-  font-size:12px;
-  width: 110px;
-  height: 110px;
-  background-size:110px;
-  margin-left: 10px;
-  margin-top: 10px;
-  padding-top: 10px;
-  background-repeat:no-repeat;
-  
-}
-</style>
-

+ 0 - 383
src/components/area/gy-card.vue

@@ -1,383 +0,0 @@
-/* 自定义tabs */
-<template>
-    <transition>
-        <div :class='areaClass' @mouseover="hover = false"
-             @mouseleave="hover = false" onselectstart="return false">
-            <div :class="headerClass"> <!-- @dblclick="gyCardDbClick" -->
-                <div :class='circleClass'></div>
-                <span class="gy-card-title">{{ title }}</span>
-                <img class="gy-card-decoration01" src="../../assets/img/controlcenter/decoration01.png">
-                <img class="gy-card-decoration02" src="../../assets/img/controlcenter/decoration02.png">
-            </div>
-            <div :class='contentClass'>
-                <el-scrollbar style="height: 100%">
-                    <slot></slot>
-                </el-scrollbar>
-            </div>
-        </div>
-    </transition>
-</template>
-
-<script>
-    /**
-     * todo 拖动
-     * todo 控制区
-     *
-     * 动态值:
-     * 1. gy-card-area-label中的 height,margin-top
-     * 2. gy-card-circle-yellow中的颜色
-     * 3. gy-card-content-25 中的高度
-     *
-     * 使用事例:
-     * <gy-card title="校验区" area-style="check" circle-style="green" content-style="44">
-     * <div>动态内容</div>
-     * </gy-card>
-     */
-    export default {
-        name: 'gy-card',
-        emits: ["parentRun"],
-        props: {
-            title: {
-                type: String,
-                default: '校验区',
-                required: true
-            },
-            areaStyle: {
-                type: String,
-                default: 'check',
-                required: true
-            },
-            circleStyle: {
-                type: String,
-                default: 'green',
-                required: true
-            },
-            contentStyle: {
-                type: String,
-                default: '44',
-                required: true
-            }
-        },
-        data() {
-            return {
-                hover: false,
-                big: false
-            }
-        },
-        computed: {
-            areaClass() {
-                if (this.big) {
-                    return `gy-card-area-big`;
-                } else {
-                    return `gy-card-area-${this.areaStyle}`;
-                }
-            },
-            circleClass() {
-                return `gy-card-circle gy-card-circle-${this.circleStyle}`;
-            },
-            contentClass() {
-                if (this.big) {
-                    return `gy-card-content-big`;
-                } else {
-                    return `gy-card-content-${this.contentStyle}`;
-                }
-            },
-            headerClass() {
-                if (this.hover) {
-                    return `gy-card-header-hover`;
-                } else {
-                    return `gy-card-header`;
-                }
-            }
-        },
-        methods: {
-            /* gyCardDbClick() {
-                let big = this.big
-                if (big) {
-                    this.big = false
-                } else {
-                    this.big = false
-                }
-            }, */
-        }
-    }
-</script>
-
-<style scoped="scoped">
-    .gy-card-header {
-        position: relative;
-        height: 40px;
-        background-color: #292929;
-        color: white;
-        box-sizing: border-box;
-    }
-
-    .gy-card-content-89 {
-        position: relative;
-        height: calc(89vh - 50px);
-        background-color: #000000;
-        color: white;
-        box-sizing: border-box;
-        border-radius: 7px;
-    }
-
-    .gy-card-content-44 {
-        position: relative;
-        height: calc(44vh - 50px);
-        background-color: #000000;
-        color: white;
-        box-sizing: border-box;
-        border-radius: 7px;
-    }
-
-    .gy-card-content-37 {
-        position: relative;
-        height: calc(37vh - 50px);
-        background-color: #000000;
-        color: white;
-        box-sizing: border-box;
-        border-radius: 7px;
-    }
-
-    .gy-card-content-25 {
-        position: relative;
-        height: calc(25vh - 50px);
-        background-color: #000000;
-        color: white;
-        box-sizing: border-box;
-        border-radius: 7px;
-    }
-
-    .gy-card-circle{
-        position: relative;
-        top: 7px;
-        display: inline-block;
-        width: 7px;
-        height: 7px;
-        -moz-border-radius: 50%;
-        -webkit-border-radius: 50%;
-        border-radius: 50%;
-    }
-
-    .gy-card-circle-green {
-        background-color: #008000;
-    }
-
-    .gy-card-circle-yellow {
-        background-color: #ffff00;
-    }
-
-    .gy-card-title {
-        position: relative;
-        top: 10px;
-        left: 10px;
-    }
-
-    .gy-card-decoration01 {
-        position: absolute;
-        right: 80px;
-    }
-
-    .gy-card-decoration02 {
-        position: absolute;
-        top: 20px;
-        right: 20px;
-    }
-
-    .gy-card-area-problem {
-        position: relative;
-        height: 89vh;
-        background-color: #292929;
-        border-radius: 7px;
-        margin: 0px;
-        padding-top: 0;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-    .gy-card-area-alarm {
-        position: relative;
-        height: 25vh;
-        margin-top: 10px;
-        background-color: #292929;
-        border-radius: 7px;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-    .gy-card-area-check {
-        position: relative;
-        height: 44vh;
-        background-color: #292929;
-        border-radius: 7px;
-        margin-top: 10px;
-        padding-top: 0;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-    .gy-card-area-control {
-        position: relative;
-        width: 100%;
-        height: 44vh;
-        background-color: #292929;
-        border-radius: 7px;
-        margin: 0px;
-        padding-top: 0;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-    .gy-card-area-label {
-        position: relative;
-        height: 25vh;
-        margin-top: 10px;
-        background-color: #292929;
-        border-radius: 7px;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-    .gy-card-area-recommended {
-        position: relative;
-        height: 37vh;
-        background-color: #292929;
-        border-radius: 7px;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-    .gy-card-header-hover {
-        position: relative;
-        height: 40px;
-        background-color: #292929;
-        color: white;
-        box-sizing: border-box;
-    }
-
-    .gy-card-area-problem:hover {
-        position: relative;
-        height: 89vh;
-        background-color: #292929;
-        border-radius: 7px;
-        margin: 0px;
-        padding-top: 0;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-    .gy-card-area-alarm:hover {
-        position: relative;
-        height: 25vh;
-        margin-top: 10px;
-        background-color: #292929;
-        border-radius: 7px;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-/*     .gy-card-area-check:hover {
-        position: relative;
-        height: 44vh;
-        background-color: #292929;
-        border-radius: 7px;
-        margin: 0px;
-        padding-top: 0;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
- */
-/*     .gy-card-area-control:hover {
-        position: relative;
-        width: 100%;
-        height: 44vh;
-        background-color: #292929;
-        border-radius: 7px;
-        margin-top: 10px;
-        padding-top: 0;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    } */
-
-    .gy-card-area-label:hover {
-        position: relative;
-        height: 25vh;
-        margin-top: 10px;
-        background-color: #292929;
-        border-radius: 7px;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-    .gy-card-area-recommended:hover {
-        position: relative;
-        height: 37vh;
-        background-color: #292929;
-        border-radius: 7px;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-    }
-
-
-    .gy-card-area-big {
-        position: fixed;
-        top: 0px;
-        left: 0px;
-        width: 100vw;
-        height: 100vh;
-        background-color: #292929;
-        border-radius: 7px;
-        margin: 0px;
-        padding-top: 0;
-        padding-left: 10px;
-        padding-right: 10px;
-        padding-bottom: 10px;
-        box-sizing: border-box;
-        z-index: 900;
-    }
-
-    .gy-card-content-big {
-        position: relative;
-        height: calc(100vh - 50px);
-        background-color: #000000;
-        color: white;
-        box-sizing: border-box;
-        border-radius: 7px;
-    }
-
-    .el-scrollbar__wrap {
-        overflow: scroll;
-        width: 110%;
-        height: 120%;
-    }
-
-    ::-webkit-scrollbar {
-        width: 0;
-        height: 0;
-    }
-
-</style>

+ 0 - 6
src/components/area/index.js

@@ -1,6 +0,0 @@
-import gyCard from './gy-card'
-
-gyCard.install = function (Vue) {
-    Vue.component(gyCard.name, gyCard)
-}
-export default gyCard

+ 0 - 252
src/components/area/windturbine/BasicInformationDetail.vue

@@ -1,252 +0,0 @@
-<template>
-  <div class="firstdiv">
-    <div v-for="(item, index) in warnList" :key="index">
-      <div :class="'worning' + item.type">
-        <Worning :worn="item.alertText"></Worning>
-      </div>
-    </div>
-    <img style="float: left; margin-left: 40px; margin-top: 90px;width:50vh;height:25vh;"
-      src="../../../assets/img/WindturbineDetailPages/变桨.png" object-fit="fill" />
-    <div class="twodiv">
-      <table>
-        <tr>
-          <th>温度信息</th>
-        </tr>
-        <tr v-for="itm in temperatureInfo" :key="itm">
-          <td>{{ itm.name }}</td>
-          <td>{{ itm.value }}</td>
-          <td>{{ itm.unit }}</td>
-        </tr>
-      </table>
-      <table v-if="pitchInfo.length > 0">
-        <tr>
-          <th>变桨信息</th>
-        </tr>
-        <tr v-for="itm in pitchInfo" :key="itm">
-          <td>{{ itm.name }}</td>
-          <td>{{ itm.value }}</td>
-          <td>{{ itm.unit }}</td>
-        </tr>
-      </table>
-    </div>
-    <div class="onediv">
-      <table>
-        <tr>
-          <th>基本信息</th>
-        </tr>
-        <tr v-for="itm in generalInfo" :key="itm">
-          <td>{{ itm.name }}</td>
-          <td>{{ itm.value }}</td>
-          <td>{{ itm.unit }}</td>
-        </tr>
-      </table>
-      <table>
-        <tr>
-          <th>电网信息</th>
-        </tr>
-        <tr v-for="itm in powerGridInfo" :key="itm">
-          <td>{{ itm.name }}</td>
-          <td>{{ itm.value }}</td>
-          <td>{{ itm.unit }}</td>
-        </tr>
-      </table>
-    </div>
-    <!-- <div>{{alarms[0].alertText}}</div> -->
-  </div>
-</template>
-
-<script>
-  import BackgroundData from "../../../assets/script/BackgroundData";
-  import Worning from "./warning.vue"
-  export default {
-    name: "BasicInformationDetail",
-    components: {
-      Worning,
-    },
-    props: {
-      alarms: Array,
-    },
-    mounted() {
-      this.show()
-    },
-    data() {
-      return {
-        warnList: [],
-        BasicInfo: {},
-        temperatureInfo: new Array() /* 温度信息 */,
-        pitchInfo: new Array() /* 变桨信息 */,
-        generalInfo: new Array() /* 基本信息 */,
-        powerGridInfo: new Array() /* 电网信息 */,
-      };
-    },
-    methods: {
-      show() {
-        // axios.get(`http://${config.calcUrl}/alarm/real-time-alarm?objectId=${this.windturbine.windturbineId}&pageIndex=1&pageSize=50`)
-        // .then(msg=>{
-        //   var vs = msg.data;
-        //   if(vs.length<=0)return;
-        //   this.alarmTime = BackgroundData.getInstance().formatDate(vs[0].lastUpdateTime);
-        //   this.alarmContent = vs[0].alertText;
-        //   this.alarms = msg.data;
-        //   console.log(this.alarms)
-        // })
-      },
-      start(bi) {
-        this.BasicInfo = bi;
-        this.bindData();
-
-        this.refreshData();
-        this.refreshTimer = setInterval(this.refreshData, 3000);
-      },
-      end() {
-        clearInterval(this.refreshTimer);
-      },
-      alarmd(bi) {
-        let dataList = []
-        let warnList = []
-        let date1 = {
-          type: 1,
-          alertText :[]
-        }
-        let date2 = {
-          type: 2,
-          alertText :[]
-        }
-        let date3 = {
-          type: 3,
-          alertText :[]
-        }
-        let date4 = {
-          type: 4,
-          alertText :[]
-        }
-        let date5 = {
-          type: 5,
-          alertText :[]
-        }
-        bi.forEach(item => {
-          let data = {}
-          data.alertText = item.alertText
-          if (item.alertText.indexOf("变桨") >= 0) {
-            data.type = 1
-          } else if (item.alertText.indexOf("偏航") >= 0) {
-            data.type = 5
-          }
-          else if (item.alertText.indexOf("发电机") >= 0) {
-            data.type = 3
-          }
-          else if (item.alertText.indexOf("齿轮箱") >= 0) {
-            data.type = 2
-          }
-          else if (item.alertText.indexOf("液压") >= 0) {
-            data.type = 4
-          }
-          data.type ? warnList.push(data) : ''
-        })
-        warnList.forEach(item =>{
-          switch (item.type) {
-            case 1:
-              date1.alertText.push(item.alertText)
-              break;
-            case 2:
-              date2.alertText.push(item.alertText)
-              break;
-            case 3:
-              date3.alertText.push(item.alertText)
-              break;
-            case 4:
-              date4.alertText.push(item.alertText)
-              break;
-            case 5:
-              date5.alertText.push(item.alertText)
-              break;
-          }
-        })
-        date1.alertText.length>0?dataList.push(date1):''
-        date2.alertText.length>0?dataList.push(date2):''
-        date3.alertText.length>0?dataList.push(date3):''
-        date4.alertText.length>0?dataList.push(date4):''
-        date5.alertText.length>0?dataList.push(date5):''
-        this.warnList = dataList
-      },
-      /* 刷新数据 */
-      refreshData() {
-        var bg = BackgroundData.getInstance();
-        bg.initWinturbineBaseData(this.BasicInfo, this.onMessage);
-      },
-
-      /* 获得数据 */
-      onMessage(msg) {
-        this.BasicInfo.BasicInfo.forEach((element) => {
-          element.param.forEach((im) => {
-            var val = msg[im.code];
-            if (typeof val !== "undefined") {
-              if (im.unit == "万度") {
-                im.value = (val.doubleValue / 10000).toFixed(2);
-              } else {
-                im.value = val.doubleValue.toFixed(2);
-              }
-            }
-          });
-        });
-        console.log(msg);
-      },
-
-      bindData() {
-        this.BasicInfo.BasicInfo.forEach((element) => {
-          if (element.tag == "基本信息") {
-            this.generalInfo = element.param;
-          } else if (element.tag == "温度信息") {
-            this.temperatureInfo = element.param;
-          } else if (element.tag == "电网信息") {
-            this.powerGridInfo = element.param;
-          } else if (element.tag == "桨叶信息") {
-            this.pitchInfo = element.param;
-          }
-        });
-      },
-    },
-  };
-</script>
-
-<style scoped>
-.firstdiv {
-  height: 50vh;
-}
-.onediv {
-  float: right;
-  margin-right: 30px;
-}
-.twodiv {
-  float: right;
-  margin-right: 30px;
-}
-td:nth-child(1) {
-  height: 25px;
-  width: 130px;
-  text-align: right;
-  color: rgb(220, 220, 220);
-}
-td:nth-child(2) {
-  width: 78px;
-  text-align: right;
-  color: rgb(5, 176, 71);
-}
-td:nth-child(3) {
-  text-align: center;
-  width: 30px;
-  color: rgb(220, 220, 220);
-}
-tr:nth-child(1) {
-  font-size: 20px;
-  width: 90px;
-  text-align: right;
-  color: rgb(220, 220, 220);
-}
-th {
-  height: 40px;
-}
-table{
-  margin-top: 30px;
-}
-</style>

+ 0 - 62
src/components/area/windturbine/MatrixCard.vue

@@ -1,62 +0,0 @@
-<template>
-  <div class="main" v-if="values.length > 0">
-    <div style="font-size:15px">{{ title }}</div>
-    <div class="content">
-      <WindturbineMinCard
-        v-for="vs in values"
-        :key="vs"
-        :status="vs.status"
-        :power="vs.power"
-        :windSpeed="vs.windSpeed"
-        :rollSpeed="vs.rollSpeed"
-        :windturbineId="vs.windturbineId"
-      ></WindturbineMinCard>
-    </div>
-    <div class="bottom"></div>
-  </div>
-</template>
-
-<script>
-import WindturbineMinCard from "./WindturbineMinCard.vue";
-export default {
-  name: "MatrixCard",
-  props: ["title", "datas"],
-  data() {
-    return {
-      values: [],
-    };
-  },
-
-  mounted() {
-    this.values = this.datas.value || [];
-  },
-
-  components: {
-    WindturbineMinCard,
-  },
-
-  watch: {
-    datas(val) {
-      this.values = val.value;
-    },
-  },
-};
-</script>
-
-<style scoped>
-.content {
-  display: grid;
-  grid-template-columns: repeat(5, 20%);
-}
-.bottom {
-  background-color: #292929;
-  width: 100%;
-  height: 2px;
-  margin-top: 5px;
-}
-.main {
-  margin-bottom: 15px;
-  margin-left: 5px;
-  margin-right: 5px;
-}
-</style>

+ 0 - 175
src/components/area/windturbine/WindturbineDetailPages.vue

@@ -1,175 +0,0 @@
-<template>
-  <el-dialog
-    width="65%"
-    @opened="opened()"
-    @closed="closed()"
-    :show-close="false"
-  >
-  <template #title>
-    <div style="margin-top:-10px;">风机详情</div>
-  </template>
-    
-    <div style="background-color: black;margin-top:-30px;margin-left:-10px;margin-right:-10px;margin-bottom:-10px;">
-      <table width="99.8%">
-        <tr>
-          <td>
-            <div class="chunkdiv">
-              <img
-                src="../../../assets/img/WindturbineDetailPages/pic_01.png"
-              />
-              <div>&emsp;</div>
-              <div>{{ windturbine.windturbineId }}</div>
-            </div>
-          </td>
-          <td>
-            <div class="chunkdiv">
-              <div>所属线路&emsp;</div>
-              <div>{{line}}</div>
-            </div>
-          </td>
-          <td>
-            <div class="chunkdiv">
-              <div>机型&emsp;</div>
-              <div>{{windturbine.modelId}}</div>
-            </div>
-          </td>
-          <td>
-            <div class="chunkdiv">
-              <div>告警时间:</div>
-              <div>{{alarmTime}}</div>
-            </div>
-          </td>
-          <td>
-            <div class="chunkdiv">
-              <div>告警内容:</div>
-              <div>{{alarmContent}}</div>
-            </div>
-          </td>
-        </tr>
-      </table>
-
-      <BasicInformationDetail ref="BasicInfo"></BasicInformationDetail>
-      <!--<div class="worning1">
-        <Worning></Worning>
-      </div>
-      <div class="worning2">
-        <Worning></Worning>
-      </div>
-      <el-tabs type="border-card" tab-position="bottom" stretch="true">
-        <el-tab-pane label="基本信息">
-          <BasicInformationDetail ref="BasicInfo" :alarms="alarms"></BasicInformationDetail>
-        </el-tab-pane>
-        <el-tab-pane label="机舱信息" disabled>
-        </el-tab-pane>
-        <el-tab-pane label="故障信息" disabled>
-        </el-tab-pane>
-        <el-tab-pane label="齿轮箱" disabled>
-        </el-tab-pane>
-        <el-tab-pane label="变桨" disabled>
-        </el-tab-pane>
-        <el-tab-pane label="偏航" disabled>
-        </el-tab-pane>
-        <el-tab-pane label="液压" disabled>
-        </el-tab-pane>
-        <el-tab-pane label="发电机" disabled>
-        </el-tab-pane>
-      </el-tabs> -->
-    </div>
-  </el-dialog>
-</template>
-
-<script>
-/* import YawDetail from "./YawDetail.vue"; */
-import BasicInformationDetail from "./BasicInformationDetail.vue";
-import UniformCodes from "../../../assets/script/UniformCodes";
-import {config} from '../../../config';
-import axios from 'axios';
-import BackgroundData from "../../../assets/script/BackgroundData";
-// import Worning from "./warning.vue"
-export default {
-  components: {
-    BasicInformationDetail,
-    // Worning,
-  },
-  props: {
-    windturbine: Object,
-  },
-  data() {
-    return {
-      BasicInfo: {},
-      line:"",
-      alarmTime:"",
-      alarmContent:"",
-      alarms:[],
-    };
-  },
-  created() {
-    this.UniformCodes = new UniformCodes();
-  },
-  methods: {
-    opened() {
-      this.line="";
-      this.alarmTime="";
-      this.alarmContent="";
-      this.BasicInfo = this.UniformCodes.getStationInfos(this.windturbine);
-      this.BasicInfo.windturbineId = this.windturbine.windturbineId;
-      
-      this.$refs.BasicInfo.start(this.BasicInfo);
-
-      this.initData();
-
-      //this.refreshData();
-      //this.refreshTimer = setInterval(this.refreshData, 3000);
-    },
-    closed() {
-      // todo 切换页面的时候应该让上一个页面停止刷新数据(调用end方法)
-      this.$refs.BasicInfo.end();
-
-      //clearInterval(this.refreshTimer);
-    },
-    initData(){
-      axios.get(`http://${config.calcUrl}/windturbine/line/${this.windturbine.windturbineId}`)
-      .then(msg=>this.line=msg.data);
-      axios.get(`http://${config.calcUrl}/alarm/real-time-alarm?objectId=${this.windturbine.windturbineId}&pageIndex=1&pageSize=50`)
-      .then(msg=>{
-        var vs = msg.data;
-        if(vs.length<=0)return;
-        this.alarmTime = BackgroundData.getInstance().formatDate(vs[0].lastUpdateTime);
-        this.alarmContent = vs[0].alertText;
-        this.alarms = msg.data;
-        this.$refs.BasicInfo.alarmd(this.alarms);
-        console.log(this.alarms)
-      })
-      .catch(err=>{
-        console.log(err);
-      });
-    }
-  },
-};
-</script>
-<style scoped>
-/*   .titeldiv{
-    display: flex;
-    justify-content: space-around;
-  } */
-.chunkdiv {
-  display: flex;
-  justify-content: center;
-  background-color: #363636;
-  margin: 1px;
-  padding: 2px;
-  color: rgb(220, 220, 220);
-  overflow:hidden;
-  white-space:nowrap;
-}
-table {
-  margin-left: 2px;
-  margin-right: 2px;
-}
-td {
-  width: 20%;
-}
-el-tabs {
-  background-color: black;
-}
-</style>

+ 0 - 341
src/components/area/windturbine/WindturbineMinCard.vue

@@ -1,341 +0,0 @@
-/* 风机矩阵小卡片 */
-<template>
-    <div :class="cardStyle" @click="sigSelectClick" @dblclick="dbcDetailPages">
-        <el-row>
-            <div :class="leftStyle">
-                <el-row>
-                    <div :class="title1Style">{{stationName}}</div>
-                </el-row>
-                <el-row>
-                    <div :class="title2Style">{{windturbineName}}</div>
-                </el-row>
-            </div>
-            <div :class="rightStyle">
-                <el-row>
-                    <div :class="contentStyle" style="font-size: 12px;position: absolute;right: 5px;">{{power.toFixed(2)}} kw</div>
-                </el-row>
-                <el-row>
-                    <div :class="contentStyle" style="font-size: 12px;position: absolute;right: 5px;top:15px;">{{windSpeed.toFixed(2)}} m/s</div>
-                </el-row>
-                <el-row>
-                    <div :class="contentStyle" style="font-size: 12px;position: absolute;right: 5px;top:30px;">{{rollSpeed.toFixed(2)}} rpm</div>
-                </el-row>
-            </div>
-        </el-row>
-        
-    </div>
-</template>
-
-<script>
-
-
-    export default {
-        name: "WindturbineMinCard",
-        props: {
-            status: Number,
-            power:Number,
-            windSpeed:Number,
-            rollSpeed:Number,
-            windturbineId:String,
-        },
-        data() {
-            return {
-                sigSelect: false
-            }
-        },
-        components: {
-            
-        },
-        computed: {
-            cardStyle: function () {
-                if (this.sigSelect) {
-                    return "card-style card-style-select-" + this.status;
-                } else {
-                    return "card-style card-style-" + this.status;
-                }
-            },
-            leftStyle: function () {
-                if (this.sigSelect) {
-                    return "card-style-left card-left-style-select-" + this.status;
-                } else {
-                    return "card-style-left card-left-style-" + this.status;
-                }
-            },
-            rightStyle: function () {
-                if (this.sigSelect) {
-                    return "card-right-style card-right-style-select-" + this.status;
-                } else {
-                    return "card-right-style card-right-style-" + this.status;
-                }
-            },
-            title1Style: function () {
-                return "card-title1-style card-title1-style-" + this.status;
-            },
-            title2Style: function () {
-                return "card-title2-style card-title2-style-" + this.status;
-            },
-            contentStyle: function () {
-                return "card-content-style-" + this.status;
-            },
-            stationName:function () {
-                return this.windturbineId.slice(0,2);
-            },
-            windturbineName:function () {
-                var vs = this.windturbineId.split('_');
-                return vs[1];
-            }
-        },
-        methods: {
-            sigSelectClick() {
-                let sigSelect = this.sigSelect
-                if (sigSelect) {
-                    this.sigSelect = false
-                } else {
-                    this.sigSelect = true
-                }
-                // todo retun id,父组件中接收id
-            }
-        }
-    };
-</script>
-<style scoped>
-    .card-style{
-        position: relative;
-        width: 116px;
-        height: 50px;
-        box-sizing: border-box;
-        display: inline-block;
-        margin-top: 5px;
-    }
-    /* 卡片整体样式(边框和整体背景) */
-    /* 停机 */
-    .card-style-0 {
-        border: 2px solid rgb(255, 255, 255);
-        background-color: rgba(255, 255, 255, 0.15);
-    }
-    /* 上电 */
-    .card-style-1 {
-        border: 2px solid rgb(197, 48, 72);
-        background-color: rgba(197, 48, 72, 0.15);
-    }
-    /* 待机 */
-    .card-style-2 {
-        border: 2px solid rgb(05, 187, 76);
-        background-color: rgba(05, 187, 76, 0.15);
-    }
-    /* 启动 */
-    .card-style-3 {
-        border: 2px solid rgb(05, 187, 76);
-        background-color: rgba(05, 187, 76, 0.15);
-    }
-    /* 并网 */
-    .card-style-4 {
-        border: 2px solid rgb(75, 85, 174);
-        background-color: rgba(75, 85, 174, 0.15);
-    }
-    /* 故障 */
-    .card-style-5 {
-        border: 2px solid rgba(186, 50, 55);
-        background-color: rgba(186, 50, 55, 0.15);
-    }
-    /* 维护 */
-    .card-style-6 {
-        border: 2px solid rgb(225, 125, 36);
-        background-color: rgba(225, 125, 36, 0.15);
-    }
-    /* 离线 */
-    .card-style-7 {
-        border: 2px solid rgb(96, 103, 105);
-        background-color: rgba(96, 103, 105, 0.15);
-    }
-    /* 卡片整体样式-选择 */
-    .card-style-select-0 {
-        border: 2px solid rgba(255, 255, 255, 0.5);
-        background-color: rgba(255, 255, 255, 0.1);
-    }
-    .card-style-select-1 {
-        border: 2px solid rgba(197, 48, 72, 0.5);
-        background-color: rgba(197, 48, 72, 0.1);
-    }
-    .card-style-select-2 {
-        border: 2px solid rgba(05, 187, 76, 0.5);
-        background-color: rgba(05, 187, 76, 0.1);
-    }
-    .card-style-select-3 {
-        border: 2px solid rgba(05, 187, 76, 0.5);
-        background-color: rgba(05, 187, 76, 0.1);
-    }
-    .card-style-select-4 {
-        border: 2px solid rgba(75, 85, 174, 0.5);
-        background-color: rgba(75, 85, 174, 0.1);
-    }
-    .card-style-select-5 {
-        border: 2px solid rgba(186, 50, 55, 0.5);
-        background-color: rgba(186, 50, 55, 0.1);
-    }
-    .card-style-select-6 {
-        border: 2px solid rgba(225, 125, 36, 0.5);
-        background-color: rgba(225, 125, 36, 0.1);
-    }
-    .card-style-select-7 {
-        border: 2px solid rgba(159, 163, 165, 0.5);
-        background-color: rgba(159, 163, 165, 0.1);
-    }
-    .card-style-left{
-        position: relative;
-        width: 25px;
-        height: 41px;
-        box-sizing: border-box;
-        margin: 3px;
-        display: inline-block;
-    }
-    /* 卡片左边样式 */
-    .card-left-style-0 {
-        background-color: rgb(255, 255, 255);
-        color: rgb(0, 0, 0);
-    }
-    .card-left-style-1 {
-        background-color: rgb(121, 73, 81);
-    }
-    .card-left-style-2 {
-        background-color: rgb(05, 187, 76);
-    }
-    .card-left-style-3 {
-        background-color: rgb(05, 187, 76);
-    }
-    .card-left-style-4 {
-        background-color: rgb(75, 85, 174);
-    }
-    .card-left-style-5 {
-        background-color: rgb(186, 50, 55);
-    }
-    .card-left-style-6 {
-        background-color: rgb(225, 125, 36);
-    }
-    .card-left-style-7 {
-        background-color: rgb(159, 163, 165);
-    }
-    /* 卡片左边样式-选择 */
-    .card-left-style-select-0 {
-        background-color: rgba(255, 255, 255,0.7);
-        color: rgba(0, 0, 0,0.7);
-    }
-    .card-left-style-select-1 {
-        background-color: rgba(121, 73, 81,0.7);
-    }
-    .card-left-style-select-2 {
-        background-color: rgba(05, 187, 76,0.7);
-    }
-    .card-left-style-select-3 {
-        background-color: rgba(05, 187, 76,0.7);
-    }
-    .card-left-style-select-4 {
-        background-color: rgba(75, 85, 174,0.7);
-    }
-    .card-left-style-select-5 {
-        background-color: rgba(186, 50, 55,0.7);
-    }
-    .card-left-style-select-6 {
-        background-color: rgba(225, 125, 36,0.7);
-    }
-    .card-left-style-select-7 {
-        background-color: rgba(159, 163, 165,0.7);
-    }
-
-    .card-left-style-select {
-        position: relative;
-        width: 25px;
-        height: 41px;
-        box-sizing: border-box;
-        margin: 3px;
-        display: inline-block;
-    }
-
-    .card-right-style{
-        width: calc(116px - 4px - 6px - 25px);
-        height: calc(50px - 2px);
-        box-sizing: border-box;
-        display: inline-block;
-        position: absolute;
-        right: 0px;
-    }
-    /* 卡片虚线样式 */
-    .card-right-style-0 {
-        border-left: 2px dashed rgb(255, 255, 255);
-        color: rgb(255, 255, 255);
-    }
-    .card-right-style-1 {
-        border-left: 2px dashed rgb(121, 73, 81);
-    }
-    .card-right-style-2 {
-        border-left: 2px dashed rgb(05, 187, 76);
-    }
-    .card-right-style-3 {
-        border-left: 2px dashed rgb(05, 187, 76);
-    }
-    .card-right-style-4 {
-        border-left: 2px dashed rgb(75, 85, 174);
-    }
-    .card-right-style-5 {
-        border-left: 2px dashed rgb(186, 50, 55);
-    }
-    .card-right-style-6 {
-        border-left: 2px dashed rgb(225, 125, 36);
-    }
-    .card-right-style-7 {
-        border-left: 2px dashed rgb(159, 163, 165);
-    }
-    /* 卡片虚线样式-选择 */
-    .card-right-style-select-0 {
-        border-left: 2px dashed rgba(255, 255, 255,0.7);
-        color: rgba(255, 255, 255,0.7);
-    }
-    .card-right-style-select-1 {
-        border-left: 2px dashed rgba(121, 73, 81,0.7);
-    }
-    .card-right-style-select-2 {
-        border-left: 2px dashed rgba(05, 187, 76,0.7);
-    }
-    .card-right-style-select-3 {
-        border-left: 2px dashed rgba(05, 187, 76,0.7);
-    }
-    .card-right-style-select-4 {
-        border-left: 2px dashed rgba(75, 85, 174,0.7);
-    }
-    .card-right-style-select-5 {
-        border-left: 2px dashed rgba(186, 50, 55,0.7);
-    }
-    .card-right-style-select-6 {
-        border-left: 2px dashed rgba(225, 125, 36,0.7);
-    }
-    .card-right-style-select-7 {
-        border-left: 2px dashed rgba(159, 163, 165,0.7);
-    }
-
-    .card-title1-style{
-        margin-top: 2px;
-        font-size: 14px;
-        width: 100%;
-        text-align: center;
-    }
-    .card-title1-style-1 {
-        font-size: 14px;
-    }
-    .card-title2-style{
-        margin-top: 2px;
-        font-size: 12px;
-        width: 100%;
-        text-align: center;
-    }
-    .card-title2-style-1 {
-        font-size: 12px;
-    }
-    .card-content-style{
-        width: 100%;
-        text-align: right;
-        font-size: 12px;
-    }
-    .card-content-style-1 {
-        font-size: 12px;
-    }
-</style>

+ 0 - 99
src/components/area/windturbine/YawDetail.vue

@@ -1,99 +0,0 @@
-<template>
-    <div class="firstdiv">
-    <img
-      style="float: left; margin-left: 40px; margin-top: 90px;width:50vh;height:25vh;"
-      src="../../../assets/img/WindturbineDetailPages/变桨.png"
-      object-fit="fill"
-    />
-    <div class="twodiv">
-    <table>
-        <tr>
-            <th>状态信息</th>
-        </tr>
-        <tr>
-            <td>左极限位置</td>
-            <td><green></green></td>
-        </tr>
-        <tr>
-            <td>右极限位置</td>
-            <td><red></red></td>
-        </tr>
-    </table>
-        <table>
-        <tr>
-            <th>状态信息</th>
-        </tr>
-        <tr>
-            <td>电机1保护OK</td>
-            <td><green></green></td>
-        </tr>
-        <tr>
-            <td>电机2保护OK</td>
-            <td><green></green></td>
-        </tr>
-    </table>
-        <table>
-        <tr>
-            <th>数值信息</th>
-        </tr>
-        <tr>
-            <td>对风偏差</td>
-            <td>28.07</td>
-            <td>度</td>
-        </tr>
-        <tr>
-            <td>对风偏差角度</td>
-            <td>710.07</td>
-            <td>度</td>
-        </tr>
-    </table>
-    </div>
-  </div>
-</template>
-<script>
-
-export default{
-    components: {
-        
-    }
-}
-</script>
-
-<style scoped>
-.firstdiv {
-  height: 50vh;
-}
-.onediv {
-  float: right;
-  margin-right: 30px;
-}
-.twodiv {
-  float: right;
-  margin-right: 30px;
-}
-td:nth-child(1) {
-  height: 25px;
-  width: 130px;
-  text-align: right;
-}
-td:nth-child(2) {
-  width: 78px;
-  text-align: right;
-  color: rgb(5, 176, 71);
-}
-td:nth-child(3) {
-  text-align: center;
-  width: 30px;
-}
-tr:nth-child(1) {
-  font-size: 20px;
-  width: 90px;
-  text-align: right;
-}
-th {
-  height: 40px;
-}
-table{
-  margin-top: 30px;
-}
-</style>

+ 0 - 457
src/components/area/windturbine/control/ControlMatrixCard.vue

@@ -1,457 +0,0 @@
-<template>
-  <div class="main" v-if="values.length > 0">
-    <div>{{ title }}</div>
-    <div class="content">
-      <div
-        class="card"
-        v-for="(item, index) in values"
-        :key="index"
-        :class="
-          item.active
-            ? 'card-select-' + item.status
-            : 'card-unselect-' + item.status
-        "
-        @click="onSelectHandler(item)"
-        @dblclick="sendMsg(item)"
-      >
-        <div
-          class="card-left"
-          :class="
-            item.active
-              ? 'card-left-select-' + item.status
-              : 'card-left-unselect-' + item.status
-          "
-        >
-          <div>{{ item.windturbineId.slice(0, 2) }}</div>
-          <div>{{ item.windturbineId.slice(5) }}</div>
-        </div>
-        <div
-          class="card-right"
-          :class="
-            item.active
-              ? 'card-right-select-' + item.status
-              : 'card-right-unselect-' + item.status
-          "
-        >
-        
-          <div class="rightrow">{{ item.windSpeed.toFixed(2) }} m/s</div>
-          <div class="rightrow">{{ item.power.toFixed(2) }} kw</div>
-          <div class="rightrow">{{ item.rollSpeed.toFixed(2) }} rpm</div>
-        </div>
-      </div>
-    </div>
-    <div class="bottom"></div>
-  </div>
-  <WindturbineDetailPages
-    v-model="dialogVisible"
-    :windturbine="currentWindturbine"
-  ></WindturbineDetailPages>
-</template>
-
-<script>
-import WindturbineDetailPages from "../WindturbineDetailPages.vue";
-export default {
-  name: "ControlMatrixCard",
-  props: { title: String, datas: Object, operateStyle: Number },
-  data() {
-    return {
-      values: [],
-      dialogVisible: false,
-      currentWindturbine: {},
-    };
-  },
-  components: {
-    WindturbineDetailPages,
-  },
-  created() {
-    //this.CheckTimer = setInterval(this.checkCard,2000);
-  },
-  methods: {
-    // 点击卡片事件
-    onSelectHandler(item) {
-      item.active = !item.active;
-    },
-
-    sendMsg: function (itm) {
-      this.dialogVisible = true;
-      this.currentWindturbine = itm;
-    },
-
-    /* 获取选中的项目 */
-    getSelectedItems() {
-      var ls = new Array();
-      this.values.forEach((item) => {
-        if (item.active) {
-          ls.push(item);
-        }
-      });
-      return ls;
-    },
-    /* 将选中的项目填充到数组中 */
-    outputSelectedItems(ls) {
-      this.values.forEach((item) => {
-        if (item.active) {
-          ls.push(item);
-        }
-      });
-    },
-
-    /* 导出所有的项目 */
-    outputAllItems(ls) {
-      this.values.forEach((item) => {
-        ls.push(item);
-      });
-    },
-
-    /* 清除选中的项目 */
-    clearSelected() {
-      this.values.forEach((item) => (item.active = false));
-    },
-
-    /* checkCard(){
-      var st = 2;// 待机
-      if(this.operateStyle==2){
-        st = 4;
-      }else if(this.operateStyle==1){
-        st = 2;
-      }else{
-        return;
-      }
-      var ll = new Array();
-      for(var vvs in this.values){
-        if(this.values[vvs].status!=st){
-          ll.push(vvs);
-        }
-      }
-      for(var it in ll){
-        this.values.splice(it,1);
-      }
-    }, */
-  },
-  watch: {
-    "$store.getters.windturbinelist": {
-      deep: true,
-      handler: function (json) {
-        var val = {};
-        this.datas.value.forEach((item) => {
-          var data = json[item];
-          var active = undefined;
-          var status = data.status;
-          // 设置当前状态
-          for (var i = 0; i < this.values.length; i++) {
-            if (this.values[i].windturbineId == item) {
-              active = this.values[i].active;
-              break;
-            }
-          }
-          val[item] = 0;
-          var obj = {
-            active: active,
-            status: status,
-            power: data.power,
-            windSpeed: data.windSpeed,
-            rollSpeed: data.rollSpeed,
-            windturbineId: item,
-            modelId: data.modelId,
-            projectId: data.projectId,
-            stationId: data.stationId,
-            controlType: this.operateStyle,
-          };
-          if (obj.modelId.indexOf("105") >= 0) {
-            obj.rollSpeed *= 9.55;
-          }
-          // 替换实时刷新的值
-          this.values.splice(i, 1, obj);
-        });
-
-        var lls = new Array();
-        for (var i1 = 0; i1 < this.values.length; ++i1) {
-          var vvv = this.values[i1];
-          if (typeof val[vvv.windturbineId] === "undefined") {
-            lls.push(i1);
-          }
-        }
-        for (var v2 in lls) {
-          this.values.splice(v2, 1);
-        }
-      },
-    },
-  },
-};
-</script>
-
-<style scoped>
-.rightrow{
-  margin-right:3px;
-}
-.content {
-  display: flex;
-  flex-direction: row;
-  flex-wrap: wrap;
-}
-.bottom {
-  background-color: #292929;
-  width: 100%;
-  height: 2px;
-  margin-top: 5px;
-}
-.main {
-  margin: 0 5px 15px 5px;
-}
-/*  最外层卡片 */
-.card {
-  width: 112px;
-  height: 49px;
-  font-size: 12px;
-  margin-top: 4px;
-  margin-left: 3px;
-  display: flex;
-  flex-direction: row;
-  cursor: pointer;
-  /* border: 2px solid rgb(75, 85, 174); */
-}
-/*  卡片左边部分 */
-.card-left {
-  width: 25px;
-  margin: 3px;
-  font-size: 14px;
-  display: flex;
-  flex-direction: column;
-  justify-content: space-around;
-  align-items: center;
-  /* background-color: rgb(75, 85, 174); */
-}
-/* 卡片右边部分 */
-.card-right {
-  display: flex;
-  flex: 1;
-  flex-direction: column;
-  justify-content: space-around;
-  align-items: flex-end;
-  padding-right: 3px;
-  /* border-left: 2px dashed rgb(75, 85, 174); */
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-0 {
-  border: 2px solid rgb(255, 255, 255, 0.5);
-}
-.card-unselect-0 {
-  border: 2px solid rgb(255, 255, 255);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-0 {
-  background-color: rgb(255, 255, 255, 0.5);
-  color:rgb(0, 0, 0,0.5);
-}
-.card-left-unselect-0 {
-  background-color: rgb(255, 255, 255, .5);
-  color:rgb(0, 0, 0);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-0 {
-  border-left: 2px dashed rgb(255, 255, 255, 0.5);
-}
-.card-right-unselect-0 {
-  border-left: 2px dashed rgb(255, 255, 255, .5);
-  background-color: rgb(255, 255, 255, .15);
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-1 {
-  border: 2px solid rgb(197, 48, 200, 0.5);
-}
-.card-unselect-1 {
-  border: 2px solid rgb(197, 48, 200);
-}
-.card-select-1 {
-  border: 2px solid rgb(197, 48, 200, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-1 {
-  background-color: rgb(197, 48, 200, 0.5);
-}
-.card-left-unselect-1 {
-  background-color: rgb(197, 48, 200, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-1 {
-  border-left: 2px dashed rgb(197, 48, 200, 0.5);
-}
-.card-right-unselect-1 {
-  border-left: 2px dashed rgb(197, 48, 200, .5);
-  background-color: rgb(197, 48, 200, .15);
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-2 {
-  border: 2px solid rgb(05, 187, 76, 0.5);
-}
-.card-unselect-2 {
-  border: 2px solid rgb(05, 187, 76);
-}
-.card-select-2 {
-  border: 2px solid rgb(05, 187, 76, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-2 {
-  background-color: rgb(05, 187, 76, 0.5);
-}
-.card-left-unselect-2 {
-  background-color: rgb(05, 187, 76, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-2 {
-  border-left: 2px dashed rgb(05, 187, 76, 0.5);
-}
-.card-right-unselect-2 {
-  border-left: 2px dashed rgb(05, 187, 76, .5);
-  background-color: rgb(05, 187, 76,.15);
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-3 {
-  border: 2px solid rgb(05, 187, 76, 0.5);
-}
-.card-unselect-3 {
-  border: 2px solid rgb(05, 187, 76);
-}
-.card-select-3 {
-  border: 2px solid rgb(05, 187, 76, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-3 {
-  background-color: rgb(05, 187, 76, 0.5);
-}
-.card-left-unselect-3 {
-  background-color: rgb(05, 187, 76, 0.5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-3 {
-  border-left: 2px dashed rgb(05, 187, 76, 0.5);
-}
-.card-right-unselect-3 {
-  border-left: 2px dashed rgba(88, 160, 115, 0.5);
-  background-color: rgb(05, 187, 76,.15);
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-4 {
-  border: 2px solid rgb(75, 85, 174, 0.5);
-}
-.card-unselect-4 {
-  border: 2px solid rgb(75, 85, 174);
-}
-.card-select-4 {
-  border: 2px solid rgb(75, 85, 174, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-4 {
-  background-color: rgb(75, 85, 174, 0.5);
-}
-.card-left-unselect-4 {
-  background-color: rgb(75, 85, 174, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-4 {
-  border-left: 2px dashed rgb(75, 85, 174, 0.5);
-}
-.card-right-unselect-4 {
-  border-left: 2px dashed rgb(75, 85, 174, .5);
-  background-color: rgb(75, 85, 174, .15);
-}
-
-/* ***********颜色************ */
-/* *********************** *
-/*  最外层卡片选中和未选中 */
-.card-select-5 {
-  border: 2px solid rgb(186, 50, 55, 0.5);
-}
-.card-unselect-5 {
-  border: 2px solid rgb(186, 50, 55);
-}
-.card-select-5 {
-  border: 2px solid rgb(186, 50, 55, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-5 {
-  background-color: rgb(186, 50, 55, 0.5);
-}
-.card-left-unselect-5 {
-  background-color: rgb(186, 50, 55,.5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-5 {
-  border-left: 2px dashed rgb(186, 50, 55, 0.5);
-}
-.card-right-unselect-5 {
-  border-left: 2px dashed rgb(186, 50, 55, .5);
-  background-color: rgb(186, 50, 55,.15);
-}
-
-/* ***********颜色************ */
-/* *********************** *
-/*  最外层卡片选中和未选中 */
-.card-select-6 {
-  border: 2px solid rgb(225, 125, 36, 0.5);
-}
-.card-unselect-6 {
-  border: 2px solid rgb(225, 125, 36);
-}
-.card-select-6 {
-  border: 2px solid rgb(225, 125, 36, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-6 {
-  background-color: rgb(225, 125, 36, 0.5);
-}
-.card-left-unselect-6 {
-  background-color: rgb(225, 125, 36, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-6 {
-  border-left: 2px dashed rgb(225, 125, 36, 0.5);
-}
-.card-right-unselect-6 {
-  border-left: 2px dashed rgb(225, 125, 36, .5);
-  background-color: rgb(225, 125, 36, .15);
-}
-
-/* ***********颜色************ */
-/* *********************** *
-/*  最外层卡片选中和未选中 */
-.card-select-7 {
-  border: 2px solid rgb(96, 103, 105, 0.5);
-}
-.card-unselect-7 {
-  border: 2px solid rgb(96, 103, 105);
-}
-.card-select-7 {
-  border: 2px solid rgb(96, 103, 105, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-7 {
-  background-color: rgb(96, 103, 105, 0.5);
-}
-.card-left-unselect-7 {
-  background-color: rgb(96, 103, 105, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-7 {
-  border-left: 2px dashed rgb(96, 103, 105, 0.5);
-}
-.card-right-unselect-7 {
-  border-left: 2px dashed rgb(96, 103, 105, .5);
-  background-color: rgb(96, 103, 105, .15);
-}
-</style>

+ 0 - 448
src/components/area/windturbine/problem/ProblemMatrixCard.vue

@@ -1,448 +0,0 @@
-<template>
-  <div class="main" v-if="values.length > 0">
-    <div>{{ title }}</div>
-    <div class="content">
-      <div
-        class="card"
-        v-for="(item, index) in values"
-        :key="index"
-        :class="
-          item.active
-            ? 'card-select-' + item.status
-            : 'card-unselect-' + item.status
-        "
-        @click="onSelectHandler(item)"
-        @dblclick="sendMsg(item)"
-      >
-        <div
-          class="card-left"
-          :class="
-            item.active
-              ? 'card-left-select-' + item.status
-              : 'card-left-unselect-' + item.status
-          "
-        >
-          <div>{{ item.windturbineId.slice(0, 2) }}</div>
-          <div>{{ item.windturbineId.slice(5) }}</div>
-        </div>
-        <div
-          class="card-right"
-          :class="
-            item.active
-              ? 'card-right-select-' + item.status
-              : 'card-right-unselect-' + item.status
-          "
-        >
-          <div class="rightrow">{{ item.windSpeed.toFixed(2) }} m/s</div>
-          <div class="rightrow">{{ item.power.toFixed(2) }} kw</div>
-          <div class="rightrow">{{ item.rollSpeed.toFixed(2) }} rpm</div>
-        </div>
-      </div>
-    </div>
-    <div class="bottom"></div>
-  </div>
-  <WindturbineDetailPages
-    v-model="dialogVisible"
-    :windturbine="currentWindturbine"
-  ></WindturbineDetailPages>
-</template>
-
-<script>
-import WindturbineDetailPages from "../WindturbineDetailPages.vue";
-export default {
-  name: "ControlMatrixCard",
-  props: { title: String, type: Number, datas: Object },
-  data() {
-    return {
-      values: [],
-      dialogVisible: false,
-      currentWindturbine:{},
-    };
-  },
-  components: {
-    WindturbineDetailPages,
-  },
-  methods: {
-    // 点击卡片事件
-    onSelectHandler(item) {
-      item.active = !item.active;
-    },
-    sendMsg: function (itm) {
-      this.dialogVisible = true;
-      this.currentWindturbine=itm;
-    },
-    filter(value, windturbineId) {
-      var array = [];
-      var flag = false;
-      for (var i = 0; i < value.length; i++) {
-        if (value[i].windturbineId == windturbineId) {
-          flag = true;
-          array.push(flag); // 风机是否已经存在
-          array.push(i); // 风机在values数组的位置
-          array.push(value[i].active); // 当前风机是否被选中
-          break;
-        }
-      }
-      return array;
-    },
-    addCard(val) {
-      var active = false;
-      var array = this.filter(this.values, val.windturbineId);
-      if (!array[0]) {
-        // 维护
-        val.active = active;
-        if(val.modelId.indexOf("105")>=0){
-          val.rollSpeed*=9.55;
-        }
-        this.values.push(val);
-      } else {
-        val.active = array[2];
-        this.values.splice(array[1], 1, val);
-      }
-    },
-    /* 获取选中的项目 */
-    getSelectedItems() {
-      var ls = new Array();
-      this.values.forEach((item) => {
-        if (item.active) {
-          ls.push(item);
-        }
-      });
-      return ls;
-    },
-    /* 将选中的项目填充到数组中 */
-    outputSelectedItems(ls) {
-      this.values.forEach((item) => {
-        if (item.active && !this.isHas(item, ls)) {
-          ls.push(item);
-        }
-      });
-    },
-
-    /* 清除选中的项目 */
-    clearSelected() {
-      this.values.forEach((item) => (item.active = false));
-    },
-
-    isHas(item, ls) {
-      for (var id in ls) {
-        if (ls[id].windturbineId == item.windturbineId) {
-          return true;
-        }
-      }
-      return false;
-    },
-
-    clear(vs) {
-      var ll = new Array();
-      this.values.forEach((item) => {
-        var it = vs[item.windturbineId];
-        if (typeof it === "undefined") {
-          ll.push(item);
-        }
-      });
-      for (var v1 in ll) {
-        var ind = this.values.indexOf(ll[v1]);
-        if (ind < 0) continue;
-        this.values.splice(ind, 1);
-      }
-    },
-  },
-  watch: {
-    "$store.getters.windturbinelist": {
-      deep: true,
-      handler: function (json) {
-        var vs = {};
-        for (var id in json) {
-          var val = json[id];
-          if (val.status == this.type) {
-            this.addCard(val);
-            vs[val.windturbineId] = 0;
-          }
-          if (this.type < 0 && val.lockValue) {
-            this.addCard(val);
-            vs[val.windturbineId] = 0;
-          }
-        }
-        this.clear(vs);
-      },
-    },
-  },
-};
-</script>
-
-<style scoped>
-.rightrow{
-  margin-right:3px;
-}
-.content {
-  display: flex;
-  flex-direction: row;
-  flex-wrap: wrap;
-}
-.bottom {
-  background-color: #292929;
-  width: 100%;
-  height: 2px;
-  margin-top: 5px;
-}
-.main {
-  margin: 0 5px 15px 5px;
-}
-/*  最外层卡片 */
-.card {
-  width: 112px;
-  height: 49px;
-  font-size: 12px;
-  margin-left: 3px;
-  margin-top: 4px;
-  display: flex;
-  flex-direction: row;
-  cursor: pointer;
-  /* border: 2px solid rgb(75, 85, 174); */
-}
-/*  卡片左边部分 */
-.card-left {
-  width: 25px;
-  margin: 3px;
-  font-size: 14px;
-  display: flex;
-  flex-direction: column;
-  justify-content: space-around;
-  align-items: center;
-  /* background-color: rgb(75, 85, 174); */
-}
-/* 卡片右边部分 */
-.card-right {
-  display: flex;
-  flex: 1;
-  flex-direction: column;
-  justify-content: space-around;
-  align-items: flex-end;
-  padding-right: 3px;
-  /* border-left: 2px dashed rgb(75, 85, 174); */
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-0 {
-  border: 2px solid rgb(255, 255, 255, 0.5);
-}
-.card-unselect-0 {
-  border: 2px solid rgb(255, 255, 255);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-0 {
-  background-color: rgb(255, 255, 255, 0.5);
-  color:rgb(0, 0, 0,0.5);
-}
-.card-left-unselect-0 {
-  background-color: rgb(255, 255, 255, .5);
-  color:rgb(0, 0, 0);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-0 {
-  border-left: 2px dashed rgb(255, 255, 255, 0.5);
-}
-.card-right-unselect-0 {
-  border-left: 2px dashed rgb(255, 255, 255, .5);
-  background-color: rgb(255, 255, 255, .15);
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-1 {
-  border: 2px solid rgb(197, 48, 200, 0.5);
-}
-.card-unselect-1 {
-  border: 2px solid rgb(197, 48, 200);
-}
-.card-select-1 {
-  border: 2px solid rgb(197, 48, 200, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-1 {
-  background-color: rgb(197, 48, 200, 0.5);
-}
-.card-left-unselect-1 {
-  background-color: rgb(197, 48, 200, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-1 {
-  border-left: 2px dashed rgb(197, 48, 200, 0.5);
-}
-.card-right-unselect-1 {
-  border-left: 2px dashed rgb(197, 48, 200, .5);
-  background-color: rgb(197, 48, 200, .15);
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-2 {
-  border: 2px solid rgb(05, 187, 76, 0.5);
-}
-.card-unselect-2 {
-  border: 2px solid rgb(05, 187, 76);
-}
-.card-select-2 {
-  border: 2px solid rgb(05, 187, 76, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-2 {
-  background-color: rgb(05, 187, 76, 0.5);
-}
-.card-left-unselect-2 {
-  background-color: rgb(05, 187, 76, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-2 {
-  border-left: 2px dashed rgb(05, 187, 76, 0.5);
-}
-.card-right-unselect-2 {
-  border-left: 2px dashed rgb(05, 187, 76, .5);
-  background-color: rgb(05, 187, 76,.15);
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-3 {
-  border: 2px solid rgb(05, 187, 76, 0.5);
-}
-.card-unselect-3 {
-  border: 2px solid rgb(05, 187, 76);
-}
-.card-select-3 {
-  border: 2px solid rgb(05, 187, 76, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-3 {
-  background-color: rgb(05, 187, 76, 0.5);
-}
-.card-left-unselect-3 {
-  background-color: rgb(05, 187, 76,.5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-3 {
-  border-left: 2px dashed rgb(05, 187, 76, 0.5);
-}
-.card-right-unselect-3 {
-  border-left: 2px dashed rgb(05, 187, 76, .5);
-  background-color: rgb(05, 187, 76,.15);
-}
-
-/* ***********颜色************ */
-/* *********************** */
-/*  最外层卡片选中和未选中 */
-.card-select-4 {
-  border: 2px solid rgb(75, 85, 174, 0.5);
-}
-.card-unselect-4 {
-  border: 2px solid rgb(75, 85, 174);
-}
-.card-select-4 {
-  border: 2px solid rgb(75, 85, 174, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-4 {
-  background-color: rgb(75, 85, 174, 0.5);
-}
-.card-left-unselect-4 {
-  background-color: rgb(75, 85, 174, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-4 {
-  border-left: 2px dashed rgb(75, 85, 174, 0.5);
-}
-.card-right-unselect-4 {
-  border-left: 2px dashed rgb(75, 85, 174, .5);
-  background-color: rgb(75, 85, 174, .15);
-}
-
-/* ***********颜色************ */
-/* *********************** *
-/*  最外层卡片选中和未选中 */
-.card-select-5 {
-  border: 2px solid rgb(186, 50, 55, 0.5);
-}
-.card-unselect-5 {
-  border: 2px solid rgb(186, 50, 55);
-}
-.card-select-5 {
-  border: 2px solid rgb(186, 50, 55, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-5 {
-  background-color: rgb(186, 50, 55, 0.5);
-}
-.card-left-unselect-5 {
-  background-color: rgb(186, 50, 55, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-5 {
-  border-left: 2px dashed rgb(186, 50, 55, 0.5);
-}
-.card-right-unselect-5 {
-  border-left: 2px dashed rgb(186, 50, 55, .5);
-  background-color: rgb(186, 50, 55,.15);
-}
-
-/* ***********颜色************ */
-/* *********************** *
-/*  最外层卡片选中和未选中 */
-.card-select-6 {
-  border: 2px solid rgb(225, 125, 36, 0.5);
-}
-.card-unselect-6 {
-  border: 2px solid rgb(225, 125, 36);
-}
-.card-select-6 {
-  border: 2px solid rgb(225, 125, 36, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-6 {
-  background-color: rgb(225, 125, 36, 0.5);
-}
-.card-left-unselect-6 {
-  background-color: rgb(225, 125, 36, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-6 {
-  border-left: 2px dashed rgb(225, 125, 36, 0.5);
-}
-.card-right-unselect-6 {
-  border-left: 2px dashed rgb(225, 125, 36, .5);
-  background-color: rgb(225, 125, 36, .15);
-}
-
-/* ***********颜色************ */
-/* *********************** *
-/*  最外层卡片选中和未选中 */
-.card-select-7 {
-  border: 2px solid rgb(96, 103, 105, 0.5);
-}
-.card-unselect-7 {
-  border: 2px solid rgb(96, 103, 105);
-}
-.card-select-7 {
-  border: 2px solid rgb(96, 103, 105, 0.5);
-}
-/*  左边卡片选中和未选中 */
-.card-left-select-7 {
-  background-color: rgb(96, 103, 105, 0.5);
-}
-.card-left-unselect-7 {
-  background-color: rgb(96, 103, 105, .5);
-}
-/*  右边卡片选中和未选中 */
-.card-right-select-7 {
-  border-left: 2px dashed rgb(96, 103, 105, 0.5);
-}
-.card-right-unselect-7 {
-  border-left: 2px dashed rgb(96, 103, 105, .5);
-  background-color: rgb(96, 103, 105, .15);
-}
-</style>

+ 0 - 143
src/components/area/windturbine/warning.vue

@@ -1,143 +0,0 @@
-<template>
-    <div class="container">
-        <div class="dot"></div>
-        <div class="pulse"></div>
-        <div class="content" v-for="(item , index) in worn" :key="index">{{item}}</div>
-    </div>
-</template>
-
-<script>
-    export default {
-        props: {
-            worn: Array,
-        },
-    }
-</script>
-<style scoped>
-    @keyframes warn {
-        0% {
-            transform: scale(0.3);
-            -webkit-transform: scale(0.3);
-            opacity: 0.0;
-        }
-
-        25% {
-            transform: scale(0.3);
-            -webkit-transform: scale(0.3);
-            opacity: 0.1;
-        }
-
-        50% {
-            transform: scale(0.5);
-            -webkit-transform: scale(0.5);
-            opacity: 0.3;
-        }
-
-        75% {
-            transform: scale(0.8);
-            -webkit-transform: scale(0.8);
-            opacity: 0.5;
-        }
-
-        100% {
-            transform: scale(1);
-            -webkit-transform: scale(1);
-            opacity: 0.0;
-        }
-    }
-
-    @keyframes warn1 {
-        0% {
-            transform: scale(0.3);
-            -webkit-transform: scale(0.3);
-            opacity: 0.0;
-        }
-
-        25% {
-            transform: scale(0.3);
-            -webkit-transform: scale(0.3);
-            opacity: 0.1;
-        }
-
-        50% {
-            transform: scale(0.3);
-            -webkit-transform: scale(0.3);
-            opacity: 0.3;
-        }
-
-        75% {
-            transform: scale(0.5);
-            -webkit-transform: scale(0.5);
-            opacity: 0.5;
-        }
-
-        100% {
-            transform: scale(0.8);
-            -webkit-transform: scale(0.8);
-            opacity: 0.0;
-        }
-    }
-
-    .container {
-        position: absolute;
-        width: 40px;
-        height: 40px;
-        z-index: 99;
-        /*border: 1px solid #000; hovertree.com */
-    }
-
-    .content{
-        position: relative;
-        display: none;
-        z-index: 9999;
-    }
-
-    .container:hover .content{
-        /* position: absolute;  */
-        padding: 10px;
-        width: 200px;
-        color: #000000;
-        background-color: #ffffff;
-        display: block;
-        min-height: 20px;
-        z-index: 9999;
-        margin-left: 40px;
-    }
-
-    /* 保持大小不变的小圆圈 何问起 */
-    .dot {
-        position: absolute;
-        width: 8px;
-        height: 8px;
-        left: 42px;
-        top: 42px;
-        -webkit-border-radius: 50%;
-        -moz-border-radius: 50%;
-        /* border: 2px solid rgba(255,0,0,.5); */
-        border-radius: 50%;
-        z-index: 2;
-        background-color: rgba(255,0,0,.8);
-    }
-
-    /* 产生动画(向外扩散变大)的圆圈  */
-    .pulse {
-        position: absolute;
-        width: 80px;
-        height: 80px;
-        left: 2px;
-        top: 2px;
-        border: 3px solid rgba(255,0,0,.8);
-        -webkit-border-radius: 50%;
-        -moz-border-radius: 50%;
-        border-radius: 50%;
-        z-index: 1;
-        opacity: 0;
-        -webkit-animation: warn 1.5s linear;
-        -moz-animation: warn 1.5s linear;
-        animation: warn 1.5s linear;
-        -webkit-animation-iteration-count: infinite;
-        -moz-animation-iteration-count: infinite;
-        animation-iteration-count: infinite;
-        box-shadow: 1px 1px 15px rgba(255,0,0,.8);
-    }
-</style>

+ 0 - 2
src/components/area/wtbDetailPages.js

@@ -1,2 +0,0 @@
-import Vue from 'Vue'
-export default new Vue;

+ 731 - 0
src/components/areaCard.vue

@@ -0,0 +1,731 @@
+/* 自定义tabs */
+<template>
+    <!-- <transition>
+        <div :class='areaClass' @mouseover="hover = false" @mouseleave="hover = false" onselectstart="return false">
+            <div :class="headerClass">
+                <div :class='circleClass'></div>
+                <span class="gy-card-title">{{ title }}</span>
+                <img class="gy-card-decoration01" src="../../assets/img/controlcenter/decoration01.png">
+                <img class="gy-card-decoration02" src="../../assets/img/controlcenter/decoration02.png">
+            </div>
+            <div :class='contentClass'>
+                <el-scrollbar style="height: 100%">
+                    <slot></slot>
+                </el-scrollbar>
+            </div>
+        </div>
+    </transition> -->
+    <div class="body" :style="style">
+        <img class="logo" src="../assets/img/logo.png" alt="">
+        <div class="title">{{ title }}</div>
+        <div style="margin-top: 50px; height: 91%;">
+            <el-scrollbar>
+                <div class="scoll">
+                    <div class="matrix" v-if="faultList.length>0">
+                        <div class="problemTitle">故障</div>
+                        <MatrixBlock @on-click="handleClick" :dataList="faultList"></MatrixBlock>
+                    </div>
+                    <div class="matrix" v-if="maintainList.length>0">
+                        <div class="problemTitle">维护</div>
+                        <MatrixBlock @on-click="handleClick" :dataList="maintainList"></MatrixBlock>
+                    </div>
+                    <div class="matrix" v-if="offlineList.length>0">
+                        <div class="problemTitle">离线</div>
+                        <MatrixBlock @on-click="handleClick" :dataList="offlineList"></MatrixBlock>
+                    </div>
+                    <div class="matrix" v-if="listedList.length>0">
+                        <div class="problemTitle">挂牌</div>
+                        <MatrixBlock @on-click="handleClick" :dataList="listedList"></MatrixBlock>
+                    </div>
+                    <div class="matrix" v-if="listedList.length>0">
+                        <div class="problemTitle">挂牌</div>
+                        <MatrixBlock @on-click="handleClick" :dataList="listedList"></MatrixBlock>
+                    </div>
+                </div>
+            </el-scrollbar>
+        </div>
+    </div>
+</template>
+
+<script>
+    import BackgroundData from 'utils/BackgroundData'
+    // import ProblemMatrixCard from "./problem/ProblemMatrixCard.vue";
+    import MatrixBlock from "./matrixBlock.vue";
+    export default {
+        name: 'gy-card',
+        components: {
+            // ProblemMatrixCard,
+            MatrixBlock
+        },
+        emits: ["parentRun"],
+        props: {
+            title: {
+                type: String,
+                default: '校验区',
+                required: true
+            },
+            height: {
+                type: Number,
+                default: 200,
+            },
+            areaStyle: {
+                type: String,
+                default: 'check',
+                required: true
+            },
+            circleStyle: {
+                type: String,
+                default: 'green',
+                required: true
+            },
+            contentStyle: {
+                type: String,
+                default: '44',
+                required: true
+            },
+            showFlag: {
+                type: Boolean,
+                default: false,
+            }
+        },
+        data() {
+            return {
+                dialogVisible: false,
+                currentWindturbine: {},
+                values: [],
+                hover: false,
+                big: false,
+                current: 0,
+                faultList: [],
+                maintainList: [],
+                offlineList: [],
+                listedList: [],
+                chooseList: [],
+                titleList: [
+                    {
+                        id: 0,
+                        title: '麻黄山',
+                    },
+                    {
+                        id: 1,
+                        title: '牛首山',
+                    },
+                    {
+                        id: 2,
+                        title: '青山',
+                    },
+                    {
+                        id: 3,
+                        title: '石板泉',
+                    },
+                    {
+                        id: 4,
+                        title: '香山',
+                    },
+                ],
+            }
+        },
+        computed: {
+            style() {
+                return `width: 100%; height: 82%;`
+            },
+            areaClass() {
+                if (this.big) {
+                    return `gy-card-area-big`;
+                } else {
+                    return `gy-card-area-${this.areaStyle}`;
+                }
+            },
+            circleClass() {
+                return `gy-card-circle gy-card-circle-${this.circleStyle}`;
+            },
+            contentClass() {
+                if (this.big) {
+                    return `gy-card-content-big`;
+                } else {
+                    return `gy-card-content-${this.contentStyle}`;
+                }
+            },
+            headerClass() {
+                if (this.hover) {
+                    return `gy-card-header-hover`;
+                } else {
+                    return `gy-card-header`;
+                }
+            }
+        },
+        methods: {
+            handleClick(values) {
+                if (values.active) {
+                    let showIndex = null
+                    this.chooseList.forEach((item, index) => {
+                        if (item.windturbineId === values.windturbineId) {
+                            showIndex = index
+                        }
+                    })
+                    this.chooseList.splice(showIndex, 1);
+                } else {
+                    this.chooseList.push(values)
+                }
+            },
+            /* 右键菜单 */
+            contextmenu() {
+                const { remote } = require("electron");
+                let that = this;
+                const menuTemplate = [
+                    {
+                        label: "启动",
+                        click() {
+                            that.menuClicked({ type: "send", controlType: '1' });
+                        },
+                    },
+                    {
+                        label: "停机",
+                        click() {
+                            that.menuClicked({ type: "send", controlType: '2' });
+                        },
+                    },
+                    {
+                        label: "复位",
+                        click() {
+                            that.menuClicked({ type: "send", controlType: '5' });
+                        },
+                    },
+                    {
+                        label: "维护",
+                        click() {
+                            that.menuClicked({ type: "send", controlType: '6' });
+                        },
+                    },
+                    {
+                        label: "取消维护",
+                        click() {
+                            that.menuClicked({ type: "send", controlType: '8' });
+                        },
+                    },
+                    {
+                        label: "挂牌",
+                        submenu: [
+                            {
+                                label: "检修",
+                                click() {
+                                    that.menuClicked({ type: "lock", value: "CheckLock" });
+                                },
+                            },
+                            {
+                                label: "故障维修",
+                                click() {
+                                    that.menuClicked({ type: "lock", value: "FaultLock" });
+                                },
+                            },
+                            {
+                                label: "场内受累检修",
+                                click() {
+                                    that.menuClicked({ type: "lock", value: "StationCheckLock" });
+                                },
+                            },
+                            {
+                                label: "场内受累故障",
+                                click() {
+                                    that.menuClicked({ type: "lock", value: "StationFaulLock" });
+                                },
+                            },
+                            {
+                                label: "场外受累电网",
+                                click() {
+                                    that.menuClicked({
+                                        type: "lock",
+                                        value: "StationPowerLineLock",
+                                    });
+                                },
+                            },
+                            {
+                                label: "场外受累天气",
+                                click() {
+                                    that.menuClicked({ type: "lock", value: "StationWeatherLock" });
+                                },
+                            },
+                        ],
+                    },
+                    {
+                        label: "取消挂牌",
+                        click() {
+                            that.menuClicked({ type: 'lock', value: 'UnLock' });
+                        },
+                    },
+                    // {
+                    //     label: "标注",
+                    //     click() {
+                    //         that.menuClicked({ type: "marking" });
+                    //     },
+                    // },
+                ];
+                const menu = remote.Menu.buildFromTemplate(menuTemplate);
+
+                menu.popup(remote.getCurrentWindow());
+            },
+            menuClicked(msg) {
+                let bd = BackgroundData.getInstance();
+                
+                if (msg.type == "lock") {
+                    // 挂牌
+                    let los = this.getSelectedItems();
+                    for (let id in los) {
+                        los[id].lockType = msg.value;
+                    }
+                    bd.windturbineControl(
+                        los,
+                        true,
+                        '',
+                        this.controlSuccess,
+                        this.controlError
+                    );
+                } else if (msg.type == "send") {
+                    // 发送
+                    let vs = this.getSelectedItems(true);
+                    for (let item in los) {
+                        los[item].controlType = Number(msg.controlType)
+                    }
+                    bd.windturbineControl(
+                        vs,
+                        false,
+                        '',
+                        '',
+                        this.controlSuccess,
+                        this.controlError
+                    );
+                } else if (msg.type == "marking") {
+                    // 标注
+                    let vvs = this.getSelectedItems();
+                    bd.marking(vvs);
+                }
+                this.clearSelected();
+            },
+            /* 获取选中的项目,isControl:是否是控制 */
+            getSelectedItems() {
+                // isControl
+                let ls = new Array();
+                this.$refs.malfunction.outputSelectedItems(ls);
+                return ls;
+            },
+            /* 清除所有选择 */
+            clearSelected() {
+                this.$refs.malfunction.clearSelected();
+            },
+            filter(value, windturbineId) {
+                let array = [];
+                let flag = false;
+                for (let i = 0; i < value.length; i++) {
+                    if (value[i].windturbineId == windturbineId) {
+                        flag = true;
+                        array.push(flag); // 风机是否已经存在
+                        array.push(i); // 风机在values数组的位置
+                        array.push(value[i].active); // 当前风机是否被选中
+                        break;
+                    }
+                }
+                return array;
+            },
+            changeTitle(id) {
+                this.current = id
+                this.$refs.malfunction.dateClick(id)
+            },
+            addCard(val) {
+                let active = false;
+                let array = this.filter(this.values, val.windturbineId);
+                if (!array[0]) {
+                    // 维护
+                    val.active = active;
+                    if (val.modelId.indexOf("105") >= 0) {
+                        val.rollSpeed *= 9.55;
+                    }
+                    this.values.push(val);
+                } else {
+                    val.active = array[2];
+                    this.values.splice(array[1], 1, val);
+                }
+                console.log(this.values)
+            },
+            showWindows(item) {
+                this.dialogVisible = true;
+                this.currentWindturbine = item;
+            }
+        },
+        watch: {
+            "$store.getters.windturbinelist": {
+                deep: true,
+                handler: function (json) {
+                    let vs = {};
+                    this.faultList = []
+                    this.maintainList = []
+                    this.offlineList = []
+                    this.listedList = []
+                    let arr = Object.keys(json).sort()
+                    for (let id of arr) {
+                        let val = json[id];
+                        this.chooseList.forEach(item => {
+                            if (item.windturbineId === val.windturbineId) {
+                                val.active = true
+                            }
+                        })
+                        switch (val.status) {
+                            case 5:
+                                this.faultList.push(val)
+                                break;
+                            case 6:
+                                this.maintainList.push(val)
+                                break;
+                            case 7:
+                                this.offlineList.push(val)
+                                break;
+                        }
+                        if (val.lockValue > 0) {
+                            this.listedList.push(val)
+                        }
+                    }
+                },
+            },
+        },
+    }
+</script>
+
+<style scoped="scoped">
+    .body {
+        border: 1px solid #373737;
+        width: 100%;
+        margin-left: 15px;
+        margin-top: 10px;
+    }
+
+    .body .scoll {
+        height: 91%;
+    }
+
+    .title {
+        color: #ffffff;
+        font-size: 14px;
+        margin-left: 32px;
+        /* margin-top: 12px; */
+        margin-bottom: 10px;
+        width: 570px;
+        height: 50px;
+        display: flex;
+        align-items: center;
+        position: absolute;
+        background-color: #000000;
+    }
+
+    .title::before {
+        z-index: 1;
+        content: '';
+        position: absolute;
+        left: -18px !important;
+        /* top: 30px !important; */
+        width: 5px;
+        height: 5px;
+        background-color: #54B75A;
+        border-radius: 50%;
+    }
+
+    .logo {
+        position: absolute;
+        top: 2px;
+        left: 18px;
+    }
+
+    .matrix {
+        margin-left: 20px;
+        margin-right: 10px;
+        padding-bottom: 20px;
+        border-bottom: 1px solid rgba(31, 31, 31, 1);
+    }
+
+    .problemTitle {
+        font-size: 12px;
+        color: #BFBFBF;
+        margin-top: 20px;
+        margin-bottom: 20px;
+        margin-left: 12px;
+    }
+
+    .gy-card-header {
+        position: relative;
+        height: 40px;
+        background-color: #292929;
+        color: white;
+        box-sizing: border-box;
+    }
+
+    .gy-card-content-89 {
+        position: relative;
+        height: calc(89vh - 50px);
+        background-color: #000000;
+        color: white;
+        box-sizing: border-box;
+        border-radius: 7px;
+    }
+
+    .gy-card-content-44 {
+        position: relative;
+        height: calc(44vh - 50px);
+        background-color: #000000;
+        color: white;
+        box-sizing: border-box;
+        border-radius: 7px;
+    }
+
+    .gy-card-content-37 {
+        position: relative;
+        height: calc(37vh - 50px);
+        background-color: #000000;
+        color: white;
+        box-sizing: border-box;
+        border-radius: 7px;
+    }
+
+    .gy-card-content-25 {
+        position: relative;
+        height: calc(25vh - 50px);
+        background-color: #000000;
+        color: white;
+        box-sizing: border-box;
+        border-radius: 7px;
+    }
+
+    .gy-card-circle {
+        position: relative;
+        top: 7px;
+        display: inline-block;
+        width: 7px;
+        height: 7px;
+        -moz-border-radius: 50%;
+        -webkit-border-radius: 50%;
+        border-radius: 50%;
+    }
+
+    .gy-card-circle-green {
+        background-color: #008000;
+    }
+
+    .gy-card-circle-yellow {
+        background-color: #ffff00;
+    }
+
+    .gy-card-title {
+        position: relative;
+        top: 10px;
+        left: 10px;
+    }
+
+    .gy-card-decoration01 {
+        position: absolute;
+        right: 80px;
+    }
+
+    .gy-card-decoration02 {
+        position: absolute;
+        top: 20px;
+        right: 20px;
+    }
+
+    .gy-card-area-problem {
+        position: relative;
+        height: 89vh;
+        background-color: #292929;
+        border-radius: 7px;
+        margin: 0px;
+        padding-top: 0;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+    .gy-card-area-alarm {
+        position: relative;
+        height: 25vh;
+        margin-top: 10px;
+        background-color: #292929;
+        border-radius: 7px;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+    .gy-card-area-check {
+        position: relative;
+        height: 44vh;
+        background-color: #292929;
+        border-radius: 7px;
+        margin-top: 10px;
+        padding-top: 0;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+    .gy-card-area-control {
+        position: relative;
+        width: 100%;
+        height: 44vh;
+        background-color: #292929;
+        border-radius: 7px;
+        margin: 0px;
+        padding-top: 0;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+    .gy-card-area-label {
+        position: relative;
+        height: 25vh;
+        margin-top: 10px;
+        background-color: #292929;
+        border-radius: 7px;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+    .gy-card-area-recommended {
+        position: relative;
+        height: 37vh;
+        background-color: #292929;
+        border-radius: 7px;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+    .gy-card-header-hover {
+        position: relative;
+        height: 40px;
+        background-color: #292929;
+        color: white;
+        box-sizing: border-box;
+    }
+
+    .gy-card-area-problem:hover {
+        position: relative;
+        height: 89vh;
+        background-color: #292929;
+        border-radius: 7px;
+        margin: 0px;
+        padding-top: 0;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+    .gy-card-area-alarm:hover {
+        position: relative;
+        height: 25vh;
+        margin-top: 10px;
+        background-color: #292929;
+        border-radius: 7px;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+    .gy-card-area-label:hover {
+        position: relative;
+        height: 25vh;
+        margin-top: 10px;
+        background-color: #292929;
+        border-radius: 7px;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+    .gy-card-area-recommended:hover {
+        position: relative;
+        height: 37vh;
+        background-color: #292929;
+        border-radius: 7px;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+    }
+
+
+    .gy-card-area-big {
+        position: fixed;
+        top: 0px;
+        left: 0px;
+        width: 100vw;
+        height: 100vh;
+        background-color: #292929;
+        border-radius: 7px;
+        margin: 0px;
+        padding-top: 0;
+        padding-left: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        box-sizing: border-box;
+        z-index: 900;
+    }
+
+    .gy-card-content-big {
+        position: relative;
+        height: calc(100vh - 50px);
+        background-color: #000000;
+        color: white;
+        box-sizing: border-box;
+        border-radius: 7px;
+    }
+
+    .el-scrollbar__wrap {
+        overflow: scroll;
+        width: 110%;
+        height: 120%;
+    }
+
+    ::-webkit-scrollbar {
+        width: 0;
+        height: 0;
+    }
+
+    .scroll {
+        color: #ffffff;
+        min-height: 300px;
+        height: 400px;
+    }
+
+
+    .content {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 80px;
+        color: #ffffff;
+        height: 25px;
+        border: 1px solid blue;
+        margin-right: 10px;
+        margin-bottom: 10px;
+    }
+
+    .content_on {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 80px;
+        color: #ffffff;
+        height: 25px;
+        border: 1px solid blue;
+        margin-right: 10px;
+        margin-bottom: 10px;
+        background-color: chartreuse;
+    }
+</style>

+ 438 - 0
src/components/basicDataDetails.vue

@@ -0,0 +1,438 @@
+<template>
+    <el-dialog width="50%" @closed="closed()" :show-close="false" class="my-info-dialog">
+        <template #title>
+            <div class="showTitles">
+                <div class="titles">{{partsName}}详情</div>
+                <div class="model">
+                    <div class="selects" v-show="!switchFlag">
+                        <!-- filterable allow-create default-first-option -->
+                        <el-select @change="search()" class="inputs" v-model="selectValue" placeholder="请选择">
+                            <el-option v-for="item in options" :key="item.value" :label="item.label"
+                                :value="item.value">
+                            </el-option>
+                        </el-select>
+                    </div>
+                    <div class="choose">
+                        <div :class="switchFlag?'interval':'interval_on'" @click="switchChange">等间隔</div>
+                        <div :class="switchFlag?'original_on':'original'" @click="switchChange">原始数据</div>
+                    </div>
+                </div>
+            </div>
+        </template>
+        <div class="bodys">
+            <div class="dataTitle">
+                <div class="operate">
+                    <el-date-picker class="picker" @change="changes" v-model="timeValue" type="datetimerange"
+                        range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
+                    </el-date-picker>
+                    <div class="buttons" @click="search()">查询</div>
+                </div>
+                <div class="buttons" @click="search('flag')">导出</div>
+            </div>
+            <div :id="echartsId" class="showEcharts"></div>
+        </div>
+    </el-dialog>
+</template>
+<script>
+    import * as echarts from "echarts";
+    import dayjs from 'dayjs'
+    import XLSX from 'xlsx'
+    export default {
+        props: {
+            datas: {
+                type: Array,
+                default: () => {
+                    return []
+                },
+            },
+            partsName: Object,
+            echartsId: Object,
+        },
+        updated() {
+            if (this.timeValue.length === 0) {
+                let date = new Date()
+                this.timeValue[0] = date.getTime() - 28800000
+                this.timeValue[1] = date.getTime()
+            }
+            this.chooseTime = this.timeValue
+            this.xdata = []
+            this.values = []
+            if ((this.timeValue[1] - this.timeValue[0]) <= 86400000) {
+                this.datas.map(item => {
+                    this.xdata.push(dayjs(item.ts).format('HH:mm'))
+                    this.values.push(item.doubleValue ? item.doubleValue.toFixed(2) : item.doubleValue === 0 ? item.doubleValue : item.longValue)
+                })
+                console.log(this.values)
+            } else {
+                this.datas.map(item => {
+                    this.xdata.push(dayjs(item.ts).format('MM-DD HH:mm'))
+                    this.values.push(item.doubleValue ? item.doubleValue.toFixed(2) : item.doubleValue === 0 ? item.doubleValue : item.longValue)
+                })
+            }
+            this.getEcharts()
+        },
+        mounted() {
+
+        },
+        data() {
+            return {
+                xdata: [],
+                values: [],
+                timeValue: [],
+                chooseTime: [],
+                switchFlag: false,
+                selectValue: '60',
+                options: [{
+                    value: '60',
+                    label: '一分钟'
+                }, {
+                    value: '300',
+                    label: '五分钟'
+                }, {
+                    value: '600',
+                    label: '十分钟'
+                }, {
+                    value: '1800',
+                    label: '三十分钟'
+                }, {
+                    value: '3600',
+                    label: '一小时'
+                }, {
+                    value: '86400',
+                    label: '一天'
+                }],
+            }
+        },
+        methods: {
+            changes() {
+                let timeValue = []
+                this.timeValue?.forEach(item => {
+                    timeValue.push(dayjs(item).valueOf())
+                })
+                this.chooseTime = timeValue
+            },
+            switchChange() {
+                this.switchFlag = !this.switchFlag
+                this.selectValue = '60'
+                this.search();
+                const loading = this.$loading({
+                    lock: true,
+                    text: '数据加载中',
+                    spinner: 'el-icon-loading',
+                    background: 'rgba(0, 0, 0, 0.7)'
+                });
+                setTimeout(() => {
+                    loading.close();
+                }, 1000);
+            },
+            search(values) {
+                let times = []
+                this.chooseTime.forEach(item => {
+                    times.push(dayjs(item).valueOf())
+                })
+                times.length > 0 ?
+                    this.switchFlag ? this.$emit('original-data', times) : this.$emit('search-data', times, Number(this.selectValue))
+                    :
+                    this.$message({
+                        showClose: true,
+                        message: '请选择查询日期',
+                        center: true,
+                        type: 'error'
+                    });
+                if (values) {
+                    this.$message({
+                        showClose: true,
+                        center: true,
+                        message: '下载中'
+                    });
+                    setTimeout(() => {
+                        this.export()
+                    }, 2000)
+                }
+            },
+            export() {
+                // 数据源
+                let data = []
+                this.datas.forEach(item => {
+                    let values = {
+                        '时间': dayjs(item.ts).format('MM-DD HH:mm:ss'),
+                        '数值': item.doubleValue,
+                    }
+                    data.push(values)
+                })
+                // 下载的路径
+                let fileName = `${this.partsName}.xlsx`
+                let filePath = '/root/' + fileName
+                // 新建workbook
+                const wb = XLSX.utils.book_new()
+                // 新建worksheet,并载入数据
+                const ws = XLSX.utils.json_to_sheet(data)
+                // 设置每列的列宽,10代表10个字符,注意中文占2个字符
+                ws['!cols'] = [
+                    { wch: 30 },
+                    { wch: 30 },
+                ]
+                // 生成xlsx文件(workbook,worksheet数据,sheet命名)
+                XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
+
+                // 写文件(workbook,xlsx文件路径+文件名)
+                XLSX.writeFile(wb, filePath)
+                this.$message({
+                    showClose: true,
+                    message: '下载成功',
+                    center: true,
+                    type: 'success'
+                });
+            },
+            getEcharts() {
+                let chartDom = document.getElementById(this.echartsId);
+                let myChart = echarts.init(chartDom, '#ffffff');
+                let option;
+                option = {
+                    legend: {
+                        show: true,
+                        data: [this.partsName],
+                        right: 56,
+                        icon: "circle",
+                        itemWidth: 6,
+                        inactiveColor: '#606769',
+                        textStyle: {
+                            color: '#B3BDC0',
+                            fontSize: 12,
+                        },
+                    },
+                    xAxis: [
+                        {
+                            type: "category",
+                            boundaryGap: false,
+                            axisLabel: {
+                                interval: (Number((this.xdata.length / 8).toFixed(0)) > 2) ? Number((this.xdata.length / 8).toFixed(0)) : 0,
+                                showMinLabel: true,
+                                showMaxLabel: true,
+                                formatter: "{value}",
+                                fontSize: 14,
+                                textStyle: {
+                                    color: '#606769',
+                                },
+                            },
+                            axisLine: {
+                                show: false,
+                            },
+                            data: this.xdata,
+                        },
+                    ],
+                    yAxis: {
+                        type: "value",
+                        axisLabel: {
+                            formatter: "{value}",
+                            fontSize: 14,
+                        },
+                        axisLine: {
+                            show: false,
+                        },
+                        splitLine: {
+                            show: true,
+                            lineStyle: {
+                                color: '#606769',
+                                type: "dashed",
+                            },
+                        },
+                    },
+                    series: [{
+                        // name: this.partsName,
+                        smooth: true,
+                        showSymbol: false,
+                        data: this.values,
+                        type: 'line'
+                    }]
+                };
+                option && myChart.setOption(option);
+            },
+            closed() {
+                this.chooseTime = []
+                this.timeValue = []
+                this.switchFlag = false
+                this.selectValue = '60'
+                this.$emit('closed');
+            },
+        },
+    }
+</script>
+
+<style>
+    .showTitles {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: space-between;
+        margin-top: -10px;
+        font-size: 18px;
+        color: #FFFFFF;
+        height: 40px;
+    }
+
+    .titles {
+        font-size: 16px;
+        color: #FFFFFF;
+    }
+
+    .el-dialog__body {
+        padding: 30px 10px 10px 10px;
+    }
+
+    .bodys {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        background-color: black;
+        width: 100%;
+        margin-top: -30px;
+    }
+
+    .showEcharts {
+        width: 1030px;
+        height: 480px;
+        margin-left: 30px;
+        /* padding-top: 20px; */
+    }
+
+    .dataTitle {
+        width: 100%;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: space-between;
+        margin-top: 10px;
+    }
+
+    .picker {
+        margin-left: 20px;
+        margin-right: 16px;
+    }
+
+    .el-date-editor .el-range-input {
+        background-color: rgba(26, 26, 26, 1) !important;
+        border: none;
+        color: #ffffff !important;
+    }
+
+    .el-input__inner {
+        background-color: rgba(26, 26, 26, 1) !important;
+    }
+
+    .el-date-editor .el-range-separator {
+        color: #ffffff !important;
+    }
+
+    .el-date-table td.in-range div,
+    .el-date-table td.in-range div:hover,
+    .el-date-table.is-week-mode .el-date-table__row.current div,
+    .el-date-table.is-week-mode .el-date-table__row:hover div {
+        background-color: #CECEFF !important;
+    }
+
+    .operate {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: center;
+        /* margin-right: 65px; */
+    }
+
+    .buttons {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 100px;
+        height: 40px;
+        background-color: rgba(26, 26, 26, 1);
+        border: 1px solid rgba(77, 77, 77, 1);
+        color: #ffffff;
+        margin-right: 28px;
+        font-size: 12px;
+    }
+
+    .model {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        color: rgba(240, 240, 240, 1);
+        font-size: 12px;
+    }
+
+    .el-switch {
+        width: 453px;
+    }
+
+    .el-switch__label {
+        color: #999999 !important;
+    }
+
+    .el-switch__label.is-active {
+        color: rgba(37, 116, 219, 1) !important;
+    }
+
+    .selects {
+        margin-right: 16px;
+    }
+
+    .choose {
+        width: 160px;
+        height: 25px;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        color: #FFFFFF;
+    }
+
+    .interval {
+        width: 50%;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border: 1px solid rgba(77, 77, 77, 1);
+        border-top-left-radius: 12.5px;
+        border-bottom-left-radius: 12.5px;
+    }
+
+    .interval_on {
+        width: 50%;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background-color: rgba(29, 106, 235, 1);
+        border: 1px solid rgba(29, 106, 235, 1);
+        border-top-left-radius: 12.5px;
+        border-bottom-left-radius: 12.5px;
+    }
+
+    .original {
+        width: 50%;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border: 1px solid rgba(77, 77, 77, 1);
+        border-top-right-radius: 12.5px;
+        border-bottom-right-radius: 12.5px;
+    }
+
+    .original_on {
+        width: 50%;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background-color: rgba(29, 106, 235, 1);
+        border: 1px solid rgba(29, 106, 235, 1);
+        border-top-right-radius: 12.5px;
+        border-bottom-right-radius: 12.5px;
+    }
+
+    .inputs {
+        border: none;
+        width: 110px !important;
+    }
+</style>

+ 180 - 0
src/components/boxSelect.vue

@@ -0,0 +1,180 @@
+<template>
+    <div class="box-select__container" @mousedown.left="mouseDown" @mousemove.stop="mouseMove" :class="uuid">
+        <div class="box-select__coordinate" :style="style" ref="selectContainer"></div>
+        <slot></slot>
+    </div>
+</template>
+
+<script>
+    import { debounce, isNumber } from "lodash"
+    import { ref, onUnmounted, nextTick, shallowRef } from "vue"
+
+    /**
+     * @description 判断元素是否在范围内
+     * @param {Object} dom dom元素
+     */
+    const isWithinRange = (dom, top, bottom, left, right) => {
+        const eleRect = dom.getBoundingClientRect()
+        return !(
+            eleRect.top > bottom ||
+            eleRect.bottom < top ||
+            eleRect.right < left ||
+            eleRect.left > right
+        )
+    }
+
+    export default {
+        name: "BoxSelect",
+        /**
+         * @member props
+         * @property  {String} [node] 要框选的元素,可以是元素名,也可以是class名, 也可以是id名
+         * @property  {String} [selectedClass] 已选中元素附加的class名
+         */
+        props: {
+            node: {
+                required: true,
+                type: String
+            },
+            selectedClass: {
+                type: String,
+                default: 'box-select__hypocritical'
+            }
+        },
+        // 鼠标按下
+        emits: ["mouseUp", "mouseDown"],
+        setup(props, { emit }) {
+            let top = 0,
+                left = 0,
+                width = 0,
+                height = 0,
+                startX = 0,
+                startY = 0,
+                timer = null,
+                // 记录是框选还是点击
+                mouseOn = false
+
+            const style = ref({}),
+                selectContainer = ref(null),
+                // 给当前框容器加一个唯一识别符, 以保证所选择到的元素都是当前容器的. 否则会选择到容器外同名的元素
+                uuid = shallowRef("uuid_" + new Date().valueOf())
+
+            const query = (className = '') => {
+                let domName = `.${uuid.value} ${props.node}`
+                className && (domName += `.${className}`)
+                return Array.from(document.querySelectorAll(domName) || [])
+            }
+
+            const classOperation = (ele, method = 'add', className = '') => ele.classList[method](className)
+
+            const setStyle = (styles = {}, newStyles = {}) => {
+                Object.keys(styles).map((item) => {
+                    newStyles[item] = styles[item] + (isNumber(styles[item]) ? "px" : '')
+                })
+                style.value = newStyles
+            }
+
+            const getAreaWithinElements = () => {
+                const {
+                    bottom,
+                    left,
+                    right,
+                    top
+                } = selectContainer.value.getBoundingClientRect()
+
+                // 所有可框选元素
+                const elements = query()
+                // 已选中元素
+                const selectedElements = elements.filter(item => classOperation(item, 'contains', props.selectedClass))
+                // 未选中元素
+                const unselectedElements = elements.filter(item => !classOperation(item, 'contains', props.selectedClass))
+
+                selectedElements.map(item => {
+                    const withinRange = isWithinRange(item, top, bottom, left, right)
+                    withinRange &&
+                        classOperation(item, 'contains', props.selectedClass) &&
+                        classOperation(item, 'remove', props.selectedClass)
+                })
+
+                unselectedElements.map((item) =>
+                    isWithinRange(item, top, bottom, left, right) &&
+                    classOperation(item, 'add', props.selectedClass))
+
+                return query(props.selectedClass)
+            }
+
+            const mouseDown = debounce((event) => {
+                timer = setTimeout(() => {
+                    mouseOn = true
+                    startX = event.clientX
+                    startY = event.clientY
+                    emit("mouseDown")
+                }, 300)
+                // 重置本次框选的元素列表
+                setStyle({ left, startX, top: startY, width: 0, height: 0, display: "block" })
+            })
+
+            const mouseMove = debounce((event) => {
+                if (!mouseOn) return false
+                const _width = event.clientX - startX
+                const _height = event.clientY - startY
+
+                top = _height > 0 ? startY : event.clientY
+                left = _width > 0 ? startX : event.clientX
+                width = Math.abs(_width)
+                height = Math.abs(_height)
+                setStyle({ left, top, width, height })
+            })
+
+            const mouseUp = debounce((event) => {
+                timer && clearTimeout(timer)
+                // 判断是否鼠标左键
+                if (event.which !== 1) return false
+                // 判断是框选还是点击
+                if (!mouseOn) return false
+                mouseOn = false
+                setStyle({ display: "none" })
+                // 获得已选中的元素
+                const selectedEles = getAreaWithinElements()
+                // 响应事件,并传递本次框选的元素列表
+                emit("mouseUp", selectedEles)
+            })
+
+            nextTick(() => document.addEventListener("mouseup", mouseUp))
+            onUnmounted(() => document.removeEventListener("mouseup", mouseUp))
+
+            return {
+                mouseUp,
+                mouseDown,
+                mouseMove,
+                timer,
+                style,
+                selectContainer,
+                uuid
+            }
+        }
+    }
+</script>
+
+<style lang="scss">
+    .box-select__container {
+        background-color: #ffffff;
+        height: 50vh;
+    }
+
+    .box-select__coordinate {
+        position: fixed;
+        z-index: 11;
+        left: 0;
+        top: 0;
+        width: 0;
+        height: 0;
+        background: rgba(0, 0, 0, .5);
+        border: 1px solid rgba(0, 0, 0, 1);
+        opacity: 0.6;
+        pointer-events: none;
+    }
+
+    .box-select__hypocritical {
+        background-color: blue;
+    }
+</style>

+ 186 - 0
src/components/check/areaCard.vue

@@ -0,0 +1,186 @@
+/* 自定义tabs */
+<template>
+    <!-- <transition>
+        <div :class='areaClass' @mouseover="hover = false" @mouseleave="hover = false" onselectstart="return false">
+            <div :class="headerClass">
+                <div :class='circleClass'></div>
+                <span class="gy-card-title">{{ title }}</span>
+                <img class="gy-card-decoration01" src="../../assets/img/controlcenter/decoration01.png">
+                <img class="gy-card-decoration02" src="../../assets/img/controlcenter/decoration02.png">
+            </div>
+            <div :class='contentClass'>
+                <el-scrollbar style="height: 100%">
+                    <slot></slot>
+                </el-scrollbar>
+            </div>
+        </div>
+    </transition> -->
+    <div class="body">
+        <img class="logo" src="../../assets/img/logo.png" alt="">
+        <div class="title">{{ title }}</div>
+        <div class="record" @click="showRecord">校验记录</div>
+        <div style="margin-top: 50px; margin-left: 20px; height: 80%;">
+            <el-scrollbar>
+                <div class="scoll" style="margin-left: 5px;">
+                    <MatrixBlock  @on-click="handleClick" :dataList="showList"></MatrixBlock>
+                </div>
+            </el-scrollbar>
+        </div>
+        <OperationRecords ref="records" v-model="display" @closed="closed()"></OperationRecords>
+        <WindturbineDetailPages v-model="dialogVisible" @close="handleClose" :windturbine="currentWindturbine">
+    </WindturbineDetailPages>
+    </div>
+</template>
+
+<script>
+    import BackgroundData from 'utils/BackgroundData'
+    import MatrixBlock from "../matrixBlock.vue";
+    import OperationRecords from "./operationRecords.vue";
+    import WindturbineDetailPages from "../WindturbineDetailPages.vue";
+    export default {
+        props: {
+            title: {
+                type: String,
+                default: '校验区',
+                required: true
+            },
+            height: {
+                type: Number,
+                default: 200,
+            },
+        },
+        components: {
+            MatrixBlock,
+            OperationRecords,
+            WindturbineDetailPages
+        },
+        data() {
+            return {
+                showList: [],
+                arr: [],
+                list: [],
+                display:false,
+                dialogVisible:false,
+                currentWindturbine: {},
+            }
+        },
+        methods: {
+            dataDeal() {
+                let flag = false
+                let showList = []
+                let arr = []
+                let checks = BackgroundData.getInstance().checkouts;
+                checks.forEach(item => {
+                    if (item.status === this.list[item.windturbineId].status) {
+                        showList.push(this.list[item.windturbineId])
+                    } else {
+                        BackgroundData.getInstance().removeCheckouts(item);
+                    }
+                    if ((new Date()).getTime() - item.checkTime > 120000) {
+                        BackgroundData.getInstance().removeCheckouts(item);
+                        arr.push(item.windturbineId)
+                        flag = true
+                    }
+                })
+                this.showList = showList
+                if (flag) {
+                    let mss = arr.join(',') + '风机超时未响应,已移除'
+                    this.$notify({
+                        title: "控制",
+                        message: mss,
+                        type: "warning",
+                        position: "bottom-right",
+                        offset: 60,
+                        duration: 3000,
+                    });
+                    flag = false
+                }
+            },
+            showRecord(){
+                this.display = true
+                this.$refs.records.dataDeal() 
+            },
+            closed(){
+                this.display = false
+            },
+            handleClick(itm) {
+                this.dialogVisible = true;
+                this.currentWindturbine = itm;
+            },
+            handleClose() {
+                this.dialogVisible = false
+            },
+        },
+        watch: {
+            "$store.getters.windturbinelist": {
+                deep: true,
+                handler: function (json) {
+                    this.list = json
+                    this.arr = BackgroundData.getInstance().checkouts;
+                    this.dataDeal()
+                },
+            },
+        },
+    }
+</script>
+
+<style scoped="scoped">
+    .body {
+        border: 1px solid #373737;
+        width: 100%;
+        margin-left: 15px;
+        margin-top: 10px;
+        height: 25vh;
+    }
+
+    .body .scoll {
+        height: 91%;
+    }
+
+    .title {
+        color: #ffffff;
+        font-size: 14px;
+        margin-left: 32px;
+        /* margin-top: 12px; */
+        margin-bottom: 10px;
+        /* width: 570px; */
+        width: 29vw;
+        height: 50px;
+        display: flex;
+        align-items: center;
+        position: absolute;
+        background-color: #000000;
+    }
+
+    .title::before {
+        z-index: 1;
+        content: '';
+        position: absolute;
+        left: -18px !important;
+        /* top: 30px !important; */
+        width: 5px;
+        height: 5px;
+        background-color: #54B75A;
+        border-radius: 50%;
+    }
+
+    .record {
+        position: absolute;
+        color: #ffffff;
+        font-size: 14px;
+        right: 0;
+        top: 23px;
+        width: 80px;
+        height: 30px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background-color: rgba(37, 116, 219, 1);
+    }
+
+    .logo {
+        position: absolute;
+        top: 2px;
+        left: 12px;
+    }
+</style>

+ 33 - 0
src/components/check/checkArea.vue

@@ -0,0 +1,33 @@
+<template>
+  <div class="problem">
+    <AreaCard title="校验区" height="25"></AreaCard>
+  </div>
+</template>
+
+<script>
+  import AreaCard from "./areaCard.vue";
+  import BackgroundData from 'utils/BackgroundData'
+  export default {
+    name: "ProblemArea",
+    components: {
+      AreaCard,
+    },
+    props: {},
+    data() {
+      return {
+      };
+    },
+    computed: {},
+    created: function () {
+
+    },
+    methods: {
+      
+    },
+  };
+</script>
+<style scoped>
+  .problem {
+    height: 100%;
+  }
+</style>

+ 393 - 0
src/components/check/operationRecords.vue

@@ -0,0 +1,393 @@
+<template>
+    <el-dialog width="50%" @open="opened()" @closed="closed()" :show-close="false" class="my-info-dialog">
+        <template #title>
+            <div class="showTitles">
+                <div class="titles">校验记录详情</div>
+            </div>
+        </template>
+        <div class="bodys">
+            <!-- <el-cascader ref="cascaderHandle" :options="options" :props="{ checkStrictly: true }" clearable @change="handleChange">
+            </el-cascader> -->
+            <div class="left">
+                <el-scrollbar>
+                    <el-input placeholder="输入关键字进行过滤" v-model="filterText">
+                    </el-input>
+                    <el-tree class="filter-tree" :data="showData" :props="defaultProps" :filter-node-method="filterNode"
+                        node-key="id" :default-expanded-keys="[0]" ref="tree" @node-click="handleChange">
+                    </el-tree>
+                </el-scrollbar>
+            </div>
+            <div class="rights">
+                <div class="dateBar">
+                    <el-date-picker class="pickers" @change="changes" v-model="timeValue" type="datetimerange"
+                        range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
+                    </el-date-picker>
+                    <div class="buttons" @click="getControlRecord()">查询</div>
+                </div>
+                <el-scrollbar style="height:86%;">
+                    <div class="tables">
+                        <el-table :data="recordData" class="table" style=" width:100%" height="49vh" :header-cell-style="{
+                            background: 'rgb(30,30,30)',
+                            color: 'rgb(220,220,220)',
+                            padding: '4px',
+                            fontSize: '14px',
+                            'border-bottom': 'solid 1px rgba(77, 77, 77, 1)',
+                          }" :cell-style="{
+                            height: '40px',
+                            background: 'rgb(30,30,30)',
+                            color: 'rgb(220,220,220)',
+                            padding: '3px',
+                            fontSize: '12px',
+                            'border-bottom': '1px solid #000000'
+                          }">
+                            <el-table-column prop="time" label="日期" width="120" align="center">
+                            </el-table-column>
+                            <el-table-column prop="windturbineId" label="风机号" width="120" align="center">
+                            </el-table-column>
+                            <el-table-column prop="controls" label="控制命令" width="120" align="center">
+                            </el-table-column>
+                            <el-table-column prop="result" label="操作结果" align="center">
+                            </el-table-column>
+                            <el-table-column prop="userName" label="操作人" width="120" align="center">
+                            </el-table-column>
+                        </el-table>
+                    </div>
+                </el-scrollbar>
+                <div class="paginations">
+                    <el-pagination :hide-on-single-page="true" :page-size="currentPage" background
+                        layout="prev, pager, next" :total="total" @current-change="handleCurrentChange">
+                    </el-pagination>
+                </div>
+            </div>
+        </div>
+
+    </el-dialog>
+</template>
+<script>
+    import dayjs from 'dayjs'
+    import api from "api/index";
+    export default {
+        props: {
+
+        },
+        updated() {
+            if (this.timeValue.length === 0) {
+                let date = new Date()
+                this.timeValue[0] = date.getTime() - 28800000
+                this.timeValue[1] = date.getTime() + 3600000
+            }
+        },
+        mounted() {
+
+        },
+        data() {
+            return {
+                currentPage: 10,
+                filterText: '',
+                pageIndex: 1,
+                datas: {},
+                chooseStation: {},
+                timeValue: [],
+                showData: [
+                    {
+                        id: 0,
+                        windturbineId: '全部',
+                        stationId: "",
+                        children: [
+                            {
+                                id: 1,
+                                windturbineId: '麻黄山',
+                                stationId: "MHS_FDC",
+                                children: []
+                            }, {
+                                id: 2,
+                                windturbineId: '牛首山',
+                                stationId: "NSS_FDC",
+                                children: []
+                            }, {
+                                id: 3,
+                                windturbineId: '青山',
+                                stationId: "QS_FDC",
+                                children: []
+                            }, {
+                                id: 4,
+                                windturbineId: '石板泉',
+                                stationId: "SBQ_FDC",
+                                children: []
+                            }, {
+                                id: 5,
+                                windturbineId: '香山',
+                                stationId: "XS_FDC",
+                                children: []
+                            },
+                        ]
+                    },
+                ],
+                defaultProps: {
+                    children: 'children',
+                    label: 'windturbineId'
+                },
+                recordData: [],
+                total: '',
+                controlErorCodes: [
+                    "控制成功",
+                    "控制命令发送失败",
+                    "无效的控制地址",
+                    "被控设备异常",
+                    "无效的控制功能",
+                    "网络连接错误,检查场站通信",
+                    "控制结果读取超时",
+                    "未知错误",
+                    "控制命令错误",
+                    "收到无法识别数据",
+                    "未读取到数据包",
+                    "未知错误",
+                    "风机操作过频繁",
+                    "风机被挂牌",
+                    "风机操作与风机状态不符",
+                    "需要登录",
+                ],
+            };
+        },
+        methods: {
+            dataDeal() {
+                this.datas = this.$store.state.windturbinelist ? this.$store.state.windturbinelist : {}
+                let arr = Object.keys(this.datas).sort()
+                for (let id of arr) {
+                    let item = this.datas[id];
+                    switch (item.windturbineId.slice(0, 2)) {
+                        case 'MG':
+                            this.showData[0].children[0].children.push(item)
+                            break;
+                        case 'NG':
+                            this.showData[0].children[1].children.push(item)
+                            break;
+                        case 'QG':
+                            this.showData[0].children[2].children.push(item)
+                            break;
+                        case 'SG':
+                            this.showData[0].children[3].children.push(item)
+                            break;
+                        case 'XG':
+                            this.showData[0].children[4].children.push(item)
+                            break;
+                    }
+                }
+                console.log(this.showData);
+            },
+            handleChange(value) {
+                this.chooseStation = value
+                this.pageIndex = 1
+                this.getControlRecord(value)
+            },
+            closed() {
+                this.pageIndex = 1
+                this.chooseStation = {}
+                this.showData = [
+                    {
+                        id: 0,
+                        windturbineId: '全部',
+                        stationId: "",
+                        children: [
+                            {
+                                id: 1,
+                                windturbineId: '麻黄山',
+                                stationId: "MHS_FDC",
+                                children: []
+                            }, {
+                                id: 2,
+                                windturbineId: '牛首山',
+                                stationId: "NSS_FDC",
+                                children: []
+                            }, {
+                                id: 3,
+                                windturbineId: '青山',
+                                stationId: "QS_FDC",
+                                children: []
+                            }, {
+                                id: 4,
+                                windturbineId: '石板泉',
+                                stationId: "SBQ_FDC",
+                                children: []
+                            }, {
+                                id: 5,
+                                windturbineId: '香山',
+                                stationId: "XS_FDC",
+                                children: []
+                            },
+                        ]
+                    },
+                ],
+                this.$emit('closed');
+            },
+            filterNode(value, data) {
+                if (!value) return true;
+                return data.windturbineId.indexOf(value) !== -1;
+            },
+            handleCurrentChange(val) {
+                this.pageIndex = val
+                this.getControlRecord()
+            },
+            opened(){
+                let date = new Date()
+                this.timeValue[0] = date.getTime() - 28800000
+                this.timeValue[1] = date.getTime() + 3600000
+                this.getControlRecord()
+            },
+            getControlRecord() {
+                api.controlRecord({
+                    stationId: this.chooseStation.stationId ? this.chooseStation.stationId : "",
+                    userName: "",
+                    windturbineId: this.chooseStation.id ? "" : this.chooseStation.stationId ? this.chooseStation.windturbineId : "",
+                    startTime: dayjs(this.timeValue[0]).format('YYYY/MM/DD HH:mm:ss'),
+                    endTime: dayjs(this.timeValue[1]).format('YYYY/MM/DD HH:mm:ss'),
+                    pageSize: this.currentPage,
+                    pageIndex: this.pageIndex,
+                }).then(res => {
+                    if (res) {
+                        let types = {
+                            Start: '启动',
+                            Stop: '停止',
+                            Reset: '复位',
+                            Maintain: '维护',
+                            UnMaintain: '取消维护',
+                            Lock: '挂牌',
+                            UnLock: '取消挂牌',
+
+                        }
+                        res.data.dataList.forEach(item => {
+                            item.time = dayjs(item.time).format('MM-DD HH:mm:ss')
+                            item.result = this.controlErorCodes[item.errorCode]
+                            item.controls = types[item.controlType]
+                        })
+                        this.total = res.data.total
+                        this.recordData = res.data.dataList
+                    }
+                })
+            },
+        },
+        watch: {
+            filterText(val) {
+                this.$refs.tree.filter(val);
+            }
+        },
+    }
+</script>
+
+<style scoped>
+    .showTitles {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: space-between;
+        margin-top: -10px;
+        font-size: 18px;
+        color: #FFFFFF;
+        height: 40px;
+    }
+
+    .titles {
+        font-size: 16px;
+        color: #FFFFFF;
+    }
+
+    .el-dialog__body {
+        padding: 30px 10px 10px 10px;
+    }
+
+    .bodys {
+        display: flex;
+        flex-direction: row;
+        background-color: black;
+        width: 100%;
+        margin-top: -30px;
+        height: 60vh;
+    }
+
+    .left {
+        width: 20%;
+        height: 100%;
+        background-color: rgba(77, 77, 77, 1);
+        border-right: 2px solid #000000;
+    }
+
+    .rights {
+        width: 80%;
+        height: 100%;
+        background-color: rgba(77, 77, 77, 1);
+    }
+
+    .el-tree {
+        color: #FFFFFF !important;
+        background-color: rgba(77, 77, 77, 1) !important;
+    }
+
+    .el-tree-node:focus>.el-tree-node__content {
+        background-color: #000000 !important;
+    }
+
+    .el-tree-node__content:hover {
+        background-color: #000000 !important;
+    }
+
+    .dateBar {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: space-between;
+        margin-left: 20px;
+    }
+
+    .pickers {
+        margin-left: 20px;
+    }
+
+    .tables {
+        margin-top: 20px;
+        width: 95%;
+        margin-left: 3%;
+    }
+
+    .table {
+        background-color: rgba(77, 77, 77, 1) !important;
+    }
+
+    .el-table td,
+    .el-table th.is-leaf {
+        border-bottom: 1px solid rgba(77, 77, 77, 1) !important;
+    }
+
+    .el-table__header {
+        width: 100% !important;
+    }
+
+    .el-table__body-wrapper {
+        background-color: rgba(77, 77, 77, 1) !important;
+    }
+
+    .el-table::before {
+        width: 0;
+    }
+
+    tr {
+        line-height: 1.5;
+        background: #1e1e1e;
+        margin-bottom: 2px;
+        border-radius: 5px;
+    }
+
+    .table-main {
+        font-size: 14px;
+        width: 600px;
+        text-align: center;
+        background: #000000;
+        margin: 5px;
+        border-collapse: separate;
+        border-spacing: 0px 5px;
+    }
+
+    .paginations {
+        display: flex;
+        flex-direction: row-reverse;
+    }
+</style>

+ 853 - 0
src/components/control/areaCard.vue

@@ -0,0 +1,853 @@
+/* 自定义tabs */
+<template>
+    <div class="body" :style="style">
+        <img class="logo" src="../../assets/img/logo.png" alt="">
+        <div class="title">{{ title }}</div>
+        <div style="margin-top: 50px; height:85%;" @contextmenu="contextmenu">
+            <el-scrollbar>
+                <div class="scoll">
+                    <div class="matrix" v-if="startList.length>0">
+                        <div class="problemTitle">启动</div>
+                        <MatrixBlock @on-click="handleDetial" @choose-click="handleClick" :dataList="startList">
+                        </MatrixBlock>
+                    </div>
+                    <div class="matrix" v-if="stopList.length>0">
+                        <div class="problemTitle">停机</div>
+                        <MatrixBlock @on-click="handleDetial" @choose-click="handleClick" :dataList="stopList">
+                        </MatrixBlock>
+                    </div>
+                    <div class="matrix" v-if="maintainList.length>0">
+                        <div class="problemTitle">维护</div>
+                        <MatrixBlock @on-click="handleDetial" @choose-click="handleClick" :dataList="maintainList">
+                        </MatrixBlock>
+                    </div>
+                    <div class="matrix" v-if="unMaintainList.length>0">
+                        <div class="problemTitle">取消维护</div>
+                        <MatrixBlock @on-click="handleDetial" @choose-click="handleClick" :dataList="unMaintainList">
+                        </MatrixBlock>
+                    </div>
+                </div>
+            </el-scrollbar>
+        </div>
+        <div v-if="current==1" class="send" @click="handleSend">发送</div>
+        <!-- <div class="success" v-if="showFlag&&current===0">指令发送成功</div> -->
+    </div>
+    <WindturbineDetailPages v-model="dialogVisible" @close="handleClose" :windturbine="currentWindturbine">
+    </WindturbineDetailPages>
+    <StationSvgDetailPages v-model="svgVisible" :stationName="stationName" :svgWeb="svgWeb" @close="handleClose">
+    </StationSvgDetailPages>
+</template>
+
+<script>
+    import BackgroundData from 'utils/BackgroundData'
+    import WindturbineDetailPages from "../WindturbineDetailPages.vue";
+    import MatrixBlock from "../matrixBlock.vue";
+    import MessageBridge from 'utils/MessageBridge'
+    import api from "api/index";
+    import StationSvgDetailPages from "../stationSvgDetailPages.vue";
+    export default {
+        name: 'gy-card',
+        components: {
+            MatrixBlock,
+            WindturbineDetailPages,
+            StationSvgDetailPages
+        },
+        created: function () {
+            this.initData();
+            this.suggestion();
+        },
+        emits: ["parentRun"],
+        props: {
+            title: {
+                type: String,
+                default: '',
+                required: true,
+
+            },
+            height: {
+                type: Number,
+                default: 200,
+            },
+        },
+        data() {
+            return {
+                current: 1,
+                vss: {},
+                windturbinelist: {},
+                titleList: [],
+                startList: [],
+                stopList: [],
+                maintainList: [],
+                unMaintainList: [],
+                chooseList: [],
+                sendList: [],
+                currentWindturbine: {},
+                dialogVisible: false,
+                svgVisible: false,
+                // showFlag: false,
+                postData: false,
+                svgWeb: '',
+                stationName: '',
+                // 定时器
+                timer: "",
+
+                controlErorCodes: [
+                    "控制成功",
+                    "控制命令发送失败",
+                    "无效的控制地址",
+                    "被控设备异常",
+                    "无效的控制功能",
+                    "网络连接错误,检查场站通信",
+                    "控制结果读取超时",
+                    "未知错误",
+                    "控制命令错误",
+                    "收到无法识别数据",
+                    "未读取到数据包",
+                    "未知错误",
+                    "风机操作过频繁",
+                    "风机被挂牌",
+                    "风机操作与风机状态不符",
+                    "需要登录",
+                ],
+                windStation: {
+                    'NG01': {
+                        name: '牛首山'
+                    },
+                    'MG01': {
+                        name: '麻黄山'
+                    },
+                    'QG01': {
+                        name: '青山'
+                    },
+                    'NG01': {
+                        name: '牛首山'
+                    },
+                    'SG01': {
+                        name: '石板泉'
+                    },
+                    'XG01': {
+                        name: '香山'
+                    },
+                },
+                boosterStation: {
+                    'MHS_SYZ': {
+                        name: '麻黄山升压站'
+                    },
+                    'NSS_SYZ': {
+                        name: '牛首山升压站'
+                    },
+                    'QS_SYZ': {
+                        name: '青山升压站'
+                    },
+                    'QS3_SYZ': {
+                        name: '青山三期升压站'
+                    },
+                    'SBQ_SYZ': {
+                        name: '石板泉升压站'
+                    },
+                    'XS_SYZ': {
+                        name: '香山升压站'
+                    },
+                    'DWK_SYZ': {
+                        name: '大武口升压站'
+                    },
+                    'PL_SYZ': {
+                        name: '平罗升压站'
+                    },
+                    'PL2_SYZ': {
+                        name: '平罗二期升压站'
+                    },
+                    'XH_SYZ': {
+                        name: '宣和升压站'
+                    },
+                    'MCH_SYZ': {
+                        name: '马场湖升压站'
+                    },
+                    'HZJ_SYZ': {
+                        name: '海子井升压站'
+                    },
+                },
+                indexsss: 0,
+            }
+        },
+        computed: {
+            style() {
+                return `width: 100%; height: ${this.height}vh;`
+            },
+        },
+        methods: {
+            control(current) {
+                this.current = current === 0 ? current : current === 1 ? current : 1
+                this.suggestion()
+            },
+            initData: function () {
+                let mb = MessageBridge.getInstance();
+                mb.unregister({ key: "/topic/suggestion" });
+                let vs = [{ key: "/topic/suggestion", action: this.suggestion }];
+                let vss = [{ key: "/topic/voice-control", action: this.windturbineMessage }];
+                this.vss = vss
+                mb.register(vs);
+                mb.register(vss);
+            },
+            suggestion(msg, headers) {
+                msg ? this.$store.commit('suggestion', JSON.parse(msg)) : ''
+                let bd = BackgroundData.getInstance();
+                this.titleList = msg ? JSON.parse(msg) : this.$store.state.suggestion
+                if (msg && JSON.parse(msg).length > 0) {
+                    if (bd.LoginUser) {
+                        this.postData = true
+                    }
+                }
+                if (this.current === 0) {
+                    let dateList = []
+                    this.titleList.forEach(item => {
+                        if (item.windturbineId.slice(0, 2) === 'NG' || item.windturbineId.slice(0, 2) === 'MG') {
+                            let arr = Object.keys(this.windturbinelist).sort()
+                            this.windturbinelist = (arr.length !== 0) ? this.windturbinelist : this.$store.state.windturbinelist
+                            switch (item.operateStyle) {
+                                case 'Start':
+                                    this.windturbinelist[item.windturbineId].controlType = 1
+                                    break;
+                                case 'Stop':
+                                    this.windturbinelist[item.windturbineId].controlType = 2
+                                    break;
+                                case 'Maintain':
+                                    this.windturbinelist[item.windturbineId].controlType = 6
+                                    break;
+                                case 'UnMaintain':
+                                    this.windturbinelist[item.windturbineId].controlType = 8
+                                    break;
+                            }
+                            dateList.push(this.windturbinelist[item.windturbineId])
+                        }
+                    })
+                    let mss = {}
+                    mss.type = 'send'
+                    this.timer = setTimeout(() => {
+                        this.sendCommand(mss, dateList, 'automatic')
+                        // this.showFlag = true
+                        clearInterval(this.timer);
+                    }, 3000);
+                }
+            },
+            windturbineMessage(msg) {
+                if (this.$store.state.current === 1 || this.$store.state.current === 0) {
+                    let arr = []
+                    if (msg === 'CLOSE') {
+                        arr.push(msg)
+                    } else {
+                        arr = msg.split('-')
+                    }
+                    this.dialogVisible = false
+                    this.svgVisible = false
+                    this.svgWeb = ''
+                    if (arr[0] === 'OPEN_FJ') {
+                        this.currentWindturbine = this.windturbinelist[arr[1]]
+                        setTimeout(() => {
+                            this.dialogVisible = true;
+                        }, 500);
+                    } else if (arr[0] === 'CLOSE') {
+                        this.dialogVisible = false
+                        this.svgVisible = false
+                    } else if (arr[0] === 'OPEN_SYZ') {
+                        this.showSvg = true
+                        this.svgVisible = true
+                        this.svgWeb = arr[1];
+                        this.stationName = this.boosterStation[arr[1]].name
+                    } else if (arr[0] === 'CONTROL_START' || arr[0] === 'CONTROL_STOP' || arr[0] === 'CONTROL_MAINTAIN' || arr[0] === 'CONTROL_UNMAINTAIN') {
+                        let windControlList = [];
+                        let mss = {}
+                        arr.forEach(item => {
+                            if (item === (this.windturbinelist[item] ? this.windturbinelist[item].windturbineId : '')) {
+                                switch (arr[0]) {
+                                    case 'CONTROL_START':
+                                        this.windturbinelist[item].controlType = '1'
+                                        break
+                                    case 'CONTROL_STOP':
+                                        this.windturbinelist[item].controlType = '2'
+                                        break
+                                    case 'CONTROL_MAINTAIN':
+                                        this.windturbinelist[item].controlType = '6'
+                                        break
+                                    case 'CONTROL_UNMAINTAIN':
+                                        this.windturbinelist[item].controlType = '8'
+                                        break
+                                }
+                                windControlList.push(this.windturbinelist[item])
+                            }
+                        })
+                        mss.type = 'send'
+                        this.sendCommand(mss, windControlList)
+                    } else if (arr[0] === 'CONTROL_LOCK_OVERHAUL' || arr[0] === 'CONTROL_LOCK_MAINTAIN' || arr[0] === 'CONTROL_LOCK_LNVOLVED_OVERHAUL' ||
+                        arr[0] === 'CONTROL_LOCK_LNVOLVED_MAINTAIN' || arr[0] === 'CONTROL_LOCK_LNVOLVED_PG' || arr[0] === 'CONTROL_LOCK_LNVOLVED_WEATHER' || arr[0] === 'CONTROL_UNLOCK') {
+                        let windturbine = this.windturbinelist[arr[1]]
+                        switch (arr[0]) {
+                            case 'CONTROL_LOCK':
+                                this.sendLock({ value: "Lock" }, windturbine);
+                                break;
+                            case 'CONTROL_LOCK_OVERHAUL':
+                                this.sendLock({ value: "CheckLock" }, windturbine);
+                                break;
+                            case 'CONTROL_LOCK_MAINTAIN':
+                                this.sendLock({ value: "FaultLock" }, windturbine);
+                                break;
+                            case 'CONTROL_LOCK_LNVOLVED_OVERHAUL':
+                                this.sendLock({ value: "StationCheckLock" }, windturbine);
+                                break;
+                            case 'CONTROL_LOCK_LNVOLVED_MAINTAIN':
+                                this.sendLock({ value: "StationFaulLock" }, windturbine);
+                                break;
+                            case 'CONTROL_LOCK_LNVOLVED_PG':
+                                this.sendLock({ value: "StationPowerLineLock" }, windturbine);
+                                break;
+                            case 'CONTROL_LOCK_LNVOLVED_WEATHER':
+                                this.sendLock({ value: "StationWeatherLock" }, windturbine);
+                                break;
+                            case 'CONTROL_UNLOCK':
+                                this.sendLock({ value: "UnLock" }, windturbine);
+                                break;
+                        }
+                    } else if (arr[0] === 'CONTROL_SART_RECOMMENDATION') {
+                        let mss = {}
+                        mss.type = 'send'
+                        this.startList.forEach(item => {
+                            item.controlType = '1'
+                        })
+                        this.sendCommand(mss, this.startList)
+                    } else if (arr[0] === 'CONTROL_STOP_RECOMMENDATION') {
+                        let mss = {}
+                        mss.type = 'send'
+                        this.stopList.forEach(item => {
+                            item.controlType = '2'
+                        })
+                        this.sendCommand(mss, this.stopList)
+                    } else if (arr[0] === 'CONTROL_RECOMMENDATION_ALL') {
+                        let windControlList = []
+                        let mss = {}
+                        mss.type = 'send'
+                        this.startList.forEach(item => {
+                            item.controlType = '1'
+                            windControlList.push(item)
+                        })
+                        this.stopList.forEach(item => {
+                            item.controlType = '2'
+                            windControlList.push(item)
+                        })
+                        this.maintainList.forEach(item => {
+                            item.controlType = '6'
+                            windControlList.push(item)
+                        })
+                        this.unMaintainList.forEach(item => {
+                            item.controlType = '8'
+                            windControlList.push(item)
+                        })
+                        this.sendCommand(mss, windControlList)
+                    }
+                }
+
+            },
+            handleClick(values) {
+                if (values.active) {
+                    let showIndex = null
+                    this.chooseList.forEach((item, index) => {
+                        if (item.windturbineId === values.windturbineId) {
+                            showIndex = index
+                        }
+                    })
+                    this.chooseList.splice(showIndex, 1);
+                } else {
+                    this.chooseList.push(values)
+                }
+                this.startList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active } })
+                this.stopList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active } })
+                this.maintainList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active } })
+                this.unMaintainList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active } })
+            },
+            handleDetial(itm) {
+                this.dialogVisible = true;
+                this.currentWindturbine = itm;
+            },
+            handleClose() {
+                this.dialogVisible = false
+                this.svgVisible = false
+            },
+            handleSend() {
+                if (this.chooseList.length > 0) {
+                    this.chooseList.forEach(item => {
+                        if (item.operateStyle === "Start") {
+                            item.controlType = 1
+                        } else if (item.operateStyle === "Stop") {
+                            item.controlType = 2
+                        } else if (item.operateStyle === "Maintain") {
+                            item.controlType = 6
+                        } else if (item.operateStyle === "UnMaintain") {
+                            item.controlType = 8
+                        }
+                    })
+                    let mss = {}
+                    mss.type = 'send'
+                    this.sendCommand(mss, this.chooseList)
+                }
+            },
+            /* 右键菜单 */
+            contextmenu() {
+                const { remote } = require("electron");
+                let that = this;
+                const menuTemplate = [
+                    {
+                        label: "发送",
+                        click() {
+                            that.handleSend();
+                        },
+                    },
+                    {
+                        label: "挂牌",
+                        submenu: [
+                            {
+                                label: "检修",
+                                click() {
+                                    that.sendLock({ value: "CheckLock" });
+                                },
+                            },
+                            {
+                                label: "故障维修",
+                                click() {
+                                    that.sendLock({ value: "FaultLock" });
+                                },
+                            },
+                            {
+                                label: "场内受累检修",
+                                click() {
+                                    that.sendLock({ value: "StationCheckLock" });
+                                },
+                            },
+                            {
+                                label: "场内受累故障",
+                                click() {
+                                    that.sendLock({ value: "StationFaulLock" });
+                                },
+                            },
+                            {
+                                label: "场外受累电网",
+                                click() {
+                                    that.sendLock({ value: "StationPowerLineLock" });
+                                },
+                            },
+                            {
+                                label: "场外受累天气",
+                                click() {
+                                    that.sendLock({ value: "StationWeatherLock" });
+                                },
+                            },
+                        ],
+                    },
+                ];
+                const menu = remote.Menu.buildFromTemplate(menuTemplate);
+
+                menu.popup(remote.getCurrentWindow());
+            },
+            sendCommand(msg, windturbine) {
+                let bd = BackgroundData.getInstance();
+                if (!bd.LoginUser) {
+                    this.$notify({
+                        title: "请登录",
+                        message: "控制风机需要先登录!",
+                        type: "warning",
+                        position: "bottom-right",
+                        offset: 60,
+                        duration: 3000,
+                    });
+                    return;
+                }
+                let sendList = windturbine
+                if (sendList.length > 0) {
+                    bd.checkout(sendList);
+                    this.chooseList = []
+                    let pairs = {}
+                    sendList.forEach(item => {
+                        let ct = {
+                            windturbineId: item.windturbineId,
+                            stationId: item.stationId,
+                            projectId: item.projectId,
+                            modelId: item.modelId,
+                            controlType: item.controlType,
+                            lockType: item.lockType,
+                            userName: `system_${bd.LoginUser.name}`,
+                            userId: 0,
+                            auto: this.current === 0 ? true : false,
+                        };
+                        pairs[ct.windturbineId] = ct;
+                    })
+                    api.windturbControl(pairs).then(res => {
+                        if (res) {
+                            // this.showFlag = false
+                            this.controlSuccess(res)
+                        }
+                    })
+                }
+            },
+            sendLock(msg, windturbine) {
+                let bd = BackgroundData.getInstance();
+                if (!bd.LoginUser) {
+                    this.$notify({
+                        title: "请登录",
+                        message: "控制风机需要先登录!",
+                        type: "warning",
+                        position: "bottom-right",
+                        offset: 60,
+                        duration: 3000,
+                    });
+                    return;
+                }
+                let sendList = []
+                if (windturbine) {
+                    windturbine.lockType = msg.value;
+                    sendList.push(windturbine)
+                } else {
+                    this.chooseList.forEach(item => {
+                        item.lockType = msg.value;
+                    })
+                    sendList = this.chooseList
+                }
+                if (sendList.length > 0) {
+                    this.chooseList = []
+                    let pairs = {}
+                    sendList.forEach(item => {
+                        let ct = {
+                            windturbineId: item.windturbineId,
+                            stationId: item.stationId,
+                            projectId: item.projectId,
+                            modelId: item.modelId,
+                            controlType: item.controlType,
+                            lockType: item.lockType,
+                            userName: `system_${bd.LoginUser.name}`,
+                            userId: 0,
+                        };
+                        pairs[ct.windturbineId] = ct;
+                    })
+                    api.windturbControlLock(pairs).then(res => {
+                        if (res) {
+                            this.controlSuccess(res)
+                        }
+                    })
+                }
+            },
+            clearSelected() {
+                this.startList.forEach(item => {
+                    item.active = false
+                })
+                this.stopList.forEach(item => {
+                    item.active = false
+                })
+                this.chooseList = []
+            },
+            /* 控制成功 */
+            controlSuccess(msg) {
+                let bd = BackgroundData.getInstance();
+                for (let id in msg.data) {
+                    let val = msg.data[id]
+                    if(val.errorCode !=='0'){
+                        bd.removeCheckouts(val);
+                    }
+                }
+                if (msg.data || msg.data !== {}) {
+                    // if (this.current !== 0) {
+                    //     let successReport = ''
+                    //     let failureReport = ''
+                    //     let successList = []
+                    //     let failureList = []
+                    //     for (let item in msg.data) {
+                    //         if (msg.data[item].errorCode === '0') {
+                    //             successList.push(msg.data[item])
+                    //         } else {
+                    //             failureList.push(msg.data[item])
+                    //         }
+                    //     }
+                    //     successList.forEach((item, index) => {
+                    //         if (index < 3) {
+                    //             let wind = item.windturbineId.split('_')
+                    //             successReport = successReport + this.windStation[wind[0]].name + wind[1] + '风机,'
+                    //         }
+                    //     })
+                    //     failureList.forEach((item, index) => {
+                    //         if (index < 3) {
+                    //             let wind = item.windturbineId.split('_')
+                    //             failureReport = failureReport + this.windStation[wind[0]].name + wind[1] + '风机,'
+                    //         }
+                    //     })
+                    //     if (successReport !== '') {
+                    //         let url1 = process.env.VUE_APP_API + '/api/voice-control/send-topic/TTS:' + successReport + (successList.length > 3 ? '等风机操作成功' : '操作成功')
+                    //         this.sendMessage(url1)
+                    //     }
+                    //     if (failureReport !== '') {
+                    //         let url1 = process.env.VUE_APP_API + '/api/voice-control/send-topic/TTS:' + failureReport + (failureList.length > 3 ? '等风机操作失败' : '操作失败')
+                    //         this.sendMessage(url1)
+                    //     }
+                    // }
+                    let mss = '';     // 信息
+                    let iserror = false;// 是否有控制错误的风机
+                    for (let v in msg.data) {
+                        let val = msg.data[v];
+                        if (val.errorCode > 0) {
+                            iserror = true;
+                            mss += `${val.windturbineId}  ${this.controlErorCodes[val.errorCode]}\n`;
+                        }
+                    }
+                    let tp = iserror ? "warning" : "success";
+                    if (!iserror) {
+                        mss = "控制成功";
+                    }
+                    this.$notify({
+                        title: "控制",
+                        message: mss,
+                        type: tp,
+                        position: "bottom-right",
+                        offset: 60,
+                        duration: 3000,
+                    });
+                } else {
+                    this.$notify({
+                        title: "控制出现错误",
+                        message: '控制失败,请重试',
+                        type: "warning",
+                        position: "bottom-right",
+                        offset: 60,
+                        duration: 3000,
+                    });
+                }
+            },
+
+            /* 控制失败 */
+            controlError(err) {
+                this.$notify({
+                    title: "控制出现错误",
+                    message: err.message,
+                    type: "warning",
+                    position: "bottom-right",
+                    offset: 60,
+                    duration: 3000,
+                });
+            },
+            sendMessage(url1) {
+                this.messageUrl = url1
+                // let link = document.createElement('a')
+                // link.href = url1
+                // link.click()
+            }
+        },
+        watch: {
+            "$store.getters.windturbinelist": {
+                deep: true,
+                handler: function (json) {
+                    this.windturbinelist = json
+                    let arr = Object.keys(json).sort()
+                    this.stopList = []
+                    this.startList = []
+                    this.maintainList = []
+                    this.unMaintainList = []
+                    for (let id of arr) {
+                        let val = json[id];
+                        this.chooseList.forEach(item => {
+                            if (item.windturbineId === val.windturbineId) {
+                                val.active = true
+                            }
+                        })
+                        this.titleList.forEach(item => {
+                            if (item.windturbineId === val.windturbineId) {
+                                val.operateStyle = item.operateStyle
+                                if (item.operateStyle === "Start" && val.status === 2) {
+                                    this.startList.push(val)
+                                } else if (item.operateStyle === "Stop" && val.status === 4) {
+                                    if(item.reasonType === 'ElectricityRestrictions'){
+                                        val.reasonType = item.reasonType
+                                    } 
+                                    this.stopList.push(val)
+                                }
+                                else if (item.operateStyle === "Maintain" && val.status === 2) {
+                                    this.maintainList.push(val)
+                                }
+                                else if (item.operateStyle === "UnMaintain" && val.status === 6) {
+                                    this.unMaintainList.push(val)
+                                }
+                            }
+                        })
+                    }
+                    if (this.postData && (this.current === 1)) {
+                        let postList = [...this.startList, ...this.stopList]
+                        api.sendRecommend(postList).then(res => {
+                            if (res) {
+
+                            }
+                        })
+                    }
+                    this.postData = false
+                    let checkoutList = BackgroundData.getInstance().checkouts;
+                    checkoutList.forEach(item => {
+                        let starIndex = null
+                        let stopIndex = null
+                        let maintainIndex = null
+                        let unMaintainIndex = null
+                        let starFlag = false
+                        let stopFlag = false
+                        let maintainFlag = false
+                        let unMaintainFlag = false
+                        this.startList.forEach((param, index) => {
+                            if (item.windturbineId === param.windturbineId) {
+                                starIndex = index
+                                starFlag = true
+                            }
+                        })
+                        this.stopList.forEach((param, index) => {
+                            if (item.windturbineId === param.windturbineId) {
+                                stopIndex = index
+                                stopFlag = true
+                            }
+                        })
+                        this.maintainList.forEach((param, index) => {
+                            if (item.windturbineId === param.windturbineId) {
+                                maintainIndex = index
+                                maintainFlag = true
+                            }
+                        })
+                        this.unMaintainList.forEach((param, index) => {
+                            if (item.windturbineId === param.windturbineId) {
+                                unMaintainIndex = index
+                                unMaintainFlag = true
+                            }
+                        })
+                        starFlag ? this.startList.splice(starIndex, 1) : '';
+                        stopFlag ? this.stopList.splice(stopIndex, 1) : '';
+                        maintainFlag ? this.maintainList.splice(maintainIndex, 1) : '';
+                        unMaintainFlag ? this.unMaintainList.splice(unMaintainIndex, 1) : '';
+                    })
+                },
+            },
+            "$store.getters.current": {
+                handler: function (json) {
+                    this.current = json
+                    if (json === 0) {
+                        let dateList = []
+                        this.titleList.forEach(item => {
+                            if (item.windturbineId.slice(0, 2) === 'NG' || item.windturbineId.slice(0, 2) === 'MG') {
+                                let arr = Object.keys(this.windturbinelist).sort()
+                                this.windturbinelist = (arr.length !== 0) ? this.windturbinelist : this.$store.state.windturbinelist
+                                switch (item.operateStyle) {
+                                    case 'Start':
+                                        this.windturbinelist[item.windturbineId].controlType = 1
+                                        break;
+                                    case 'Stop':
+                                        this.windturbinelist[item.windturbineId].controlType = 2
+                                        break;
+                                    case 'Maintain':
+                                        this.windturbinelist[item.windturbineId].controlType = 6
+                                        break;
+                                    case 'UnMaintain':
+                                        this.windturbinelist[item.windturbineId].controlType = 8
+                                        break;
+                                }
+                                dateList.push(this.windturbinelist[item.windturbineId])
+                            }
+                        })
+                        let mss = {}
+                        mss.type = 'send'
+                        this.timer = setTimeout(() => {
+                            this.sendCommand(mss, dateList)
+                            this.showFlag = false
+                            clearInterval(this.timer);
+                        }, 3000);
+                    }
+                }
+            }
+        },
+    }
+</script>
+
+<style scoped="scoped">
+    .body {
+        border: 1px solid #373737;
+        width: 100%;
+        margin-left: 15px;
+        margin-top: 20px;
+    }
+
+    .body .scoll {
+        height: 91%;
+    }
+
+    .title {
+        color: #ffffff;
+        font-size: 14px;
+        margin-left: 32px;
+        /* margin-top: 12px; */
+        margin-bottom: 10px;
+        /* width: 570px; */
+        width: 29vw;
+        height: 50px;
+        display: flex;
+        align-items: center;
+        position: absolute;
+        background-color: #000000;
+    }
+
+    .title::before {
+        z-index: 1;
+        content: '';
+        position: absolute;
+        left: -18px !important;
+        /* top: 30px !important; */
+        width: 5px;
+        height: 5px;
+        background-color: #54B75A;
+        border-radius: 50%;
+    }
+
+    .logo {
+        position: absolute;
+        top: 12px;
+        left: 12px;
+    }
+
+    .matrix {
+        margin-left: 20px;
+        /* margin-right: 10px; */
+        padding-bottom: 20px;
+        border-bottom: 1px solid rgba(31, 31, 31, 1);
+    }
+
+    .problemTitle {
+        font-size: 12px;
+        color: #BFBFBF;
+        margin-top: 20px;
+        margin-bottom: 20px;
+        margin-left: 12px;
+    }
+
+    .send {
+        width: 86px;
+        height: 26px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background-color: rgba(84, 183, 90, 1);
+        color: #ffffff;
+        font-size: 14px;
+        position: absolute;
+        bottom: 20px;
+        right: 10px;
+    }
+
+    .success {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 250px;
+        height: 48px;
+        position: absolute;
+        bottom: 20px;
+        right: 20%;
+        border: 1px solid rgba(55, 55, 55, 1);
+        border-radius: 10px;
+        color: #ffffff;
+        font-size: 14px;
+    }
+</style>

+ 867 - 0
src/components/control/controlAllArea.vue

@@ -0,0 +1,867 @@
+<template>
+  <div class="problem" @contextmenu="contextmenu">
+    <div class="body">
+      <img class="logo" src="../../assets/img/logo.png" alt="" />
+      <div class="titleBar">
+        <div class="title">设备区</div>
+        <el-select
+          @change="listedChange()"
+          class="inputs"
+          v-model="selectValue"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in options"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div style="margin-top: 20px; margin-left: 35px; height: 85%">
+        <el-scrollbar>
+          <div class="scoll">
+            <div class="matrix" v-if="showList.length > 0">
+              <!-- <div class="problemTitle">待启动</div> -->
+              <MatrixBlock
+                @choose-click="handleClick"
+                @on-click="handleDetails"
+                :dataList="showList"
+              >
+              </MatrixBlock>
+            </div>
+          </div>
+        </el-scrollbar>
+      </div>
+    </div>
+    <WindturbineDetailPages
+      v-model="dialogVisible"
+      :showSvg="showSvg"
+      @close="handleClose"
+      :svgWeb="svgWeb"
+      :windturbine="currentWindturbine"
+    ></WindturbineDetailPages>
+  </div>
+</template>
+
+<script>
+import WindturbineDetailPages from "../WindturbineDetailPages.vue";
+import MatrixBlock from "../matrixBlock.vue";
+import BackgroundData from "utils/BackgroundData";
+import MessageBridge from "utils/MessageBridge";
+import api from "api/index";
+export default {
+  name: "ProblemArea",
+  components: {
+    WindturbineDetailPages,
+    MatrixBlock,
+  },
+  props: {
+    current: {
+      type: Number,
+    },
+    datas: {
+      type: String,
+    },
+  },
+  data() {
+    return {
+      dataList: [],
+      showList: [],
+      chooseList: [],
+      lockValues: [],
+      currentWindturbine: {},
+      dialogVisible: false,
+      showSvg: false,
+      svgWeb: "",
+      windturbinelist: {},
+      options: [
+        {
+          value: "0",
+          label: "问题设备",
+        },
+        {
+          value: "1",
+          label: "故障",
+        },
+        {
+          value: "2",
+          label: "维护",
+        },
+        {
+          value: "3",
+          label: "离线",
+        },
+        {
+          value: "4",
+          label: "挂牌",
+        },
+        {
+          value: "5",
+          label: "麻黄山",
+        },
+        {
+          value: "6",
+          label: "牛首山",
+        },
+        {
+          value: "7",
+          label: "青山",
+        },
+        {
+          value: "8",
+          label: "石板泉",
+        },
+        {
+          value: "9",
+          label: "香山",
+        },
+      ],
+      selectValue: "0",
+      controlErorCodes: [
+        "控制成功",
+        "控制命令发送失败",
+        "无效的控制地址",
+        "被控设备异常",
+        "无效的控制功能",
+        "网络连接错误,检查场站通信",
+        "控制结果读取超时",
+        "未知错误",
+        "控制命令错误",
+        "收到无法识别数据",
+        "未读取到数据包",
+        "未知错误",
+        "风机操作过频繁",
+        "风机被挂牌",
+        "风机操作与风机状态不符",
+        "需要登录",
+      ],
+    };
+  },
+  computed: {},
+  created: function () {
+    this.initData();
+    this.controls();
+    this.getLocks();
+  },
+  methods: {
+    controls() {
+      let json = this.$store.state.windturbinelist;
+      this.dataList = [];
+      this.showList = [];
+      let arr = Object.keys(json).sort();
+      for (let id of arr) {
+        let val = json[id];
+        this.chooseList.forEach((item) => {
+          if (item.windturbineId === val.windturbineId) {
+            val.active = true;
+          }
+        });
+        this.dataList.push(val);
+        switch (Number(this.selectValue)) {
+          case 0:
+            if (
+              val.status === 5 ||
+              val.status === 6 ||
+              val.status === 7 ||
+              val.lockValue > 0
+            ) {
+              this.showList.push(val);
+            }
+            break;
+          case 1:
+            val.status === 5 ? this.showList.push(val) : "";
+            break;
+          case 2:
+            val.status === 6 ? this.showList.push(val) : "";
+            break;
+          case 3:
+            val.status === 7 ? this.showList.push(val) : "";
+            break;
+          case 4:
+            val.lockValue > 0 ? this.showList.push(val) : "";
+            break;
+          case 5:
+            val.windturbineId.substring(0, 2) === "MG"
+              ? this.showList.push(val)
+              : "";
+            break;
+          case 6:
+            val.windturbineId.substring(0, 2) === "NG"
+              ? this.showList.push(val)
+              : "";
+            break;
+          case 7:
+            val.windturbineId.substring(0, 2) === "QG"
+              ? this.showList.push(val)
+              : "";
+            break;
+          case 8:
+            val.windturbineId.substring(0, 2) === "SG"
+              ? this.showList.push(val)
+              : "";
+            break;
+          case 9:
+            val.windturbineId.substring(0, 2) === "XG"
+              ? this.showList.push(val)
+              : "";
+            break;
+        }
+      }
+      let checkoutList = BackgroundData.getInstance().checkouts;
+      checkoutList.forEach((item) => {
+        let showIndex = null;
+        this.showList.forEach((param, index) => {
+          if (item.windturbineId === param.windturbineId) {
+            showIndex = index;
+          }
+        });
+        this.showList.splice(showIndex, 1);
+      });
+    },
+    getLocks() {
+      api.getCustomerLock().then((res) => {
+        if (res) {
+          this.lockValues = res.data;
+        }
+      });
+    },
+    initData: function () {
+      let mb = MessageBridge.getInstance();
+      let vss = [
+        { key: "/topic/voice-control", action: this.windturbineMessage },
+      ];
+      mb.register(vss);
+    },
+    windturbineMessage(msg) {
+      if (this.$store.state.current === 2) {
+        let arr = [];
+        if (msg === "CLOSE") {
+          arr.push(msg);
+        } else {
+          arr = msg.split("-");
+        }
+        this.dialogVisible = false;
+        this.showSvg = false;
+        this.svgWeb = "";
+        if (arr[0] === "OPEN_FJ") {
+          this.currentWindturbine = this.windturbinelist[arr[1]];
+          this.dialogVisible = true;
+        } else if (arr[0] === "CLOSE") {
+          this.dialogVisible = false;
+        } else if (arr[0] === "OPEN_SYZ") {
+          this.showSvg = true;
+          this.dialogVisible = true;
+          this.svgWeb = arr[1];
+        } else if (
+          arr[0] === "CONTROL_START" ||
+          arr[0] === "CONTROL_STOP" ||
+          arr[0] === "CONTROL_MAINTAIN"
+        ) {
+          let windControlList = [];
+          let mss = {};
+          arr.forEach((item) => {
+            if (
+              item ===
+              (this.windturbinelist[item]
+                ? this.windturbinelist[item].windturbineId
+                : "")
+            ) {
+              switch (arr[0]) {
+                case "CONTROL_START":
+                  this.windturbinelist[item].controlType = "1";
+                  break;
+                case "CONTROL_STOP":
+                  this.windturbinelist[item].controlType = "2";
+                  break;
+                case "CONTROL_MAINTAIN":
+                  this.windturbinelist[item].controlType = "6";
+                  break;
+                case "CONTROL_UNMAINTAIN":
+                  this.windturbinelist[item].controlType = "8";
+                  break;
+              }
+              windControlList.push(this.windturbinelist[item]);
+            }
+          });
+          mss.type = "send";
+          this.sendCommand(mss, windControlList);
+        } else if (
+          arr[0] === "CONTROL_LOCK_OVERHAUL" ||
+          arr[0] === "CONTROL_LOCK_MAINTAIN" ||
+          arr[0] === "CONTROL_LOCK_LNVOLVED_OVERHAUL" ||
+          arr[0] === "CONTROL_LOCK_LNVOLVED_MAINTAIN" ||
+          arr[0] === "CONTROL_LOCK_LNVOLVED_PG" ||
+          arr[0] === "CONTROL_LOCK_LNVOLVED_WEATHER" ||
+          arr[0] === "CONTROL_UNLOCK"
+        ) {
+          let windturbine = this.windturbinelist[arr[1]];
+          switch (arr[0]) {
+            case "CONTROL_LOCK_OVERHAUL":
+              this.sendLock({ value: "CheckLock" }, windturbine);
+              break;
+            case "CONTROL_LOCK_MAINTAIN":
+              this.sendLock({ value: "FaultLock" }, windturbine);
+              break;
+            case "CONTROL_LOCK_LNVOLVED_OVERHAUL":
+              this.sendLock({ value: "StationCheckLock" }, windturbine);
+              break;
+            case "CONTROL_LOCK_LNVOLVED_MAINTAIN":
+              this.sendLock({ value: "StationFaulLock" }, windturbine);
+              break;
+            case "CONTROL_LOCK_LNVOLVED_PG":
+              this.sendLock({ value: "StationPowerLineLock" }, windturbine);
+              break;
+            case "CONTROL_LOCK_LNVOLVED_WEATHER":
+              this.sendLock({ value: "StationWeatherLock" }, windturbine);
+              break;
+            case "CONTROL_UNLOCK":
+              this.sendLock({ value: "UnLock" }, windturbine);
+              break;
+          }
+        }
+      }
+    },
+    /* 右键菜单 */
+    contextmenu() {
+      const remote = require("electron").remote;
+      let that = this;
+      let menuTemplate = [];
+      if (
+        this.selectValue === "0" ||
+        this.selectValue === "1" ||
+        this.selectValue === "2" ||
+        this.selectValue === "3" ||
+        this.selectValue === "4"
+      ) {
+        menuTemplate = [
+          // {
+          //     label: "标注",
+          //     click() {
+          //         that.sendLock({ type: "marking" });
+          //     },
+          // },
+          {
+            label: "挂牌",
+            submenu: [
+              {
+                label: "检修",
+                click() {
+                  that.sendLock({ value: "CheckLock" });
+                },
+              },
+              {
+                label: "故障维修",
+                click() {
+                  that.sendLock({ value: "FaultLock" });
+                },
+              },
+              {
+                label: "场内受累检修",
+                click() {
+                  that.sendLock({ value: "StationCheckLock" });
+                },
+              },
+              {
+                label: "场内受累故障",
+                click() {
+                  that.sendLock({ value: "StationFaulLock" });
+                },
+              },
+              {
+                label: "场外受累电网",
+                click() {
+                  that.sendLock({ value: "StationPowerLineLock" });
+                },
+              },
+              {
+                label: "场外受累天气",
+                click() {
+                  that.sendLock({ value: "StationWeatherLock" });
+                },
+              },
+            ],
+          },
+          {
+            label: "取消挂牌",
+            click() {
+              that.sendLock({ value: "UnLock" });
+            },
+          },
+        ];
+      } else {
+        menuTemplate = [
+          {
+            label: "启动",
+            click() {
+              that.sendCommand({ controlType: "1" });
+            },
+          },
+          {
+            label: "停机",
+            click() {
+              that.sendCommand({ controlType: "2" });
+            },
+          },
+          {
+            label: "复位",
+            click() {
+              that.sendCommand({ controlType: "5" });
+            },
+          },
+          {
+            label: "维护",
+            click() {
+              that.sendCommand({ controlType: "6" });
+            },
+          },
+          {
+            label: "取消维护",
+            click() {
+              that.sendCommand({ controlType: "8" });
+            },
+          },
+          {
+            label: "挂牌",
+            submenu: [
+              {
+                label: "检修",
+                click() {
+                  that.sendLock({ value: "CheckLock" });
+                },
+              },
+              {
+                label: "故障维修",
+                click() {
+                  that.sendLock({ value: "FaultLock" });
+                },
+              },
+              {
+                label: "场内受累检修",
+                click() {
+                  that.sendLock({ value: "StationCheckLock" });
+                },
+              },
+              {
+                label: "场内受累故障",
+                click() {
+                  that.sendLock({ value: "StationFaulLock" });
+                },
+              },
+              {
+                label: "场外受累电网",
+                click() {
+                  that.sendLock({ value: "StationPowerLineLock" });
+                },
+              },
+              {
+                label: "场外受累天气",
+                click() {
+                  that.sendLock({ value: "StationWeatherLock" });
+                },
+              },
+            ],
+          },
+          {
+            label: "取消挂牌",
+            click() {
+              that.sendLock({ value: "UnLock" });
+            },
+          },
+          // {
+          //     label: "标注",
+          //     click() {
+          //         that.sendLock({ type: "marking" });
+          //     },
+          // },
+        ];
+      }
+
+      const menu = remote.Menu.buildFromTemplate(menuTemplate);
+
+      menu.popup(remote.getCurrentWindow());
+    },
+
+    sendCommand(msg, windturbine) {
+      let bd = BackgroundData.getInstance();
+      if (!bd.LoginUser) {
+        this.$notify({
+          title: "请登录",
+          message: "控制风机需要先登录!",
+          type: "warning",
+          position: "bottom-right",
+          offset: 60,
+          duration: 3000,
+        });
+        return;
+      }
+      let sendList = [];
+      if (windturbine) {
+        sendList = windturbine;
+      } else {
+        this.chooseList.forEach((item) => {
+          item.controlType = Number(msg.controlType);
+        });
+        sendList = this.chooseList;
+      }
+
+      if (sendList.length > 0) {
+        bd.checkout(sendList);
+        this.chooseList = [];
+        let pairs = {};
+        sendList.forEach((item) => {
+          let ct = {
+            windturbineId: item.windturbineId,
+            stationId: item.stationId,
+            projectId: item.projectId,
+            modelId: item.modelId,
+            controlType: item.controlType,
+            lockType: item.lockType,
+            userName: `system_${bd.LoginUser.name}`,
+            userId: 0,
+          };
+          pairs[ct.windturbineId] = ct;
+        });
+        api.windturbControl(pairs).then((res) => {
+          if (res) {
+            this.controlSuccess(res);
+          }
+        });
+      }
+    },
+    sendLock(msg, windturbine) {
+      let bd = BackgroundData.getInstance();
+      if (!bd.LoginUser) {
+        this.$notify({
+          title: "请登录",
+          message: "控制风机需要先登录!",
+          type: "warning",
+          position: "bottom-right",
+          offset: 60,
+          duration: 3000,
+        });
+        return;
+      }
+      let sendList = [];
+      if (windturbine) {
+        windturbine.lockType = msg.value;
+        sendList.push(windturbine);
+      } else {
+        this.chooseList.forEach((item) => {
+          item.lockType = msg.value;
+        });
+        sendList = this.chooseList;
+      }
+      if (sendList.length > 0) {
+        this.chooseList = [];
+        let pairs = {};
+        sendList.forEach((item) => {
+          let ct = {
+            windturbineId: item.windturbineId,
+            stationId: item.stationId,
+            projectId: item.projectId,
+            modelId: item.modelId,
+            controlType: item.controlType,
+            lockType: item.lockType,
+            userName: `system_${bd.LoginUser.name}`,
+            userId: 0,
+          };
+          pairs[ct.windturbineId] = ct;
+        });
+        api.windturbControlLock(pairs).then((res) => {
+          if (res) {
+            this.controlSuccess(res);
+          }
+        });
+      }
+    },
+
+    /* 清除所有选择 */
+    clearSelected() {
+      this.chooseList = [];
+    },
+    /* 控制成功 */
+    controlSuccess(msg) {
+      let bd = BackgroundData.getInstance();
+      for (let id in msg.data) {
+        let val = msg.data[id];
+        if (val.errorCode !== "0") {
+          bd.removeCheckouts(val);
+        }
+      }
+      let mss = ""; // 信息
+      let iserror = false; // 是否有控制错误的风机
+      for (let v in msg.data) {
+        let val = msg.data[v];
+        if (val.errorCode > 0) {
+          iserror = true;
+          mss += `${val.windturbineId}  ${
+            this.controlErorCodes[val.errorCode]
+          }\n`;
+        }
+      }
+      let tp = iserror ? "warning" : "success";
+      if (!iserror) {
+        mss = "控制成功";
+      }
+
+      this.$notify({
+        title: "控制",
+        message: mss,
+        type: tp,
+        position: "bottom-right",
+        offset: 60,
+        duration: 3000,
+      });
+    },
+
+    /* 控制失败 */
+    controlError(err) {
+      this.$notify({
+        title: "控制出现错误",
+        message: err.message,
+        type: "warning",
+        position: "bottom-right",
+        offset: 60,
+        duration: 3000,
+      });
+    },
+    handleClick(values) {
+      if (values.active) {
+        let showIndex = null;
+        this.chooseList.forEach((item, index) => {
+          if (item.windturbineId === values.windturbineId) {
+            showIndex = index;
+          }
+        });
+        this.chooseList.splice(showIndex, 1);
+      } else {
+        this.chooseList.push(values);
+      }
+      this.showList.forEach((item) => {
+        if (item.windturbineId === values.windturbineId) {
+          item.active = !item.active;
+        }
+      });
+    },
+    listedChange() {
+      this.chooseList = [];
+      this.showList = [];
+      this.dataList.forEach((val) => {
+        val.active = false;
+        switch (Number(this.selectValue)) {
+          case 0:
+            if (
+              val.status === 5 ||
+              val.status === 6 ||
+              val.status === 7 ||
+              val.lockValue > 0
+            ) {
+              this.showList.push(val);
+            }
+            break;
+          case 1:
+            val.status === 5 ? this.showList.push(val) : "";
+            break;
+          case 2:
+            val.status === 6 ? this.showList.push(val) : "";
+            break;
+          case 3:
+            val.status === 7 ? this.showList.push(val) : "";
+            break;
+          case 4:
+            val.lockValue > 0 ? this.showList.push(val) : "";
+            break;
+          case 5:
+            val.windturbineId.substring(0, 2) === "MG"
+              ? this.showList.push(val)
+              : "";
+            break;
+          case 6:
+            val.windturbineId.substring(0, 2) === "NG"
+              ? this.showList.push(val)
+              : "";
+            break;
+          case 7:
+            val.windturbineId.substring(0, 2) === "QG"
+              ? this.showList.push(val)
+              : "";
+            break;
+          case 8:
+            val.windturbineId.substring(0, 2) === "SG"
+              ? this.showList.push(val)
+              : "";
+            break;
+          case 9:
+            val.windturbineId.substring(0, 2) === "XG"
+              ? this.showList.push(val)
+              : "";
+            break;
+        }
+      });
+    },
+    handleDetails(itm) {
+      this.dialogVisible = true;
+      this.currentWindturbine = itm;
+    },
+    handleClose() {
+      this.dialogVisible = false;
+      this.showSvg = false;
+      this.getLocks();
+    },
+  },
+  watch: {
+    "$store.getters.windturbinelist": {
+      deep: true,
+      handler: function (json) {
+        this.windturbinelist = json;
+        this.dataList = [];
+        this.showList = [];
+        let arr = Object.keys(json).sort();
+        for (let id of arr) {
+          let val = json[id];
+          this.chooseList.forEach((item) => {
+            if (item.windturbineId === val.windturbineId) {
+              val.active = true;
+            }
+          });
+          if (val.lockValue === 9) {
+            val.lockValues = this.lockValues.filter(
+              (item) => val.windturbineId === item.windturbineID
+            )[0]?.value;
+          }
+          this.dataList.push(val);
+          switch (Number(this.selectValue)) {
+            case 0:
+              if (
+                val.status === 5 ||
+                val.status === 6 ||
+                val.status === 7 ||
+                val.lockValue > 0
+              ) {
+                this.showList.push(val);
+              }
+              break;
+            case 1:
+              val.status === 5 ? this.showList.push(val) : "";
+              break;
+            case 2:
+              val.status === 6 ? this.showList.push(val) : "";
+              break;
+            case 3:
+              val.status === 7 ? this.showList.push(val) : "";
+              break;
+            case 4:
+              val.lockValue > 0 ? this.showList.push(val) : "";
+              break;
+            case 5:
+              val.windturbineId.substring(0, 2) === "MG"
+                ? this.showList.push(val)
+                : "";
+              break;
+            case 6:
+              val.windturbineId.substring(0, 2) === "NG"
+                ? this.showList.push(val)
+                : "";
+              break;
+            case 7:
+              val.windturbineId.substring(0, 2) === "QG"
+                ? this.showList.push(val)
+                : "";
+              break;
+            case 8:
+              val.windturbineId.substring(0, 2) === "SG"
+                ? this.showList.push(val)
+                : "";
+              break;
+            case 9:
+              val.windturbineId.substring(0, 2) === "XG"
+                ? this.showList.push(val)
+                : "";
+              break;
+          }
+        }
+        let checkoutList = BackgroundData.getInstance().checkouts;
+        checkoutList.forEach((item) => {
+          let showIndex = null;
+          this.showList.forEach((param, index) => {
+            if (item.windturbineId === param.windturbineId) {
+              showIndex = index;
+            }
+          });
+          this.showList.splice(showIndex, 1);
+        });
+      },
+    },
+  },
+};
+</script>
+<style scoped>
+.problem {
+  height: 100%;
+}
+
+.body {
+  border: 1px solid #373737;
+  width: 100%;
+  margin-left: 15px;
+  margin-top: 10px;
+  height: 61vh;
+}
+
+.body .scoll {
+  height: 91%;
+}
+
+.titleBar {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+
+.title {
+  color: #ffffff;
+  font-size: 14px;
+  margin-left: 32px;
+  /* margin-top: 12px; */
+  margin-bottom: 10px;
+  /* width: 570px; */
+  width: 29vw;
+  height: 50px;
+  display: flex;
+  align-items: center;
+  position: absolute;
+  background-color: #000000;
+}
+
+.title::before {
+  z-index: 1;
+  content: "";
+  position: absolute;
+  left: -18px !important;
+  /* top: 30px !important; */
+  width: 5px;
+  height: 5px;
+  background-color: #54b75a;
+  border-radius: 50%;
+}
+
+.inputs {
+  border: none;
+  width: 174px !important;
+  margin-left: 110px;
+}
+
+.el-input__inner {
+  background-color: rgb(100, 100, 100) !important;
+  color: rgb(220, 220, 220) !important;
+  border: 1px solid red !important;
+}
+
+.logo {
+  position: absolute;
+  top: 2px;
+  left: 12px;
+}
+</style>

+ 45 - 0
src/components/control/controlArea.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="problem">
+    <AreaCard title="控制区" height="60" :current="current" ref="areaCard"></AreaCard>
+  </div>
+</template>
+
+<script>
+  import AreaCard from "./areaCard.vue";
+  import BackgroundData from 'utils/BackgroundData'
+  export default {
+    name: "ProblemArea",
+    components: {
+      AreaCard,
+    },
+    props: {
+      current: {
+        type: Number,
+      },
+    },
+    data() {
+      return {
+        ls: {
+          maintain: { key: "维护", value: [] },
+          malfunction: { key: "故障", value: [] },
+          offline: { key: "离线", value: [] },
+          lockd: { key: "挂牌", value: [] },
+        },
+      };
+    },
+    computed: {},
+    created: function () {
+      console.log(this.current);
+    },
+    methods: {
+      control(current){
+        this.$refs.areaCard.control(current)
+      }
+    }
+  };
+</script>
+<style scoped>
+  .problem {
+    height: 100%;
+  }
+</style>

Diferenças do arquivo suprimidas por serem muito extensas
+ 145 - 0
src/components/dataDetails.vue


+ 264 - 0
src/components/focus/PhotoelectricDetailPages.vue

@@ -0,0 +1,264 @@
+<template>
+	<el-dialog width="55%" @closed="closed()" :show-close="false" class="my-info-dialog">
+		<template #title>
+			<div class="showTitle">
+				<img class="titleImg" src="../../assets/img/controlcenter/daraTrue.png" alt="">
+				<div class="titles">{{stationName}}</div>
+				<!-- <div class="icon">(麻黄山)</div> -->
+			</div>
+		</template>
+		<div class="body">
+			<div class="dataList">
+				<div class="data">
+					<div class="name">{{data.PowerSet.name}}:</div>
+					<div class="num">{{data.PowerSet?.value}}</div>
+					<div class="unit">MW</div>
+				</div>
+				<div class="data">
+					<div class="name">{{data.TheoryPower.name}}:</div>
+					<div class="num">{{data.TheoryPower?.value}}</div>
+					<div class="unit">MW</div>
+				</div>
+				<div class="data">
+					<div class="name">{{data.AgcLower.name}}:</div>
+					<div class="num">{{data.AgcLower?.value}}</div>
+					<div class="unit">MW</div>
+				</div>
+				<div class="data">
+					<div class="name">{{data.ActualPower.name}}:</div>
+					<div class="num">{{data.ActualPower?.value}}</div>
+					<div class="unit">MW</div>
+				</div>
+				<div class="data">
+					<div class="name">{{data.AgcUp.name}}:</div>
+					<div class="num">{{data.AgcUp?.value}}</div>
+					<div class="unit">MW</div>
+				</div>
+				<div class="data">
+					<div class="name">{{data.ForecastPower.name}}:</div>
+					<div class="num">{{data.ForecastPower?.value}}</div>
+					<div class="unit">MW</div>
+				</div>
+			</div>
+			<div class="condition">
+				<div class="status">
+					<div class="name">{{data.AgcIn.name}}:</div>
+					<img v-if="data.AgcIn.value === 0" class="statusIcon"
+						src="../../assets/img/controlcenter/daraTrue.png">
+					<img v-else-if="data.AgcIn.value === 1" class="statusIcon"
+						src="../../assets/img/controlcenter/dataFalse.png">
+					<div v-else-if="data.AgcIn.value === ''">
+						暂无数据
+					</div>
+				</div>
+				<div class="status">
+					<div class="name">{{data.AgcFar.name}}:</div>
+					<img v-if="data.AgcFar.value === 0" class="statusIcon"
+						src="../../assets/img/controlcenter/daraTrue.png">
+					<img v-else-if="data.AgcFar.value === 1" class="statusIcon"
+						src="../../assets/img/controlcenter/dataFalse.png">
+					<div v-else-if="data.AgcFar.value === ''">
+						暂无数据
+					</div>
+				</div>
+				<div class="status">
+					<div class="name">{{data.SumLock.name}}:</div>
+					<img v-if="data.SumLock.value === 0" class="statusIcon"
+						src="../../assets/img/controlcenter/daraTrue.png">
+					<img v-else-if="data.SumLock.value === 1" class="statusIcon"
+						src="../../assets/img/controlcenter/dataFalse.png">
+					<div v-else-if="data.SumLock.value === ''">
+						暂无数据
+					</div>
+				</div>
+				<div class="status">
+					<div class="name">{{data.SubLock.name}}:</div>
+					<img v-if="data.SubLock.value === 0" class="statusIcon"
+						src="../../assets/img/controlcenter/daraTrue.png">
+					<img v-else-if="data.SubLock.value === 1" class="statusIcon"
+						src="../../assets/img/controlcenter/dataFalse.png">
+					<div v-else-if="data.SubLock.value === ''">
+						暂无数据
+					</div>
+				</div>
+			</div>
+			<!-- <button @click='ChangeColors()'>测试按钮</button> -->
+			<!-- <div id="main" class="echartsBox"></div> -->
+			<MultipleLineChart ref="multipleLineChart" height="400px" :units="powerLineChartData.units" :list="powerLineChartData.value"
+				 :showLegend="true" />
+		</div>
+	</el-dialog>
+</template>
+
+<script>
+	// import UniformCodes from "../../assets/script/UniformCodes";
+	// import { config } from '../../config';
+	// import axios from 'axios';
+	// import BackgroundData from "../../assets/script/BackgroundData"
+	import MultipleLineChart from "./multiple-line-chart.vue";
+	import dayjs from 'dayjs'
+	export default {
+		components: {
+			MultipleLineChart
+		},
+		props: {
+			stationName: {
+				type: String,
+				default: ''
+			},
+			data: {
+				type: Array
+			},
+		},
+		data() {
+			return {
+				chartData: {
+					units: [""],
+					value: [],
+				},
+				colors: ["rgba(75, 85, 174, 1)", "rgba(05, 187, 76, 1)"],
+				timeData: [],
+				PowerSet: [],
+				ActualPower: [],
+				index: 0,
+				powerLineChartData: {},
+			};
+		},
+		methods: {
+			closed() {
+				//勿删,传递关闭方法
+			},
+			ChangeColors() {
+				this.colors = ["#aa2116", "#fcaf17"]
+			},
+			initData(PowerSet, ActualPower) {
+				// this.chartData.units = ["(MW)", "(MW)"];
+				this.chartData.value[0] = {
+					title: "有功设定限值(MW)",
+					yAxisIndex: 0,
+					value: []
+				};
+				this.chartData.value[1] = {
+					title: "实发有功(MW)",
+					yAxisIndex: 0,
+					value: []
+				}
+				PowerSet.forEach(item => {
+					this.chartData.value[0].value.push({
+						text: dayjs(item.ts).format('hh:mm'),
+						value: parseFloat((item.doubleValue).toFixed(2))
+					})
+				})
+				ActualPower.forEach(item => {
+					this.chartData.value[1].value.push({
+						text: dayjs(item.ts).format('hh:mm'),
+						value: parseFloat((item.doubleValue).toFixed(2))
+					})
+				})
+				this.powerLineChartData = this.chartData;
+				this.$refs.multipleLineChart.initChart(this.chartData)
+			}
+		},
+	};
+</script>
+<style scoped>
+	.echartsBox {
+		width: 64rem;
+		height: 220px;
+		overflow: hidden;
+	}
+
+	.el-dialog__header {
+		background-color: #000000;
+	}
+
+	.showTitle {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		margin-top: -10px;
+		font-size: 18px;
+		color: #FFFFFF;
+	}
+
+	.titleImg {
+		width: 16px;
+		height: 16px;
+		margin-right: 13px;
+	}
+
+	.icon {
+		font-size: 12px;
+		margin-left: 10px;
+		margin-top: 5px;
+	}
+
+	.body {
+		background-color: black;
+		width: 100%;
+		margin-top: -30px;
+		/* height: 200px; */
+	}
+
+	.dataList {
+		display: flex;
+		flex-direction: row;
+		flex-wrap: wrap;
+		align-items: center;
+		padding-top: 27px;
+	}
+
+	.data {
+		width: 50%;
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		margin-bottom: 22px;
+	}
+
+	.name {
+		width: 40%;
+		display: flex;
+		flex-direction: row-reverse;
+		font-size: 12px;
+		color: #FFFFFF;
+	}
+
+	.num {
+		margin-left: 59px;
+		font-size: 16px;
+		color: #05BB4C;
+		min-width: 40px;
+	}
+
+	.unit {
+		font-size: 16px;
+		color: #FFFFFF;
+		margin-left: 20px;
+	}
+
+	.condition {
+		width: 100%;
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		margin-bottom: 20px;
+		border-bottom: 1px solid #3D3D3D;
+		padding-bottom: 10px;
+	}
+
+	.status {
+		width: 25%;
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.statusIcon {
+		width: 14px;
+		height: 14px;
+		margin-left: 8px;
+	}
+</style>

+ 220 - 0
src/components/focus/agcDetails.vue

@@ -0,0 +1,220 @@
+<template>
+    <el-dialog width="90%" @open="opened()" @closed="closed()" :fullscreen="true" :show-close="true" class="dialogs">
+        <template #title>
+            <div class="showTitles">
+                <div class="titles">AGC监控</div>
+            </div>
+        </template>
+        <div class="bodyy">
+            <DataDetails ref="detailst" :allDate="allDate" :allChartDate="allChartDate" :station="station"
+                @handleClick="handleClicks"></DataDetails>
+            <DetailsCharts v-model="detailsDisplay" :showData="showData" @closeds="closeds"></DetailsCharts>
+        </div>
+    </el-dialog>
+</template>
+<script>
+    import DataDetails from './dataDetails'
+    import DetailsCharts from './detailsCharts'
+    import { Photoelectric } from "utils/PhotoelectricDetailPages";
+    import api from "api/index";
+    export default {
+        components: {
+            DataDetails,
+            DetailsCharts
+        },
+        data() {
+            return {
+                station: [
+                    {
+                        id: 'MHS_BT',
+                        name: '麻黄山第二风电场',
+                        names: '麻黄山',
+                    },
+
+                    {
+                        id: 'NSS_BT',
+                        name: '牛首山第二风电场',
+                        names: '牛首山',
+                    },
+                    {
+                        id: 'QS_BT',
+                        name: '麻黄山第六风电场',
+                        names: '青山',
+                    },
+                    {
+                        id: 'XN6_BT',
+                        name: '星能第六风电场',
+                        names: '石板泉一期',
+                    },
+                    {
+                        id: 'N5_BT',
+                        name: '牛首山第五风电场',
+                        names: '二三四期',
+                    },
+                    {
+                        id: 'XS_BT',
+                        name: '香山第五风电场',
+                        names: '香山',
+                    },
+                    {
+                        id: 'SL_BT',
+                        name: '宋堡第六风电场',
+                        names: '青山三期',
+                    },
+                ],
+                allDate: {},
+                allChartDate: [],
+                detailsDisplay: false,
+                showData: {},
+            };
+        },
+        mounted() {
+
+        },
+        updated() {
+            this.getLatest(0)
+            this.getChartData(0)
+        },
+        methods: {
+            getLatest(index) {
+                let dialogData = {}
+                let thisKey = Photoelectric[this.station[index].id];
+                let array = []
+                thisKey.forEach(item => { item.value ? array.push(item.value) : '' })
+                let params = array.join(',')
+                api.getLatest(params).then(res => {
+                    for (let v in res.data) {
+                        thisKey.forEach(item => {
+                            let calc = item.calc ? item.calc : 1;
+                            if (item.value === v) {
+                                dialogData[item.tag] = {
+                                    name: item.name,
+                                    value: res.data[v].doubleValue ? res.data[v].doubleValue === 0 ? '0' : (res.data[v].doubleValue * calc).toFixed(2) : (res.data[v].booleanValue ? 1 : 0)
+                                }
+                            }
+                        })
+                    }
+                    this.allDate[this.station[index].id] = dialogData
+                    this.allDate[this.station[index].id].InstalledCapacity = Photoelectric[this.station[index].id].find(ele => {
+                        return ele.tag == 'InstalledCapacity'
+                    });
+                    index++
+                    if (index >= this.station.length) {
+                        setTimeout(() => {
+                            this.getLatest(0)
+                        }, 3000);
+                    } else {
+                        this.getLatest(index)
+                    }
+                })
+            },
+            getChartData(index) {
+                let thisKey = Photoelectric[this.station[index].id];
+                let date = new Date()
+                let endTs = date.getTime();
+                let starTs = endTs - 28800000;
+                let chartData = {
+                    value: []
+                }
+                const PowerSet = thisKey.find(ele => {
+                    return ele.tag == 'PowerSet'
+                });
+                const ActualPower = thisKey.find(ele => {
+                    return ele.tag == 'ActualPower'
+                });
+                let PowerSetData = [],
+                    ActualPowerData = [];
+                api.getPower({
+                    tagName: PowerSet.value,
+                    startTs: starTs,
+                    endTs: endTs,
+                    interval: 60,
+                }).then(res1 => {
+                    api.getPower({
+                        tagName: ActualPower.value,
+                        startTs: starTs,
+                        endTs: endTs,
+                        interval: 60,
+                    }).then(res2 => {
+                        res1.data.forEach(item => {
+                            PowerSetData.push({
+                                ts: item.ts,
+                                doubleValue: item.doubleValue * PowerSet.calc
+                            })
+                        })
+                        res2.data.forEach(item => {
+                            ActualPowerData.push({
+                                ts: item.ts,
+                                doubleValue: item.doubleValue * ActualPower.calc
+                            })
+                        })
+                        chartData.value[0] = {
+                            title: "有功设定限值(MW)",
+                            yAxisIndex: 0,
+                            value: []
+                        };
+                        chartData.value[1] = {
+                            title: "实发有功(MW)",
+                            yAxisIndex: 0,
+                            value: []
+                        }
+                        PowerSetData.forEach(item => {
+                            chartData.value[0].value.push({
+                                text: dayjs(item.ts).format('hh:mm'),
+                                value: parseFloat((item.doubleValue).toFixed(2))
+                            })
+                        })
+                        ActualPowerData.forEach(item => {
+                            chartData.value[1].value.push({
+                                text: dayjs(item.ts).format('hh:mm'),
+                                value: parseFloat((item.doubleValue).toFixed(2))
+                            })
+                        })
+                        chartData.id = this.station[index].id
+                        this.allChartDate.push(chartData)
+                        console.log(this.allChartDate);
+                        index++
+                        if (index >= this.station.length) {
+                            this.$refs.detailst.totleErtcher()
+                            setTimeout(() => {
+                                this.allChartDate = []
+                                this.getChartData(0)
+                            }, 60000);
+                        } else {
+                            this.getChartData(index)
+                        }
+                    })
+                })
+            },
+            opened() {
+
+            },
+            closed() {
+
+            },
+            handleClicks(id) {
+                this.showData = this.allChartDate.find(ele => {
+                    return ele.id == id
+                });
+                this.showData.name = this.station.find(ele => {
+                    return ele.id == id
+                });
+                this.detailsDisplay = true
+            },
+            closeds() {
+                this.detailsDisplay = false
+            },
+        },
+    }
+</script>
+
+<style scoped>
+    .bodyy {
+        display: flex;
+        flex-direction: row;
+        background-color: black;
+        width: 100%;
+        margin-top: -30px;
+        height: 91vh;
+    }
+</style>

+ 394 - 0
src/components/focus/dataDetails.vue

@@ -0,0 +1,394 @@
+<template>
+    <div class="body">
+        <div :class="index<3?'showContents':'showContents'" v-for="(item, index) in station" :key="index">
+            <div class="stationName">
+                <div class="titleName">{{item.name}}</div>
+                <div class="titleNames">({{item.names}})</div>
+                <img v-if="allDate[item.id]?.Status?.value === 0" class="statusIcons"
+                    src="../../assets/img/controlcenter/daraTrue.png">
+                <img v-else class="statusIcons"
+                    src="../../assets/img/controlcenter/dataFalse.png">
+                <div class="titleNames" v-if="allDate[item.id]?.Status?.value !== 0">
+                    {{((1-this.allDate[item.id]?.PowerSet?.value/this.allDate[item.id]?.InstalledCapacity?.value)*100).toFixed(2)}}%
+                </div>
+            </div>
+            <div class="dataList">
+                <div class="data">
+                    <div class="name">有功设定限值:</div>
+                    <div :class="index<3?'nums':'nums'">{{allDate[item.id]?.PowerSet?.value??0}}</div>
+                    <div class="unit">MW</div>
+                </div>
+                <div class="data">
+                    <div class="name">实发有功:</div>
+                    <div :class="index<3?'nums':'nums'">{{allDate[item.id]?.ActualPower?.value??0}}</div>
+                    <div class="unit">MW</div>
+                </div>
+                <div class="data">
+                    <div class="name">AGC可调上限:</div>
+                    <div :class="index<3?'nums':'nums'">{{allDate[item.id]?.AgcUp?.value??0}}</div>
+                    <div class="unit">MW</div>
+                </div>
+                <div class="data">
+                    <div class="name">理论功率:</div>
+                    <div :class="index<3?'nums':'nums'">{{allDate[item.id]?.TheoryPower?.value??0}}</div>
+                    <div class="unit">MW</div>
+                </div>
+                <div class="data">
+                    <div class="name">AGC可调下限:</div>
+                    <div :class="index<3?'nums':'nums'">{{allDate[item.id]?.AgcLower?.value??0}}</div>
+                    <div class="unit">MW</div>
+                </div>
+
+                <div class="data">
+                    <div class="name">预测功率:</div>
+                    <div :class="index<3?'nums':'nums'">{{allDate[item.id]?.ForecastPower?.value??0}}</div>
+                    <div class="unit">MW</div>
+                </div>
+            </div>
+            <div class="condition">
+                <div class="status">
+                    <div class="name">{{allDate[item.id]?.AgcIn?.name}}:</div>
+                    <img v-if="allDate[item.id]?.AgcIn?.value === 0" class="statusIcon"
+                        src="../../assets/img/controlcenter/daraTrue.png">
+                    <img v-else-if="allDate[item.id]?.AgcIn?.value === 1" class="statusIcon"
+                        src="../../assets/img/controlcenter/dataFalse.png">
+                    <div v-else-if="allDate[item.id]?.AgcIn?.value === ''">
+                        暂无数据
+                    </div>
+                </div>
+                <div class="status">
+                    <div class="name">{{allDate[item.id]?.AgcFar?.name}}:</div>
+                    <img v-if="allDate[item.id]?.AgcFar?.value === 0" class="statusIcon"
+                        src="../../assets/img/controlcenter/daraTrue.png">
+                    <img v-else-if="allDate[item.id]?.AgcFar?.value === 1" class="statusIcon"
+                        src="../../assets/img/controlcenter/dataFalse.png">
+                    <div v-else-if="allDate[item.id]?.AgcFar?.value === ''">
+                        暂无数据
+                    </div>
+                </div>
+                <div class="status">
+                    <div class="name">{{allDate[item.id]?.SumLock?.name}}:</div>
+                    <img v-if="allDate[item.id]?.SumLock?.value === 0" class="statusIcon"
+                        src="../../assets/img/controlcenter/daraTrue.png">
+                    <img v-else-if="allDate[item.id]?.SumLock?.value === 1" class="statusIcon"
+                        src="../../assets/img/controlcenter/dataFalse.png">
+                    <div v-else-if="allDate[item.id]?.SumLock?.value === ''">
+                        暂无数据
+                    </div>
+                </div>
+                <div class="status">
+                    <div class="name">{{allDate[item.id]?.SubLock?.name}}:</div>
+                    <img v-if="allDate[item.id]?.SubLock?.value === 0" class="statusIcon"
+                        src="../../assets/img/controlcenter/daraTrue.png">
+                    <img v-else-if="allDate[item.id]?.SubLock?.value === 1" class="statusIcon"
+                        src="../../assets/img/controlcenter/dataFalse.png">
+                    <div v-else-if="allDate[item.id]?.SubLock?.value === ''">
+                        暂无数据
+                    </div>
+                </div>
+            </div>
+            <div :id="item.id" class="echarts" @click="handleClick(item.id)"></div>
+        </div>
+        
+    </div>
+    
+</template>
+<script>
+    import * as echarts from "echarts";
+    export default {
+        data() {
+            return {
+            };
+        },
+        props: {
+            allDate: {
+                type: String,
+                default: ''
+            },
+            allChartDate: {
+                type: Array,
+                default: () => {
+                    return []
+                },
+            },
+            station: {
+                type: Array,
+                default: () => {
+                    return []
+                },
+            },
+        },
+        updated() {
+            // this.totleErtcher() 
+        },
+        mounted() {
+
+        },
+        methods: {
+            totleErtcher() {
+                console.log(this.allDate);
+                this.allChartDate.forEach(item => {
+                    let chartDom = document.getElementById(item.id);
+                    let myChart = echarts.init(chartDom, '#ffffff');
+                    let option;
+                    option = {
+                        legend: {
+                            show: true,
+                            data: item.value.map((t) => {
+                                return t.title;
+                            }),
+                            right: 56,
+                            icon: "circle",
+                            itemWidth: 6,
+                            inactiveColor: '#606769',
+                            textStyle: {
+                                color: '#B3BDC0',
+                                fontSize: 12,
+                            },
+                        },
+
+                        xAxis: [
+                            {
+                                type: "category",
+                                boundaryGap: false,
+                                axisLabel: {
+                                    // interval: 60,
+                                    showMinLabel: true,
+                                    showMaxLabel: true,
+                                    formatter: "{value}",
+                                    fontSize: 14,
+                                    textStyle: {
+                                        color: '#606769',
+                                    },
+                                },
+                                axisLine: {
+                                    show: false,
+                                },
+                                data: item.value[0].value.map(items => {
+                                    return items.text;
+                                }),
+                            },
+                        ],
+                        yAxis: {
+                            type: "value",
+                            axisLabel: {
+                                formatter: "{value}",
+                                fontSize: 14,
+                            },
+                            axisLine: {
+                                show: false,
+                            },
+                            splitLine: {
+                                show: true,
+                                lineStyle: {
+                                    color: '#606769',
+                                    type: "dashed",
+                                },
+                            },
+                        },
+                        dataZoom: [
+                            {
+                                show: false,
+                                type: 'inside',
+                                start: 0,
+                                end: 100
+                            },
+                        ],
+                        series: [{
+                            name: item.value[0].title,
+                            smooth: true,
+                            showSymbol: false,
+                            data: item.value[0].value.map(items => {
+                                return items.value;
+                            }),
+                            type: 'line',
+                            lineStyle: {
+                                normal: {
+                                    color: 'rgba(75, 85, 174, 1)',
+                                    width: 1,
+                                },
+                            },
+                        },
+                        {
+                            name: item.value[1].title,
+                            smooth: true,
+                            showSymbol: false,
+                            data: item.value[1].value.map(items => {
+                                return items.value;
+                            }),
+                            type: 'line',
+                            lineStyle: {
+                                normal: {
+                                    color: 'rgba(05, 187, 76, 1)',
+                                    width: 1,
+                                },
+                            },
+                        }]
+                    };
+                    option && myChart.setOption(option);
+                })
+
+            },
+            handleClick(id) {
+                this.$emit('handleClick', id);
+            },
+            opened() {
+
+            },
+            closed() {
+                this.detailsDisplay = false 
+            }
+        },
+    }
+</script>
+
+<style scoped>
+    .showTitles {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: center;
+        margin-top: -10px;
+        font-size: 18px;
+        color: #FFFFFF;
+    }
+
+    .showContent {
+        width: 32%;
+        display: flex;
+        flex-direction: column;
+        border: 1px solid rgba(77, 77, 77, 1);
+        /* background-color: rgba(77, 77, 77, 1); */
+        margin-right: 10px;
+        margin-left: 10px;
+        height: 44vh;
+        margin-top: 20px;
+        align-items: center;
+    }
+
+    .showContents {
+        width: 23.7%;
+        display: flex;
+        flex-direction: column;
+        border: 1px solid rgba(77, 77, 77, 1);
+        /* background-color: rgba(77, 77, 77, 1); */
+        margin-right: 10px;
+        margin-left: 10px;
+        height: 43vh;
+        margin-top: 20px;
+        align-items: center;
+    }
+
+    .stationName {
+        font-size: 20px;
+        width: 400px;
+        height: 45px;
+        border: 1px solid rgba(77, 77, 77, 1);
+        display: flex;
+        flex-direction: row;
+        align-items: baseline;
+        justify-content: center;
+        color: #FFFFFF;
+        background-color: #000000;
+        margin-top: -15px;
+    }
+
+    .titleName {
+        margin-top: 10px;
+    }
+
+    .titleNames {
+        font-size: 12px;
+        margin-left: 10px;
+        margin-top: 10px;
+    }
+
+    .body {
+        background-color: black;
+        width: 100%;
+        display: flex;
+        flex-direction: row;
+        flex-wrap: wrap;
+        justify-content: center;
+    }
+
+    .echarts {
+        width: 110%;
+        height: 290px;
+        margin-left: 10px;
+        padding-top: 20px;
+    }
+
+    .dataList {
+        display: flex;
+        flex-direction: row;
+        flex-wrap: wrap;
+        align-items: center;
+        padding-top: 27px;
+    }
+
+    .data {
+        width: 50%;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-bottom: 12px;
+        justify-content: center;
+    }
+
+    .name {
+        display: flex;
+        flex-direction: row-reverse;
+        font-size: 12px;
+        color: #FFFFFF;
+    }
+
+    .num {
+        margin-left: 59px;
+        font-size: 16px;
+        color: #05BB4C;
+        min-width: 40px;
+    }
+
+    .nums {
+        margin-left: 29px;
+        font-size: 16px;
+        color: #05BB4C;
+        min-width: 40px;
+    }
+
+    .unit {
+        font-size: 16px;
+        color: #FFFFFF;
+        margin-left: 15px;
+    }
+
+    .condition {
+        width: 100%;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-bottom: 20px;
+        border-bottom: 1px solid #3D3D3D;
+        padding-bottom: 10px;
+    }
+
+    .status {
+        width: 25%;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: center;
+    }
+
+    .statusIcon {
+        width: 14px;
+        height: 14px;
+        margin-left: 8px;
+    }
+    .statusIcons {
+        width: 14px;
+        height: 14px;
+        margin-left: 20px;
+    }
+</style>

+ 155 - 0
src/components/focus/detailsCharts.vue

@@ -0,0 +1,155 @@
+<template>
+    <el-dialog width="70%" @open="opened()" @closed="closed()" :show-close="true" class="dialogs">
+        <template #title>
+            <div class="showTitles">
+                <div class="stationName">
+                    <div class="titleName">{{showData?.name?.name}}</div>
+                    <div class="titleNames">({{showData?.name?.names}})</div>
+                </div>
+            </div>
+        </template>
+        <div class="bodyy">
+            <div id="showEcharts" class="echarts"></div>
+        </div>
+    </el-dialog>
+</template>
+<script>
+    import * as echarts from "echarts";
+    export default {
+        props: {
+            showData: {
+                type: String,
+                default: ''
+            },
+        },
+        updated() {
+            this.showEcharts(this.showData)
+        },
+        methods: {
+            showEcharts(showData) {
+                let chartDom = document.getElementById('showEcharts');
+                let myChart = echarts.init(chartDom, '#ffffff');
+                let option;
+                option = {
+					legend: {
+						show: true,
+						data: showData.value.map((t) => {
+							return t.title;
+						}),
+						right: 56,
+						icon: "circle",
+						itemWidth: 6,
+						inactiveColor: '#606769',
+						textStyle: {
+							color: '#B3BDC0',
+							fontSize: 12,
+						},
+					},
+					xAxis: [
+						{
+							type: "category",
+							boundaryGap: false,
+							axisLabel: {
+								interval: 60,
+								showMinLabel: true,
+								showMaxLabel: true,
+								formatter: "{value}",
+								fontSize: 14,
+								textStyle: {
+									color: '#606769',
+								},
+							},
+							axisLine: {
+								show: false,
+							},
+							data: showData.value[0].value.map(item => {
+								return item.text;
+							}),
+						},
+					],
+					yAxis: {
+						type: "value",
+						axisLabel: {
+							formatter: "{value}",
+							fontSize: 14,
+						},
+						axisLine: {
+							show: false,
+						},
+						splitLine: {
+							show: true,
+							lineStyle: {
+								color: '#606769',
+								type: "dashed",
+							},
+						},
+					},
+					series: [{
+						name: showData.value[0].title,
+						smooth: true,
+						showSymbol: false,
+						data: showData.value[0].value.map(item => {
+							return item.value;
+						}),
+						type: 'line',
+						lineStyle: {
+							normal: {
+								color: 'rgba(75, 85, 174, 1)',
+								width: 1,
+							},
+						},
+					},
+					{
+						name: showData.value[1].title,
+						smooth: true,
+						showSymbol: false,
+						data: showData.value[1].value.map(item => {
+							return item.value;
+						}),
+						type: 'line',
+						lineStyle: {
+							normal: {
+								color: 'rgba(05, 187, 76, 1)',
+								width: 1,
+							},
+						},
+					}]
+				};
+                option && myChart.setOption(option);
+            },
+            opened() {
+
+            },
+            closed() {
+                this.$emit('closeds');
+            },
+        },
+    }
+</script>
+<style scoped>
+    .echarts {
+        width: 1300px;
+        height: 60vh;
+    }
+
+    .stationName {
+        font-size: 20px;
+        width: 400px;
+        height: 45px;
+        display: flex;
+        flex-direction: row;
+        align-items: baseline;
+        justify-content: center;
+        color: #FFFFFF;
+    }
+
+    .titleName {
+        margin-top: 10px;
+    }
+
+    .titleNames {
+        font-size: 12px;
+        margin-left: 10px;
+        margin-top: 10px;
+    }
+</style>

+ 101 - 0
src/components/focus/focusArea.vue

@@ -0,0 +1,101 @@
+<template>
+    <div class="body">
+        <img class="logo" src="../../assets/img/logo.png" alt="">
+        <div class="title">关注区</div>
+        <div class="agc" @click="showAGC">AGC监控</div>
+        <div style="margin-top: 50px; margin-left: 10px; height: 24vh;">
+            <el-scrollbar>
+                <div class="scoll" style="margin-left: 5px;">
+                    <FocusCard></FocusCard>
+                </div>
+            </el-scrollbar>
+        </div>
+        <AGCDetails v-model="display"></AGCDetails>
+    </div>
+
+</template>
+<script>
+    import FocusCard from "./focusCard.vue";
+    import AGCDetails from "./agcDetails.vue";
+    
+    // import boxSelect from "components/boxSelect.vue";
+    export default {
+        data() {
+            return {
+                display: false,
+                
+            };
+        },
+        components: {
+            FocusCard,
+            AGCDetails
+            // boxSelect,
+        },
+        methods: {
+            showAGC() {
+                this.display = true
+            },
+            
+        },
+    }
+</script>
+<style scoped>
+    .body {
+        border: 1px solid #373737;
+        width: 100%;
+        margin-left: 15px;
+        margin-top: 10px;
+        height: 30.5vh
+    }
+
+    .body .scoll {
+        height: 91%;
+    }
+
+    .title {
+        color: #ffffff;
+        font-size: 14px;
+        margin-left: 32px;
+        /* margin-top: 12px; */
+        margin-bottom: 10px;
+        /* width: 570px; */
+        width: 29vw;
+        height: 50px;
+        display: flex;
+        align-items: center;
+        position: absolute;
+        background-color: #000000;
+    }
+
+    .title::before {
+        z-index: 1;
+        content: '';
+        position: absolute;
+        left: -18px !important;
+        /* top: 30px !important; */
+        width: 5px;
+        height: 5px;
+        background-color: rgba(230, 191, 65, 1);
+        border-radius: 50%;
+    }
+
+    .logo {
+        position: absolute;
+        top: 2px;
+        left: 12px;
+    }
+
+    .agc {
+        position: absolute;
+        color: #ffffff;
+        font-size: 14px;
+        right: 0;
+        top: 23px;
+        width: 80px;
+        height: 30px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background-color: rgba(37, 116, 219, 1);
+    }
+</style>

+ 272 - 0
src/components/focus/focusCard.vue

@@ -0,0 +1,272 @@
+/* 推荐区 */
+<template>
+	<div style="display: flex;justify-content: flex-start;flex-wrap: wrap;">
+		<div class="area" v-for="(vl , index) in values" :key="vl" @dblclick="sendMsg(vl,index)">
+			<img class="imgs" src="../../assets/img/RecommendedArea/background.png" alt="">
+			<div class="content">{{vl.showType}}</div>
+			<div class="">{{vl.name}}</div>
+			<div class="">{{vl.createTime}}</div>
+		</div>
+	</div>
+	<PhotoelectricDetailPages ref="photo" @closed="closed()" :data="dialogData.data"
+		:stationName="dialogData.stationName" v-model="dialogVisible">
+	</PhotoelectricDetailPages>
+	<WindturbineDetailPages v-model="windVisible" :windturbine="currentWindturbine" @close="close">
+	</WindturbineDetailPages>
+	<StationSvgDetailPages v-model="svgVisible" :stationName="stationNames" :svgWeb="svgWeb" @close="close">
+	</StationSvgDetailPages>
+</template>
+
+<script>
+	import BackgroundData from "utils/BackgroundData"
+	import { Photoelectric } from "utils/PhotoelectricDetailPages";
+	import PhotoelectricDetailPages from "./PhotoelectricDetailPages.vue"
+	import MessageBridge from 'utils/MessageBridge'
+	import StationSvgDetailPages from "../stationSvgDetailPages.vue";
+	import WindturbineDetailPages from "../WindturbineDetailPages.vue";
+	import api from "api/index";
+	import axios from 'axios';
+	import dayjs from 'dayjs'
+	export default {
+		name: "RecommendedArea",
+		props: ["datas"],
+		data() {
+			return {
+				values: [],
+				currentWindturbine: {},
+				dialogVisible: false,
+				svgVisible: false,
+				windVisible: false,
+				svgWeb: '',
+				stationNames: '',
+				dialogData: {
+					data: {
+						PowerSet: '',
+						AgcUp: '',
+						AgcLower: '',
+						ActualPower: '',
+						TheoryPower: '',
+						ForecastPower: '',
+						AgcIn: '',
+						AgcFar: '',
+						SumLock: '',
+						SubLock: '',
+					}
+				},
+				dataMsg: [],
+				interval: '',
+				arrKey: [],
+				timeIndex: 0
+			};
+		},
+		components: {
+			PhotoelectricDetailPages,
+			StationSvgDetailPages,
+			WindturbineDetailPages,
+		},
+		created() {
+			this.datacontrol();
+			// this.initData();
+		},
+		methods: {
+			datacontrol() {
+				let mb = MessageBridge.getInstance();
+				let vss = [{ key: "/topic/voice-control", action: this.windturbineMessage }];
+				let attention = [{ key: "/topic/attention", action: this.attention }];
+				mb.register(attention);
+				mb.register(vss);
+			},
+			attention(msg) {
+				let list = JSON.parse(msg)
+				let types = {
+					ElectricityRestrictions: '限电',
+					Offline: '离线',
+					Accident: '故障',
+				}
+				list.forEach(item => {
+					item.createTime = dayjs(item.time).format('YYYY-MM-DD HH:mm:ss')
+					item.showType = types[item.type]
+				})
+				this.values = list
+			},
+			windturbineMessage(msg) {
+				let bd = BackgroundData.getInstance();
+				let arr = []
+				if (msg === 'CLOSE') {
+					arr.push(msg)
+				} else {
+					arr = msg.split('-')
+				}
+				this.dialogVisible = false
+				this.svgWeb = ''
+				if (arr[0] === 'OPEN_AGC' && arr[1] !== 'GS') {
+					let data = bd.Recommends
+					for (let v in data) {
+						if (arr[1] === data[v].stationID) {
+							this.sendMsg(data[v])
+						}
+					}
+				} else if (arr[0] === 'CLOSE') {
+					this.dialogVisible = false
+					this.svgVisible = false
+				}
+			},
+			closed() {
+				clearInterval(this.interval);
+			},
+			close() {
+				this.svgVisible = false;
+			},
+			initData() {
+				setInterval(this.refreshData, 2000);
+			},
+			refreshData() {
+				let bd = BackgroundData.getInstance();
+				let list = new Array();
+				let thisKey = ''
+				for (let v in bd.Recommends) {
+					thisKey += v + ',';
+				}
+				axios.get(process.env.VUE_APP_ADAPTERURL + `/ts/latest?keys=` + thisKey)
+					.then(msg => {
+						for (let v in msg.data) {
+							if (msg.data[v].doubleValue ? (msg.data[v].doubleValue > 0) : (msg.data[v].booleanValue)) {
+								bd.Recommends[v].isActive = true
+							}
+						}
+						for (let rec in bd.Recommends) {
+							if (bd.Recommends[rec].isActive) {
+								list.push(bd.Recommends[rec])
+							}
+						}
+						list.forEach(item => {
+							item.createTime = dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss')
+						})
+						this.values = list
+					})
+			},
+			sendMsg: function (vl, index) {
+				if (vl.attentionType === 'Station' && vl.type === 'Accident') {
+					this.svgVisible = true;
+					this.svgWeb = vl.stationId;
+					this.stationNames = vl.name
+				} else if (vl.attentionType === 'Station' && vl.type === 'ElectricityRestrictions') {
+					let that = this;
+					that.timeIndex = 0;
+					that.ajaxDetail(vl, index);
+					that.interval = window.setInterval(function () {
+						that.ajaxDetail(vl, index);
+					}, 3000);
+					that.dialogVisible = true;
+					that.dialogData.stationName = vl.name;
+				} else if (vl.attentionType === 'WindTurbine') {
+					this.windVisible = true;
+					this.currentWindturbine = this.$store.state.windturbinelist[vl.id];
+				}
+
+			},
+			ajaxDetail(data, index) {
+				let thisKey = Photoelectric[data.id];
+				let array = []
+				thisKey.forEach(item => { item.value ? array.push(item.value) : '' })
+				let params = array.join(',')
+				api.getLatest(params).then(res => {
+					if (res) {
+						console.log(res, this.dialogData.data, thisKey);
+						for (let v in res.data) {
+							thisKey.forEach(item => {
+								let calc = item.calc ? item.calc : 1;
+								if (item.value === v) {
+									this.dialogData.data[item.tag] = {
+										name: item.name,
+										value: res.data[v].doubleValue ? res.data[v].doubleValue === 0 ? '0' : (res.data[v].doubleValue * calc).toFixed(2) : (res.data[v].booleanValue ? 1 : 0)
+									}
+									console.log(this.dialogData.data);
+								}
+							})
+						}
+					}
+				})
+				if (this.timeIndex == 0) {//一分钟执行一次
+					let date = new Date()
+					let endTs = date.getTime();
+					let starTs = endTs - 28800000;
+					const PowerSet = thisKey.find(ele => {
+						return ele.tag == 'PowerSet'
+					});
+					const ActualPower = thisKey.find(ele => {
+						return ele.tag == 'ActualPower'
+					});
+					let PowerSetData = [],
+						ActualPowerData = [];
+					api.getPower({
+						tagName: PowerSet.value,
+						startTs: starTs,
+						endTs: endTs,
+						interval: 60,
+					}).then(res1 => {
+						api.getPower({
+							tagName: ActualPower.value,
+							startTs: starTs,
+							endTs: endTs,
+							interval: 60,
+						}).then(res2 => {
+							res1.data.forEach(item => {
+								PowerSetData.push({
+									ts: item.ts,
+									doubleValue: item.doubleValue * PowerSet.calc
+								})
+							})
+							res2.data.forEach(item => {
+								ActualPowerData.push({
+									ts: item.ts,
+									doubleValue: item.doubleValue * ActualPower.calc
+								})
+							})
+							this.$refs.photo.initData(PowerSetData, ActualPowerData);
+						});
+					});
+				} else if (this.timeIndex == 20) {
+					this.timeIndex = -1;
+				}
+				this.timeIndex++;
+			},
+		},
+	};
+</script>
+<style scoped>
+	/* table {
+		background-image: url("../../assets/img/RecommendedArea/background.png");
+		text-align: center;
+		font-size: 12px;
+		background-size: 110px;
+		margin-left: 10px;
+		margin-top: 10px;
+		padding-top: 10px;
+		background-repeat: no-repeat;
+		color: #ffffff;
+	} */
+	.imgs {
+		/* width: 70px;
+		height: 66px; */
+	}
+
+	.area {
+		display: flex;
+		flex-direction: column;
+		font-size: 12px;
+		color: #ffffff;
+		width: 130px;
+		align-items: center;
+		margin-bottom: 10px;
+	}
+
+	.content {
+		margin-top: -70px;
+		width: 25px;
+		height: 34px;
+		margin-bottom: 20px;
+		display: flex;
+		align-items: center;
+	}
+</style>

+ 125 - 0
src/components/focus/multiple-line-chart.vue

@@ -0,0 +1,125 @@
+<template>
+  <div class="chart" id="showEchart"></div>
+</template>
+
+<script>
+  import * as echarts from "echarts";
+  export default {
+    name: "multiple-line-chart",
+    componentName: "multiple-line-chart",
+    data() {
+      return {
+        id: "",
+        chart: null,
+      };
+    },
+    methods: {
+      initChart(chartData) {
+        let chartDom = document.getElementById('showEchart');
+        let myChart = echarts.init(chartDom, '#ffffff');
+        let option = {
+          legend: {
+            show: true,
+            data: chartData.value.map((t) => {
+              return t.title;
+            }),
+            right: 56,
+            icon: "circle",
+            itemWidth: 6,
+            inactiveColor: '#606769',
+            textStyle: {
+              color: '#B3BDC0',
+              fontSize: 12,
+            },
+          },
+
+          xAxis: [
+            {
+              type: "category",
+              boundaryGap: false,
+              axisLabel: {
+                // interval: 60,
+                showMinLabel: true,
+                showMaxLabel: true,
+                formatter: "{value}",
+                fontSize: 14,
+                textStyle: {
+                  color: '#606769',
+                },
+              },
+              axisLine: {
+                show: false,
+              },
+              data: chartData.value[0].value.map(items => {
+                return items.text;
+              }),
+            },
+          ],
+          yAxis: {
+            type: "value",
+            axisLabel: {
+              formatter: "{value}",
+              fontSize: 14,
+            },
+            axisLine: {
+              show: false,
+            },
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: '#606769',
+                type: "dashed",
+              },
+            },
+          },
+          dataZoom: [
+            {
+              show: false,
+              type: 'inside',
+              start: 0,
+              end: 100
+            },
+          ],
+          series: [{
+            name: chartData.value[0].title,
+            smooth: true,
+            showSymbol: false,
+            data: chartData.value[0].value.map(items => {
+              return items.value;
+            }),
+            type: 'line',
+            lineStyle: {
+              normal: {
+                color: 'rgba(75, 85, 174, 1)',
+                width: 1,
+              },
+            },
+          },
+          {
+            name: chartData.value[1].title,
+            smooth: true,
+            showSymbol: false,
+            data: chartData.value[1].value.map(items => {
+              return items.value;
+            }),
+            type: 'line',
+            lineStyle: {
+              normal: {
+                color: 'rgba(05, 187, 76, 1)',
+                width: 1,
+              },
+            },
+          }]
+        };
+        option && myChart.setOption(option);
+      },
+    },
+  };
+</script>
+
+<style lang="less">
+  .chart {
+    width: 1050px;
+    height: 40vh;
+  }
+</style>

+ 723 - 0
src/components/matrixBlock.vue

@@ -0,0 +1,723 @@
+<template>
+    <div style="display: flex; flex-direction: row; flex-wrap: wrap;">
+        <div :class="item.active?'box-' + item.status:'unbox-' + item.status" v-for="(item, index) in dataList"
+            :key="index" @click="onSelectHandler(item)" @dblclick="sendMsg(item)" style="margin-right: 15px;">
+            <div :class="item.active?'left-' + item.status:'unleft-' + item.status">
+                <div>{{ item.windturbineId.slice(0, 2) }}</div>
+                <div>{{ item.windturbineId.slice(5) }}</div>
+            </div>
+            <div :class="item.active?'right-' + item.status:'unright-' + item.status">
+                <div class="rightrow">{{ item.windSpeed.toFixed(2) }} m/s</div>
+                <div class="rightrow">{{ item.power.toFixed(2) }} kw</div>
+                <div class="rightrow">{{ (item.modelId.indexOf("105") >= 0)?(item.rollSpeed *
+                    9.55).toFixed(2):item.rollSpeed.toFixed(2) }} rpm</div>
+            </div>
+            <div class="locks" v-if="item.lockValue > 0">
+                <el-popover placement="bottom-start" :width="150" trigger="hover" class="popoverBack"
+                    :show-arrow="false">
+                    <template #reference>
+                        <img class="lock" src="../assets/img/type/lock.png" alt="">
+                    </template>
+                    <input class="lock_input" type="text" placeholder="" :value="item.lockValue ===9 ? item.lockValues:options[item.lockValue]" disabled>
+                </el-popover>
+            </div>
+            <div class="locks" v-if="item.reasonType">
+                <img class="lock" src="../assets/img/type/electricityRestrictions.png" alt="">
+            </div>
+        </div>
+    </div>
+    <WindturbineDetailPages v-model="dialogVisible" :showSvg="showSvg" @close="handleClose"
+        :windturbine="currentWindturbine"></WindturbineDetailPages>
+</template>
+<script>
+    import WindturbineDetailPages from "./WindturbineDetailPages.vue";
+    export default {
+        components: {
+            WindturbineDetailPages,
+        },
+        props: {
+            dataList: {
+                type: Array,
+                default: () => {
+                    return []
+                },
+            },
+            area: String,
+        },
+        mounted() {
+
+        },
+        updated() {
+            
+        },
+        methods: {
+            onSelectHandler(values) {
+                if (this.area === 'problem') {
+                    this.$emit('problem-click', values);
+                } else {
+                    this.$emit('choose-click', values);
+                }
+                // values.active = !values.active;
+            },
+            sendMsg: function (itm) {
+                // this.dialogVisible = true;
+                this.$emit('on-click', itm);
+                // this.currentWindturbine = itm;
+            },
+            handleClose() {
+                this.dialogVisible = false
+                this.showSvg = false
+            },
+        },
+        data() {
+            return {
+                dialogVisible: false,
+                showSvg: false,
+                currentWindturbine: {},
+                options: {
+                    8: '检修',
+                    7: '故障维修',
+                    2: '场内受累检修',
+                    3: '场内受累故障',
+                    4: '场外受累电网',
+                    5: '场外受累天气',
+                },
+            };
+        },
+    }
+</script>
+<style scoped>
+    .lock {
+        width: 10px;
+        height: 10px;
+        position: relative;
+        right: 6px;
+        top: -15px;
+    }
+
+    .lock-on {
+        width: 0px;
+        height: 0px;
+        opacity: 0;
+    }
+
+    .locks:hover .lock-on {
+        position: fixed;
+        display: flex;
+        align-items: center;
+        width: 80px;
+        height: 30px;
+        border: 1px solid #999999;
+        background-color: #999999;
+        opacity: 1;
+        color: #ffffff;
+        z-index: 999;
+    }
+
+    .lock_input {
+        width: 140px;
+        background-color: #292929;
+        height: 40px;
+        color: #ffffff;
+    }
+
+    .box-0 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(255, 255, 255, 1);
+        background-color: rgba(255, 255, 255, .05);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+        box-shadow: 0px 0px 6px #ffffff;
+    }
+
+    .unbox-0 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(255, 255, 255, 1);
+        background-color: rgba(255, 255, 255, .2);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+    }
+
+    .left-0 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(255, 255, 255, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .unleft-0 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(255, 255, 255, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .right-0 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(255, 255, 255, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .unright-0 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(255, 255, 255, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .box-1 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(197, 48, 200, 1);
+        background-color: rgba(197, 48, 200, .05);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+        box-shadow: 0px 0px 6px #ef3af2;
+    }
+
+    .unbox-1 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(197, 48, 200, 1);
+        background-color: rgba(197, 48, 200, .2);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+    }
+
+    .left-1 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(197, 48, 200, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .unleft-1 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(197, 48, 200, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .right-1 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(197, 48, 200, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .unright-1 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(197, 48, 200, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .box-2 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(05, 187, 76, 1);
+        background-color: rgba(05, 187, 76, .05);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+        box-shadow: 0px 0px 6px #09e45e;
+    }
+
+    .unbox-2 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(05, 187, 76, 1);
+        background-color: rgba(05, 187, 76, .2);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+    }
+
+    .left-2 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(05, 187, 76, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .unleft-2 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(05, 187, 76, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .right-2 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(05, 187, 76, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .unright-2 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(05, 187, 76, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .box-3 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(05, 187, 76, 1);
+        background-color: rgba(05, 187, 76, .05);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+        box-shadow: 0px 0px 6px #09e45e;
+    }
+
+    .unbox-3 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(05, 187, 76, 1);
+        background-color: rgba(05, 187, 76, .2);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+    }
+
+    .left-3 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(05, 187, 76, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .unleft-3 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(05, 187, 76, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .right-3 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(05, 187, 76, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .unright-3 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(05, 187, 76, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .box-4 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(75, 85, 174, 1);
+        background-color: rgba(75, 85, 174, .05);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+        box-shadow: 0px 0px 6px #6876f2;
+    }
+
+    .unbox-4 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(75, 85, 174, 1);
+        background-color: rgba(75, 85, 174, .2);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+    }
+
+    .left-4 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(75, 85, 174, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .unleft-4 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(75, 85, 174, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .right-4 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(75, 85, 174, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .unright-4 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(75, 85, 174, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .box-5 {
+        width: 133px;
+        height: 48px;
+        color: #ffffff;
+        border: 2px solid rgba(186, 50, 55, 1);
+        background-color: rgba(186, 50, 55, .05);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+        box-shadow: 0px 0px 6px #ff1313;
+    }
+
+    .unbox-5 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(186, 50, 55, 1);
+        background-color: rgba(186, 50, 55, .2);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+    }
+
+    .left-5 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(186, 50, 55, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .unleft-5 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(186, 50, 55, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .right-5 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(186, 50, 55, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .unright-5 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(186, 50, 55, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .box-6 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(225, 125, 36, 1);
+        background-color: rgba(225, 125, 36, .05);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+        box-shadow: 0px 0px 6px #f28627;
+    }
+
+    .unbox-6 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(225, 125, 36, 1);
+        background-color: rgba(225, 125, 36, .2);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+    }
+
+    .left-6 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(225, 125, 36, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .unleft-6 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(225, 125, 36, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .right-6 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(225, 125, 36, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .unright-6 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(225, 125, 36, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .box-7 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(96, 103, 105, 1);
+        background-color: rgba(96, 103, 105, .05);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+        box-shadow: 0px 0px 6px #ffffff;
+    }
+
+    .unbox-7 {
+        width: 135px;
+        height: 50px;
+        color: #ffffff;
+        border: 1px solid rgba(96, 103, 105, 1);
+        background-color: rgba(96, 103, 105, .2);
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 5px;
+        margin-top: 10px;
+    }
+
+    .left-7 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(96, 103, 105, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .unleft-7 {
+        width: 40%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(96, 103, 105, 1);
+        font-weight: 600;
+        line-height: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .right-7 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(96, 103, 105, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .unright-7 {
+        width: 60%;
+        height: 100%;
+        font-size: 12px;
+        color: rgba(96, 103, 105, 1);
+        line-height: 15px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+</style>

+ 408 - 0
src/components/modeControl/detailPages.vue

@@ -0,0 +1,408 @@
+<template>
+	<el-dialog width="55%" @closed="closed()" :show-close="false" class="my-info-dialog">
+		<template #title>
+			<div class="showTitle">
+				<img class="titleImg" src="../../assets/img/controlcenter/daraTrue.png" alt="">
+				<div class="titles">国电电力宁夏新能源开发有限公司</div>
+			</div>
+		</template>
+		<div class="body">
+			<div class="dataList">
+				<div class="data">
+					<div class="name">健康指数:</div>
+					<div class="num">{{showDate?.healthIndex?.value}}</div>
+				</div>
+				<div class="data">
+					<div class="name">资源指数:</div>
+					<div class="num">{{showDate?.resourceIndex?.value}}</div>
+				</div>
+				<div class="data">
+					<div class="name">风能利用率:</div>
+					<div class="num">{{showDate?.windEnergyRate?.value}}%</div>
+				</div>
+				<div class="data">
+					<div class="name">曲线跟随率:</div>
+					<div class="num">{{showDate?.curveFollowingRate?.value}}%</div>
+				</div>
+				<div class="data">
+					<div class="name">实际功率:</div>
+					<div class="num">{{showDate?.realTimePower?.value}}</div>
+					<div class="unit">MW</div>
+				</div>
+				<div class="data">
+					<div class="name">理论功率:</div>
+					<div class="num">{{showDate?.theoreticalPower?.value}}</div>
+					<div class="unit" @click='ChangeColor()'>MW</div>
+				</div>
+				<div class="data">
+					<div class="name">AGC有功设定:</div>
+					<div class="num">{{showDate?.agcPowerSet?.value}}</div>
+					<div class="unit" @click='ChangeColors()'>MW</div>
+				</div>
+			</div>
+			<div id="totleEcharts" class="echarts"></div>
+			<!-- <MultipleLineChart height="400px" :units="powerLineChartData.units" :list="powerLineChartData.value" :colors="colors"
+				:showLegend="true" /> -->
+		</div>
+	</el-dialog>
+</template>
+
+<script>
+	import MultipleLineChart from "../focus/multiple-line-chart.vue";
+	import MessageBridge from 'utils/MessageBridge'
+	import dayjs from 'dayjs'
+	import api from "api/index";
+	import * as echarts from "echarts";
+	export default {
+		components: {
+			MultipleLineChart
+		},
+		props: {
+			stationName: {
+				type: String,
+				default: ''
+			},
+			data: {
+				type: Array
+			},
+		},
+		created() {
+			// this.initData()
+		},
+		mounted() {
+			this.initData()
+		},
+		data() {
+			return {
+				// 定时器
+				timer: "",
+				colors: ["rgba(75, 85, 174, 1)", "rgba(05, 187, 76, 1)"],
+				showDate: {},
+				chartData: {
+					units: [""],
+					value: [
+						{
+							title: "实际功率(MW)",
+							yAxisIndex: 0,
+							value: []
+						},
+						{
+							title: "理论功率(MW)",
+							yAxisIndex: 0,
+							value: []
+						},
+					],
+				},
+				timeData: [],
+				PowerSet: [],
+				ActualPower: [],
+				index: 0,
+				powerLineChartData: {},
+			};
+		},
+		methods: {
+			initData() {
+				let mb = MessageBridge.getInstance();
+				let vs = [{ key: "/topic/title-info", action: this.getMessage }];
+				mb.register(vs);
+			},
+			getMessage(msg) {
+				let data = JSON.parse(msg)
+				data.healthIndex.value = Number(data.healthIndex.value).toFixed(0)
+				data.resourceIndex.value = Number(data.resourceIndex.value).toFixed(0)
+				data.realTimePower.value = data.realTimePower.value.toFixed(2)
+				data.theoreticalPower.value = data.theoreticalPower.value.toFixed(2)
+				data.agcPowerSet.value = data.agcPowerSet.value.toFixed(2)
+				data.windEnergyRate.value = data.windEnergyRate.value.toFixed(2)
+				data.curveFollowingRate.value = data.curveFollowingRate.value.toFixed(2)
+				this.showDate = data
+			},
+			async getDate() {
+				await this.getPower({
+					PowerSet: 'JSFW.NX_GD_FDC_XX_XX_XXX_XXX_CI0135',
+					name: 'PowerSet',
+				})
+				await this.getPower({
+					ActualPower: 'JSFW.NX_GD_FDC_XX_XX_XXX_XXX_CI0192',
+					name: 'ActualPower',
+				})
+				this.timer = setTimeout(() => {
+					this.getDate()
+				}, 60000);
+			},
+			getPower(values) {
+				let date = new Date()
+				let endTs = date.getTime();
+				let startTs = endTs - 28800000;
+				let names = values.name
+				// 	this.powerLineChartData = this.chartData;
+				api.getPower({
+					tagName: values.PowerSet ? values.PowerSet : values.ActualPower,
+					startTs: startTs,
+					endTs: endTs,
+					interval: 60,
+				}).then(res => {
+					if (res) {
+						if (names === 'PowerSet') {
+							let list = []
+							res.data.forEach(item => {
+								list.push({
+									text: dayjs(item.ts).format('hh:mm'),
+									value: parseFloat((item.doubleValue).toFixed(2))
+								})
+								this.chartData.value[0].value = list
+							})
+						} else {
+							let list = []
+							res.data.forEach(item => {
+								list.push({
+									text: dayjs(item.ts).format('hh:mm'),
+									value: (parseFloat((item.doubleValue).toFixed(2)) / 1000)
+								})
+								this.chartData.value[1].value = list
+							})
+						}
+						// this.powerLineChartData = this.chartData;
+						this.totleErtcher(this.chartData)
+					}
+				})
+			},
+			totleErtcher(chartData) {
+				console.log(document.getElementById('totleEcharts'));
+				let chartDom = document.getElementById('totleEcharts');
+				let myChart = echarts.init(chartDom, '#ffffff');
+				let option;
+				option = {
+					legend: {
+						show: true,
+						data: chartData.value.map((t) => {
+							return t.title;
+						}),
+						right: 56,
+						icon: "circle",
+						itemWidth: 6,
+						inactiveColor: '#606769',
+						textStyle: {
+							color: '#B3BDC0',
+							fontSize: 12,
+						},
+					},
+					xAxis: [
+						{
+							type: "category",
+							boundaryGap: false,
+							axisLabel: {
+								interval: 60,
+								showMinLabel: true,
+								showMaxLabel: true,
+								formatter: "{value}",
+								fontSize: 14,
+								textStyle: {
+									color: '#606769',
+								},
+							},
+							axisLine: {
+								show: false,
+							},
+							data: chartData.value[0].value.map(item => {
+								return item.text;
+							}),
+						},
+					],
+					yAxis: {
+						type: "value",
+						axisLabel: {
+							formatter: "{value}",
+							fontSize: 14,
+						},
+						axisLine: {
+							show: false,
+						},
+						splitLine: {
+							show: true,
+							lineStyle: {
+								color: '#606769',
+								type: "dashed",
+							},
+						},
+					},
+					series: [{
+						name: chartData.value[0].title,
+						smooth: true,
+						showSymbol: false,
+						data: chartData.value[0].value.map(item => {
+							return item.value;
+						}),
+						type: 'line',
+						lineStyle: {
+							normal: {
+								color: 'rgba(75, 85, 174, 1)',
+								width: 1,
+							},
+						},
+					},
+					{
+						name: chartData.value[1].title,
+						smooth: true,
+						showSymbol: false,
+						data: chartData.value[1].value.map(item => {
+							return item.value;
+						}),
+						type: 'line',
+						lineStyle: {
+							normal: {
+								color: 'rgba(05, 187, 76, 1)',
+								width: 1,
+							},
+						},
+					}]
+				};
+
+				option && myChart.setOption(option);
+			},
+			ChangeColors() {
+				this.colors = ["#aa2116", "#fcaf17"]
+			},
+			ChangeColor() {
+				this.colors = ["rgba(75, 85, 174, 1)", "rgba(05, 187, 76, 1)"]
+			},
+			closed() {
+				clearInterval(this.timer);
+				//勿删,传递关闭方法
+			},
+			// initData(PowerSet, ActualPower) {
+			// 	// this.chartData.units = ["(MW)", "(MW)"];
+			// 	this.chartData.value[0] = {
+			// 		title: "有功设定限值(MW)",
+			// 		yAxisIndex: 0,
+			// 		value: []
+			// 	};
+			// 	this.chartData.value[1] = {
+			// 		title: "实发有功(MW)",
+			// 		yAxisIndex: 0,
+			// 		value: []
+			// 	}
+			// 	PowerSet.forEach(item => {
+			// 		this.chartData.value[0].value.push({
+			// 			text: dayjs(item.ts).format('hh:mm'),
+			// 			value: parseFloat((item.doubleValue).toFixed(2))
+			// 		})
+			// 	})
+			// 	ActualPower.forEach(item => {
+			// 		this.chartData.value[1].value.push({
+			// 			text: dayjs(item.ts).format('hh:mm'),
+			// 			value: parseFloat((item.doubleValue).toFixed(2))
+			// 		})
+			// 	})
+			// 	this.powerLineChartData = this.chartData;
+			// }
+		},
+	};
+</script>
+<style scoped>
+	.echartsBox {
+		width: 64rem;
+		height: 220px;
+		overflow: hidden;
+	}
+
+	.el-dialog__header {
+		background-color: #000000;
+	}
+
+	.showTitle {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		margin-top: -10px;
+		font-size: 18px;
+		color: #FFFFFF;
+	}
+
+	.titleImg {
+		width: 16px;
+		height: 16px;
+		margin-right: 13px;
+	}
+
+	.icon {
+		font-size: 12px;
+		margin-left: 10px;
+		margin-top: 5px;
+	}
+
+	.body {
+		background-color: black;
+		width: 100%;
+		margin-top: -30px;
+		/* height: 200px; */
+	}
+
+	.dataList {
+		display: flex;
+		flex-direction: row;
+		flex-wrap: wrap;
+		align-items: center;
+		padding-top: 27px;
+	}
+
+	.data {
+		width: 50%;
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		margin-bottom: 22px;
+	}
+
+	.name {
+		width: 40%;
+		display: flex;
+		flex-direction: row-reverse;
+		font-size: 12px;
+		color: #FFFFFF;
+	}
+
+	.num {
+		margin-left: 59px;
+		font-size: 16px;
+		color: #05BB4C;
+		min-width: 40px;
+	}
+
+	.unit {
+		font-size: 16px;
+		color: #FFFFFF;
+		margin-left: 20px;
+	}
+
+	.condition {
+		width: 100%;
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		margin-bottom: 20px;
+		border-bottom: 1px solid #3D3D3D;
+		padding-bottom: 10px;
+	}
+
+	.status {
+		width: 25%;
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.statusIcon {
+		width: 14px;
+		height: 14px;
+		margin-left: 8px;
+	}
+
+	.echarts {
+		width: 100%;
+		height: 400px;
+		display: inline-block;
+	}
+</style>

+ 576 - 0
src/components/modeControl/modeControl.vue

@@ -0,0 +1,576 @@
+<template>
+    <div class="body">
+        <div class="control">
+            <div :class="current===0?'smart_on':'smart'" @click="ChangeBar(0)">智能</div>
+            <div :class="current===1?'recommend_on':'recommend'" @click="ChangeBar(1)">推荐</div>
+            <div :class="current===2?'manual_on':'manual'" @click="ChangeBar(2)">手动</div>
+        </div>
+        <div style="display: flex;flex-direction: row;z-index: 2;">
+            <div class="showData">
+                <div class="dataBox" @dblclick="dbClicks(showDate.healthIndex,'健康指数')">
+                    <div class="dataTitle">健康指数</div>
+                    <div class="datas">{{showDate.healthIndex?.value.toFixed(0)}}</div>
+                </div>
+                <div class="dataBox" @dblclick="dbClicks(showDate.resourceIndex,'资源指数')">
+                    <div class="dataTitle">资源指数</div>
+                    <div class="datas">{{showDate.resourceIndex?.value.toFixed(0)}}</div>
+                </div>
+            </div>
+            <div>
+                <div id="mainEcharts" @dblclick="dbClick()" class="echarts"></div>
+                <div class="powerContent">
+                    <div class="power" @dblclick="dbClicks(showDate.realTimePower,'实际功率')">
+                        <div class="powerTitle">实际功率</div>
+                        <div class="powerDatas" style="background-color: rgba(75, 85, 174, 1);">
+                            {{showDate.realTimePower?.value.toFixed(2)}}</div>
+                    </div>
+                    <div class="power1" @dblclick="dbClicks(showDate.theoreticalPower,'理论功率')">
+                        <div class="powerTitle">理论功率</div>
+                        <div class="powerDatas" style="background-color: rgba(05, 187, 76, 1);">
+                            {{showDate.theoreticalPower?.value.toFixed(2)}}</div>
+                    </div>
+                    <div class="power2" @dblclick="dbClicks(showDate.agcPowerSet,'AGC有功设定')">
+                        <div class="powerTitle">AGC有功设定</div>
+                        <div class="powerDatas" style="background-color: rgba(186, 50, 55, 1);">
+                            {{showDate.agcPowerSet?.value.toFixed(2)}}</div>
+                    </div>
+                </div>
+            </div>
+            <div class="showData">
+                <div class="dataBox-right" @dblclick="dbClicks(showDate.windEnergyRate,'风能利用率')">
+                    <div class="dataTitle">风能利用率</div>
+                    <div class="datas" v-if="showDate.windEnergyRate?.value <= 100">
+                        {{showDate.windEnergyRate?.value.toFixed(2)}}%</div>
+                </div>
+                <div class="dataBox-right" @dblclick="dbClicks(showDate.curveFollowingRate,'曲线跟随率')">
+                    <div class="dataTitle">曲线跟随率</div>
+                    <div class="datas" v-if="showDate.curveFollowingRate?.value <= 100">
+                        {{showDate.curveFollowingRate?.value.toFixed(2)}}%</div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <DetailPages ref="detials" @closed="closed()" v-model="dialogVisible">
+    </DetailPages>
+    <Details @closed="closeds()" v-model="display" :partsName='partsName' echartsId="modelEcharts" :datas="modelDetails"
+        @search-data="search" @original-data="originalData"></Details>
+</template>
+<script>
+    import BackgroundData from 'utils/BackgroundData'
+    import api from "api/index";
+    import MessageBridge from 'utils/MessageBridge'
+    import * as echarts from "echarts";
+    import DetailPages from "./detailPages.vue";
+    import Details from "../basicDataDetails.vue";
+    export default {
+        props: {
+            // current: {
+            //     type: Number,
+            // },
+        },
+        components: {
+            DetailPages,
+            Details
+        },
+        data() {
+            return {
+                current: 1,
+                datas: {},
+                list: {},
+                showDate: {},
+                winFlag: 0,
+                curveFlag: 0,
+                fieldFlag: 0,
+                dialogVisible: false,
+                display: false,
+                modelDetails: [],
+                partsName: '',
+                modelData: {},
+                interval: 60,
+            };
+        },
+        created() {
+            this.initData();
+        },
+        computed: {
+
+        },
+        mounted() {
+            this.$nextTick(() => {
+                if (document.getElementById('mainEcharts')) {
+                    this.getEcharts()
+                }
+            });
+        },
+        methods: {
+            initData() {
+                let mb = MessageBridge.getInstance();
+                let vss = [{ key: "/topic/voice-control", action: this.windturbineMessage }];
+                let vs = [{ key: "/topic/title-info", action: this.getEchartss }];
+                mb.register(vs);
+                mb.register(vss);
+            },
+            windturbineMessage(msg) {
+                let arr = []
+                if (msg === 'CLOSE') {
+                    arr.push(msg)
+                } else {
+                    arr = msg.split('-')
+                }
+                this.dialogVisible = false
+                this.showSvg = false
+                this.svgWeb = ''
+                console.log(arr);
+                if (arr[0] === 'OPEN_PAGE_MANUAL') {
+                    this.ChangeBar(2)
+                } else if (arr[0] === 'OPEN_PAGE_AUTOMATIC') {
+                    this.ChangeBar(0)
+                } else if (arr[0] === 'OPEN_PAGE_RECOMMENDATION') {
+                    this.ChangeBar(1)
+                } else if (msg === 'OPEN_AGC-GS') {
+                    this.dbClick()
+                }
+            },
+            getEchartss(msg) {
+                this.showDate = JSON.parse(msg)
+                this.getEcharts()
+            },
+            getEcharts() {
+                let chartDom = document.getElementById('mainEcharts');
+                let myChart = echarts.init(chartDom, '#000000');
+                let option;
+                option = {
+                    series: [{
+                        type: 'gauge',
+                        max: 664,
+                        splitNumber: 8,
+                        anchor: {
+                            show: true,
+                            showAbove: true,
+                            size: 9,
+                            width: 5,
+                            itemStyle: {
+                                color: '#FAC858'
+                            }
+                        },
+                        pointer: {
+                            icon: '',
+                            width: 3,
+                            length: '80%',
+                            offsetCenter: [0, '8%']
+                        },
+
+                        progress: {
+                            show: true,
+                            overlap: true,
+                            roundCap: true
+                        },
+                        axisLine: {
+                            lineStyle: {//仪表盘轴线相关配置。
+                                width: 2,
+                                color: [[1, 'rgba(83, 92, 93, 0.5)']]
+                            }
+                        },
+                        axisLabel: {
+                            // textStyle: {//数字刻度样式
+                            //     color: '#000000',
+                            //     fontSize: 12,
+                            // }
+                        },
+                        splitLine: {//分隔线样式相关
+                            length: 0,//分割线的长度
+                            lineStyle: {
+                                width: 1,
+                                color: '#000000'
+                            }
+                        },
+                        data: [{
+                            value: 125.85,
+                            // name: '实际功率',
+                            itemStyle: {
+                                color: 'rgba(75, 85, 174, 1)'
+                            },
+                            // title: {
+                            //     color: '#999999',
+                            //     offsetCenter: ['-70%', '90%']
+                            // },
+                            // detail: {
+                            //     width: 50,
+                            //     height: 12,
+                            //     fontSize: 18,
+                            //     offsetCenter: ['-70%', '110%']
+                            // }
+                        },
+                        {
+                            value: 137.63,
+                            // name: '理论功率',
+                            itemStyle: {
+                                color: 'rgba(05, 187, 76, 1)'
+                            },
+                            // title: {
+                            //     color: '#999999',
+                            //     offsetCenter: ['0%', '90%']
+                            // },
+                            // detail: {
+                            //     width: 50,
+                            //     height: 12,
+                            //     fontSize: 18,
+                            //     offsetCenter: ['0%', '110%']
+                            // }
+                        },
+                        {
+                            value: 132.04,
+                            // name: 'AGC有功设定',
+                            itemStyle: {
+                                color: 'rgba(186, 50, 55, 1)'
+                            },
+                            // title: {
+                            //     color: '#999999',
+                            //     offsetCenter: ['70%', '90%']
+                            // },
+                            // detail: {
+                            //     align: 'center',
+                            //     width: 50,
+                            //     height: 12,
+                            //     fontSize: 18,
+                            //     offsetCenter: ['70%', '110%']
+                            // }
+                        }
+                        ],
+                        title: false,
+                        detail: false,
+                        //     title: {
+                        //         fontSize: 12
+                        //     },
+                        //     detail: {
+                        //         width: 20,
+                        //         height: 7,
+                        //         fontSize: 12,
+                        //         color: '#fff',
+                        //         backgroundColor: 'auto',
+                        //         borderRadius: 3,
+                        //         formatter: ''
+                        //     }
+                    }]
+                };
+                option.series[0].data[0].value = Number(this.showDate.realTimePower?.value);
+                option.series[0].data[1].value = Number(this.showDate.theoreticalPower?.value);
+                option.series[0].data[2].value = Number(this.showDate.agcPowerSet?.value);
+                myChart.setOption(option, true);
+            },
+            ChangeBar(values) {
+                let bd = BackgroundData.getInstance();
+                // let mb = MessageBridge.getInstance();
+                // let vss = { key: "/topic/voice-control" };
+                // let popup = { key: "/topic/fault-popup" };
+                // mb.unregister(popup);
+                // mb.unregister(vss);
+                this.$router.push(`/?current=${values}`)
+                if (!bd.LoginUser) {
+                    this.$notify({
+                        title: "请登录",
+                        message: "切换模式需要先登录!",
+                        type: "warning",
+                        position: "bottom-right",
+                        offset: 60,
+                        duration: 3000,
+                    });
+                    return;
+                }
+                if (this.current !== values) {
+                    this.$store.commit('current', Number(values))
+                    if (values === 2) {
+                        this.current = values
+                        this.$router.push(`/ManualPage?current=${values}`)
+                    } else if (values === 1) {
+                        this.$store.commit('current', values)
+                        if (this.current === 0) {
+                            this.current = values
+                        } else {
+                            this.current = values
+                            this.$router.push(`/?current=${values}`)
+                        }
+                    } else if (values === 0) {
+                        this.$store.commit('current', values)
+                        if (this.current === 2) {
+                            this.current = values
+                            this.$router.push(`/?current=${values}`)
+                        } else {
+                            this.current = values
+                        }
+                    }
+                }else{
+                    this.$router.push(`/ManualPage?current=${values}`)
+                }
+            },
+            dbClick() {
+                this.dialogVisible = true;
+                this.$refs.detials.getDate()
+            },
+            dbClicks(data, partsName, timeValues) {
+                this.modelData = data
+                let date = new Date()
+                let endTs = timeValues ? (timeValues[1] > date.getTime()) ? date.getTime() : timeValues[1] : date.getTime();
+                let startTs = timeValues ? timeValues[0] : endTs - 28800000;
+                api.getPower({
+                    tagName: data.tag,
+                    startTs: startTs,
+                    endTs: endTs,
+                    interval: this.interval,
+                }).then(res => {
+                    if (res.data.length > 0) {
+                        this.partsName = partsName
+                        this.display = true;
+                        this.modelDetails = res.data
+                    } else {
+                        this.modelDetails = []
+                    }
+                })
+            },
+            original(data, partsName, timeValues) {
+                this.modelData = data
+                let date = new Date()
+                let endTs = timeValues ? (timeValues[1] > date.getTime()) ? date.getTime() : timeValues[1] : date.getTime();
+                let startTs = timeValues ? timeValues[0] : endTs - 28800000;
+                api.getOriginalPower({
+                    tagName: data.tag,
+                    startTs: startTs,
+                    endTs: endTs,
+                }).then(res => {
+                    if (res.data.length > 0) {
+                        this.partsName = partsName
+                        this.display = true;
+                        this.modelDetails = res.data
+                    } else {
+                        this.modelDetails = []
+                    }
+                })
+            },
+            search(values, interval) {
+                this.interval = interval
+                this.dbClicks(this.modelData, this.partsName, values)
+            },
+            originalData(values) {
+                this.original(this.modelData, this.partsName, values)
+            },
+            closed() {
+                this.dialogVisible = false;
+            },
+            closeds() {
+                this.display = false;
+                this.interval = 60
+            }
+        },
+    }
+</script>
+<style scoped>
+    .body {
+        width: 100%;
+        height: 28.5vh;
+        /* background-color: #ffffff; */
+        margin-left: 15px;
+        margin-top: 20px;
+        border-left: 1px solid #373737;
+        border-right: 1px solid #373737;
+        border-bottom: 1px solid #373737;
+        /* background-image: url('../../assets/img/type/background.png'); */
+        background-repeat: no-repeat;
+        background-position: center;
+        background-size: cover;
+    }
+
+    .control {
+        display: flex;
+        flex-direction: row-reverse;
+        align-items: center;
+        font-size: 14px;
+        color: #ffffff;
+        /* margin-right: 5px; */
+        position: absolute;
+        right: 10px;
+        z-index: 99;
+    }
+
+    .manual {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        height: 29px;
+        width: 86px;
+        border-left: 1px solid rgba(51, 51, 51, 1);
+        border-top: 1px solid rgba(51, 51, 51, 1);
+        border-bottom: 1px solid rgba(51, 51, 51, 1);
+        border-top-left-radius: 15px;
+        border-bottom-left-radius: 15px;
+    }
+
+    .manual_on {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        height: 29px;
+        width: 86px;
+        border-left: 1px solid rgba(37, 116, 219, 1);
+        border-top: 1px solid rgba(37, 116, 219, 1);
+        border-bottom: 1px solid rgba(37, 116, 219, 1);
+        border-top-left-radius: 15px;
+        border-bottom-left-radius: 15px;
+        background-color: rgba(37, 116, 219, 1);
+    }
+
+    .recommend {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        height: 29px;
+        width: 86px;
+        border-top: 1px solid rgba(51, 51, 51, 1);
+        border-bottom: 1px solid rgba(51, 51, 51, 1);
+    }
+
+    .recommend_on {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        height: 29px;
+        width: 86px;
+        border-top: 1px solid rgba(37, 116, 219, 1);
+        border-bottom: 1px solid rgba(37, 116, 219, 1);
+        background-color: rgba(37, 116, 219, 1);
+    }
+
+    .smart {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        height: 29px;
+        width: 86px;
+        border-right: 1px solid rgba(51, 51, 51, 1);
+        border-top: 1px solid rgba(51, 51, 51, 1);
+        border-bottom: 1px solid rgba(51, 51, 51, 1);
+        border-top-right-radius: 15px;
+        border-bottom-right-radius: 15px;
+    }
+
+    .smart_on {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        height: 29px;
+        width: 86px;
+        border-right: 1px solid rgba(37, 116, 219, 1);
+        border-top: 1px solid rgba(37, 116, 219, 1);
+        border-bottom: 1px solid rgba(37, 116, 219, 1);
+        border-top-right-radius: 15px;
+        border-bottom-right-radius: 15px;
+        background-color: rgba(37, 116, 219, 1);
+    }
+
+    .echarts {
+        width: 300px;
+        height: 280px;
+        margin-top: 10px;
+        /* background-color: #000000; */
+        margin-left: 10px;
+    }
+
+    .showData {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+    }
+
+    .dataBox {
+        display: flex;
+        flex-direction: column;
+        width: 120px;
+        height: 60px;
+        border: 1px solid rgba(83, 92, 93, 1);
+        margin-bottom: 15px;
+        margin-top: 15px;
+        margin-left: 30px;
+    }
+
+    .dataBox-right {
+        display: flex;
+        flex-direction: column;
+        width: 120px;
+        height: 60px;
+        border: 1px solid rgba(83, 92, 93, 1);
+        margin-bottom: 15px;
+        margin-top: 15px;
+        margin-right: 30px;
+    }
+
+    .dataTitle {
+        height: 50%;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        font-size: 12px;
+        color: rgba(153, 162, 163, 1);
+        margin-left: 5px;
+    }
+
+    .datas {
+        height: 50%;
+        display: flex;
+        flex-direction: row-reverse;
+        align-items: center;
+        font-size: 16px;
+        color: rgba(05, 187, 76, 1);
+        margin-right: 5px;
+    }
+
+    .powerContent {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        color: #ffffff;
+        position: relative;
+        bottom: 18%;
+        left: 11%;
+    }
+
+    .power {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        font-size: 14px;
+        padding: 5px 10px;
+    }
+
+    .power1 {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        font-size: 14px;
+        padding: 5px 3px 5px 10px;
+    }
+
+    .power2 {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        font-size: 14px;
+        padding: 5px 3px;
+    }
+
+    .powerTitle {
+        margin-bottom: 3px;
+    }
+
+    .powerDatas {
+        border-radius: 2px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 16px;
+        font-weight: 600;
+        padding: 2px 5px;
+    }
+</style>

+ 39 - 0
src/components/problem/ProblemArea.vue

@@ -0,0 +1,39 @@
+/* 问题区 */
+<template>
+  <div class="problem" >
+    <AreaCard title="问题区" height="86"></AreaCard>
+  </div>
+</template>
+
+<script>
+  import AreaCard from "./areaCard.vue";
+  import BackgroundData from 'utils/BackgroundData'
+  export default {
+    name: "ProblemArea",
+    components: {
+      AreaCard,
+    },
+    props: {},
+    data() {
+      return {
+        ls: {
+          maintain: { key: "维护", value: [] },
+          malfunction: { key: "故障", value: [] },
+          offline: { key: "离线", value: [] },
+          lockd: { key: "挂牌", value: [] },
+        },
+      };
+    },
+    computed: {},
+    created: function () {
+
+    },
+    methods: {
+    },
+  };
+</script>
+<style scoped>
+  .problem {
+    height: 100%;
+  }
+</style>

+ 0 - 0
src/components/problem/ProblemMatrixCard.vue


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