浏览代码

Merge branch 'lining' of http://61.161.152.110:10101/r/electronic-map into yx

Koishi 3 年之前
父节点
当前提交
ee83e14234
共有 30 个文件被更改,包括 8154 次插入368 次删除
  1. 36 2
      src/App.vue
  2. 41 81
      src/api/axios.js
  3. 0 3
      src/components/chart/line/multiple-y-line-chart-normal.vue
  4. 3 1
      src/components/other/cesium/index.vue
  5. 23 18
      src/components/other/healthReport/index.vue
  6. 4 9
      src/router/index.js
  7. 0 0
      src/views/MalfunctionWarning/DBscan.vue
  8. 987 208
      src/views/MalfunctionWarning/MalfunctionWarning.vue
  9. 3390 0
      src/views/MalfunctionWarning/components/UniformCodes.json
  10. 146 0
      src/views/MalfunctionWarning/components/barChart.vue
  11. 133 0
      src/views/MalfunctionWarning/components/batchData.vue
  12. 41 0
      src/views/MalfunctionWarning/components/chartDetails.vue
  13. 534 0
      src/views/MalfunctionWarning/components/dataClassify.vue
  14. 174 0
      src/views/MalfunctionWarning/components/detectionRecord.vue
  15. 58 0
      src/views/MalfunctionWarning/components/exportZip.vue
  16. 101 0
      src/views/MalfunctionWarning/components/lineChart.vue
  17. 463 0
      src/views/MalfunctionWarning/components/records.vue
  18. 430 0
      src/views/MalfunctionWarning/components/superviseDataClassify.vue
  19. 273 0
      src/views/MalfunctionWarning/components/testReport.vue
  20. 401 0
      src/views/MalfunctionWarning/components/trainingResults.vue
  21. 二进制
      src/views/MalfunctionWarning/img/generator.png
  22. 0 0
      src/views/MalfunctionWarning/mdjl.vue
  23. 581 0
      src/views/MalfunctionWarning/supervised.vue
  24. 0 1
      src/views/NewPages/alarm-center-1.vue
  25. 48 4
      src/views/NewPages/multiple-y-line-chart-normal.vue
  26. 2 2
      src/views/Others/index.vue
  27. 6 6
      src/views/SandTable/SandTable.vue
  28. 12 17
      src/views/layout/Menu.vue
  29. 33 16
      src/views/sampleDatabase/performance/index.vue
  30. 234 0
      src/views/sampleDatabase/performance/performanceEcharts.vue

+ 36 - 2
src/App.vue

@@ -253,11 +253,11 @@ l16.229-16.229l16.229,16.229l42.867-42.867C115.034,45.228,109.133,42.189,102.956
     <login-page />
   </div>
   <!-- <login-page v-if="!showSisView && !isLogined" @onLogin="login" /> -->
-   <!-- <div v-else-if="token == ''">
+  <!-- <div v-else-if="token == ''">
     {{token}}
  <login-page  @onLogin="login" />
    </div> -->
- 
+
   <sisView v-else-if="showSisView" />
 </template>
 
@@ -441,5 +441,39 @@ body {
     //   transition-timing-function: ease-in-out;
     // }
   }
+  .el-table__body tr.current-row > td {
+    color: #fff;
+    background: rgba(66, 66, 66, 0.66) !important;
+  }
+
+  .el-transfer-panel {
+    width: 450px !important;
+    height: 73vh;
+    background-color: #111d1c !important;
+    border: 1px solid #999999 !important;
+
+    .el-transfer-panel__body {
+      height: 100% !important;
+
+      .el-transfer-panel__list {
+        height: 100% !important;
+      }
+    }
+  }
+  .el-transfer-panel .el-transfer-panel__header {
+    background-color: #111d1c !important;
+    color: #05bb4c !important;
+
+    .el-checkbox .el-checkbox__label {
+      color: #05bb4c !important;
+    }
+  }
+  .el-button--primary.is-disabled,
+  .el-button--primary.is-disabled:active,
+  .el-button--primary.is-disabled:focus,
+  .el-button--primary.is-disabled:hover {
+    background-color: #05bb4c;
+    border-color: #05bb4c;
+  }
 }
 </style>

+ 41 - 81
src/api/axios.js

@@ -66,87 +66,47 @@ export function requestData(options) {
       params.append(key, options.data[key]);
     }
 
-    if (options.body) {
-      let url = (options.baseURL || window.__MODE__.baseURL || '/api/') + options.subUrl
-      axios[options.method.toLowerCase()](url, options.body, { params: options.data || {} }).then(response => {
-        if (options.showLoading) {
-          BASE.closeLoading();
-        }
-        if (response.code === 501) { // 用户类请求错误code (账号密码错误、用户锁定、token过期等)
-
-          localStorage.removeItem('authToken');
-          BASE.showMsg({
-            msg: (response.data && response.data.msg) || ("请求出错[" + response.data.code + "]")
-          });
-
-          // window.location.reload();
-          // window.__STATICVUE__.$router.replace('/login');
-
-        } else if (response.data.code === 200 || response.data.length > 0) { // 请求成功 code
-
-          options.success && options.success(response.data);
-          resolve(response);
-
-        } else { // 其他code
-          BASE.closeLoading();
-          BASE.showMsg({
-            msg: (response.data && response.data.msg) || ("请求出错[" + response.data.code + "]")
-          });
-
-        }
-      }).catch(error => {
-
-        if (options.showLoading) {
-          BASE.closeLoading();
-        }
-
-        options.fail && options.fail(error);
-        reject(error);
-
-      });
-    } else {
-      // 发起请求
-      XHRReq({
-        url: options.subUrl,
-        method: options.method || 'GET',
-        params
-      }).then(response => {
-        if (options.showLoading) {
-          BASE.closeLoading();
-        }
-        if (response.code === 501) { // 用户类请求错误code (账号密码错误、用户锁定、token过期等)
-
-          localStorage.removeItem('authToken');
-          BASE.showMsg({
-            msg: (response.data && response.data.msg) || ("请求出错[" + response.data.code + "]")
-          });
-
-          // window.location.reload();
-          // window.__STATICVUE__.$router.replace('/login');
-
-        } else if (response.data.code === 200 || response.data.length > 0) { // 请求成功 code
-
-          options.success && options.success(response.data);
-          resolve(response);
-
-        } else { // 其他code
-          BASE.closeLoading();
-          BASE.showMsg({
-            msg: (response.data && response.data.msg) || ("请求出错[" + response.data.code + "]")
-          });
-
-        }
-      }).catch(error => {
-
-        if (options.showLoading) {
-          BASE.closeLoading();
-        }
-
-        options.fail && options.fail(error);
-        reject(error);
-
-      });
-    }
+    // 发起请求
+    XHRReq({
+      url: options.subUrl,
+      method: options.method || 'GET',
+      params,
+    }).then(response => {
+      if (options.showLoading) {
+        BASE.closeLoading();
+      }
+      if (response.code === 501) { // 用户类请求错误code (账号密码错误、用户锁定、token过期等)
+
+        localStorage.removeItem('authToken');
+        BASE.showMsg({
+          msg: (response.data && response.data.msg) || ("请求出错[" + response.data.code + "]")
+        });
+
+        // window.location.reload();
+        // window.__STATICVUE__.$router.replace('/login');
+
+      } else if (response.data.code === 200 || response.data.length>=0) { // 请求成功 code
+
+        options.success && options.success(response.data);
+        resolve(response);
+
+      } else { // 其他code
+        BASE.closeLoading();
+        BASE.showMsg({
+          msg: (response.data && response.data.msg) || ("请求出错[" + response.data.code + "]")
+        });
+
+      }
+    }).catch(error => {
+
+      if (options.showLoading) {
+        BASE.closeLoading();
+      }
+
+      options.fail && options.fail(error);
+      reject(error);
+
+    });
   });
 }
 

+ 0 - 3
src/components/chart/line/multiple-y-line-chart-normal.vue

@@ -375,8 +375,6 @@ console.log('yResult:',result)
             chart.clear();
           
             chart.setOption(option);
-              console.log('111111111111111111111',option);
-
             this.resize = function() {
                 chart.resize();
             };
@@ -436,7 +434,6 @@ console.log('yResult:',result)
             const chart = echarts.getInstanceByDom(this.$el);
             chart.clear();
             let option = this.option();
-            console.log('111111111111111111111',option);
             chart.setOption(option);
         },
     },

+ 3 - 1
src/components/other/cesium/index.vue

@@ -620,6 +620,8 @@ export default {
     position: relative;
   }
 }
