Переглянути джерело

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

chenminghua 3 роки тому
батько
коміт
31a85191ce

+ 6 - 0
src/App.vue

@@ -476,4 +476,10 @@ body {
     border-color: #05bb4c;
   }
 }
+.el-tree-node__content{
+  height: 40px !important;
+}
+.el-tree-node__label{
+  font-size: 18px !important;
+}
 </style>

+ 289 - 0
src/api/api.js

@@ -0,0 +1,289 @@
+import request from './zmaxios.js'
+
+
+//获取服务端公钥
+export const getPublickey = query => {
+        return request.get(`/info/publickey`);
+    }
+    // login
+export const loginRequest = params => {
+    return request.post("/user/login", params);
+};
+//register
+export const registerRequest = params => {
+    return request.post("/user/register", params);
+};
+// ----------------------------------------user------------------------------------------------
+export const getUserList = () => {
+    return request.get(`/user/get`);
+}
+export const editRequest = params => {
+    return request.post("/user/edit", params);
+};
+export const deleteUser = data => {
+        return request.delete(`/user/${data}`);
+    }
+    // ----------------------------------------user------------------------------------------------
+
+
+//获取所有风场
+export const fetchStationList = () => {
+    return request({
+        url: '/' + 'info/station',
+        method: 'get'
+    });
+};
+//根据风场id获取所有风机
+export const fetchWindturbineList = query => {
+    return request({
+        url: '/' + 'info/windturbine',
+        method: 'get',
+        params: {
+            stationId: query
+        }
+    });
+};
+// ----------------------------------------基础数据- 设备管理------------------------------------------------
+//查询全部设备型号接口
+export const device_list = () => {
+        return request.get(`/device/model/list`);
+    }
+    //获取结构tree
+export function tree(params) {
+    return request({
+        url: '/device/structure/tree/windturbine',
+        method: 'get',
+    });
+}
+//根据结构获取测点
+export function point(params) {
+    return request({
+        url: `/device/metrics/windturbine/${params}`,
+        method: 'get',
+    });
+}
+//测点新增
+export function metrics(params) {
+    return request.post(`/device/metrics/single`, params);
+}
+//测点删除
+export function delmetrics(params) {
+    return request.delete(`/device/metrics/single/delete/${params}`);
+}
+
+//tree新增 添加一个设备结构节点
+export function treeAdd(params) {
+    return request.post(`/device/structure`, params);
+}
+//tree删除 tree删除一个设备结构节点
+export function treeDel(params) {
+    return request.delete(`/device/structure/delete/${params}`);
+}
+
+
+// 故障模式
+// get All
+export const faultmode_windturbine = () => {
+        return request.get(`/device/faultmode/windturbine`);
+    }
+    // 根据 structurecode get
+export const faultmode_structurecode = params => {
+        return request.get(`/device/faultmode/windturbine/${params}`);
+    }
+    // 根据 id delete
+export const faultmode_delete = params => {
+    return request.delete(`/device/faultmode/delete/${params}`);
+}
+
+// 新增 修改
+export const faultmode_add_edit = data => {
+    return request.post(`/device/faultmode`, data);
+}
+
+// ----------------------------------------end 基础数据- 风机管理------------------------------------------------
+
+
+// ---------------------------------------- 报警配置- 自定义预警------------------------------------------------
+export function custombj_fetchTableData(params) {
+    return request.get(`/alertrule2/page/`, {
+        params: params
+    });
+}
+
+//根据场站编号,风机型号获取AI测点
+export const fetchAIPointList = (stationId, modelId) => {
+    return request({
+        url: '/' + 'info/testing_point_ai',
+        method: 'get',
+        params: {
+            stationId: stationId,
+            modelId: modelId
+        }
+    });
+};
+//根据场站编号,风机型号获取DI测点
+export const fetchDIPointList = (stationId, modelId) => {
+    return request({
+        url: '/' + 'info/testing_point_di',
+        method: 'get',
+        params: {
+            stationId: stationId,
+            modelId: modelId
+        }
+    });
+};
+//根据场站编号,获取电气DI测点
+export const fetchElectricDIPointList = (stationId) => {
+    return request({
+        url: '/' + 'info/electrical_point_di',
+        method: 'get',
+        params: {
+            stationId: stationId
+        }
+    });
+};
+//根据电气测点,获取测点信息
+export const fetchElectricDIPointByPointId = (pointId) => {
+    return request({
+        url: '/' + 'info/electrical_point_di/byId',
+        method: 'get',
+        params: {
+            pointId: pointId
+        }
+    });
+};
+
+//获取风机关联部件列表
+export const fetchRelatePart = () => {
+    return request({
+        url: '/' + 'info/windturbine_parts',
+        method: 'get',
+    });
+};
+//根据风场编号获取电气AI测点
+export const fetch_electrical_point_ai = (stationId) => {
+    return request({
+        url: '/' + 'info/electrical_point_ai',
+        method: 'get',
+        params: {
+            stationId: stationId
+        }
+    });
+};
+//根据风场编号获取电气DI测点
+export const fetch_electrical_point_di = (stationId) => {
+    return request({
+        url: '/' + 'info/electrical_point_di',
+        method: 'get',
+        params: {
+            stationId: stationId
+        }
+    });
+};
+//获取报警类型
+export const fetchWarningType = () => {
+    return request({
+        url: '/' + 'info/warning_type',
+        method: 'get',
+    });
+};
+//获取报警种类
+export const fetchWarningClassify = () => {
+    return request({
+        url: '/' + 'info/warning_classify',
+        method: 'get',
+    });
+};
+export const custombj_batchImport = list => {
+    return Axrequestios.post('/' + "alertrule2/save-batch", list);
+};
+export const custombj_postSave = form => {
+    return request.post('/' + "alertrule2/save", form)
+};
+
+//******************************end****************************************//
+
+
+//******************************升压站报警************************************//
+
+export const scadabj_fetchTableData = query => {
+    return request({
+        url: '/' + 'scadabj/page',
+        method: 'get',
+        params: query,
+        timeout: 20000,
+    });
+};
+export const scadabj_postSave = objData => {
+    return request.post('/' + "scadabj/save", objData);
+};
+export const scadabj_batchImport = list => {
+    return request.post('/' + "scadabj/save-batch", list);
+};
+//********************************************end********************************//\
+
+
+
+//******************************风机报警************************************//
+export const windturbinebj_fetchTableData = query => {
+    return request({
+        url: '/' + 'warning2/page',
+        method: 'get',
+        params: query,
+        timeout: 20000,
+    });
+};
+export const windturbinebj_postSave = form => {
+    return Axios.post('/' + 'warning2/save', form);
+};
+export const windturbinebj_batchImport = list => {
+    return Axios.post('/' + "warning2/save-batch", list);
+};
+
+export const fetchLeaf = () => {
+    return request({
+        url: '/' + 'warning2/page',
+        method: 'get',
+        params: {
+            pagenum: 1,
+            pagesize: 10000,
+            isLeaf: 0,
+        }
+    });
+};
+
+
+//根据风机型号获取DI测点统一编码相关数据 testingpointdi2
+export const getDIPointByModelId = query => {
+    return request({
+        url: '/' + 'info/testing_point_di',
+        method: 'get',
+        params: query
+    });
+};
+
+//******************************end*******************************************// 
+//******************************预警统计*******************************************//
+export const statistics_querymap = params => {
+    return request.get(`/alarm/count/querymap`, { params: params })
+        // return request.get(`/alarm/count/querymap?stationid=XS_FDC&datebegin=2021-10-12&dateend=2021-11-13`)
+};
+export const statistics_querybyname = params => {
+    return request.get('/alarm/count/querybyname', { params: params })
+};
+export const statistics_lineandproject = params => {
+    return request.get('/alarm/count/lineandproject', { params: params })
+};
+//******************************end*******************************************//
+
+//******************************预警分析*******************************************//
+export const warning_query_new = params => {
+    return request.get(`/alarm/count/query/new`, { params: params })
+};
+export const warning_detail = params => {
+    return request.get('/analysis/detail', { params: params })
+};
+// export const statistics_lineandproject = params => {
+//     return request.get('/alarm/count/lineandproject', { params: params })
+// };
+//******************************end*******************************************//

+ 1 - 1
src/api/axios.js

@@ -85,7 +85,7 @@ export function requestData(options) {
         // window.location.reload();
         // window.__STATICVUE__.$router.replace('/login');
 
-      } else if (response.data.code === 200 || response.data.length>=0) { // 请求成功 code
+      } else if (response.data.code === 200 || response.data.length>=0 || response.data.records) { // 请求成功 code
 
         options.success && options.success(response.data);
         resolve(response);

+ 61 - 0
src/api/zmaxios.js

@@ -0,0 +1,61 @@
+import axios from 'axios';
+import { ElMessage, ElMessageBox } from 'element-plus';
+
+// 配置新建一个 axios 实例
+const service = axios.create({
+    baseURL: 'http://192.168.1.14:8075',
+    timeout: 50000,
+    headers: { 'Content-Type': 'application/json' },
+});
+
+// 添加请求拦截器
+service.interceptors.request.use(
+    (config) => {
+        // 在发送请求之前做些什么 token
+        let token = sessionStorage.getItem('token')
+        if (token) {
+            config.headers.common['token'] = token;
+        }
+        return config
+    },
+    (error) => {
+        // 对请求错误做些什么
+        return Promise.reject(error);
+    }
+);
+
+// 添加响应拦截器
+service.interceptors.response.use(
+    (response) => {
+        // 对响应数据做点什么
+        const res = response.data;
+        if (res.code && res.code !== 0 && res.code == !200) {
+            // `token` 过期或者账号已在别处登录
+            if (res.code === 401 || res.code === 4001) {
+                localStorage.clear(); // 清除浏览器全部临时缓存
+                window.location.href = '/'; // 去登录页
+                ElMessageBox.alert('你已被登出,请重新登录', '提示', {})
+                    .then(() => {})
+                    .catch(() => {});
+            }
+            return Promise.reject(service.interceptors.response);
+        } else {
+            return response.data;
+        }
+    },
+    (error) => {
+        // 对响应错误做点什么
+        if (error.message.indexOf('timeout') != -1) {
+            ElMessage.error('网络超时');
+        } else if (error.message == 'Network Error') {
+            ElMessage.error('网络连接错误');
+        } else {
+            if (error.response.data) ElMessage.error(error.response.statusText);
+            else ElMessage.error('接口路径找不到');
+        }
+        return Promise.reject(error);
+    }
+);
+
+// 导出 axios 实例
+export default service;

+ 13 - 0
src/router/index.js

@@ -809,6 +809,12 @@ const routes = [{
 	name: "warning",
 	component: () => import("../views/sampleDatabase/warning/index.vue")
 },
+//性能预警综合分析
+{
+	path: "/others/analysis",
+	name: "analysis",
+	component: () => import("../views/sampleDatabase/analysis/index.vue")
+},
 //智能营销样本库
 {
 	path: "/others/market",
@@ -874,7 +880,14 @@ const routes = [{
 	name: 'knowledge7',
 	component: () =>
 		import('../views/Knowledge/Knowledge7.vue'),
+},
+{
+	path: '/device/device', //设备管理
+	name: 'device',
+	component: () =>
+		import('../views/device/device.vue'),
 }
+
 	/***********************************************************其他************************************************************ */
 	,
 {

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

@@ -252,6 +252,7 @@
       v-model="resultsDisplay"
       :allData="showList"
       :intervalValue="intervalValue"
+      :moudleList="faultLists"
       @save-date="saveData"
     ></TrainingResults>
     <Records @results="recordResults" v-model="recordsDisplay"></Records>

+ 28 - 21
src/views/MalfunctionWarning/components/testReport.vue

@@ -83,20 +83,30 @@
           </div>
           <div class="charts">
             <BarChart
-            v-if="barList.length > 0"
-            id="reportBar"
-            :barList="barList"
-          ></BarChart>
-          <LineChart v-if="lossList" id="reporLoss" :reportFlag="true" :dataList="lossList"></LineChart>
-          <LineChart
-            v-if="accuracyList"
-            id="reporAccuracy"
-            :reportFlag="true"
-            :dataList="accuracyList"
-          ></LineChart>
+              v-if="barList.length > 0"
+              id="reportBar"
+              :barList="barList"
+            ></BarChart>
+            <LineChart
+              v-if="lossList"
+              id="reporLoss"
+              :reportFlag="true"
+              :dataList="lossList"
+            ></LineChart>
+            <LineChart
+              v-if="accuracyList"
+              id="reporAccuracy"
+              :reportFlag="true"
+              :dataList="accuracyList"
+            ></LineChart>
           </div>
           <div class="resultContent">
-            该模型训练和测试的准确率分别为<text style="color: #dc143c">74.2%和73.3%</text>;误差率分别为<text style="color: #dc143c">2%和1%</text>;该模型训练所倚重的测点比重分别为:<text style="color: #dc143c">偏航位置7.2%、发电机转速4.4%、有功功率3.4%、U1项绕组电流2.9%、齿轮箱轴2温度2.1%</text>。模型训练过程所有测点倚重占比如下表所示:
+            该模型训练和测试的准确率分别为<text style="color: #dc143c"
+              >74.2%和73.3%</text
+            >;误差率分别为<text style="color: #dc143c">2%和1%</text
+            >;该模型训练所倚重的测点比重分别为:<text style="color: #dc143c"
+              >偏航位置7.2%、发电机转速4.4%、有功功率3.4%、U1项绕组电流2.9%、齿轮箱轴2温度2.1%</text
+            >。模型训练过程所有测点倚重占比如下表所示:
           </div>
           <div class="resultTable">
             <el-table
@@ -154,8 +164,8 @@ export default {
   data() {
     return {
       barList: [],
-      lossList:{},
-      accuracyList:{},
+      lossList: {},
+      accuracyList: {},
       faultList: [
         {
           name: "齿轮箱故障",
@@ -167,10 +177,10 @@ export default {
         },
         {
           name: "变桨系统故障",
-          percent: "13%",
+          percent: "3%",
         },
       ],
-      proportionList:[
+      proportionList: [
         {
           name: "偏航位置",
           percent: "7.2%",
@@ -205,10 +215,7 @@ export default {
         type: "success",
         msg: "正在导出...请稍后...",
       });
-      Get_PDF.downloadPDF(
-        document.querySelector(".pdfDom"),
-        "故障检测报告"
-      );
+      Get_PDF.downloadPDF(document.querySelector(".pdfDom"), "故障检测报告");
     },
   },
 };
@@ -262,7 +269,7 @@ export default {
         margin-left: 30%;
       }
 
-      .charts{
+      .charts {
         display: flex;
         flex-direction: row;
         align-items: center;

+ 9 - 53
src/views/MalfunctionWarning/components/trainingResults.vue

@@ -77,7 +77,6 @@
                 align="center"
               ></el-table-column>
               <el-table-column width="150">
-                     
                 <template #default="scope">
                   <span>
                     <el-select
@@ -90,15 +89,14 @@
                     >
                       <el-option
                         v-for="item in moudleList"
-                        :key="item.value"
-                        :label="item.label"
-                        :value="item.value"
+                        :key="item.faultcode"
+                        :label="item.faulttype"
+                        :value="item.faultcode"
                       >
                       </el-option>
                     </el-select>
                   </span>
                 </template>
-                   
               </el-table-column>
             </el-table>
           </div>
@@ -155,6 +153,12 @@ export default {
       type: Number,
       default: 1,
     },
+    moudleList: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
   },
   data() {
     return {
@@ -162,54 +166,6 @@ export default {
       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: "",

+ 12 - 5
src/views/MalfunctionWarning/supervised.vue

@@ -11,7 +11,6 @@
               clearable
               placeholder="请选择"
               popper-class="select"
-              @clear="clear()"
             >
               <el-option
                 v-for="item in algorithm"
@@ -23,7 +22,7 @@
             </el-select>
           </div>
         </div>
-        <div v-for="(item, index) in chooseAlgorithm.parameters" :key="index">
+        <!-- <div v-for="(item, index) in chooseAlgorithm.parameters" :key="index">
           {{ item.name }}:
           <input
             v-model="item.value"
@@ -31,7 +30,7 @@
             @focus="inputChange(item)"
             @blur="inputChange(item)"
           />
-        </div>
+        </div> -->
       </div>
     </div>
     <div class="actions mg-b-8">
@@ -215,7 +214,7 @@ export default {
       accuracyList: {},
       barList: [],
       algorithm: [], //算法
-      chooseAlgorithm: {},
+      chooseAlgorithm: '',
       timeValue: [],
       showBarList: [],
       moudleList: [],
@@ -326,7 +325,7 @@ export default {
           if (res) {
             that.algorithm = res;
             that.value1 = res[0];
-            that.chooseAlgorithm = res[0];
+            that.chooseAlgorithm = res[0].name;
           }
         },
       });
@@ -445,6 +444,14 @@ export default {
     handleClose() {
       this.barList = this.ceshiList.bar.slice(0, 5);
     },
+    algorithmChange(val) {
+      this.chooseAlgorithm = this.algorithm.filter(
+        (item) => item.name === val
+      )[0].name;
+    },
+    // clear() {
+    //   this.chooseAlgorithm = '';
+    // },
     Compare(property) {
       return function (a, b) {
         var value1 = a[property];

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

@@ -458,24 +458,24 @@ 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,
+        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,
       };
     },

+ 4 - 3
src/views/SandTable/SandTable.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="sand-table">
+  <div class="sand-table" id="sandTable">
     <img :src="require('@assets/png/3dback.png')" class="i3dback" />
     <!-- <img :src="require('@assets/png/3dcloud.png')" class="i3dcloud" /> -->
     <StBack></StBack>
@@ -1137,7 +1137,8 @@ export default {
 </script>
 
 <style lang="less">
-.sand-table {
+
+ .sand-table {
   width: 100%;
   height: 91.667vh;
   position: relative;
@@ -1381,7 +1382,7 @@ export default {
     background: #b3bdc0;
   }
 
-  .el-dialog__body {
+  #sandTable .el-dialog__body {
     max-height: 600px;
     overflow-y: scroll;
   }

+ 705 - 0
src/views/device/device.vue

@@ -0,0 +1,705 @@
+<template>
+  <div class="main deviceClass">
+    <el-card class="box-card-tree">
+      <button  class="btn green" style="margin-bottom:10px" @click="handleTreeAdd()"
+        >新增</button
+      >
+      <button
+        class="btn green"
+        @click="handleTreeDel()"
+        :disabled="state.isDel == ''"
+        >删除</button
+      >
+      <el-tree
+        :data="state.treedata"
+        :props="state.defaultProps"
+        node-key="id"
+        highlight-current
+        :default-expanded-keys="['23']"
+        @node-click="handleNodeClick"
+      />
+    </el-card>
+    <el-card class="box-card">
+      <el-tabs type="card" class="tab">
+        <el-tab-pane label="传感点">
+          <el-row :gutter="24" align="middle">
+            <el-col :span="2">
+              <button
+                 class="btn green"
+                style="margin-bottom: 10px"
+                @click="handleEdit(state.addFormData)"
+                :disabled='state.desc.code==""'
+                >新增</button
+              ></el-col
+            >
+            <el-col :span="5">
+              <el-input
+                v-model="state.SearchVal"
+                placeholder="筛选"
+                :prefix-icon="Search"
+                @input="fifterSearch()"
+                size="small"
+              />
+            </el-col>
+          </el-row>
+          <el-table
+            :data="state.fifterSearchTableData"
+            stripe
+            style="width: 100%"
+            height="700"
+          >
+            <el-table-column type="index" width="50" />
+            <el-table-column
+              prop="metriccode"
+              label="测点编码"
+            ></el-table-column>
+            <el-table-column label="名称">
+              <template #default="scope">
+                <el-popover placement="right" :width="260" trigger="click">
+                  <template #reference>
+                    <el-button type="text" style="color: #B3BDC0" size="small">{{
+                      scope.row.name
+                    }}</el-button>
+                  </template>
+                  <el-table :data="scope.row.deviceModelMetrics" max-height="400px">
+                    <el-table-column
+                      property="devicemodel"
+                      label="机型"
+                      align="center"
+                    ></el-table-column>
+                    <el-table-column
+                      property="uniformcode"
+                      label="统一编码"
+                      align="center"
+                    ></el-table-column>
+                    <el-table-column
+                      property="multiplier"
+                      label="倍率"
+                      align="center"
+                    ></el-table-column>
+                  </el-table>
+                </el-popover>
+              </template>
+            </el-table-column>
+
+            <el-table-column prop="unitname" label="单位"></el-table-column>
+            <el-table-column
+              prop="categorydata"
+              label="测点类型"
+            ></el-table-column>
+            <el-table-column
+              prop="categorysci"
+              label="物理类型"
+            ></el-table-column>
+            <el-table-column prop="description" label="描述"></el-table-column>
+            <el-table-column label="操作" width="180" align="center">
+              <template #default="scope">
+                <el-button
+                  type="text"
+                  style="color: #B3BDC0"
+                  @click="handleEdit(scope.row)"
+                  >编辑</el-button
+                >
+                <el-button
+                  type="text"
+                  style="color: #B3BDC0"
+                  @click="handleDelete(scope.row)"
+                  >删除</el-button
+                >
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-tab-pane>
+        <el-tab-pane label="故障模式">
+          <faultmode />
+        </el-tab-pane>
+        <el-tab-pane label="基本信息" style="width: 50%">
+          <el-form :model="state.desc" label-width="100px">
+            <el-form-item label="结构编码">
+              <el-input v-model="state.desc.code"></el-input>
+            </el-form-item>
+            <el-form-item label="上级节点">
+              <el-cascader
+                v-model="state.desc.parentcode"
+                :options="state.cascaderdata"
+                :props="{ checkStrictly: true, emitPath: false }"
+                :show-all-levels="false"
+                clearable
+              />
+            </el-form-item>
+            <el-form-item label="设备ID">
+              <el-input v-model="state.desc.deviceid" disabled></el-input>
+            </el-form-item>
+            <el-form-item label="结构名称">
+              <el-input v-model="state.desc.name"></el-input>
+            </el-form-item>
+            <el-form-item label="结构英文名称">
+              <el-input v-model="state.desc.enname"></el-input>
+            </el-form-item>
+            <el-form-item label="描述">
+              <el-input
+                v-model="state.desc.description"
+                :rows="4"
+                clearable
+                type="textarea"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="序号">
+              <el-input v-model="state.desc.orderno"></el-input>
+            </el-form-item>
+            <el-form-item label="是否有效">
+              <el-switch
+              class="elswitch"
+                v-model="state.desc.enabled"
+                active-color="#13ce66"
+                inactive-color="#ff4949"
+              />
+            </el-form-item>
+          </el-form>
+          <button
+            style="float: right"
+             class="btn green"
+            @click="savedesc"
+            :disabled="state.desc.code == ''"
+            >保存</button
+          >
+        </el-tab-pane>
+      </el-tabs>
+    </el-card>
+    <!-- 传感点编辑弹出框 -->
+    <el-dialog v-model="editVisible" width="40%" custom-class="modal">
+      <el-form :model="editFormData" label-width="80px">
+        <el-form-item label="指标">
+          <el-input v-model="editFormData.metriccode"></el-input>
+        </el-form-item>
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="名称">
+              <el-input v-model="editFormData.name"></el-input>
+            </el-form-item>
+          </el-col>
+
+          <el-col :span="12">
+            <el-form-item label="英文名称">
+              <el-input v-model="editFormData.enname"></el-input>
+            </el-form-item> </el-col
+        ></el-row>
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="标准单位">
+              <el-input
+                v-model="editFormData.unitname"
+              ></el-input> </el-form-item
+          ></el-col>
+
+          <el-col :span="12">
+            <el-form-item label="单位名称">
+              <el-input v-model="editFormData.unitnamecn"></el-input>
+            </el-form-item> </el-col
+        ></el-row>
+        <el-form-item label="描述">
+          <el-input
+            v-model="editFormData.description"
+            :rows="3"
+            type="textarea"
+            clearable
+          ></el-input>
+        </el-form-item>
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="数据类型">
+              <el-select
+                v-model="editFormData.categorydata"
+                placeholder="Select"
+              >
+                <el-option
+                  v-for="item in state.options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select> </el-form-item
+          ></el-col>
+          <el-col :span="12">
+            <el-form-item label="结构">
+              <el-cascader
+                v-model="editFormData.structurecode"
+                :options="state.cascaderdata"
+                :props="{ checkStrictly: true ,emitPath:false}"
+                clearable
+              /> </el-form-item
+          ></el-col>
+        </el-row>
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="科学类型">
+              <el-input
+                v-model="editFormData.categorysci"
+              ></el-input> </el-form-item
+          ></el-col>
+          <el-col :span="12"
+            ><el-form-item label="系统分类">
+              <el-input
+                v-model="editFormData.categorysys"
+              ></el-input> </el-form-item
+          ></el-col>
+        </el-row>
+
+        <el-form-item label="适配机型" class="deviceModelClass">
+        
+          <el-select
+            v-model="state.deviceModelSel"
+            style="margin-right: 20px"
+            placeholder="新增机型"
+            size="mini"
+          >
+            <el-option
+              v-for="item in state.deviceModel"
+              :key="item.code"
+              :label="item.code"
+              :value="item.code"
+            >
+            </el-option>
+          </el-select>
+            <button  class="btn green"  v-show="state.deviceModelSel !=''" size="mini" type="primary" @click="deviceModelAdd()"
+            >新增机型</button
+          >
+          <el-table
+            :data="editFormData.deviceModelMetrics"
+            style="width: 100%"
+            max-height="200px"
+          >
+            <el-table-column prop="devicemodel" label="机型" />
+            <el-table-column  label="倍率">
+              <template #default="scope">
+                <el-input v-model="scope.row.multiplier" size="mini" />
+              </template>
+            </el-table-column>
+            <el-table-column label="统一编码">
+              <template #default="scope">
+                <el-input v-model="scope.row.uniformcode" size="mini" />
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <button  class="btn green"  @click="editVisible = false">取 消</button>
+          <button  class="btn green"  type="primary" @click="saveEdit">确 定</button>
+        </span>
+      </template>
+    </el-dialog>
+    <!-- tree add 弹出框 -->
+    <el-dialog v-model="treeVisible" width="40%"  custom-class="modal">
+      <el-form :model="state.treeAddFormData" label-width="80px">
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="结构编码">
+              <el-input
+                v-model="state.treeAddFormData.code"
+              ></el-input> </el-form-item
+          ></el-col>
+          <el-col :span="12">
+            <el-form-item label="上级节点" label-width="100px">
+              <el-cascader
+                v-model="state.treeAddFormData.parentcode"
+                :options="state.cascaderdata"
+                :props="{ checkStrictly: true, emitPath: false }"
+                :show-all-levels="false"
+                clearable
+              /> </el-form-item
+          ></el-col>
+        </el-row>
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="结构名称">
+              <el-input
+                v-model="state.treeAddFormData.name"
+              ></el-input> </el-form-item
+          ></el-col>
+          <el-col :span="12">
+            <el-form-item label="结构英文名称" label-width="100px">
+              <el-input
+                v-model="state.treeAddFormData.enname"
+              ></el-input> </el-form-item
+          ></el-col>
+        </el-row>
+        <el-row :gutter="24">
+          <el-col :span="12"
+            ><el-form-item label="序号">
+              <el-input
+                v-model="state.treeAddFormData.orderno"
+              ></el-input> </el-form-item
+          ></el-col>
+          <el-col :span="4">
+            <el-form-item label="是否有效">
+               <el-switch 
+                v-model="state.treeAddFormData.enabled"
+                 class="elswitch"
+                active-color="#13ce66"
+                inactive-color="#ff4949"
+              />
+              </el-form-item
+          ></el-col>
+          <el-col :span="8">
+            <el-form-item label="设备ID">
+              <el-input
+                v-model="state.treeAddFormData.deviceid"
+                disabled
+              ></el-input> </el-form-item
+          ></el-col>
+        </el-row>
+        <el-form-item label="描述">
+          <el-input
+            v-model="state.treeAddFormData.description"
+            :rows="4"
+            clearable
+            type="textarea"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <button  class="btn green"  @click="treeVisible = false">取 消</button>
+          <button  class="btn green"  type="primary" @click="saveTreeAdd">确 定</button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import { ref, onMounted, reactive, provide, computed } from "vue";
+import { ElMessageBox, ElMessage, ElLoading } from "element-plus";
+import faultmode from "./faultmode.vue";
+import {
+  tree,
+  point,
+  metrics,
+  delmetrics,
+  treeAdd,
+  treeDel,
+  device_list,
+} from "@/api/api.js";
+let editVisible = ref(false); //传感点
+let treeVisible = ref(false); //传感点
+let editFormData = ref({});
+onMounted(() => {
+  getData();
+  getDeviceModel();
+});
+let state = reactive({
+  isDel: "", //是否能被删除
+  SearchVal: "",
+  treedata: [],
+  cascaderdata: [],
+  defaultProps: {
+    children: "children",
+    label: (a) => {
+      return a.node.name;
+    },
+  },
+  pointTableData: [],
+  fifterSearchTableData: [],
+  textarea: "",
+  textarea1: "",
+  treeCurClick: null,
+  addFormData: {
+    categorydata: "AI",
+    categoryres1: null,
+    categoryres2: null,
+    categoryres3: null,
+    categoryres4: null,
+    categoryres5: null,
+    categorysci: null,
+    categorysys: null,
+    description: null,
+    deviceid: "windturbine",
+    enname: null,
+    id:null,
+    metriccode: "",
+    name: "",
+    structurecode: "101010205",
+    unitname: null,
+    unitnamecn: null,
+    deviceModelMetrics: [],
+  },
+  treeAddFormData: {
+    code: "",
+    parentcode: "",
+    deviceid: "windturbine",
+    name: "",
+    enname: "",
+    description: "",
+    orderno: "",
+    enabled: true,
+  },
+  options: [
+    {
+      value: "AI",
+      label: "AI",
+    },
+    {
+      value: "DI",
+      label: "DI",
+    },
+    {
+      value: "CI",
+      label: "CI",
+    },
+  ],
+  desc: {
+    code: "",
+    parentcode: "",
+    deviceid: "",
+    name: "",
+    enname: "",
+    description: "",
+    orderno: "",
+    enabled: true,
+  },
+  treeDelVal: "",
+  deviceModel: [],
+  deviceModelSel: "",
+});
+
+// 父子传参
+provide(
+  "cascaderdata",
+  computed(() => state.cascaderdata)
+);
+//fifterSearch
+const fifterSearch = () => {
+  state.fifterSearchTableData = state.pointTableData.filter((e) => {
+    return (
+      e.name.includes(state.SearchVal) |
+      e.categorydata.includes(state.SearchVal) |
+      e.metriccode.includes(state.SearchVal)
+    );
+  });
+};
+// tree click
+const handleNodeClick = (data) => {
+  console.log(data);
+  state.isDel = data.children;
+  state.desc = data.node;
+  state.addFormData.structurecode = data.node.code
+  getPoint(data.node);
+};
+// 测点 编辑
+const handleEdit = (row) => {
+  editFormData.value = row;
+  editVisible.value = true;
+};
+// tree add
+const handleTreeAdd = () => {
+  treeVisible.value = true;
+};
+// tree Del
+const handleTreeDel = () => {
+  console.warn(state.desc);
+  if (state.isDel != null) {
+    ElMessage.error(`不能删除该节点!!`);
+    return;
+  }
+  ElMessageBox.confirm(`确定要删除 ${state.desc.name} 吗?`, "提示", {
+    type: "warning",
+  })
+    .then(async () => {
+      const res = await treeDel(state.desc.id);
+      console.warn(res);
+      if (res == 1) {
+        ElMessage.success(`删除成功!`);
+        getData();
+      } else {
+        ElMessage.warning(`删除失败!`);
+      }
+    })
+    .catch(() => {});
+};
+// delTreeBtn
+const delTreeBtn = async () => {
+  console.warn(state.treeDelVal);
+  const res = await treeDel(state.treeDelVal);
+  console.warn(res);
+  if (res == 1) {
+    ElMessage.success(`删除成功!`);
+    getData();
+  } else {
+    ElMessage.warning(`删除失败!`);
+  }
+  state.treeDelVal = "";
+};
+//保存tree add
+const saveTreeAdd = async () => {
+  const res = await treeAdd(state.treeAddFormData);
+  console.warn(res);
+  if (res.status == 20000) {
+    ElMessage.success(`操作成功!`);
+    treeVisible.value = false;
+    getData();
+  } else {
+    ElMessage.warning(res.msg);
+  }
+};
+
+// 测点 删除
+const handleDelete = (row) => {
+  // 二次确认删除
+  ElMessageBox.confirm("确定要删除吗?", "提示", {
+    type: "warning",
+  })
+    .then(async () => {
+      console.warn(row);
+      const res = await delmetrics(row.id);
+      console.warn(res);
+      if (res == 1) {
+        ElMessage.success(`删除成功!`);
+      } else {
+        ElMessage.success("删除失败");
+      }
+      getPoint(state.desc);
+    })
+    .catch(() => {});
+};
+// 保存编辑
+const saveEdit = async () => {
+  postmetrics();
+};
+//测点 add
+const postmetrics = async () => {
+  console.warn(editFormData.value);
+  const res = await metrics(editFormData.value);
+  console.warn(res);
+  if (res.status == 20000) {
+    ElMessage.success(`操作成功!`);
+    editVisible.value = false;
+  } else {
+    ElMessage.success(res.msg);
+  }
+  getPoint(state.desc);
+};
+// getData
+const getData = async () => {
+  const loading = ElLoading.service({
+    lock: true,
+    text: "数据加载中...",
+    background: "rgba(0, 0, 0, 0.5)",
+  });
+  const res = await tree();
+  loading.close();
+  console.warn(res);
+  state.treedata = res.children;
+  state.cascaderdata = cascaderforEach(res);
+  console.warn(state.cascaderdata);
+};
+//deviceModelAdd 新增机型
+const deviceModelAdd = async () => {
+  if (state.deviceModelSel == "") return;
+  console.warn();
+  let obj = {
+    deviceid: editFormData.value.deviceid,
+    devicemodel: state.deviceModelSel,
+    id: null,
+    metriccode: editFormData.value.metriccode,
+    multiplier: 0,
+    uniformcode: "",
+  };
+  editFormData.value.deviceModelMetrics.push(obj);
+};
+//getDeviceModel
+const getDeviceModel = async () => {
+  const res = await device_list();
+  state.deviceModel = res;
+  console.warn(res);
+};
+///// 基本信息
+
+const savedesc = async () => {
+  const res = await treeAdd(state.desc);
+  console.warn(res);
+  if (res.status == 20000) {
+    ElMessage.success(`操作成功!`);
+  } else {
+    ElMessage.success(res.msg);
+  }
+};
+
+///// 基本信息
+// getPoint
+const getPoint = async (node) => {
+  const res = await point(node.code);
+  console.warn(res);
+  state.pointTableData = res;
+  fifterSearch();
+};
+// 递归解析基础数据
+const cascaderforEach = (val) => {
+  if (val.children != null) {
+    val.children.forEach((v) => {
+      v["value"] = v.node.code;
+      v["label"] = v.node.name;
+      v["id"] = v.node.id;
+      cascaderforEach(v);
+    });
+    return val.children;
+  }
+};
+</script>
+<style lang="scss" scoped>
+.main {
+  display: flex;
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  justify-content: space-between;
+  .box-card-tree {
+    width: 20%;
+    margin-right: 1%;
+    overflow: auto;
+  }
+  .box-card {
+    flex: 1;
+    .desc {
+      display: flex;
+      margin-bottom: 30px;
+      span {
+        width: 100px;
+      }
+    }
+  }
+}
+</style>
+<style lang="less" >
+
+.deviceModelClass {
+  .el-table__header tr,
+  .el-table__header th {
+    padding: 0;
+    height: 40px;
+  }
+  .el-table__body tr,
+  .el-table__body td {
+    padding: 0;
+    height: 40px;
+  }
+}
+.tab{
+  .el-tabs__item.is-active{
+    color:@green;
+  }
+  .el-tabs__item{
+      color: #b7b7b7;
+  }
+}
+.elswitch{
+.el-switch__input{
+    position: absolute!important;
+}
+}
+.deviceClass{
+  .el-row{
+    margin-bottom: 16px;
+  }
+}
+</style>

+ 262 - 0
src/views/device/faultmode.vue

@@ -0,0 +1,262 @@
+<template>
+  <div style="display: block">
+    <button
+       class="btn green"
+      style="margin-bottom: 10px"
+      @click="handleEdit(state.addFormData)"
+      >新增</button
+    >
+    <el-table
+      :data="state.faultmodeTableData"
+      stripe
+      style="width: 100%"
+      height="700"
+    >
+      <el-table-column type="index" width="50" />
+      <el-table-column prop="name" label="名称"></el-table-column>
+      <el-table-column prop="code" label="故障编码"></el-table-column>
+      <el-table-column label="频度" width="50">
+        <template #default="scope">
+          {{ rank(scope.row.occurence) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="严酷度" width="70">
+        <template #default="scope">
+          {{ rank(scope.row.severity) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="难检度" width="70">
+        <template #default="scope" >
+          {{ rank(scope.row.detection) }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="cause" label="原因"></el-table-column>
+      <el-table-column prop="effects" label="导致结果"></el-table-column>
+      <el-table-column prop="measure" label="处理方法"></el-table-column>
+      <el-table-column label="操作" width="180" align="center">
+        <template #default="scope">
+          <el-button
+            type="text"
+                  style="color: #B3BDC0"
+            @click="handleEdit(scope.row)"
+            >编辑</el-button
+          >
+          <el-button
+            type="text"
+                  style="color: #B3BDC0"
+            @click="handleDelete(scope.row)"
+            >删除</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 传感点编辑弹出框 -->
+    <el-dialog v-model="editVisible" width="40%"  custom-class="modal">
+      <el-form :model="editFormData" label-width="80px">
+        <el-form-item label="故障编码">
+          <el-input v-model="editFormData.code"></el-input>
+        </el-form-item>
+        <el-form-item label="名称">
+          <el-input v-model="editFormData.name"></el-input>
+        </el-form-item>
+        <el-form-item label="导致结果">
+          <el-input
+            v-model="editFormData.effects"
+            :rows="2"
+            clearable
+            type="textarea"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="原因">
+          <el-input
+            v-model="editFormData.cause"
+            :rows="2"
+            clearable
+            type="textarea"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="处理方法">
+          <el-input
+            v-model="editFormData.measure"
+            :rows="3"
+            clearable
+            type="textarea"
+          ></el-input>
+        </el-form-item>
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="严酷度">
+              <el-select v-model="editFormData.severity">
+                <el-option
+                  v-for="item in selectOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="频度">
+              <el-select v-model="editFormData.occurence">
+                <el-option
+                  v-for="item in selectOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option
+              ></el-select> </el-form-item
+          ></el-col>
+        </el-row>
+        <el-row :gutter="24">
+          <el-col :span="12"
+            ><el-form-item label="难检度">
+              <el-select v-model="editFormData.detection">
+                <el-option
+                  v-for="item in selectOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option
+              ></el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="结构">
+              <el-cascader
+                v-model="editFormData.structurecode"
+                :options="cascaderdata"
+                :props="{ checkStrictly: true }"
+                clearable
+              /> </el-form-item
+          ></el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <button   class="btn green" @click="editVisible = false">取 消</button>
+          <button   class="btn green" type="primary" @click="saveEdit">确 定</button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import { ref, onMounted, reactive, inject, warn } from "vue";
+import { ElMessageBox, ElMessage, ElLoading } from "element-plus";
+import {
+  faultmode_windturbine,
+  faultmode_structurecode,
+  faultmode_delete,
+  faultmode_add_edit,
+} from "@/api/api.js";
+let cascaderdata = inject("cascaderdata");
+console.warn(cascaderdata);
+let editVisible = ref(false);
+let editFormData = ref({});
+onMounted(() => {
+  getfaultmode();
+});
+const selectV = {
+  1: "I",
+  2: "II",
+  3: "III",
+  4: "IV",
+  5: "V",
+};
+const selectOptions = [
+  {
+    label: "I",
+    value: 1,
+  },
+  {
+    label: "II",
+    value: 2,
+  },
+  {
+    label: "III",
+    value: 3,
+  },
+  {
+    label: "IV",
+    value: 4,
+  },
+  {
+    label: "V",
+    value: 5,
+  },
+];
+const rank = (v) => {
+  return selectV[v] || "";
+};
+let state = reactive({
+  faultmodeTableData: [],
+  addFormData: {
+    code: "",
+    name: "",
+    effects: "",
+    cause: "",
+    measure: "",
+    severity: null,
+    occurence: null,
+    detection: null,
+    deviceid: "windturbine",
+    structurecode: "",
+    models: null,
+  },
+});
+// 新增 编辑
+const handleEdit = (row) => {
+  editFormData.value = row;
+  editVisible.value = true;
+};
+
+// 测点 删除
+const handleDelete = (row) => {
+  // 二次确认删除
+  ElMessageBox.confirm("确定要删除吗?", "提示", {
+    type: "warning",
+  })
+    .then(async () => {
+      console.warn(row);
+      const res = await faultmode_delete(row.id);
+      console.warn(res);
+      if (res == 1) {
+        ElMessage.success(`删除成功!`);
+      } else {
+        ElMessage.success("删除失败");
+      }
+      getfaultmode();
+    })
+    .catch(() => {});
+};
+// 保存编辑
+const saveEdit = async () => {
+  const res = await faultmode_add_edit(editFormData.value);
+  console.warn(res);
+  if (res.status == 20000) {
+    ElMessage.success(`操作成功!`);
+    editVisible.value = false;
+    getfaultmode();
+  } else {
+    ElMessage.success(res.msg);
+  }
+};
+// getData
+const getfaultmode = async () => {
+  const loading = ElLoading.service({
+    lock: true,
+    text: "数据加载中...",
+    background: "rgba(0, 0, 0, 0.5)",
+  });
+  const res = await faultmode_windturbine();
+  state.faultmodeTableData = res;
+  loading.close();
+  console.warn(res);
+};
+</script>
+<style lang="scss" scoped>
+</style>

+ 10 - 0
src/views/layout/Menu.vue

@@ -879,6 +879,11 @@ export default {
                   icon: "svg-wind-site",
                   path: "/others/ExportExcel",
                 },
+                {
+                  text: "设备管理",
+                  icon: "svg-wind-site",
+                  path: "/device/device",
+                },
               ],
             },
             {
@@ -986,6 +991,11 @@ export default {
                   icon: "svg-matrix",
                   path: "/others/warning",
                 },
+                {
+                  text: "性能预警综合分析",
+                  icon: "svg-matrix",
+                  path: "/others/analysis",
+                },
                 // {
                 //   text: "风电营销样本库",
                 //   icon: "svg-matrix",

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

@@ -1,5 +1,5 @@
 <template>
-  <div class="draught-fan-list">
+  <div class="draught-fan-list" id="draughtFan">
     <div class="query mg-b-8">
       <div class="query-items">
         <div class="query-item">
@@ -527,7 +527,7 @@ export default {
 }
 
 .curDialog {
-  .el-dialog__body {
+  #draughtFan .el-dialog__body {
     max-height: 600px;
     overflow-y: scroll;
   }

+ 338 - 0
src/views/sampleDatabase/analysis/index.vue

@@ -0,0 +1,338 @@
+<template>
+  <div class="knowledge-2">
+    <div class="query mg-b-8">
+      <div class="query-items">
+        <div class="query-item">
+          <div class="lable">场站:</div>
+          <div class="search-input">
+            <el-select
+              v-model="wpId"
+              clearable
+              placeholder="请选择"
+              popper-class="select"
+            >
+              <el-option
+                v-for="item in wpArray"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              />
+            </el-select>
+          </div>
+        </div>
+        <div class="query-item">
+          <div class="lable">样本类型:</div>
+          <div class="search-input">
+            <el-select
+              v-model="sampleValue"
+              clearable
+              placeholder="请选择"
+              popper-class="select"
+              style="width: 130px; margin-left: 20px"
+            >
+              <el-option
+                v-for="item in sampleList"
+                :key="item.value"
+                :value="item.value"
+                :label="item.label"
+              />
+            </el-select>
+          </div>
+        </div>
+        <div class="query-item" style="width: 445px">
+          <div class="lable">起止时间:</div>
+          <div class="search-input">
+            <el-date-picker
+              class="picker"
+              @change="changes"
+              v-model="timeValue"
+              type="datetimerange"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+            >
+            </el-date-picker>
+          </div>
+        </div>
+        <div class="query-item" style="width: 250px">
+          <div class="lable">时间间隔:</div>
+          <div class="search-input">
+            <el-select
+              v-model="interval"
+              collapse-tags
+              placeholder="请选择"
+              popper-class="select"
+            >
+              <el-option
+                v-for="item in intervals"
+                :key="item.value"
+                :value="item.value"
+                :label="item.label"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="query-actions">
+          <button class="btn" @click="getData()">查询</button>
+        </div>
+      </div>
+    </div>
+
+    <el-row :type="'flex'" class="content">
+      <el-col :span="5">
+        <div class="left">
+          <el-tree
+            class="filter-tree"
+            :data="showData"
+            :props="defaultProps"
+            :filter-node-method="filterNode"
+            node-key="id"
+            :default-expanded-keys="[0]"
+            :default-checked-keys="[ids]"
+            ref="tree"
+            highlight-current
+            @node-click="handleChange"
+          >
+          </el-tree>
+        </div>
+      </el-col>
+      <el-col :span="19">
+        <el-row>
+          <el-col :span="15">
+            <div class="charts">
+              <div class="titles">性能分析图</div>
+              <PerformanceEcharts id="chartsData" :showTime="true" :data="scatterLineData" width="100%" height="70vh"></PerformanceEcharts>
+            </div>
+          </el-col>
+          <el-col :span="9">
+            <div class="charts" v-if="warningTimeList.length > 0">
+              <div class="titles">预警饼状图</div>
+              <PieCharts id="pie" width="100%" height="70vh" :warningTimeList="warningTimeList"></PieCharts>
+            </div>
+          </el-col>
+        </el-row>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<script>
+import PerformanceEcharts from "../performance/performanceEcharts.vue";
+import PieCharts from "./pieCharts.vue";
+import BASE from "@tools/basicTool.js";
+export default {
+  components: {
+    PerformanceEcharts,
+    PieCharts,
+  },
+  created() {
+    if (this.timeValue.length === 0) {
+      let date = new Date();
+      this.timeValue[0] = 1622476800000;
+      this.timeValue[1] = 1630252800000;
+    }
+    this.getData();
+    this.getWp();
+  },
+  data() {
+    return {
+      timeValue: [],
+      ids:'',
+      wpId: "NSS_FDC",
+      wpArray: [],
+      sampleValue: "0",
+      sampleList: [
+        {
+          label: "正样本",
+          value: "0",
+        },
+        {
+          label: "负样本",
+          value: "1",
+        },
+      ],
+      interval: "5-1008",
+      intervals: [
+        {
+          label: "小于30分钟",
+          value: "0-0.5",
+        },
+        {
+          label: "30分钟-1小时",
+          value: "0.5-1",
+        },
+        {
+          label: "1小时-2小时",
+          value: "1-2",
+        },
+        {
+          label: "2小时-5小时",
+          value: "2-5",
+        },
+        {
+          //42天
+          label: "大于5小时",
+          value: "5-1008",
+        },
+      ],
+
+      defaultProps: {
+        children: "children",
+        label: "windturbineId",
+      },
+      showData: [],
+      warningTimeList: [],
+      scatterLineData:{},
+      warningList: [
+        {
+          label: "变桨系统",
+          value: "BJXT",
+        },
+        {
+          label: "测风系统",
+          value: "CFXT",
+        },
+        {
+          label: "发电机",
+          value: "FDJ",
+        },
+        {
+          label: "传动链",
+          value: "CDL",
+        },
+        {
+          label: "齿轮箱",
+          value: "CLX",
+        },
+        {
+          label: "机舱",
+          value: "JC",
+        },
+        {
+          label: "液压系统",
+          value: "YYXT",
+        },
+        {
+          label: "偏航系统",
+          value: "PHXT",
+        },
+        {
+          label: "塔底柜",
+          value: "TDG",
+        },
+      ],
+    };
+  },
+  methods: {
+    // 获取风场
+    getWp() {
+      let that = this;
+      that.API.requestData({
+        baseURL: "http://10.155.32.4:8082/",
+        subUrl: "powercompare/windfarmAjax",
+        success(res) {
+          that.wpArray = res.data;
+          that.wpId = res.data[1].id;
+        },
+      });
+    },
+    getData() {
+      let that = this;
+      this.API.requestData({
+        method: "GET",
+        subUrl: "http://192.168.1.18:9002/analyse/basic",
+        data: {
+          station: this.wpId,
+          intervals: this.interval,
+          tag: this.sampleValue,
+          st: new Date(this.timeValue[0]).formatDate("yyyy-MM-dd hh:mm:ss"),
+          et: new Date(this.timeValue[1]).formatDate("yyyy-MM-dd hh:mm:ss"),
+        },
+        success(res) {
+          if (res) {
+            that.ids = res.data[0].children[0].id
+            that.showData = res.data;
+            that.handleChange(res.data[0].children[0])
+          }
+        },
+      });
+    },
+    async handleChange(val) {
+      if (val.st) {
+        BASE.showLoading({ text: "加载中..." });
+        let warningList = [];
+        let that = this;
+        await this.API.requestData({
+          method: "GET",
+          subUrl: "http://192.168.10.18:8075/alarm/history/page",
+          data: {
+            pagenum: 1,
+            pagesize: 20000,
+            starttime: val.st,
+            endtime: val.et,
+            stationid: this.wpId,
+            windturbineid: val.wtId,
+          },
+          success(res) {
+            if (res.records) {
+              res.records.forEach((item) => {
+                if (
+                  warningList.filter((val) => val.label === item.category3)
+                    .length > 0
+                ) {
+                  warningList.filter((val) => val.label === item.category3)[0]
+                    .num++;
+                } else {
+                  let obj = {
+                    label: item.category3,
+                    name: that.warningList.filter(
+                      (val) => val.value === item.category3
+                    )[0].label,
+                    num: 1,
+                  };
+                  warningList.push(obj);
+                }
+              });
+
+              that.warningTimeList = warningList;
+            }
+          },
+        });
+        
+        await that.API.requestData({
+        method: "GET",
+        baseURL: "http://192.168.1.18:9002/",
+        // baseURL: "http://192.168.10.4:9002/",
+        subUrl: "case/performance/line",
+        data: {
+          id: val.id,
+          interval: 30,
+        },
+        success(res) {
+          if (res.code == 200) {
+            that.scatterLineData = res.data;
+            BASE.closeLoading();
+          }
+        },
+      });
+      }
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.charts {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+.titles{
+  font-size: 16px;
+  margin: 20px 0 40px 10px;
+}
+body .el-tree {
+  height: 85vh;
+  padding-left: 30px;
+  overflow-y: auto;
+}
+</style>

+ 127 - 0
src/views/sampleDatabase/analysis/pieCharts.vue

@@ -0,0 +1,127 @@
+<template>
+  <div class="precisionEcharts" :style="style" :id="id"></div>
+</template>
+<script>
+import * as echarts from "echarts";
+export default {
+  props: {
+    warningTimeList: {
+      type: Array,
+    },
+    id: Object,
+    width: {
+      type: String,
+      default: "600px",
+    },
+    height: {
+      type: String,
+      default: "250px",
+    },
+  },
+  data() {
+    return {
+    };
+  },
+  computed: {
+    style() {
+      return `width: ${this.width}; height: ${this.height};`;
+    },
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart();
+    });
+  },
+  updated() {
+    this.$nextTick(() => {
+      this.initChart();
+    });
+  },
+  methods: {
+    initChart() {
+      let seriesData = [];
+      this.warningTimeList.forEach((item) => {
+        let obj = {
+          value: item.num,
+          name: item.name,
+        };
+        seriesData.push(obj);
+      });
+      let chartDom = document.getElementById(this.id);
+      let myChart = echarts.init(chartDom);
+      let option = {
+        title: {
+          text: "",
+        },
+        tooltip: {
+          trigger: "item",
+        },
+        legend: {
+          top: "5%",
+          left: "center",
+          textStyle: {
+            color: "#ffffff",
+            fontSize: 14,
+          },
+        },
+        series: [
+          {
+            name: "报警次数",
+            type: "pie",
+            radius: ["30%", "55%"],
+            avoidLabelOverlap: false,
+            itemStyle: {
+              borderRadius: 10,
+              borderColor: "#000",
+              borderWidth: 2,
+            },
+            label: {
+              show: true,
+              normal: {
+                show: true,
+                textStyle: {
+                  fontSize: "20",
+                  color: "#ffffff",
+                },
+              },
+              emphasis: {
+                show: true,
+                textStyle: {
+                  fontSize: "25",
+                  color: "#ffffff",
+                },
+              },
+            },
+            emphasis: {
+              label: {
+                show: true,
+                fontSize: "40",
+                fontWeight: "bold",
+              },
+            },
+            labelLine: {
+              show: true,
+            },
+            data: seriesData,
+          },
+        ],
+      };
+      option && myChart.setOption(option);
+    },
+  },
+  watch: {
+    warningTimeList: {
+      handler(newValue, oldValue) {
+        this.initChart();
+      },
+      deep: true,
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+// .precisionEcharts {
+//   width: 600px;
+//   height: 250px;
+// }
+</style>

+ 9 - 7
src/views/sampleDatabase/performance/index.vue

@@ -173,7 +173,7 @@ export default {
         },
       ],
       // 时间间隔
-      interval: "1-2",
+      interval: "5-1008",
       intervals: [
         //和明华有约定,必须这么写
         {
@@ -253,10 +253,12 @@ export default {
     async startAjax() {
       var that = this;
       that.time = [
-        new Date(new Date() - 3600 * 24 * 1000 * 15).formatDate(
-          "yyyy-MM-dd hh:mm:ss"
-        ),
-        new Date().formatDate("yyyy-MM-dd hh:mm:ss"),
+        // new Date(new Date() - 3600 * 24 * 1000 * 15).formatDate(
+        //   "yyyy-MM-dd hh:mm:ss"
+        // ),
+        // new Date().formatDate("yyyy-MM-dd hh:mm:ss"),
+        new Date(1622476800000).formatDate("yyyy-MM-dd hh:mm:ss"),
+        new Date(1630252800000).formatDate("yyyy-MM-dd hh:mm:ss")
       ];
       await that.API.requestData({
         method: "GET",
@@ -282,7 +284,7 @@ export default {
       that.API.requestData({
         method: "GET",
         // baseURL: "http://192.168.10.19:9002/",
-        baseURL: "http://192.168.10.4:9002/",
+        baseURL: "http://192.168.1.18:9002/",
         subUrl: "case/performance/line",
         data: {
           id: ids,
@@ -320,7 +322,7 @@ export default {
       that.API.requestData({
         showLoading: true,
         method: "GET",
-        baseURL: "http://192.168.10.4:9002/",
+        baseURL: "http://192.168.1.18:9002/",
         //    baseURL: "http://192.168.10.19:9002/",
         subUrl: "case/performance/list",
         data: {

+ 42 - 15
src/views/sampleDatabase/performance/performanceEcharts.vue

@@ -20,6 +20,10 @@ export default {
       type: String,
       default: "350px",
     },
+    showTime: {
+      type: Boolean,
+      default: false,
+    },
     // 传入数据
     data: {
       type: Array,
@@ -65,7 +69,7 @@ export default {
       let option = {
         legend: {
           show: true,
-          data: ["功率曲线", "风速曲线"],
+          data: ["实发功率", "理论功率", "实时风速"],
           right: 120,
           icon: "ract",
           itemWidth: 8,
@@ -98,13 +102,13 @@ export default {
             boundaryGap: false,
             axisLabel: {
               interval:
-                Number((this.xdata.length / 8).toFixed(0)) > 2
-                  ? Number((this.xdata.length / 8).toFixed(0))
+                Number((this.xdata.length / 6).toFixed(0)) > 2
+                  ? Number((this.xdata.length / 6).toFixed(0))
                   : 0,
               showMinLabel: true,
               showMaxLabel: true,
               formatter: "{value}",
-              fontSize: 14,
+              fontSize: 12,
               textStyle: {
                 color: "#606769",
               },
@@ -129,7 +133,7 @@ export default {
         // },
         yAxis: [
           {
-            name: "功率",
+            name: "功率(kWh)",
             type: "value",
             axisTick: {
               show: false,
@@ -143,7 +147,7 @@ export default {
             },
           },
           {
-            name: "风速",
+            name: "风速(m/s)",
             type: "value",
             axisTick: {
               show: false,
@@ -159,13 +163,13 @@ export default {
         ],
         series: [],
       };
-      if (this.data.power.length > 0) {
+      if (this.data?.power?.length > 0) {
         let arr = [];
         this.data.power.forEach((item) => {
           arr.push(item.doubleValue);
         });
         let obj = {
-          name: "功率曲线",
+          name: "实发功率",
           type: "line",
           data: arr,
           smooth: true, //平滑展示
@@ -174,13 +178,28 @@ export default {
 
         option.series.push(obj);
       }
-      if (this.data.speed.length > 0) {
+      if (this.data?.llglpower?.length > 0) {
+        let arr = [];
+        this.data.llglpower.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: "风速曲线",
+          name: "实时风速",
           type: "line",
           data: arr,
           smooth: true, //平滑展示
@@ -210,11 +229,19 @@ export default {
   },
   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;
+    if (this.data?.power.length > 0 || this.data?.speed.length > 0) {
+      if (this.showTime) {
+        this.data?.power.forEach((value, index) => {
+          data.push(new Date(value.ts).formatDate("MM-dd hh:mm"));
+        });
+      } else {
+        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();
     });