+</style>
+<!-- <style lang="less">
 .menu {
   .el-dropdown-menu {
     background: rgba(0, 0, 0, 0.5) !important;
@@ -631,4 +633,4 @@ export default {
 .heatmap-canvas {
   pointer-events: none;
 }
-</style>
+</style> -->

+ 23 - 18
src/components/other/healthReport/index.vue

@@ -1618,12 +1618,15 @@ export default {
       default: () => {},
     },
   },
-  created() {},
+  created() {
+	  this.getReport();
+  },
   beforeUpdate() {
     var that = this;
     that.$nextTick(() => {
       that.others();
     });
+	
   },
   mounted() {
     this.dialogVisible = this.show;
@@ -1703,7 +1706,7 @@ export default {
     },
  
     // 获取报告详情
-    getReport() {
+    getReport(wtid,recorddate) {
       let that = this;
       let reqData = this.params;
       that.API.requestData({
@@ -1712,10 +1715,10 @@ export default {
         baseURL: "http://10.155.32.4:8034/",
         subUrl: "/healthreport/healthReport",
         data: {
-          wtid: reqData.wtId,
-          // wtid: "MG01_01",
-          // date: "2021-07-30",
-          date: reqData.recorddate,
+    //       wtid: reqData.wtId,
+		  // date: reqData.recorddate,
+          wtid: wtid,
+          date: recorddate,
         }, // 请求所携带参数,默认为空,可缺省
         success(res) {
           if (res.code == 200) {
@@ -1752,6 +1755,7 @@ export default {
             that.glqxnh = glqxnh;
  
             //曲线偏差率
+	        that.qxpcls = [];
             let qxpcls = [
               {
                 title: "曲线偏差率",
@@ -1833,9 +1837,9 @@ export default {
  
             // 部件隐患对比
             that.bjyhdbs = [];
-            that.bjyhdbs = res.data.healthreport.bjyhdbs;
+            that.bjyhdbs = that.datas.healthreport.bjyhdbs;
             // 隐患模型对比
-            let ybmxdj = res.data.healthreport.yhmxdbs;
+            let ybmxdj = that.datas.healthreport.yhmxdbs;
             if (ybmxdj != null) {
               for (let item of ybmxdj) {
                 if (item.part.indexOf("传动链")) {
@@ -1909,7 +1913,7 @@ export default {
             });
  
             //设备可利用率
-            let sbklyls = res.data.healthreport.sbklyls;
+            let sbklyls = that.datas.healthreport.sbklyls;
             that.sbklyls = sbklyls;
             that.sbklyls2 = [];
             let sblyl = Object.assign([], sbklyls);
@@ -1965,7 +1969,7 @@ export default {
               that.sbklyls2.push(sbklyls7);
  
               // 风能利用率
-              let fnlyl = res.data.healthreport.fnlyls;
+              let fnlyl = that.datas.healthreport.fnlyls;
               let fnlyl1 = {
                 name: "发电量",
                 q1ysj: fnlyl[2].fdl.toFixed(2),
@@ -2032,13 +2036,13 @@ export default {
             }
  
             // 故障分类
-            that.faultclass = res.data.healthreport.faultclass.sort(
+            that.faultclass = that.datas.healthreport.faultclass.sort(
               that.compare("monthwarningnum")
             );
  
             // 功率对部件温度影响
             that.partwds = [];
-            let partwds = res.data.healthreport.partwds;
+            let partwds = that.datas.healthreport.partwds;
             let partwd = [];
             partwds && partwds.forEach((item, i) => {
               let bj = "";
@@ -2081,7 +2085,7 @@ export default {
  
             // 性能评价结果
             that.xnpjjg = [];
-            let pjmxs = res.data.healthreport.pjjgs;
+            let pjmxs = that.datas.healthreport.pjjgs;
             if (pjmxs != null && pjmxs != undefined) {
               if (pjmxs[2] != undefined) {
                 let xnpj1 = {
@@ -2114,7 +2118,7 @@ export default {
  
             // 评价结果明细
             that.xnpjmx = [];
-            let pjmx = res.data.healthreport.pjmxs[0];
+            let pjmx = that.datas.healthreport.pjmxs[0];
             that.zhrank = pjmx.rank;
             let xnpjmx1 = {
               lx: "",
@@ -2277,7 +2281,7 @@ export default {
             that.xnpjmx.push(xnpjmx19);
             that.xnpjmx.push(xnpjmx20);
             // 评价明细蜘蛛图
-            let pjmxsE = res.data.healthreport.pjmxs[0];
+            let pjmxsE = that.datas.healthreport.pjmxs[0];
             that.pjmxs = [
               {
                 indicator: [
@@ -2501,9 +2505,10 @@ export default {
   watch: {
     show(value) {
       this.dialogVisible = value;
-      if (value) {
-        this.getReport();
-      }
+	  // console.log(value)
+      // if (value) {
+      //   this.datas();
+      // }
     },
     params(res) {
       this.reqData = res;

+ 4 - 9
src/router/index.js

@@ -555,19 +555,14 @@ const routes = [{
 	component: () => import("../views/windAnalysis/fxzstmain.vue"),
 },
 {
-	path: "/health/MalfunctionWarning/", //故障预警
+	path: "/health/MalfunctionWarning/", //故障预警 无监督学习
 	name: "MalfunctionWarning",
 	component: () => import("../views/MalfunctionWarning/MalfunctionWarning.vue")
 },
 {
-	path: "/health/MalfunctionWarning/DBscan", //dbscan
-	name: "DBscan",
-	component: () => import("../views/MalfunctionWarning/DBscan.vue")
-},
-{
-	path: "/health/MalfunctionWarning/mdjl", //密度聚类
-	name: "mdjl",
-	component: () => import("../views/MalfunctionWarning/mdjl.vue")
+	path: "/health/MalfunctionWarning/Supervised", //有监督学习
+	name: "Supervised",
+	component: () => import("../views/MalfunctionWarning/Supervised.vue")
 },
 /***********************************************************智慧检修************************************************************* */
 /***********************************************************安全管控************************************************************* */

+ 0 - 0
src/views/MalfunctionWarning/DBscan.vue


文件差异内容过多而无法显示
+ 987 - 208
src/views/MalfunctionWarning/MalfunctionWarning.vue


文件差异内容过多而无法显示
+ 3390 - 0
src/views/MalfunctionWarning/components/UniformCodes.json


+ 146 - 0
src/views/MalfunctionWarning/components/barChart.vue

@@ -0,0 +1,146 @@
+<template>
+  <div class="precisionEcharts" :style="style" :id="id"></div>
+</template>
+<script>
+import * as echarts from "echarts";
+export default {
+  props: {
+    barList: {
+      type: Array,
+    },
+    id: Object,
+    width: {
+      type: String,
+      default: "600px",
+    },
+    height: {
+      type: String,
+      default: "250px",
+    },
+    baseLine:  {
+      type: String,
+      default: "0.1",
+    },
+  },
+  data() {
+    return {};
+  },
+  computed: {
+    style() {
+      return `width: ${this.width}; height: ${this.height};`;
+    },
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart();
+    });
+  },
+  updated() {
+    this.$nextTick(() => {
+      this.initChart();
+    });
+  },
+  methods: {
+    initChart() {
+      let ydata = [];
+      let values = [];
+      this.barList?.sort(this.Compare("value"));
+      this.barList?.forEach((item) => {
+        ydata.push(item.name);
+        values.push(item.value * 100);
+      });
+      let chartDom = document.getElementById(this.id);
+      let myChart = echarts.init(chartDom);
+      let option = {
+        // title: {
+        //     text: 'World Population'
+        // },
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            type: "shadow",
+          },
+        },
+        legend: {},
+        grid: {
+          left: "3%",
+          right: "5%",
+          bottom: "3%",
+          containLabel: true,
+        },
+        xAxis: {
+          name: "%",
+          type: "value",
+          boundaryGap: [0, 0.01],
+          splitLine: { show: false },
+        },
+        yAxis: {
+          name: "名称",
+          type: "category",
+          splitLine: { show: false },
+          data: ydata,
+        },
+        series: [
+          {
+            // name: '2011',
+            type: "bar",
+            data: values,
+            markLine: {
+              symbol: "none", //去掉警戒线最后面的箭头
+              label: {
+                position: "start", //将警示值放在哪个位置,三个值“start”,"middle","end"  开始  中点 结束
+              },
+              data: [
+                {
+                  silent: true, //鼠标悬停事件  true没有,false有
+                  lineStyle: {
+                    //警戒线的样式  ,虚实  颜色
+                    type: "solid",
+                    color: "#FA3934",
+                  },
+                  label: {
+                    normal: {
+                      show: true,
+                      position: "end",
+                      formatter: "基准线",
+                      textStyle: {
+                        color: "#ffffff", //标注线终点文字颜色
+                        fontSize: 14,
+                        fontWeight: 700,
+                        padding: [0, 0, 10, 0], //文字间距
+                      },
+                    },
+                  },
+                  xAxis: this.baseLine *100,
+                },
+              ],
+            },
+          },
+        ],
+      };
+      option && myChart.setOption(option);
+    },
+    Compare(property) {
+      return function (a, b) {
+        var value1 = a[property];
+        var value2 = b[property];
+        return value1 - value2;
+      };
+    },
+  },
+  watch: {
+    barList: {
+      handler(newValue, oldValue) {
+        this.initChart();
+      },
+      deep: true,
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+// .precisionEcharts {
+//   width: 600px;
+//   height: 250px;
+// }
+</style>

+ 133 - 0
src/views/MalfunctionWarning/components/batchData.vue

@@ -0,0 +1,133 @@
+<template>
+  <el-dialog
+    width="70%"
+    top="10vh"
+    custom-class="modal"
+    :close-on-click-modal="false"
+    title="批量处理"
+    v-model="dialogTableVisible"
+    @opened="opened()"
+    @closed="closed()"
+  >
+    <el-row :type="'flex'" class="contents">
+      <el-col :span="3" class="pd-l-8">
+        <div class="lables">
+          <div
+            v-for="(item, index) in moudleList"
+            :key="index"
+            :class="current ===Number(item.id) ? 'current_on' : 'current_of'"
+            @click="handleClick(Number(item.id))"
+          >
+           {{ item.faulttype }}
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="21" class="pd-l-8">
+        <div class="right">
+          <el-transfer
+            class="transfers"
+            v-model="value"
+            :data="dataList"
+            :titles="['待标记', moudleList.filter(item => Number(item.id) ===  current)[0].faulttype]"
+            @change="handleChange"
+          ></el-transfer>
+        </div>
+      </el-col>
+    </el-row>
+  </el-dialog>
+</template>
+<script>
+export default {
+  props: {
+    allData: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+    moudleList: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+  },
+  data() {
+    return {
+      current: 1,
+      value: [1, 4],
+      dataList: [
+        {
+          key: 0,
+          label: "",
+        },
+      ],
+    };
+  },
+  methods: {
+    opened() {
+      this.dataList = [];
+      this.value = [];
+      this.handleData();
+    },
+    handleData() {
+      this.allData.forEach((item, index) => {
+        let val = {};
+        val.key = index;
+        val.label = item.objectId + "-" + item.faultTime + "-" + item.alertText;
+        this.dataList.push(val);
+        if (item.labels === this.moudleList.filter(item => Number(item.id) ===  this.current)[0].faultcode) {
+          this.value.push(index);
+        }
+      });
+    },
+    handleClick(id) {
+      this.dataList = [];
+      this.value = [];
+      this.current = id;
+      this.handleData();
+    },
+    handleChange(value, direction, movedKeys) {
+      this.value.forEach((item) => {
+        if (direction === "right") {
+          this.allData[item].labels = this.moudleList.filter(item => Number(item.id) ===  this.current)[0].faultcode;
+        }
+      });
+      if (direction === "left") {
+        movedKeys.forEach((item) => {
+          this.allData[item].labels = "";
+        });
+      }
+    },
+    closed(){
+      this.$emit('handleSave', this.allData);
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.contents {
+  height: 73vh;
+
+  .lables {
+    height: 73vh;
+    display: flex;
+    flex-direction: column;
+    font-size: 18px;
+    margin-left: 20px;
+    overflow-y: auto;
+    line-height: 50px;
+
+    .current_on {
+      color: #05bb4c;
+    }
+  }
+
+  .right {
+    width: 100%;
+    height: 100%;
+    border-left: 1px solid #999999;
+    padding-left: 27px;
+  }
+}
+</style>

+ 41 - 0
src/views/MalfunctionWarning/components/chartDetails.vue

@@ -0,0 +1,41 @@
+<template>
+  <el-dialog
+    class="bodys"
+    width="70%"
+    top="10vh"
+    title="影响因素权重图"
+    custom-class="modal"
+    :close-on-click-modal="false"
+  >
+    <div>
+      <BarChart id="barDetials" :baseLine="baseLine" width="90%" height="70vh" :barList="barList"></BarChart>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import BarChart from "./barChart.vue";
+export default {
+  props: {
+    barList: {
+      type: Array,
+    },
+    baseLine:  {
+      type: String,
+      default: "0.1",
+    },
+  },
+  components: {
+    BarChart,
+  },
+  methods: {
+    
+  },
+};
+</script>
+<style lang="less" scoped>
+.bodys{
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+</style>

+ 534 - 0
src/views/MalfunctionWarning/components/dataClassify.vue

@@ -0,0 +1,534 @@
+<template>
+  <el-dialog
+    width="70%"
+    top="10vh"
+    custom-class="modal"
+    :close-on-click-modal="false"
+  >
+    <template #title>
+      <div class="showTitles">
+        <div class="left">
+          <div class="titles">模型训练</div>
+          <button v-if="!trainingFlag" class="btn" @click="startTraining()">
+            开始训练
+          </button>
+          <button v-if="trainingFlag" disabled>训练中</button>
+        </div>
+
+        <div class="selects">
+          <div style="margin-right: 20px">
+            比例:
+            <el-select
+              v-model="percent"
+              @change="selectSearch()"
+              clearable
+              placeholder="请选择"
+              popper-class="select"
+              style="width: 120px; margin-left: 20px"
+            >
+              <el-option
+                v-for="item in percentList"
+                :key="item.value"
+                :value="item.value"
+                :label="item.label"
+              />
+            </el-select>
+          </div>
+          <div>
+            故障前时间范围:
+            <el-select
+              v-model="intervalValue"
+              clearable
+              placeholder="请选择"
+              popper-class="select"
+              style="width: 105px; margin-left: 20px"
+            >
+              <el-option
+                v-for="item in timeList"
+                :key="item.value"
+                :value="item.value"
+                :label="item.label"
+              />
+            </el-select>
+          </div>
+        </div>
+      </div>
+    </template>
+    <div>
+      <el-row :type="'flex'" class="content">
+        <el-col :span="12" class="pd-l-8">
+          <div class="titleBar">
+            <div class="titleName">训练级</div>
+            <div class="buttons">
+              <button class="btn" @click="exportALLTraining()">全部导出</button>
+              <button class="btn" @click="exportTraining(0)">导出</button>
+            </div>
+          </div>
+          <el-table
+            height="60vh"
+            ref="multipleTable"
+            empty-text="暂无数据"
+            :data="trainingList"
+            @selection-change="handleSelectionChange"
+            :header-cell-style="{
+              height: '40px',
+              background: 'rgba(83, 98, 104, 0.2)',
+              color: '#b2bdc0',
+              'border-bottom': '0px solid red',
+            }"
+            :cell-style="{
+              height: '40px',
+              'border-bottom': 'solid 0px #242424',
+            }"
+            stripe
+            style="width: 100%; margin-bottom: 10px"
+          >
+            <el-table-column type="selection" width="35"> </el-table-column>
+            <el-table-column
+              prop="faultTime"
+              label="FaultTime"
+              width="150"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="stationId"
+              label="StationId"
+              width="80"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="stationName"
+              label="StationName"
+              width="120"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="objectId"
+              label="ObjectId"
+              width="120"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="modelId"
+              label="ModelId"
+              width="120"
+              align="center"
+            ></el-table-column>
+          </el-table>
+        </el-col>
+        <el-col :span="12" class="pd-l-8">
+          <div class="titleBar">
+            <div class="titleName">测试级</div>
+            <div class="buttons">
+              <button class="btn" @click="exportALLTest()">全部导出</button>
+              <button class="btn" @click="exportTest()">导出</button>
+            </div>
+          </div>
+          <el-table
+            height="60vh"
+            ref="multipleTable"
+            empty-text="暂无数据"
+            @selection-change="handleTestChange"
+            :data="testList"
+            :header-cell-style="{
+              height: '40px',
+              background: 'rgba(83, 98, 104, 0.2)',
+              color: '#b2bdc0',
+              'border-bottom': '0px solid red',
+            }"
+            :cell-style="{
+              height: '40px',
+              'border-bottom': 'solid 0px #242424',
+            }"
+            stripe
+            style="width: 100%; margin-bottom: 10px"
+          >
+            <el-table-column type="selection" width="35"> </el-table-column>
+            <el-table-column
+              prop="faultTime"
+              label="FaultTime"
+              width="150"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="stationId"
+              label="StationId"
+              width="80"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="stationName"
+              label="StationName"
+              width="120"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="objectId"
+              label="ObjectId"
+              width="120"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="modelId"
+              label="ModelId"
+              width="120"
+              align="center"
+            ></el-table-column>
+          </el-table>
+        </el-col>
+      </el-row>
+    </div>
+    <ExportZip ref="export"></ExportZip>
+  </el-dialog>
+</template>
+<script>
+import ExportZip from "./exportZip.vue";
+import UniformCodes from "./UniformCodes.json";
+import { export_blob } from "@tools/excel/Export2Excel.js";
+import axios from "axios";
+import BASE from "@tools/basicTool.js";
+export default {
+  components: {
+    ExportZip,
+  },
+  data() {
+    return {
+      trainingList: [],
+      testList: [],
+      randoms: [],
+      trainingFlag: false,
+      percent: 7,
+      intervalValue: 1,
+      percentList: [
+        {
+          label: "10%",
+          value: 1,
+        },
+        {
+          label: "20%",
+          value: 2,
+        },
+        {
+          label: "30%",
+          value: 4,
+        },
+        {
+          label: "40%",
+          value: 4,
+        },
+        {
+          label: "50%",
+          value: 5,
+        },
+        {
+          label: "60%",
+          value: 6,
+        },
+        {
+          label: "70%",
+          value: 7,
+        },
+        {
+          label: "80%",
+          value: 8,
+        },
+        {
+          label: "90%",
+          value: 9,
+        },
+        {
+          label: "100%",
+          value: 10,
+        },
+      ],
+      timeList: [
+        { label: "1小时", value: 1 },
+        { label: "1.5小时", value: 1.5 },
+        { label: "2小时", value: 2 },
+        { label: "2.5小时", value: 2.5 },
+        { label: "3小时", value: 3 },
+        { label: "3.5小时", value: 3.5 },
+        { label: "4小时", value: 4 },
+        { label: "4.5小时", value: 4.5 },
+        { label: "5小时", value: 5 },
+        { label: "5.5小时", value: 5.5 },
+        { label: "6小时", value: 6 },
+        { label: "6.5小时", value: 6.5 },
+        { label: "7小时", value: 7 },
+        { label: "7.5小时", value: 7.5 },
+        { label: "8小时", value: 8 },
+        { label: "8.5小时", value: 8.5 },
+        { label: "9小时", value: 9 },
+        { label: "9.5小时", value: 9.5 },
+        { label: "10小时", value: 10 },
+        { label: "10.5小时", value: 10.5 },
+        { label: "11小时", value: 11 },
+        { label: "11.5小时", value: 11.5 },
+        { label: "12小时", value: 12 },
+      ],
+      exportTrainingLists: [],
+      exportTestList: [],
+      exportList: [],
+      resultData: [],
+      tHeader: [],
+    };
+  },
+  props: {
+    allData: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+    chooseAlgorithm: {
+      type: String,
+    },
+  },
+  updated() {
+    this.selectSearch();
+    this.$emit('handleInterval', this.intervalValue);
+  },
+  methods: {
+    selectSearch() {
+      (this.trainingList = []),
+        (this.testList = []),
+        (this.randoms = []),
+        this.handleData();
+    },
+    handleData() {
+      let max = this.allData.length;
+      let number = ((max * this.percent) / 10).toFixed(0);
+      if (this.randoms.length >= number) {
+        this.randoms.forEach((item) => {
+          this.trainingList.push(this.allData[item]);
+        });
+        this.testList = this.allData.filter(
+          (val) => this.trainingList.indexOf(val) === -1
+        );
+        this.trainingList.sort(this.Compare("faultTime"));
+        this.testList.sort(this.Compare("faultTime"));
+      } else {
+        let num = this.getRandoms(0, max - 1);
+        if (this.randoms.filter((item) => item === num).length > 0) {
+          this.handleData();
+        } else {
+          this.randoms.push(num);
+          this.handleData();
+        }
+      }
+    },
+    getRandoms(Min, Max) {
+      let Range = Max - Min;
+      let Rand = Math.random();
+      let num = Min + Math.round(Range * Rand);
+      return num;
+    },
+    Compare(property) {
+      return function (a, b) {
+        var value1 = new Date(a[property]).getTime();
+        var value2 = new Date(b[property]).getTime();
+        return value2 - value1;
+      };
+    },
+    handleSelectionChange(val) {
+      this.exportTrainingLists = val;
+    },
+    handleTestChange(val) {
+      this.exportTestList = val;
+    },
+    exportALLTest() {
+      this.exportTrainingLists = this.testList;
+      this.exportTraining(0);
+    },
+    exportTest() {
+      this.exportTrainingLists = this.exportTestList;
+      this.exportTraining(0);
+    },
+    exportALLTraining() {
+      this.exportTrainingLists = this.trainingList;
+      this.exportTraining(0);
+    },
+    exportTraining(index) {
+      let requestList = [];
+      this.resultData = [];
+      let hearder = [];
+      let datas = this.exportTrainingLists[index];
+      UniformCodes.forEach((code) => {
+        if (datas.stationId === code.name) {
+          code.values.forEach((val) => {
+            if (datas.modelId === val.modelId) {
+              requestList = val.codes;
+              val.codes.forEach((items) => {
+                hearder[0] = "日期";
+                hearder.push(items.name);
+              });
+            }
+          });
+        }
+      });
+      this.tHeader.push(hearder);
+      this.queryData(requestList, 0, index, datas);
+    },
+    queryData(requestList, zindex, index, datas) {
+      let that = this;
+      that.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.10.18:8011/ts/history/snap",
+        data: {
+          uniformCode: requestList[zindex].code,
+          startTs:
+            new Date(datas.faultTime).getTime() - that.intervalValue * 3600000,
+          endTs: new Date(datas.faultTime).getTime(),
+          thingType: "windturbine",
+          thingId: datas.objectId,
+          interval: 1,
+        },
+        success(res) {
+          if (res) {
+            that.resultData.push(res);
+            if (zindex === requestList.length - 1) {
+              index++;
+              that.exportList.push(that.resultData);
+              if (index >= that.exportTrainingLists.length) {
+                that.exportExcel();
+              } else {
+                that.exportTraining(index);
+              }
+            } else {
+              zindex++;
+              that.queryData(requestList, zindex, index, datas);
+            }
+          }
+        },
+      });
+    },
+    exportExcel() {
+      let that = this;
+      let paths = [];
+      let filterVal = [];
+      let pathName = ["cs1", "cs2", "cs3"];
+      that.exportTrainingLists.forEach((item, index) => {
+        let dataList = [];
+        for (let flag = 0; flag < that.exportList[index][0].length; flag++) {
+          let tempArray = [];
+          if (index === 0) {
+            filterVal.push(flag);
+          }
+          that.exportList[index].forEach((val, indexs) => {
+            if (indexs === 0) {
+              tempArray[0] = new Date(val[flag].ts).formatDate(
+                "yyyy-MM-dd hh:mm:ss"
+              );
+            }
+            tempArray.push(val[flag] ? val[flag]?.doubleValue : "");
+          });
+          dataList.push(tempArray);
+        }
+        paths.push(
+          export_blob(that.tHeader[index], that.formatJson(filterVal, dataList))
+        );
+      });
+      this.$refs.export.exportZip(paths, pathName, "测试1");
+      this.exportList = [];
+    },
+    formatJson(filterVal, jsonData) {
+      //转数据格式
+      return jsonData.map((v) => filterVal.map((j) => v[j]));
+    },
+    startTraining() {
+      let params = {};
+      let dataInfos = []
+      let dataParams = []
+      this.trainingList.forEach((item) => {
+        let datas = {};
+        datas.startTs =
+          new Date(item.faultTime).getTime() - this.intervalValue * 3600000;
+        datas.endTs = new Date(item.faultTime).getTime();
+        datas.thingId = item.objectId;
+        datas.modelId = item.modelId;
+        datas.stationId = item.stationId;
+        datas.id = item.id;
+        datas.faultTime = new Date(item.faultTime).getTime();
+        dataInfos.push(datas);
+      });
+      this.chooseAlgorithm.parameters.forEach(item =>{
+          dataParams.push(item.value)
+      })
+      let algorithm = {
+        name: this.chooseAlgorithm.name,
+        parameter: JSON.stringify(dataParams)
+      }
+      params.algorithm = algorithm
+      params.dataInfos = dataInfos
+      axios({
+        method: "post",
+        url: "http://192.168.10.18:8080/api/coordinate/execute",
+        data: params,
+        header: {
+          "Content-Type": "application/json",
+        },
+      }).then((res) => {
+        if (res.data === "success") {
+          this.BASE.showMsg({
+            type: "success",
+            msg: "训练中...",
+          });
+          this.trainingFlag = true;
+          this.$emit("click-training");
+        }else{
+          this.BASE.showMsg({
+            type: "warning",
+            msg: res.data,
+          });
+        }
+      });
+    },
+    reset() {
+      this.trainingFlag = false;
+    },
+  },
+};
+</script>
+<style scope lang="less">
+.showTitles {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+
+  .left {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+
+    .titles {
+      margin-right: 20px;
+    }
+  }
+}
+.selects {
+  display: flex;
+  flex-direction: row;
+  margin-right: 43px;
+}
+.titleBar {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+
+  .titleName {
+    color: #ffffff;
+    font-size: 16px;
+  }
+}
+.buttons {
+  display: flex;
+  flex-direction: row-reverse;
+  margin-bottom: 10px;
+
+  .btn {
+    margin-right: 15px;
+  }
+}
+</style>

+ 174 - 0
src/views/MalfunctionWarning/components/detectionRecord.vue

@@ -0,0 +1,174 @@
+<template>
+  <el-dialog
+    width="50%"
+    top="10vh"
+    custom-class="modal"
+    title="检测记录"
+    :close-on-click-modal="false"
+    @opened="opened()"
+  >
+    <div style="height: 70vh; overflow-y: auto">
+      <div class="titleBar">
+        <div class="titleName">测试级</div>
+      </div>
+      <el-table
+        ref="multipleTable"
+        empty-text="暂无数据"
+        :data="allData"
+        :header-cell-style="{
+          height: '40px',
+          background: 'rgba(83, 98, 104, 0.2)',
+          color: '#b2bdc0',
+          'border-bottom': '0px solid red',
+        }"
+        :cell-style="{
+          height: '40px',
+          'border-bottom': 'solid 0px #242424',
+        }"
+        stripe
+        style="width: 100%; margin-bottom: 10px"
+      >
+        <el-table-column
+          prop="starttime"
+          label="故障时间"
+          width="180"
+          align="center"
+        ></el-table-column>
+        <el-table-column
+          prop="stationen"
+          label="风场"
+          width="120"
+          align="center"
+        ></el-table-column>
+        <el-table-column
+          prop="stationcn"
+          label="场站名称"
+          width="140"
+          align="center"
+        ></el-table-column>
+        <el-table-column
+          prop="windturbineid"
+          label="风机编号"
+          width="120"
+          align="center"
+        ></el-table-column>
+        <el-table-column
+          prop="model"
+          label="风机型号"
+          width="120"
+          align="center"
+        ></el-table-column>
+        <el-table-column width="210" label="故障标签">
+               
+          <template #default="scope">
+            <span>
+              <el-select
+                v-model="scope.row.faultcode"
+                @change="selectChange(scope.row)"
+                clearable
+                placeholder="请选择"
+                popper-class="select"
+                style="width: 150px; margin-left: 30px"
+              >
+                <el-option
+                  v-for="item in faultLists"
+                  :key="item.faultcode"
+                  :label="item.faulttype"
+                  :value="item.faultcode"
+                >
+                </el-option>
+              </el-select>
+            </span>
+          </template>
+             
+        </el-table-column>
+        <el-table-column width="120">
+          <button class="btn" @click="getReports()">查看检测报告</button>
+        </el-table-column>
+      </el-table>
+    </div>
+    <TestReport v-model="reportDisplay"></TestReport>
+  </el-dialog>
+</template>
+<script>
+import TestReport from "./testReport.vue";
+import axios from "axios";
+export default {
+  components: {
+    TestReport,
+  },
+  props: {},
+  data() {
+    return {
+      faultLists: [],
+      allData: [],
+      reportDisplay: false,
+    };
+  },
+  created() {
+    this.getfaultLables();
+  },
+  methods: {
+      opened(){
+          this.getData();
+      },
+    getData() {
+      let that = this;
+      this.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.1.18:9002/case/fault/list",
+        data: {
+        //   station: this.selectValue,
+        //   model: this.selectMoudle,
+          st: new Date(new Date().getTime()- 86400000).formatDate("yyyy-MM-dd hh:mm:ss") ,
+          et: new Date().formatDate("yyyy-MM-dd hh:mm:ss"),
+        },
+        success(res) {
+          if (res) {
+            that.allData = res.data;
+          }
+        },
+      });
+    },
+    getfaultLables() {
+      let that = this;
+      this.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.1.18:9002/know/fault/type/all",
+        success(res) {
+          if (res) {
+            that.faultLists = res.data;
+          }
+        },
+      });
+    },
+    selectChange(data) {
+        let params = [];
+        data.faulttype = this.faultLists.filter(
+              (item) => item.faultcode === data.faultcode
+            )[0]?.faulttype,
+        params.push(data)
+        axios({
+          method: "post",
+          url: "http://192.168.10.19:9002/case/fault/insert",
+          data: params,
+          header: {
+            "Content-Type": "application/json",
+          },
+        }).then((res) => {
+          if (res.data.code !== 200) {
+            this.BASE.showMsg({
+              type: "error",
+              msg: "标签修改失败",
+            });
+          }
+        });
+    },
+    getReports(){
+      this.reportDisplay = true
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+</style>

+ 58 - 0
src/views/MalfunctionWarning/components/exportZip.vue

@@ -0,0 +1,58 @@
+<template>
+  <div></div>
+</template>
+<script>
+import JsZip from "jszip";
+import { export_blob } from "@tools/excel/Export2Excel.js";
+import BASE from "@tools/basicTool.js";
+export default {
+  data() {
+    return {
+      paths: [],
+    };
+  },
+  methods: {
+    exportZip(paths, pathName, zipName) {
+      
+      var zip = new JsZip();
+      paths.forEach((item, index) => {
+        const arr_name = item; // 下载文件, 并存成ArrayBuffer对象
+        const file_name = pathName[index] + ".xlsx"; // 获取文件名
+        zip.file(file_name, arr_name, {
+          binary: true,
+        }); // 逐个添加文件
+      });
+      zip
+        .generateAsync({
+          type: "blob",
+        })
+        .then(function (content) {
+          // 下载的文件名
+          var filename = zipName + ".zip";
+          // 创建隐藏的可下载链接
+          var eleLink = document.createElement("a");
+          eleLink.download = filename;
+          eleLink.style.display = "none";
+          // 下载内容转变成blob地址
+          eleLink.href = URL.createObjectURL(content);
+          // 触发点击
+          document.body.appendChild(eleLink);
+          eleLink.click();
+          // 然后移除
+          document.body.removeChild(eleLink);
+          // if (deepIndex) {
+          //   this.allExportF(deepIndex); //递归,去执行ajax
+          //   if (this.stations.length == deepIndex) {
+          //     BASE.closeLoading();
+          //   }
+          // } else if (this.single) {
+          //   BASE.closeLoading();
+          //   this.single = false;
+          // }
+        });
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+</style>

+ 101 - 0
src/views/MalfunctionWarning/components/lineChart.vue

@@ -0,0 +1,101 @@
+<template>
+  <div class="precisionEcharts" :id="id"></div>
+</template>
+<script>
+import * as echarts from "echarts";
+export default {
+  props: {
+    dataList: {
+      type: String,
+      required: true,
+    },
+    id: Object,
+    reportFlag: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {};
+  },
+  mounted() {
+    console.log(1111111);
+    this.$nextTick(() => {
+      this.initChart();
+    });
+  },
+  updated() {
+    console.log(111111111);
+    this.$nextTick(() => {
+      this.initChart();
+    });
+  },
+  methods: {
+    initChart() {
+      let chartDom = document.getElementById(this.id);
+      let myChart = echarts.init(chartDom);
+      let option = {
+        title: {
+          text: "",
+        },
+        legend: {
+          data: [Object.keys(this.dataList)[0],Object.keys(this.dataList)[1]],
+          textStyle: {
+            color: this.reportFlag? '#000000' : "#ffffff",
+          },
+        },
+        tooltip: {
+          trigger: "axis",
+        },
+        grid: {
+          left: "3%",
+          right: "4%",
+          bottom: "3%",
+          containLabel: true,
+        },
+        xAxis: {
+          type: "category",
+          boundaryGap: false,
+          splitLine: { show: false },
+          data: this.dataList[Object.keys(this.dataList)[0]]?.forEach((item, index) => {
+            return index;
+          }),
+        },
+        yAxis: {
+          type: "value",
+          splitLine: { show: false },
+        },
+        series: [
+          {
+            name: Object.keys(this.dataList)[0],
+            type: "line",
+            smooth: true,
+            data: this.dataList[Object.keys(this.dataList)[0]],
+          },
+          {
+            name: Object.keys(this.dataList)[1],
+            type: "line",
+            smooth: true,
+            data: this.dataList[Object.keys(this.dataList)[1]],
+          },
+        ],
+      };
+      option && myChart.setOption(option);
+    },
+  },
+  watch: {
+    dataList: {
+      handler(newValue, oldValue) {
+        this.initChart();
+      },
+      deep: true,
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.precisionEcharts {
+  width: 600px;
+  height: 250px;
+}
+</style>

+ 463 - 0
src/views/MalfunctionWarning/components/records.vue

@@ -0,0 +1,463 @@
+<template>
+  <el-dialog
+    width="70%"
+    top="10vh"
+    custom-class="modal"
+    :close-on-click-modal="false"
+    title="训练记录"
+    v-model="dialogTableVisible"
+    @opened="opened()"
+    @closed="closed()"
+  >
+    <el-row :type="'flex'" class="content">
+      <el-col :span="12" class="pd-l-8">
+        <div style="font-size: 20px">历史记录</div>
+        <div style="height: 60vh; overflow-y: auto; margin-top: 30px">
+          <div v-if="supervisedFlag">
+            <div
+              class="body"
+              v-for="(item, index) in recordList"
+              :key="index"
+              @click="chooses(index)"
+            >
+              <div class="left">
+                <div :class="index === current ? 'round_on' : 'round'"></div>
+                <div class="line"></div>
+              </div>
+              <div class="right">
+                <div>{{ item.showTime }}</div>
+                <div class="content">
+                  <div class="names">
+                    {{ item.showName || item.ducumentName }}
+                  </div>
+                  <button class="btn" @click="deleteDate(item.name)">
+                    删除
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div v-else>
+            <div
+              class="body"
+              v-for="(item, index) in showResultList"
+              :key="index"
+              @click="choose(index)"
+            >
+              <div class="left">
+                <div :class="index === current ? 'round_on' : 'round'"></div>
+                <div class="line"></div>
+              </div>
+              <div class="right">
+                <div>{{ item.showTime }}</div>
+                <div class="content">
+                  <div class="names">
+                    {{ item.showName || item.ducumentName }}
+                  </div>
+                  <button class="btn" @click="deleteDate(item.name)">
+                    删除
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="12" class="pd-l-8">
+        <div style="margin-left: 30px; font-size: 20px">训练结果</div>
+        <div v-if="supervisedFlag">
+          <LineChart id="accuracyCharts" :dataList="accuracyList"></LineChart>
+          <BarChart
+            id="barCharts"
+            @click="showDetials"
+            height="350px"
+            :barList="barList"
+            :baseLine="recordList[current]?.coordinate?.BaseLine"
+          ></BarChart>
+        </div>
+        <div v-else>
+          <div
+            class="scatterEchart"
+            id="scatterEcharts"
+            @click="showResults()"
+          ></div>
+        </div>
+      </el-col>
+    </el-row>
+    <ChartDetails
+      v-model="detialsDisplay"
+      :barList="recordList[current]?.coordinate?.bar"
+      :baseLine="recordList[current]?.coordinate?.BaseLine"
+    ></ChartDetails>
+  </el-dialog>
+</template>
+<script>
+import BarChart from ".//barChart.vue";
+import LineChart from "./lineChart.vue";
+import ChartDetails from "./chartDetails.vue";
+import * as echarts from "echarts";
+export default {
+  components: {
+    BarChart,
+    LineChart,
+    ChartDetails,
+  },
+  props: {
+    supervisedFlag: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      current: 0,
+      accuracyList:{},
+      barList: [],
+      resultList: [],
+      showResultList: [],
+      recordList: [],
+      detialsDisplay: false,
+      colors: [
+        "#FFFFFF",
+        "#FF0000",
+        "#820041",
+        "#FF00FF",
+        "#8600FF",
+        "#0000C6",
+        "#00FFFF",
+        "#00DB00",
+        "#F9F900",
+        "#FF5809",
+        "#984B4B",
+        "#AFAF61",
+        "#5151A2",
+        "#FFAF60",
+        "#B766AD",
+        "#006030",
+        "#2894FF",
+        "#796400",
+      ],
+      series: [
+        {
+          name: "",
+          symbolSize: 10,
+          encode: { tooltip: [0, 1] },
+          itemStyle: {
+            color: "#ffffff",
+          },
+          data: [
+            [11.0, 8.04],
+            [8.07, 6.95],
+            [13.0, 7.58],
+            [9.05, 8.81],
+            [11.0, 8.33],
+            [14.0, 7.66],
+            [13.4, 6.81],
+            [10.0, 6.33],
+            [14.0, 8.96],
+            [12.5, 6.82],
+            [9.15, 7.2],
+            [11.5, 7.2],
+            [3.03, 4.23],
+            [12.2, 7.83],
+            [2.02, 4.47],
+            [1.05, 3.33],
+            [4.05, 4.96],
+            [6.03, 7.24],
+            [12.0, 6.26],
+            [12.0, 8.84],
+            [7.08, 5.82],
+            [5.02, 5.68],
+          ],
+          type: "scatter",
+        },
+        {
+          name: "",
+          encode: { tooltip: [0, 1] },
+          symbolSize: 10,
+          data: [
+            [1.0, 8.04],
+            [18.07, 6.95],
+            [3.0, 7.58],
+            [19.05, 8.81],
+            [1.0, 8.33],
+            [4.0, 7.66],
+            [3.4, 6.81],
+            [20.0, 6.33],
+            [4.0, 8.96],
+            [2.5, 6.82],
+            [19.15, 7.2],
+            [11.5, 7.2],
+            [3.03, 4.23],
+            [12.2, 7.83],
+            [2.02, 4.47],
+            [1.05, 3.33],
+            [4.05, 4.96],
+            [6.03, 7.24],
+            [12.0, 6.26],
+            [12.0, 8.84],
+            [7.08, 5.82],
+            [5.02, 5.68],
+          ],
+          type: "scatter",
+        },
+      ],
+    };
+  },
+  methods: {
+    opened() {
+      if (!this.supervisedFlag) {
+        this.getRecords();
+        this.getScatter();
+      } else {
+        this.getSupervisedRecord();
+      }
+    },
+    showDetials() {
+      this.detialsDisplay = true;
+    },
+    choose(index) {
+      this.current = index;
+    },
+    chooses(index) {
+      this.current = index;
+      this.accuracyList.accuracy =
+        this.recordList[this.current]?.coordinate.accuracy;
+      this.accuracyList.val_accuracy =
+        this.recordList[this.current]?.coordinate.val_accuracy;
+      this.recordList[this.current]?.coordinate.bar?.sort(
+        this.Compare("value")
+      );
+      this.barList = this.recordList[this.current]?.coordinate.bar?.slice(0, 5);
+    },
+    getRecords() {
+      let that = this;
+      this.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.10.18:8080/api/coordinate/history",
+        success(res) {
+          if (res) {
+            res.forEach((item) => {
+              let arr = item.name.split("-");
+              item.coordinate = JSON.parse(item.coordinate);
+              item.showName = arr[0];
+              item.showTime = new Date(Number(arr[1])).formatDate(
+                "yyyy-MM-dd hh:mm:ss"
+              );
+            });
+            that.showResultList = res;
+            that.dataDeal();
+          }
+        },
+      });
+    },
+    getSupervisedRecord() {
+      let that = this;
+      this.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.10.18:8080/api/supervised/history",
+        success(res) {
+          if (res) {
+            res.forEach((item) => {
+              let arr = item.name.split("-");
+              item.coordinate = JSON.parse(item.coordinate);
+              item.showName = arr[2];
+              item.showTime = new Date(Number(arr[3])).formatDate(
+                "yyyy-MM-dd hh:mm:ss"
+              );
+              item.coordinate.bar = JSON.parse(item.coordinate.bar);
+            });
+            that.accuracyList.accuracy = res[that.current]?.coordinate.accuracy;
+            that.accuracyList.val_accuracy =
+              res[that.current]?.coordinate.val_accuracy;
+            res[that.current]?.coordinate.bar?.sort(that.Compare("value"));
+            that.barList = res[that.current]?.coordinate.bar?.slice(0, 5);
+            that.recordList = res;
+          }
+        },
+      });
+    },
+    Compare(property) {
+      return function (a, b) {
+        var value1 = a[property];
+        var value2 = b[property];
+        return value2 - value1;
+      };
+    },
+    dataDeal() {
+      let that = this;
+      that.resultList = [];
+      let data = that.showResultList[that.current];
+      let dataList = [];
+      data?.coordinate.forEach((item, index) => {
+        let idList = [];
+        item.value.forEach((val) => {
+          let datas = {};
+          let arr = val[2].split("-");
+          let dataArr = [];
+          datas.name =
+            arr[0] +
+            "-" +
+            new Date(Number(arr[1])).formatDate("yyyy-MM-dd hh:mm:ss");
+          dataArr.push([Number(val[0]), Number(val[1])]);
+          idList.push(arr[2]);
+          datas.symbolSize = 10;
+          datas.encode = { tooltip: [0, 1] };
+          datas.data = dataArr;
+          datas.type = "scatter";
+          datas.itemStyle = { color: that.colors[index] };
+          dataList.push(datas);
+        });
+        that.resultList.push(idList);
+      });
+      that.series = dataList;
+      that.getScatter();
+    },
+    getScatter() {
+      let chartDom = document.getElementById("scatterEcharts");
+      let myChart = echarts.init(chartDom);
+      let option;
+      option = {
+        legend: {
+          show: true,
+          data: ["测试", "测试1"],
+          right: 56,
+          icon: "circle",
+          itemWidth: 6,
+          inactiveColor: "#606769",
+          textStyle: {
+            color: "#B3BDC0",
+            fontSize: 12,
+          },
+        },
+        xAxis: {
+          splitLine: { show: false },
+        },
+        yAxis: {
+          splitLine: { show: false },
+        },
+        tooltip: {
+          position: "top",
+        },
+        series: this.series,
+      };
+      option && myChart.setOption(option);
+    },
+    showResults() {
+      this.showList = [];
+      this.getFaultList(0);
+    },
+    deleteDate(val) {
+      let that = this;
+      this.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.10.18:8080/api/coordinate/history/remove/",
+        data: {
+          names: val,
+        },
+        success(res) {
+          if (res) {
+            that.showResultList = [];
+            that.barList = [];
+            that.recordList = [];
+            that.current = 0
+            if (!that.supervisedFlag) {
+              that.getRecords();
+              that.getScatter();
+            } else {
+              that.getSupervisedRecord();
+            }
+          }
+        },
+      });
+    },
+    getFaultList(index) {
+      let result = this.resultList[index];
+      let that = this;
+      this.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.10.18:8075/fault/history/",
+        data: {
+          ids: result.join(","),
+        },
+        success(res) {
+          if (res) {
+            res.forEach((item) => {
+              item.colors = that.colors[index];
+            });
+            that.showList =
+              that.showList.length > 0 ? [that.showList, ...res] : res;
+            index++;
+            if (index < that.resultList.length) {
+              that.getFaultList(index);
+            } else {
+              that.$emit("results", that.showList);
+            }
+          }
+        },
+      });
+    },
+    closed() {
+      this.$emit("records-closed");
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.body {
+  display: flex;
+  flex-direction: row;
+  height: 75px;
+  width: 100%;
+
+  .left {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    width: 30px;
+    margin-left: 30px;
+
+    .round_on {
+      width: 20px;
+      height: 27px;
+      border-radius: 50%;
+      background-color: rgb(30, 209, 45);
+    }
+    .round {
+      width: 20px;
+      height: 27px;
+      border-radius: 50%;
+      background-color: crimson;
+    }
+
+    .line {
+      width: 2px;
+      height: 100%;
+      background-color: #ffffff;
+    }
+  }
+
+  .right {
+    width: 100%;
+    margin-left: 20px;
+
+    .content {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+      margin-top: 10px;
+
+      .btn {
+        margin-right: 20px;
+      }
+    }
+  }
+}
+.scatterEchart {
+  width: 600px;
+  height: 500px;
+  margin-top: -20px;
+}
+</style>

+ 430 - 0
src/views/MalfunctionWarning/components/superviseDataClassify.vue

@@ -0,0 +1,430 @@
+<template>
+  <el-dialog
+    width="70%"
+    top="10vh"
+    custom-class="modal"
+    :close-on-click-modal="false"
+  >
+    <template #title>
+      <div class="showTitles">
+        <div class="left">
+          <div class="titles">模型训练</div>
+          <button v-if="!trainingFlag" class="btn" @click="startTraining()">
+            开始训练
+          </button>
+          <button v-if="trainingFlag" disabled>训练中</button>
+        </div>
+
+        <div class="selects">
+          <div style="margin-right: 20px">
+            比例:
+            <el-select
+              v-model="percent"
+              @change="selectSearch()"
+              clearable
+              placeholder="请选择"
+              popper-class="select"
+              style="width: 120px; margin-left: 20px"
+            >
+              <el-option
+                v-for="item in percentList"
+                :key="item.value"
+                :value="item.value"
+                :label="item.label"
+              />
+            </el-select>
+          </div>
+          <div>
+            故障前时间范围:
+            <el-select
+              v-model="intervalValue"
+              clearable
+              placeholder="请选择"
+              popper-class="select"
+              style="width: 105px; margin-left: 20px"
+            >
+              <el-option
+                v-for="item in timeList"
+                :key="item.value"
+                :value="item.value"
+                :label="item.label"
+              />
+            </el-select>
+          </div>
+        </div>
+      </div>
+    </template>
+    <div style="height: 70vh; overflow-y: auto">
+      <el-row :type="'flex'" class="content">
+        <el-col :span="12" class="pd-l-8">
+          <div class="titleBar">
+            <div class="titleName">训练级</div>
+          </div>
+          <el-table
+            ref="multipleTable"
+            empty-text="暂无数据"
+            :data="trainingList"
+            :header-cell-style="{
+              height: '40px',
+              background: 'rgba(83, 98, 104, 0.2)',
+              color: '#b2bdc0',
+              'border-bottom': '0px solid red',
+            }"
+            :cell-style="{
+              height: '40px',
+              'border-bottom': 'solid 0px #242424',
+            }"
+            stripe
+            style="width: 100%; margin-bottom: 10px"
+          >
+            <el-table-column
+              prop="starttime"
+              label="故障时间"
+              width="180"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="stationen"
+              label="风场"
+              width="80"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="stationcn"
+              label="场站名称"
+              width="150"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="windturbineid"
+              label="风机编号"
+              width="80"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="model"
+              label="风机型号"
+              width="100"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="faulttype"
+              label="故障"
+              width="120"
+              align="center"
+            ></el-table-column>
+          </el-table>
+        </el-col>
+        <el-col :span="12" class="pd-l-8">
+          <div class="titleBar">
+            <div class="titleName">测试级</div>
+          </div>
+          <el-table
+            ref="multipleTable"
+            empty-text="暂无数据"
+            :data="testList"
+            :header-cell-style="{
+              height: '40px',
+              background: 'rgba(83, 98, 104, 0.2)',
+              color: '#b2bdc0',
+              'border-bottom': '0px solid red',
+            }"
+            :cell-style="{
+              height: '40px',
+              'border-bottom': 'solid 0px #242424',
+            }"
+            stripe
+            style="width: 100%; margin-bottom: 10px"
+          >
+            <el-table-column
+              prop="starttime"
+              label="故障时间"
+              width="175"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="stationen"
+              label="风场"
+              width="80"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="stationcn"
+              label="场站名称"
+              width="150"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="windturbineid"
+              label="风机编号"
+              width="80"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="model"
+              label="风机型号"
+              width="100"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="faulttype"
+              label="故障"
+              width="110"
+              align="center"
+            ></el-table-column>
+          </el-table>
+        </el-col>
+      </el-row>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import axios from "axios";
+import BASE from "@tools/basicTool.js";
+export default {
+  components: {
+  },
+  data() {
+    return {
+      trainingList: [],
+      testList: [],
+      randoms: [],
+      trainingFlag: false,
+      percent: 7,
+      intervalValue: 1,
+      faultList: {
+        JC: "机舱故障",
+        BJ: "变桨故障",
+        PH: "偏航故障",
+        FDJ: "发电机故障",
+        CLX: "齿轮箱故障",
+        YY: "液压故障",
+        ZZ: "主轴故障",
+        ZK: "主控故障",
+        BPQ: "变频器故障",
+      },
+      percentList: [
+        {
+          label: "10%",
+          value: 1,
+        },
+        {
+          label: "20%",
+          value: 2,
+        },
+        {
+          label: "30%",
+          value: 4,
+        },
+        {
+          label: "40%",
+          value: 4,
+        },
+        {
+          label: "50%",
+          value: 5,
+        },
+        {
+          label: "60%",
+          value: 6,
+        },
+        {
+          label: "70%",
+          value: 7,
+        },
+        {
+          label: "80%",
+          value: 8,
+        },
+        {
+          label: "90%",
+          value: 9,
+        },
+        {
+          label: "100%",
+          value: 10,
+        },
+      ],
+      timeList: [
+        { label: "1小时", value: 1 },
+        { label: "1.5小时", value: 1.5 },
+        { label: "2小时", value: 2 },
+        { label: "2.5小时", value: 2.5 },
+        { label: "3小时", value: 3 },
+        { label: "3.5小时", value: 3.5 },
+        { label: "4小时", value: 4 },
+        { label: "4.5小时", value: 4.5 },
+        { label: "5小时", value: 5 },
+        { label: "5.5小时", value: 5.5 },
+        { label: "6小时", value: 6 },
+        { label: "6.5小时", value: 6.5 },
+        { label: "7小时", value: 7 },
+        { label: "7.5小时", value: 7.5 },
+        { label: "8小时", value: 8 },
+        { label: "8.5小时", value: 8.5 },
+        { label: "9小时", value: 9 },
+        { label: "9.5小时", value: 9.5 },
+        { label: "10小时", value: 10 },
+        { label: "10.5小时", value: 10.5 },
+        { label: "11小时", value: 11 },
+        { label: "11.5小时", value: 11.5 },
+        { label: "12小时", value: 12 },
+      ],
+      exportTrainingLists: [],
+      exportTestList: [],
+      exportList: [],
+      resultData: [],
+      tHeader: [],
+    };
+  },
+  props: {
+    allData: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+    chooseAlgorithm: {
+      type: String,
+    },
+  },
+  updated() {
+    this.selectSearch();
+  },
+  methods: {
+    selectSearch() {
+      (this.trainingList = []),
+        (this.testList = []),
+        (this.randoms = []),
+        this.handleData();
+    },
+    handleData() {
+      let max = this.allData.length;
+      let number = ((max * this.percent) / 10).toFixed(0);
+      if (this.randoms.length >= number) {
+        this.randoms.forEach((item) => {
+          this.trainingList.push(this.allData[item]);
+        });
+        this.testList = this.allData.filter(
+          (val) => this.trainingList.indexOf(val) === -1
+        );
+        this.trainingList.sort(this.Compare("faultTime"));
+        this.testList.sort(this.Compare("faultTime"));
+      } else {
+        let num = this.getRandoms(0, max - 1);
+        if (this.randoms.filter((item) => item === num).length > 0) {
+          this.handleData();
+        } else {
+          this.randoms.push(num);
+          this.handleData();
+        }
+      }
+    },
+    getRandoms(Min, Max) {
+      let Range = Max - Min;
+      let Rand = Math.random();
+      let num = Min + Math.round(Range * Rand);
+      return num;
+    },
+    Compare(property) {
+      return function (a, b) {
+        var value1 = new Date(a[property]).getTime();
+        var value2 = new Date(b[property]).getTime();
+        return value2 - value1;
+      };
+    },
+    startTraining() {
+      let params = {};
+      let dataInfos = []
+      let dataParams = []
+      this.trainingList.forEach((item) => {
+        let datas = {};
+        datas.startTs =
+          new Date(item.starttime).getTime() - this.intervalValue * 3600000;
+        datas.endTs = new Date(item.starttime).getTime();
+        datas.thingId = item.windturbineid;
+        datas.modelId = item.model;
+        datas.stationId = item.stationen;
+        datas.id = item.faultid;
+        datas.faultTime = new Date(item.starttime).getTime();
+        datas.tag = item.faultcode
+        dataInfos.push(datas);
+      });
+      this.chooseAlgorithm.parameters.forEach(item =>{
+          dataParams.push(item.value)
+      })
+      let algorithm = {
+        name: this.chooseAlgorithm.name,
+        parameter: JSON.stringify(dataParams)
+      }
+      params.algorithm = algorithm
+      params.dataInfos = dataInfos
+      axios({
+        method: "post",
+        url: "http://192.168.10.18:8080/api/supervised/execute",
+        data: params,
+        header: {
+          "Content-Type": "application/json",
+        },
+      }).then((res) => {
+        if (res.data === "success") {
+          this.BASE.showMsg({
+            type: "success",
+            msg: "训练中...",
+          });
+          // this.trainingFlag = true;
+          this.$emit("click-training");
+        }else{
+          this.BASE.showMsg({
+            type: "warning",
+            msg: res.data,
+          });
+        }
+      });
+    },
+  },
+};
+</script>
+<style scope lang="less">
+.showTitles {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+
+  .left {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+
+    .titles {
+      margin-right: 20px;
+    }
+  }
+}
+.selects {
+  display: flex;
+  flex-direction: row;
+  margin-right: 43px;
+}
+.titleBar {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+
+  .titleName {
+    color: #ffffff;
+    font-size: 16px;
+  }
+}
+.buttons {
+  display: flex;
+  flex-direction: row-reverse;
+  margin-bottom: 10px;
+
+  .btn {
+    margin-right: 15px;
+  }
+}
+</style>

文件差异内容过多而无法显示
+ 273 - 0
src/views/MalfunctionWarning/components/testReport.vue


+ 401 - 0
src/views/MalfunctionWarning/components/trainingResults.vue

@@ -0,0 +1,401 @@
+<template>
+  <el-dialog
+    width="70%"
+    top="10vh"
+    custom-class="modal"
+    :close-on-click-modal="false"
+    title="训练结果"
+    v-model="dialogTableVisible"
+    @opened="opened()"
+  >
+    <el-row :type="'flex'" class="content">
+      <el-col :span="12" class="pd-l-8">
+        <div style="display: flex; flex-direction: row-reverse">
+          <button class="btn" style="margin-top: 0px" @click="batch">
+            批量处理
+          </button>
+        </div>
+        <div style="height: 70vh; overflow-y: auto">
+          <div>
+            <el-table
+              highlight-current-row
+              @current-change="handleClick"
+              ref="multipleTable"
+              empty-text="暂无数据"
+              :data="allData"
+              :header-cell-style="{
+                height: '40px',
+                background: 'rgba(83, 98, 104, 0.2)',
+                color: '#b2bdc0',
+                'border-bottom': '0px solid red',
+              }"
+              :cell-style="{
+                height: '40px',
+                'border-bottom': 'solid 0px #242424',
+              }"
+              stripe
+              style="width: 100%; margin-bottom: 10px"
+            >
+              <el-table-column width="30">
+                     
+                <template #default="scope">
+                  <span
+                    class="mark"
+                    :style="{ 'background-color': scope.row.colors }"
+                  ></span>
+                </template>
+                   
+              </el-table-column>
+              <el-table-column
+                prop="faultTime"
+                label="FaultTime"
+                width="150"
+                align="center"
+              ></el-table-column>
+              <!-- <el-table-column
+                prop="stationId"
+                label="StationId"
+                width="80"
+                align="center"
+              ></el-table-column> -->
+              <el-table-column
+                prop="stationName"
+                label="StationName"
+                width="120"
+                align="center"
+              ></el-table-column>
+              <el-table-column
+                prop="objectId"
+                label="ObjectId"
+                width="80"
+                align="center"
+              ></el-table-column>
+              <el-table-column
+                prop="modelId"
+                label="ModelId"
+                width="100"
+                align="center"
+              ></el-table-column>
+              <el-table-column width="150">
+                     
+                <template #default="scope">
+                  <span>
+                    <el-select
+                      v-model="scope.row.labels"
+                      @change="selectSearch(scope.row)"
+                      clearable
+                      placeholder="请选择"
+                      popper-class="select"
+                      style="width: 120px; margin-left: 20px"
+                    >
+                      <el-option
+                        v-for="item in moudleList"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value"
+                      >
+                      </el-option>
+                    </el-select>
+                  </span>
+                </template>
+                   
+              </el-table-column>
+            </el-table>
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="12" class="pd-l-8">
+        <MultipleYLineChartNormal
+          height="35vh"
+          ref="multiple"
+          :list="Analysis"
+          :yAxises="AnalysisYAxises"
+          :showLegend="true"
+          :default="!batchDisplay"
+        ></MultipleYLineChartNormal>
+        <button class="btn" @click="handleSearch()" style="margin-top: 20px">
+          查询
+        </button>
+        <div class="lables">
+          <button
+            v-for="(item, index) in lableList"
+            :key="index"
+            :class="item.isShow ? 'btn green' : 'btn'"
+            @click="handleChange(item)"
+          >
+            {{ item.showName }}
+          </button>
+        </div>
+      </el-col>
+      <BatchData
+        v-model="batchDisplay"
+        :moudleList="moudleList"
+        :allData="allData"
+        @handleSave="saveData"
+      ></BatchData>
+    </el-row>
+  </el-dialog>
+</template>
+<script>
+import BatchData from "./batchData.vue";
+import UniformCodes from "./UniformCodes.json";
+import MultipleYLineChartNormal from "../../NewPages/multiple-y-line-chart-normal.vue";
+import BASE from "@tools/basicTool.js";
+import axios from "axios";
+export default {
+  components: { MultipleYLineChartNormal, BatchData },
+  props: {
+    allData: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+    intervalValue: {
+      type: Number,
+      default: 1,
+    },
+  },
+  data() {
+    return {
+      chooseData: {},
+      lableList: [],
+      lineList: [],
+      batchDisplay: false,
+      moudleList: [
+        {
+          id: 0,
+          value: "JC",
+          label: "机舱故障",
+        },
+        {
+          id: 1,
+          value: "BJ",
+          label: "变桨故障",
+        },
+        {
+          id: 2,
+          value: "PH",
+          label: "偏航故障",
+        },
+        {
+          id: 3,
+          value: "FDJ",
+          label: "发电机故障",
+        },
+        {
+          id: 4,
+          value: "CLX",
+          label: "齿轮箱故障",
+        },
+        {
+          id: 5,
+          value: "YY",
+          label: "液压故障",
+        },
+        {
+          id: 6,
+          value: "ZZ",
+          label: "主轴故障",
+        },
+        {
+          id: 7,
+          value: "ZK",
+          label: "主控故障",
+        },
+        {
+          id: 8,
+          value: "BPQ",
+          label: "变频器故障",
+        },
+      ],
+
+      Analysis: [
+        {
+          title: "",
+          yAxisIndex: 0, // 使用单位
+          value: [],
+        },
+      ],
+      AnalysisYAxises: [
+        {
+          name: "",
+          min: "",
+          max: "",
+          unit: "",
+          position: "left",
+        },
+        {
+          name: "",
+          min: "",
+          max: "",
+          unit: "",
+          position: "right",
+        },
+      ],
+    };
+  },
+  mounted() {},
+  methods: {
+    opened() {
+      (this.lableList = []),
+        (this.lineList = []),
+        (this.chooseData = this.allData[0]);
+      // this.queryData();
+      this.$refs.multipleTable.setCurrentRow(this.allData[0]);
+      this.dataDeal(this.allData[0]);
+    },
+    queryData() {
+      let param = [];
+      this.allData.forEach((item) => {
+        param.push(item.id);
+      });
+      let that = this;
+      that.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.1.18:9002/case/fault/train/all",
+        data: {
+          ids: param.join(","),
+        },
+        success(res) {
+          if (res) {
+            res.data.forEach((item) => {
+              that.allData.filter((items) => items.id === item.id)[0].labels =
+                item.labels;
+            });
+          }
+        },
+      });
+    },
+    handleClick(val) {
+      let valus = val ? val : this.allData[0];
+      if (val) {
+        this.dataDeal(valus);
+        this.handleSearch();
+      }
+    },
+    dataDeal(val) {
+      this.chooseData = val;
+      this.lableList = [];
+      UniformCodes.forEach((code) => {
+        if (val?.stationId === code.name) {
+          code.values.forEach((item) => {
+            if (val.modelId === item.modelId) {
+              item.codes.forEach((values, index) => {
+                if (values.name.length > 5) {
+                  values.showName = values.name.substring(0, 5) + "...";
+                } else {
+                  values.showName = values.name;
+                }
+                if (index < 5) {
+                  values.isShow = true;
+                } else {
+                  values.isShow = false;
+                }
+              });
+              this.lableList = item.codes;
+            }
+          });
+        }
+      });
+    },
+    handleChange(val) {
+      let index = this.lableList.filter((item) => item.isShow === true).length;
+      if (index >= 5 && val.isShow === false) {
+        this.BASE.showMsg({
+          type: "warning",
+          msg: "每次查询不可大于5个",
+        });
+        val.isShow = false;
+      } else {
+        val.isShow = !val.isShow;
+      }
+    },
+    handleSearch() {
+      this.lineList = [];
+      let max = this.lableList.filter((item) => item.isShow === true).length;
+      if (max > 0) {
+        this.historyData(0, max);
+      }
+    },
+    historyData(index, max) {
+      let dataLsit = this.lableList.filter((item) => item.isShow === true);
+      let that = this;
+      that.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.10.18:8011/ts/history/snap",
+        data: {
+          uniformCode: dataLsit[index].code,
+          startTs:
+            new Date(that.chooseData.faultTime).getTime() -
+            that.intervalValue * 3600000,
+          endTs: new Date(that.chooseData.faultTime).getTime() + 600000,
+          thingType: "windturbine",
+          thingId: that.chooseData.objectId,
+          interval: 1,
+        },
+        success(res) {
+          if (res) {
+            let obj = {
+              title: dataLsit[index].name,
+              value: res,
+            };
+            that.lineList.push(obj);
+            index++;
+            if (index < max) {
+              that.historyData(index, max);
+            } else {
+              that.Analysis = that.lineList;
+            }
+          }
+        },
+      });
+    },
+    selectSearch(val) {
+      this.saveData(this.allData);
+    },
+    batch() {
+      this.batchDisplay = true;
+    },
+    saveData(data) {
+      this.$emit('save-date', data);
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.templates {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.mark {
+  display: flex;
+  width: 15px;
+  height: 15px;
+  border-radius: 50%;
+}
+.lables {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  height: 28vh;
+  overflow-y: auto;
+  margin-top: 10px;
+}
+.btn green {
+  width: 117px;
+  margin-right: 7px;
+  margin-top: 10px;
+}
+.btn {
+  width: 117px;
+  margin-right: 7px;
+  margin-top: 10px;
+}
+.btn + button {
+  margin-left: 0px;
+}
+</style>

二进制
src/views/MalfunctionWarning/img/generator.png


+ 0 - 0
src/views/MalfunctionWarning/mdjl.vue


文件差异内容过多而无法显示
+ 581 - 0
src/views/MalfunctionWarning/supervised.vue


+ 0 - 1
src/views/NewPages/alarm-center-1.vue

@@ -334,7 +334,6 @@ export default {
           name: name,
         },
         success(res) {
-			console.log(res)
           if (res.data.length == 1) {
             that.dialogVisible = true;
             BASE.closeLoading();

+ 48 - 4
src/views/NewPages/multiple-y-line-chart-normal.vue

@@ -239,6 +239,10 @@ export default {
       type: Boolean,
       default: false,
     },
+    default: {
+      type: Boolean,
+      default: false,
+    },
     // 轴
     yAxises: {
       type: Array,
@@ -296,12 +300,19 @@ export default {
     },
     xdata() {
       if (this.list.length > 1) {
+        // this.list[1].value.forEach((lEle, lIndex) => {
+        //   console.log(
+        //     this.list[1].value.indexOf(
+        //       this.list[1].value[lIndex].text == "00:00"
+        //     )
+        //   );
+        // });
         return this.list[1]?.value.map((t) => {
-          return t.text;
+          return t.text || new Date(t.ts).formatDate("hh:mm:ss");
         });
       } else if (this.list.length == 1) {
         return this.list[0]?.value.map((t) => {
-          return t.text;
+          return t.text || new Date(t.ts).formatDate("hh:mm:ss");
         });
       }
     },
@@ -357,7 +368,13 @@ export default {
           showSymbol: false,
           yAxisIndex: value.yAxisIndex,
           data: value.value.map((t) => {
-            return t.value;
+            if (t.value || t.value === 0) {
+              return t.value;
+            } else if (t.doubleValue || t.doubleValue === 0) {
+              return t.doubleValue;
+            } else {
+              return t.longValue;
+            }
           }),
         });
       });
@@ -374,6 +391,14 @@ export default {
       chart.clear();
 
       chart.setOption(option);
+      if (this.default) {
+        chart.dispatchAction({
+          type: "showTip",
+          seriesIndex: 0, // 显示第几个series
+          dataIndex: this.list[0].value.length - 600, // 显示第几个数据
+        });
+      }
+
       this.resize = function () {
         chart.resize();
       };
@@ -385,6 +410,8 @@ export default {
         color: this.color,
         tooltip: {
           trigger: "axis",
+          triggerOn:this.default?"click":"mousemove",
+          alwaysShowContent:true,
           backgroundColor: "rgba(0,0,0,0.4)",
           borderColor: partten.getColor("gray"),
           textStyle: {
@@ -431,6 +458,23 @@ export default {
             data: this.xdata,
           },
         ],
+        // yAxis: {
+        //   type: "value",
+        //   axisLabel: {
+        //     formatter: "{value}",
+        //     fontSize: 14,
+        //   },
+        //   axisLine: {
+        //     show: false,
+        //   },
+        //   splitLine: {
+        //     show: true,
+        //     lineStyle: {
+        //       color: "#606769",
+        //       type: "dashed",
+        //     },
+        //   },
+        // },
         yAxis: this.yAxis,
         series: this.series,
       };
@@ -459,7 +503,7 @@ export default {
   },
   unmounted() {
     window.removeEventListener("resize", this.resize);
-  }
+  },
 };
 </script>
 

+ 2 - 2
src/views/Others/index.vue

@@ -505,7 +505,7 @@ export default {
   height: 100%;
   font-size: 20px;
   .df-table {
-    /deep/ .com-table thead tr th {
+    .com-table thead tr th {
       background-color: rgba(83, 98, 104, 0.2);
       height: 30px;
       line-height: 30px;
@@ -516,7 +516,7 @@ export default {
       top: 0;
       cursor: pointer;
     }
-    /deep/ .com-table tbody tr td {
+    .com-table tbody tr td {
       padding: 4px;
       color: #393a3a;
       text-align: center;

+ 6 - 6
src/views/SandTable/SandTable.vue

@@ -622,13 +622,13 @@ export default {
       videoArray: [
         [
           {
-            url: "http://10.155.32.4:9984/ws.html",
+            url: "http://192.168.10.10:9984/ws.html",
             token: "?token=SBQ_FDC_SC&autoplay=true",
             class: "",
             switch: true,
           },
           {
-            url: "http://10.155.32.4:9984/ws.html",
+            url: "http://192.168.10.10:9984/ws.html",
             token: "?token=NSS_FDC_SC&autoplay=true",
             class: "",
             switch: true,
@@ -636,13 +636,13 @@ export default {
         ],
         [
           {
-            url: "http://10.155.32.4:9984/ws.html",
+            url: "http://192.168.10.10:9984/ws.html",
             token: "?token=QS_FDC_SC&autoplay=true",
             class: "",
             switch: true,
           },
           {
-            url: "http://10.155.32.4:9984/ws.html",
+            url: "http://192.168.10.10:9984/ws.html",
             token: "?token=MHS_FDC_SC&autoplay=true",
             class: "",
             switch: true,
@@ -650,13 +650,13 @@ export default {
         ],
         [
           {
-            url: "http://10.155.32.4:9984/ws.html",
+            url: "http://192.168.10.10:9984/ws.html",
             token: "?token=XS_FDC_SC&autoplay=true",
             class: "",
             switch: true,
           },
           {
-            url: "http://10.155.32.4:9984/ws.html",
+            url: "http://192.168.10.10:9984/ws.html",
             token: "?token=PL_GDC_SC&autoplay=true",
             class: "",
             switch: true,

+ 12 - 17
src/views/layout/Menu.vue

@@ -549,23 +549,18 @@ export default {
               text: "故障预警",
               icon: "svg-预警记录",
               path: "/health/MalfunctionWarning/",
-              // children:[
-              //   {
-              //     text:"算法类型",
-              //     icon:"svg-wind-site",
-              //     path:"",
-              //   },
-              //   {
-              //      text:"DBscan",
-              //     icon:"svg-wind-site",
-              //     path:"/health/MalfunctionWarning/DBscan",
-              //   },
-              //    {
-              //      text:"密度聚类",
-              //     icon:"svg-wind-site",
-              //     path:"/health/MalfunctionWarning/mdjl",
-              //   }
-              // ]
+              children: [
+                {
+                  text: "无监督学习",
+                  icon: "svg-wind-site",
+                  path: "/health/MalfunctionWarning/",
+                },
+                {
+                  text: "有监督学习",
+                  icon: "svg-wind-site",
+                  path: "/health/MalfunctionWarning/Supervised",
+                },
+              ],
             },
           ],
         },

+ 33 - 16
src/views/sampleDatabase/performance/index.vue

@@ -113,23 +113,31 @@
       :before-close="onClickDialogClose"
       class="isvisiable"
     >
-      <scatter-line-chart
+      <!-- <scatter-line-chart
         :data="scatterLineData"
         :dotName="dotName"
         :height="'70vh'"
-      />
+      /> -->
+      <PerformanceEcharts
+        :data="scatterLineData"
+        :dotName="dotName"
+        :height="'70vh'"
+      ></PerformanceEcharts>
     </el-dialog>
   </el-scrollbar>
 </template>
 
 <script>
 import ComTable from "@/components/coms/table/table.vue";
-import ScatterLineChart from "./scatter-line-chart.vue";
+// import ScatterLineChart from "./scatter-line-chart.vue";
+import PerformanceEcharts from "./performanceEcharts.vue";
+
 import BASE from "@tools/basicTool.js";
 export default {
   components: {
     ComTable,
-    ScatterLineChart,
+    PerformanceEcharts,
+    // ScatterLineChart,
   },
   data() {
     const that = this;
@@ -274,17 +282,17 @@ export default {
       that.API.requestData({
         method: "GET",
         // baseURL: "http://192.168.10.19:9002/",
-        baseURL: "http://192.168.1.18:9002/",
-        subUrl: "case/performance/scatter",
+        baseURL: "http://192.168.10.4:9002/",
+        subUrl: "case/performance/line",
         data: {
           id: ids,
           interval: 30,
         },
         success(res) {
           if (res.code == 200) {
-            let key = Object.keys(res.data)[0];
-            that.scatterLineData = res.data[key][1];
-            that.dotName = key;
+            // let key = Object.keys(res.data)[0];
+            that.scatterLineData = res.data;
+            // that.dotName = key;
             BASE.closeLoading();
             that.dialog = true;
           }
@@ -292,19 +300,27 @@ export default {
       });
     },
     list() {
+      // var that = this;
+      // if (that.time == undefined) {
+      //   that.BASE.showMsg({
+      //     type: "warning",
+      //     msg: "请选择起始时间",
+      //   });
+      //   return;
+      // }
       var that = this;
-      if (that.time == undefined) {
-        that.BASE.showMsg({
-          type: "warning",
-          msg: "请选择起始时间",
-        });
-        return;
+      let station = "";
+      if (typeof that.time[0].valueOf() != "string") {
+        that.time[0] = new Date(that.time[0]).formatDate("yyyy-MM-dd hh:mm:ss")
+      }
+      if (typeof that.time[1].valueOf() != "string") {
+        that.time[1] = new Date(that.time[1]).formatDate("yyyy-MM-dd hh:mm:ss")
       }
 
       that.API.requestData({
         showLoading: true,
         method: "GET",
-        baseURL: "http://192.168.1.18:9002/",
+        baseURL: "http://192.168.10.4:9002/",
         //    baseURL: "http://192.168.10.19:9002/",
         subUrl: "case/performance/list",
         data: {
@@ -315,6 +331,7 @@ export default {
           et: that.time[1].valueOf(),
         },
         success(res) {
+          console.log(11111, res);
           if (res.code == 200) {
             that.tableData.data = [];
             if (res.data.length) {

+ 234 - 0
src/views/sampleDatabase/performance/performanceEcharts.vue

@@ -0,0 +1,234 @@
+<template>
+  <div class="chart" :id="id"></div>
+</template>
+
+<script>
+import util from "@/helper/util.js";
+import partten from "@/helper/partten.js";
+import * as echarts from "echarts";
+import ecStat from "echarts-stat";
+export default {
+  components: {
+    ecStat,
+  },
+  props: {
+    width: {
+      type: String,
+      default: "100%",
+    },
+    height: {
+      type: String,
+      default: "350px",
+    },
+    // 传入数据
+    data: {
+      type: Array,
+      default: () => [
+        [96.24, 11.35],
+        [33.09, 85.11],
+        [57.6, 36.61],
+        [36.77, 27.26],
+        [20.1, 6.72],
+        [45.53, 36.37],
+        [110.07, 80.13],
+        [72.05, 20.88],
+        [39.82, 37.15],
+        [48.05, 70.5],
+        [0.85, 2.57],
+        [51.66, 63.7],
+        [61.07, 127.13],
+        [64.54, 33.59],
+        [35.5, 25.01],
+        [226.55, 664.02],
+        [188.6, 175.31],
+        [81.31, 108.68],
+      ],
+    },
+    dotName: {
+      type: String,
+      default: "",
+    },
+  },
+  data() {
+    return {
+      id: "",
+      chart: null,
+      color: ["#05bb4c", "#f8de5b", "#4b55ae", "#fa8c16"],
+      xdata: [],
+    };
+  },
+  methods: {
+    resize() {},
+    initChart() {
+      const chart = echarts.init(this.$el);
+      echarts.registerTransform(ecStat.transform.regression);
+      let option = {
+        legend: {
+          show: true,
+          data: ["功率曲线", "风速曲线"],
+          right: 120,
+          icon: "ract",
+          itemWidth: 8,
+          itemHeight: 8,
+          textStyle: {
+            fontSize: "14px",
+            color: "#fff",
+          },
+        },
+        dataset: [
+          {
+            source: this.data,
+          },
+          {
+            transform: {
+              type: "ecStat:regression",
+              config: {
+                method: "polynomial",
+                order: 3,
+              },
+            },
+          },
+        ],
+        tooltip: {
+          trigger: "axis",
+        },
+        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,
+          },
+        ],
+
+        // {
+        //   name: "时间",
+        //   splitLine: {
+        //     lineStyle: {
+        //       color: partten.getColor("gray") + 55,
+        //       type: "dashed",
+        //     },
+        //   },
+        //   splitNumber: 20,
+        //   data: this.xAxisData,
+        // },
+        yAxis: [
+          {
+            name: "功率",
+            type: "value",
+            axisTick: {
+              show: false,
+              length: 1,
+            },
+            splitLine: {
+              lineStyle: {
+                color: partten.getColor("gray") + 55,
+                type: "dashed",
+              },
+            },
+          },
+          {
+            name: "风速",
+            type: "value",
+            axisTick: {
+              show: false,
+              length: 1,
+            },
+            splitLine: {
+              lineStyle: {
+                color: partten.getColor("gray") + 55,
+                type: "dashed",
+              },
+            },
+          },
+        ],
+        series: [],
+      };
+      if (this.data.power.length > 0) {
+        let arr = [];
+        this.data.power.forEach((item) => {
+          arr.push(item.doubleValue);
+        });
+        let obj = {
+          name: "功率曲线",
+          type: "line",
+          data: arr,
+          smooth: true, //平滑展示
+          yAxisIndex: 0,
+        };
+
+        option.series.push(obj);
+      }
+      if (this.data.speed.length > 0) {
+        let arr = [];
+        this.data.speed.forEach((item) => {
+          arr.push(item.doubleValue);
+        });
+        let obj = {
+          name: "风速曲线",
+          type: "line",
+          data: arr,
+          smooth: true, //平滑展示
+          yAxisIndex: 1,
+        };
+        option.series.push(obj);
+      }
+      chart.clear();
+      chart.setOption(option);
+
+      this.resize = function () {
+        chart.resize();
+      };
+
+      window.addEventListener("resize", this.resize);
+    },
+  },
+  created() {
+    this.id = "pie-chart-" + util.newGUID();
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.$el.style.width = this.width;
+      this.$el.style.height = this.height;
+      this.initChart();
+    });
+  },
+  updated() {
+    let data = [];
+    if (this.data?.power.length > 0 || this.data?.speed.length > 0)
+      this.data?.power.forEach((value, index) => {
+        data.push(new Date(value.ts).formatDate("yyyy-MM-dd hh:mm"));
+      });
+    this.xdata = data;
+    this.$nextTick(() => {
+      this.initChart();
+    });
+  },
+  unmounted() {
+    window.removeEventListener("resize", this.resize);
+  },
+};
+</script>
+
+<style lang="less">
+.chart {
+  width: 100%;
+  height: 100%;
+  display: inline-block;
+}
+</style>