Explorar o código

Merge branch 'master' of http://192.168.50.233:3000/rui.jiang/performance-test

liujiejie hai 5 meses
pai
achega
bd8bc66d56

+ 2 - 2
src/router/index.js

@@ -28,8 +28,8 @@ const createRouter = () =>
             iconName: "gps",
             component: () =>
               import(
-                /*webpackChunkName:'home-cockpitManage'*/ "../views/admin/cockpitManage/Index.vue"
-                // /*webpackChunkName:'home-cockpitManage'*/ "../views/admin/cockpitManage/HD.vue"
+                // /*webpackChunkName:'home-cockpitManage'*/ "../views/admin/cockpitManage/Index.vue"
+                /*webpackChunkName:'home-cockpitManage'*/ "../views/admin/cockpitManage/HD.vue" //华电选择这个
               ),
           },
           {

+ 38 - 27
src/views/health/components/malfunction/Eecharts.vue

@@ -1,8 +1,8 @@
 <template>
-  <div ref="chartDom" style="width: 100%; height: 400px"></div>
+  <div ref="chartDom" style="width: 100%; height: 100%"></div>
 </template>
-  
-  <script>
+
+<script>
 import * as echarts from "echarts";
 
 export default {
@@ -13,12 +13,12 @@ export default {
       required: true,
     },
     yData: {
-      type: Array,
+      type: Array, // 二维数组
       required: true,
     },
     yNames: {
       type: Array,
-      required: true,
+      required: true, // 只取第一个元素
     },
     yAxisName: {
       type: String,
@@ -34,11 +34,26 @@ export default {
     this.initChart();
   },
   watch: {
-    xData: "initChart",
-    yData: "initChart",
-    yNames: "initChart",
-    yAxisName: "initChart",
+    xData: {
+      handler: "initChart",
+      deep: true,
+      immediate: true,
+    },
+    yData: {
+      handler: "initChart",
+      deep: true,
+      immediate: true,
+    },
+    yNames: {
+      handler: "initChart",
+      immediate: true,
+    },
+    yAxisName: {
+      handler: "initChart",
+      immediate: true,
+    },
   },
+
   methods: {
     initChart() {
       if (!this.$refs.chartDom) return;
@@ -46,23 +61,19 @@ export default {
       if (!this.myChart) {
         this.myChart = echarts.init(this.$refs.chartDom);
       }
-      const colors = ["#1B3A7F", "#02aae9","#A9D598","#008000"];
-      const series = this.yData.map((dataArr, idx) => ({
-        name: this.yNames[idx] || `系列${idx + 1}`,
+
+      const colors = ["#02aae9", "#5470C6", "#3CB9B9", "#9966CC"]; // 颜色列表可以根据需要扩展
+
+      const series = this.yData.map((data, index) => ({
+        name: this.yNames[index] || `系列${index + 1}`,
         type: "line",
-        data: dataArr,
+        data: data,
         lineStyle: {
-          color: colors[idx % colors.length],
+          color: colors[index % colors.length],
         },
         itemStyle: {
-          color: colors[idx % colors.length],
+          color: colors[index % colors.length],
         },
-        // areaStyle: {
-        //   color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-        //     { offset: 0, color: colors[idx % colors.length] },
-        //     { offset: 1, color: colors[idx % colors.length] + "00" }, // 底部透明
-        //   ]),
-        // },
       }));
 
       const option = {
@@ -70,7 +81,7 @@ export default {
           trigger: "axis",
         },
         legend: {
-          data: this.yNames,
+          data: this.yNames.slice(0, series.length),
           top: 10,
         },
         grid: {
@@ -88,16 +99,16 @@ export default {
           type: "value",
           name: this.yAxisName,
         },
-        series,
-        color: colors, // 统一设定图表配色
+        series: series,
+        color: colors,
       };
 
+      this.myChart.clear(); // ✅ 清除旧配置
       this.myChart.setOption(option);
     },
   },
 };
 </script>
-  
-  <style scoped>
+
+<style scoped>
 </style>
-  

+ 126 - 224
src/views/health/components/malfunction/bearing.vue

@@ -31,7 +31,7 @@
           </el-table-column>
         </el-table>
         <div class="fenye">
-          <p><span>故障状态码说明:</span>0代表正常,1代表报警,2代表危险</p>
+          <p><span>状态码说明:</span>0正常,1报警,2危险,-1未定义</p>
 
           <el-pagination
             @current-change="handleCurrentChange"
@@ -65,13 +65,14 @@
             size="small"
             @click="automaticDiagnosis"
             class="btn-auto"
+            :loading="loading"
             >诊断</el-button
           >
         </div>
 
         <div class="Btn">
           <div style="height: 200px">
-            <bing :result="result"> </bing>
+            <bingTwo :statistics="statistics"> </bingTwo>
           </div>
 
           <div class="minp">
@@ -111,129 +112,17 @@
           yAxisName="轴承故障状态"
         ></Eecharts>
       </div>
-
-      <el-dialog
-        title="提示"
-        :visible.sync="dialogVisible"
-        width="50%"
-
-      >
-        <div class="BtRight">
-          <h4>参数设置</h4>
-          <div class="BtRightDiv">
-            <p class="BtRightP">
-              发电机到轴承测点转速传动比<span
-                ><el-input
-                  v-model="transmissionRatio"
-                  size="small"
-                  v-number-only
-                ></el-input
-              ></span>
-            </p>
-            <h4>滚动轴承参数输入</h4>
-            <div class="canshu">
-              <p class="BtRightP">
-                <span class="label-text">轴承节圆直径D(mm)</span>
-                <span
-                  ><el-input
-                    v-model="bearingPitchDiameter"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-              <p class="BtRightP">
-                <span class="label-text">滚动体直径d(mm)</span>
-                <span
-                  ><el-input
-                    v-model="rollingElementDiameter"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-              <p class="BtRightP">
-                <span class="label-text">滚动体个数Z(个)</span>
-                <span
-                  ><el-input
-                    v-model="rollingElementCount"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-              <p class="BtRightP">
-                <span class="label-text">接触角α(°)</span>
-                <span
-                  ><el-input
-                    v-model="contactAngle"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-            </div>
-            <h4>报警阈值输入</h4>
-            <div class="canshu">
-              <p class="BtRightP">
-                <span class="label-text">振动速度报警阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedAlarmThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-              <p class="BtRightP">
-                <span class="label-text">振动速度危险阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedDangerThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-              <p class="BtRightP">
-                <span class="label-text">包络总值报警阈值(gE)</span>
-                <span
-                  ><el-input
-                    v-model="envelopeTotalAlarmThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-              <p class="BtRightP">
-                <span class="label-text">包络总值危险阈值(gE)</span>
-                <span
-                  ><el-input
-                    v-model="envelopeTotalDangerThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-            </div>
-          </div>
-        </div>
-             <div class="dialog-footer">
-          <el-button type="primary" size="small" @click="submit"
-            >确定</el-button
-          >
-        </div>
-      </el-dialog>
     </div>
   </div>
 </template>
 
 <script>
+import axios from "axios";
 import Eecharts from "./Eecharts.vue";
-import bing from "./bing.vue";
+import bingTwo from "./bingTwo.vue";
 import { cacheEntryPossiblyAdded } from "plotly.js-dist";
 export default {
-  components: { Eecharts, bing },
+  components: { Eecharts, bingTwo },
   props: {
     codedata: {
       type: Array,
@@ -247,6 +136,14 @@ export default {
       type: Number,
       default: 0,
     },
+    fieldCode: {
+      type: String,
+      default: "",
+    },
+    windTurbineNumber: {
+      type: String,
+      default: "",
+    },
   },
   data() {
     return {
@@ -278,6 +175,8 @@ export default {
       hasError: false, // 标志是否已经显示过错误提示
       result: {},
       dialogVisible: false,
+      loading: false, // 控制加载状态
+      statistics: {},
     };
   },
   created() {},
@@ -306,114 +205,85 @@ export default {
     },
     handleCurrentChange(val) {
       console.log(`当前页: ${val}`);
-
+      setTimeout(() => {
+        this.automaticDiagnosis();
+      }, 500);
       this.currentPage = val; // 子组件内部更新当前页
       this.$emit("updatePage", this.currentPage); // 通知父组件,把当前页传出去
     },
- 
+
     automaticDiagnosis() {
-      this.dialogVisible = true;
-    },
-    submit() {
-      // 验证必填项
-      const requiredFields = [
-        { field: this.transmissionRatio, name: "发动机到轴承测点转速传动比" },
-        { field: this.bearingPitchDiameter, name: "轴承节圆直径D(mm)" },
-        { field: this.rollingElementDiameter, name: "滚动体直径d(mm)" },
-        { field: this.rollingElementCount, name: "滚动体个数Z(个)" },
-        { field: this.contactAngle, name: "接触角α(°)" },
-        {
-          field: this.vibrationSpeedAlarmThreshold,
-          name: "振动速度报警阈值(mm/s)",
-        },
-        {
-          field: this.vibrationSpeedDangerThreshold,
-          name: "振动速度危险阈值(mm/s)",
-        },
-        {
-          field: this.envelopeTotalAlarmThreshold,
-          name: "包络总值报警阈值(gE)",
-        },
-        {
-          field: this.envelopeTotalDangerThreshold,
-          name: "包络总值危险阈值(gE)",
-        },
-      ];
-
-      // 记录是否已弹出过错误提示
-      let hasError = false;
-
-      // 只检查必填项的字段是否为空
-      // for (const { field, name } of requiredFields) {
-      //   if (!field && !hasError) {
-      //     // 弹出提示并标记已经出现错误提示
-      //     this.$message.error(`${name} 是必填项`);
-      //     hasError = true;  // 标记已经弹出过错误提示
-      //     return;  // 停止执行后续逻辑
-      //   }
-      // }
-
-      // 如果验证通过,继续执行后续逻辑
-      const newProps = this.tableData.map(() => ({
-        innerRingFault: Math.floor(Math.random() * 3).toString(),
-        outerRingFault: Math.floor(Math.random() * 3).toString(),
-        rollingElementFault: Math.floor(Math.random() * 3).toString(),
-        cageFault: Math.floor(Math.random() * 3).toString(),
-      }));
-
-      this.tableData.forEach((row, index) => {
-        this.$set(this.tableData, index, {
-          ...row,
-          ...newProps[index], // 用每一行自己生成的随机数
-        });
-      });
+      this.loading = true;
+      const ids = this.tableData
+        .map((item) => item.id)
+        .filter((id) => id !== undefined);
 
-      const faultValues = [
-        ...this.tableData.map((record) => record.innerRingFault),
-        ...this.tableData.map((record) => record.outerRingFault),
-        ...this.tableData.map((record) => record.rollingElementFault),
-        ...this.tableData.map((record) => record.cageFault),
-      ];
-
-      // 统计各个值出现的次数
-      const counter = faultValues.reduce((acc, value) => {
-        acc[value] = (acc[value] || 0) + 1;
-        return acc;
-      }, {});
-
-      // 构造统计结果对象
-      this.result = {
-        1: counter["0"] || 0,
-        2: counter["1"] || 0,
-        3: counter["2"] || 0,
+      const params = {
+        windCode: this.fieldCode,
+        engine_code: this.windTurbineNumber,
+        autodiagType: "Bearing",
+        ids,
       };
 
-      // 更新颜色状态
-      const fields = [
-        { key: "innerRingFault", colorKey: "innerRing" },
-        { key: "outerRingFault", colorKey: "outerRing" },
-        { key: "rollingElementFault", colorKey: "rollingElement" },
-        { key: "cageFault", colorKey: "cage" },
-      ];
-
-      fields.forEach(({ key, colorKey }) => {
-        const values = newProps.map((item) => Number(item[key]));
-        const maxVal = Math.max(...values);
-        let color = "#80808057"; // 默认灰色
-        if (maxVal === 0) color = "#8AE359"; // 无故障
-        else if (maxVal === 1) color = "#EECB5F"; // 警告
-        else if (maxVal === 2) color = "#F7715F"; // 危险
-
-        this.bearingStateColors[colorKey] = color; // 更新颜色
+      const autodiagType = params.autodiagType || "Bearing";
+
+      const loadingInstance = this.$loading({
+        lock: true,
+        text: "自动诊断中...",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
       });
 
-      // 更新趋势图数据
-      // 更新趋势图数据(用tableData,不是newProps)
-      this.xData = this.tableData.map((item) => item.timeStamp);
-      this.yData = fields.map(({ key }) =>
-        this.tableData.map((item) => Number(item[key]))
-      );
-      this.dialogVisible = false;
+      axios
+        .post(`/WJJdiag/autodiag/${autodiagType}`, params)
+        .then((res) => {
+          const result = res.data.results;
+
+          this.statistics = res.data.statistics || {};
+
+          // x轴数据,时间戳
+          this.xData = this.tableData.map((item) => item.timeStamp);
+
+          // y轴数据,状态码二维数组
+          this.yData = [
+            result.BPFI?.status_codes || [],
+            result.BPFO?.status_codes || [],
+            result.BSF?.status_codes || [],
+            result.FTF?.status_codes || [],
+          ];
+
+          // 根据 max_status 设置颜色的函数
+     const setColor = (status) => {
+  switch (status) {
+    case 0:
+      return '#8ae359'
+    case 1:
+      return '#eecb5f'
+    case 2:
+      return '#f7715f'
+    default:
+      return '#80808057'
+  }
+}
+
+          this.bearingStateColors.innerRing = setColor(
+            result.BPFI?.max_status || 0
+          );
+          this.bearingStateColors.outerRing = setColor(
+            result.BPFO?.max_status || 0
+          );
+          this.bearingStateColors.rollingElement = setColor(
+            result.BSF?.max_status || 0
+          );
+          this.bearingStateColors.cage = setColor(result.FTF?.max_status || 0);
+        })
+        .catch((err) => {
+          console.error("诊断失败:", err);
+        })
+        .finally(() => {
+          loadingInstance.close();
+          this.loading = false;
+        });
     },
   },
 };
@@ -424,22 +294,28 @@ h4 {
   margin-bottom: 5px;
   font-weight: 600;
 }
+
 .TopBox {
   height: 280px;
   display: flex;
   justify-content: space-around;
+
   .leftdiv {
     width: 50%;
     display: flex;
     justify-content: space-around;
+
     .stateBox {
       .state {
         display: flex;
         flex-direction: column;
-        justify-content: center; /* 整体居中 */
+        justify-content: center;
+        /* 整体居中 */
         align-items: center;
         height: 200px;
-        gap: 20px; /* 控制间距 */
+        gap: 20px;
+
+        /* 控制间距 */
         p {
           width: 150px;
           height: 40px;
@@ -450,18 +326,24 @@ h4 {
           font-weight: 600;
         }
       }
+
       .btn-auto {
         margin-top: 10px;
         width: 100%;
       }
     }
+
     .Btn {
       width: 50%;
       display: flex;
-      flex-direction: column; /* 垂直排列 */
-      justify-content: space-between; /* 顶部和底部对齐 */
-      min-height: 100px; /* 确保容器有足够高度 */
+      flex-direction: column;
+      /* 垂直排列 */
+      justify-content: space-between;
+      /* 顶部和底部对齐 */
+      min-height: 100px;
+      /* 确保容器有足够高度 */
       margin: 10px 0;
+
       .PText {
         display: flex;
         justify-content: space-around;
@@ -469,37 +351,47 @@ h4 {
         span {
           display: flex;
           align-items: center;
+
           i {
             width: 30px;
             height: 15px;
             margin-right: 5px;
           }
+
           .color1 {
             background-color: #8ae359;
           }
+
           .color2 {
             background-color: #eecb5f;
           }
+
           .color3 {
             background-color: #f7715f;
           }
         }
       }
+
       margin: 10px 0;
+
       .minp {
         font-size: 12px;
-        margin-top: auto; /* 自动推到最底部 */
+        margin-top: auto;
+        /* 自动推到最底部 */
       }
     }
   }
+
   .rightdiv {
     width: 50%;
+
     .fenye {
       display: flex;
       justify-content: space-between;
       margin: 5px 0;
       font-size: 11px;
       line-height: 30px;
+
       span {
         font-weight: 600;
       }
@@ -511,36 +403,44 @@ h4 {
   display: flex;
   justify-content: space-around;
   margin-top: 10px;
+
   .BtLeft {
     border: 1px solid rgb(231, 231, 231);
     width: 100%;
     padding: 10px;
   }
-  .BtRight {
 
+  .BtRight {
     border: 1px solid rgb(231, 231, 231);
     padding: 10px;
+
     .BtRightDiv {
       padding: 0 10px;
+
       h4 {
         font-size: 14px;
       }
+
       .BtRightP {
         line-height: 30px;
         font-size: 12px;
         display: flex;
         margin-bottom: 5px;
         width: 50%;
+
         span {
           margin-left: 10px;
+
           .el-input {
             width: 100px;
           }
         }
+
         .label-text {
           width: 140px;
         }
       }
+
       .canshu {
         display: flex;
         flex-wrap: wrap;
@@ -548,11 +448,13 @@ h4 {
       }
     }
   }
-   .dialog-footer {
+
+  .dialog-footer {
     margin-top: 20px;
     text-align: right;
   }
 }
+
 ::v-deep .el-table__cell {
   padding: 2px 0;
   font-size: 12px;

+ 11 - 12
src/views/health/components/malfunction/bing.vue

@@ -10,8 +10,11 @@ export default {
 
   props: {
     result: {
-      type: Object, // 使用 Object 作为类型
-      default: () => ({}),
+      type: Object,
+      default: () => ({
+        normal: 0,
+        danger: 0,
+      }),
     },
   },
 
@@ -62,8 +65,8 @@ export default {
             radius: ["40%", "60%"], // 设置内外半径来形成圆环
             data: [
               { value: 0, name: "正常", itemStyle: { color: "#8AE359" } },
-              { value: 0, name: "报警", itemStyle: { color: "#EECB5F" } },
-
+              { value: 0, name: "危险", itemStyle: { color: "#EECB5F" } },
+ 
             ],
             emphasis: {
               itemStyle: {
@@ -108,20 +111,16 @@ export default {
             radius: ["40%", "60%"], // 设置内外半径来形成圆环
             data: [
               {
-                value: newResult[1] || 0,
+                value: this.result.normal || 0,
                 name: "正常",
                 itemStyle: { color: "#8AE359" },
               },
               {
-                value: newResult[2] || 0,
-                name: "报警",
-                itemStyle: { color: "#EECB5F" },
-              },
-              {
-                value: newResult[3] || 0,
+                value: this.result.danger || 0,
                 name: "危险",
-                itemStyle: { color: "#F7715F" },
+                itemStyle: { color: "#EECB5F" },
               },
+           
             ],
             emphasis: {
               itemStyle: {

+ 152 - 0
src/views/health/components/malfunction/bingTwo.vue

@@ -0,0 +1,152 @@
+<template>
+  <div ref="chartDom" style="width: 100%; height: 100%"></div>
+</template>
+
+<script>
+import * as echarts from "echarts";
+
+export default {
+  name: "EChartsComponent",
+
+  props: {
+    statistics: {
+      type: Object,
+      default: () => ({
+        normal: 0,
+        danger: 0,
+      }),
+    },
+  },
+
+  data() {
+    return {
+      myChart: null,
+    };
+  },
+
+  mounted() {
+    console.log(this.statistics, "this.statistics");
+
+    this.initChart(); // 初始化图表
+  },
+
+  watch: {
+    // 监听 statistics 的变化
+    statistics(newValue) {
+      console.log("statistics changed", newValue);
+      this.updateChart(newValue); // 更新图表
+    },
+  },
+
+  methods: {
+    initChart() {
+      const chartDom = this.$refs.chartDom;
+      this.myChart = echarts.init(chartDom);
+
+      const option = {
+        title: {
+          text: "状态统计图",
+          left: "center",
+          textStyle: {
+            fontSize: 14, // 设置字体大小
+            fontWeight: "600", // 可选,设置字体粗细
+            color: "#333", // 可选,设置字体颜色
+          },
+        },
+        tooltip: {
+          trigger: "item",
+          formatter: "{b}: {c} 次 ({d}%)", // 显示次数和百分比
+        },
+
+        series: [
+          {
+            name: "状态次数",
+            type: "pie",
+            radius: ["40%", "60%"], // 设置内外半径来形成圆环
+            data: [
+              { value: 0, name: "正常", itemStyle: { color: "#8AE359" } },
+              { value: 0, name: "危险", itemStyle: { color: "#EECB5F" } },
+              { value: 0, name: "报警", itemStyle: { color: "#f7715f" } },
+            ],
+            emphasis: {
+              itemStyle: {
+                shadowBlur: 10,
+                shadowOffsetX: 0,
+                shadowColor: "rgba(0, 0, 0, 0.5)",
+              },
+            },
+            label: {
+              // formatter: "{b}: {c} 次", // 在图表中显示次数
+            },
+          },
+        ],
+      };
+
+      this.myChart.setOption(option);
+    },
+
+    // 更新图表方法
+    updateChart(newResult) {
+      console.log(newResult, "111111111111111111");
+
+      const option = {
+        title: {
+          text: "状态统计图",
+          left: "center",
+          textStyle: {
+            fontSize: 14, // 设置字体大小
+            fontWeight: "600", // 可选,设置字体粗细
+            color: "#333", // 可选,设置字体颜色
+          },
+        },
+        tooltip: {
+          trigger: "item",
+          // formatter: "{b}: {c} 次 ({d}%)", // 显示次数和百分比
+        },
+
+        series: [
+          {
+            name: "状态次数",
+            type: "pie",
+            radius: ["40%", "60%"], // 设置内外半径来形成圆环
+            data: [
+              {
+                value: this.statistics.count_0 || 0,
+                name: "正常",
+                itemStyle: { color: "#8AE359" },
+              },
+              {
+                value: this.statistics.count_1 || 0,
+                name: "危险",
+                itemStyle: { color: "#EECB5F" },
+              },
+              {
+                    value: this.statistics.count_2 || 0,
+                name: "危险",
+                itemStyle: { color: "#f7715f" },
+              },
+            ],
+            emphasis: {
+              itemStyle: {
+                shadowBlur: 10,
+                shadowOffsetX: 0,
+                shadowColor: "rgba(0, 0, 0, 0.5)",
+              },
+            },
+            label: {
+              // formatter: "{b}: {c} 次", // 在图表中显示次数
+            },
+          },
+        ],
+      };
+
+      // 更新图表
+      this.myChart.setOption(option);
+    },
+  },
+};
+</script>
+
+<style scoped>
+/* 可根据需求添加样式 */
+</style>

+ 81 - 157
src/views/health/components/malfunction/dissymmetry.vue

@@ -31,7 +31,7 @@
           </el-table-column>
         </el-table>
         <div class="fenye">
-          <p><span>故障状态码说明:</span>0代表正常,1代表报警,2代表危险</p>
+          <p><span>状态码说明:</span>0正常,1报警,2危险,-1未定义</p>
 
           <el-pagination
             small
@@ -57,13 +57,14 @@
             size="small"
             @click="automaticDiagnosis"
             class="btn-auto"
+            :loading="loading"
             >诊断</el-button
           >
         </div>
 
         <div class="Btn">
           <div style="height: 200px">
-            <bing :result="result"> </bing>
+            <bingTwo :statistics="statistics"> </bingTwo>
           </div>
 
           <div class="minp">
@@ -75,8 +76,7 @@
 
             <h4>诊断步骤:</h4>
             <p>1、选择振动测点与起止时间,点击“查询;</p>
-            <p>2、对不对中“参数设置”输入相关信息;</p>
-            <p>3、点击“诊断”输出最终轴承状态结果。</p>
+            <p>2、点击“诊断”输出最终轴承状态结果。</p>
           </div>
         </div>
       </div>
@@ -87,76 +87,29 @@
         <el-empty
           v-if="this.xData.length === 0 || this.yData.length === 0"
           description="暂无数据"
-          style="padding: 17px 0"
+          style="padding: 48px 0"
         ></el-empty>
         <Eecharts
           v-else
-          style="height: 250px"
+          style="height: 310px"
           :xData="xData"
-          :yData="yData"
+          :yData="[yData]"
           :yNames="['不对中故障']"
           yAxisName="不对中故障状态"
+   
         ></Eecharts>
       </div>
-
-      <el-dialog title="参数" :visible.sync="dialogVisible" width="50%">
-        <div class="BtRight">
-          <h4>参数设置</h4>
-          <div class="BtRightDiv">
-            <p class="BtRightP">
-              <span>发电机到不对中测点的转速传动比</span>
-
-              <span
-                ><el-input
-                  v-model="transmissionRatio"
-                  size="small"
-                  v-number-only
-                ></el-input
-              ></span>
-            </p>
-
-            <h4>报警阈值输入</h4>
-            <div class="canshu">
-              <p class="BtRightP">
-                <span class="label-text">振动速度报警阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedAlarmThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-
-              <p class="BtRightP">
-                <span class="label-text">振动速度危险阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedDangerThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-            </div>
-          </div>
-        </div>
-        <div class="dialog-footer">
-          <el-button type="primary" size="small" @click="submit"
-            >确定</el-button
-          >
-        </div>
-      </el-dialog>
     </div>
   </div>
 </template>
 
 <script>
+import axios from "axios";
 import Eecharts from "./Eecharts.vue";
-import bing from "./bing.vue";
-import { cacheEntryPossiblyAdded } from "plotly.js-dist";
+import bingTwo from "./bingTwo.vue";
+import { cacheEntryPossiblyAdded, log10, promisify } from "plotly.js-dist";
 export default {
-  components: { Eecharts, bing },
+  components: { Eecharts, bingTwo },
   props: {
     codedata: {
       type: Array,
@@ -170,6 +123,14 @@ export default {
       type: Number,
       default: 0,
     },
+    fieldCode: {
+      type: String,
+      default: "",
+    },
+    windTurbineNumber: {
+      type: String,
+      default: "",
+    },
   },
   data() {
     return {
@@ -199,8 +160,10 @@ export default {
         cage: "#80808057",
       },
       hasError: false, // 标志是否已经显示过错误提示
-      result: {},
+      statistics: {},
       dialogVisible: false,
+      results: [],
+      loading: false, // 控制加载状态
     };
   },
   created() {},
@@ -229,113 +192,74 @@ export default {
     },
     handleCurrentChange(val) {
       console.log(`当前页: ${val}`);
+      setTimeout(() => {
+        this.automaticDiagnosis();
+      },500);
 
       this.currentPage = val; // 子组件内部更新当前页
       this.$emit("updatePage", this.currentPage); // 通知父组件,把当前页传出去
     },
     automaticDiagnosis() {
-      this.dialogVisible = true;
-    },
-    submit() {
-      // 验证必填项
-      const requiredFields = [
-        { field: this.transmissionRatio, name: "发动机到轴承测点转速传动比" },
-        { field: this.bearingPitchDiameter, name: "轴承节圆直径D(mm)" },
-        { field: this.rollingElementDiameter, name: "滚动体直径d(mm)" },
-        { field: this.rollingElementCount, name: "滚动体个数Z(个)" },
-        { field: this.contactAngle, name: "接触角α(°)" },
-        {
-          field: this.vibrationSpeedAlarmThreshold,
-          name: "振动速度报警阈值(mm/s)",
-        },
-        {
-          field: this.vibrationSpeedDangerThreshold,
-          name: "振动速度危险阈值(mm/s)",
-        },
-        {
-          field: this.envelopeTotalAlarmThreshold,
-          name: "包络总值报警阈值(gE)",
-        },
-        {
-          field: this.envelopeTotalDangerThreshold,
-          name: "包络总值危险阈值(gE)",
-        },
-      ];
-
-      // 记录是否已弹出过错误提示
-      let hasError = false;
-
-      // 只检查必填项的字段是否为空
-      // for (const { field, name } of requiredFields) {
-      //   if (!field && !hasError) {
-      //     // 弹出提示并标记已经出现错误提示
-      //     this.$message.error(`${name} 是必填项`);
-      //     hasError = true;  // 标记已经弹出过错误提示
-      //     return;  // 停止执行后续逻辑
-      //   }
-      // }
-
-      // 如果验证通过,继续执行后续逻辑
-      const newProps = this.tableData.map(() => ({
-        innerRingFault: Math.floor(Math.random() * 3).toString(),
-        // outerRingFault: Math.floor(Math.random() * 3).toString(),
-        // rollingElementFault: Math.floor(Math.random() * 3).toString(),
-        // cageFault: Math.floor(Math.random() * 3).toString(),
-      }));
-
-      this.tableData.forEach((row, index) => {
-        this.$set(this.tableData, index, {
-          ...row,
-          ...newProps[index], // 用每一行自己生成的随机数
-        });
-      });
-
-      const faultValues = [
-        ...this.tableData.map((record) => record.innerRingFault),
-        // ...this.tableData.map((record) => record.outerRingFault),
-        // ...this.tableData.map((record) => record.rollingElementFault),
-        // ...this.tableData.map((record) => record.cageFault),
-      ];
-
-      // 统计各个值出现的次数
-      const counter = faultValues.reduce((acc, value) => {
-        acc[value] = (acc[value] || 0) + 1;
-        return acc;
-      }, {});
-
-      // 构造统计结果对象
-      this.result = {
-        1: counter["0"] || 0,
-        2: counter["1"] || 0,
-        3: counter["2"] || 0,
+      this.loading = true;
+      const ids = this.tableData
+        .map((item) => item.id)
+        .filter((id) => id !== undefined);
+      const params = {
+        windCode: this.fieldCode,
+        engine_code: this.windTurbineNumber,
+        autodiagType: "Misalignment",
+        ids: ids,
       };
+      const autodiagType = params.autodiagType || "Misalignment";
 
-      // 更新颜色状态
-      const fields = [
-        { key: "innerRingFault", colorKey: "innerRing" },
-        // { key: "outerRingFault", colorKey: "outerRing" },
-        // { key: "rollingElementFault", colorKey: "rollingElement" },
-        // { key: "cageFault", colorKey: "cage" },
-      ];
+      const loadingInstance = this.$loading({
+        lock: true,
+        text: "自动诊断中...",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
 
-      fields.forEach(({ key, colorKey }) => {
-        const values = newProps.map((item) => Number(item[key]));
-        const maxVal = Math.max(...values);
-        let color = "#80808057"; // 默认灰色
-        if (maxVal === 0) color = "#8AE359"; // 无故障
-        else if (maxVal === 1) color = "#EECB5F"; // 警告
-        else if (maxVal === 2) color = "#F7715F"; // 危险
+      axios
+        .post(`/WJJdiag/autodiag/${autodiagType}`, params)
+        .then((res) => {
+          this.statistics = res.data.statistics;
+          this.$set(this, "yData", [...res.data.results]);
+          this.$set(
+            this,
+            "xData",
+            this.tableData.map((item) => item.timeStamp)
+          );
+          console.log(this.yData, "yData11");
+          console.log(this.xData, "xData22");
 
-        this.bearingStateColors[colorKey] = color; // 更新颜色
-      });
+          const maxStatus = res.data.statistics.max_status;
+          if (maxStatus === 0) {
+            this.bearingStateColors.innerRing = "#8ae359";
+          } else if (maxStatus === 1) {
+            this.bearingStateColors.innerRing = "#eecb5f";
+          } else if (maxStatus === 2) {
+            this.bearingStateColors.innerRing = "#f7715f";
+          } else {
+            this.bearingStateColors.innerRing = "#80808057";
+          }
 
-      // 更新趋势图数据
-      // 更新趋势图数据(用tableData,不是newProps)
-      this.xData = this.tableData.map((item) => item.timeStamp);
-      this.yData = fields.map(({ key }) =>
-        this.tableData.map((item) => Number(item[key]))
-      );
-      this.dialogVisible = false;
+          this.$message.success({
+            message: "诊断完成",
+            duration: 1000, // 1秒后自动关闭
+          });
+        })
+        .catch((error) => {
+          console.error("自动诊断失败:", error);
+          this.bearingStateColors.innerRing = "#80808057";
+          this.$message.error({
+            message: "诊断失败",
+            duration: 1000, // 1秒后自动关闭
+          });
+        })
+        .finally(() => {
+          loadingInstance.close();
+          this.loading = false;
+        });
     },
   },
 };

+ 133 - 166
src/views/health/components/malfunction/gear.vue

@@ -31,19 +31,18 @@
           </el-table-column>
         </el-table>
         <div class="fenye">
-          <p><span>故障状态码说明:</span>0代表正常,1代表报警,2代表危险</p>
+          <p><span>状态码说明:</span>0正常,1报警,2危险,-1未定义</p>
 
           <el-pagination
-            small
             @current-change="handleCurrentChange"
             :current-page="currentPage"
             layout="total, prev, pager, next, jumper"
             :total="totalCount"
             :page-size="10"
+            small
           ></el-pagination>
         </div>
       </div>
-
       <div class="leftdiv">
         <div class="stateBox">
           <h4>齿轮状态</h4>
@@ -51,7 +50,7 @@
             <p :style="{ backgroundColor: bearingStateColors.innerRing }">
               齿轮磨损
             </p>
-              <p :style="{ backgroundColor: bearingStateColors.innerRing }">
+            <p :style="{ backgroundColor: bearingStateColors.outerRing }">
               齿轮断齿
             </p>
           </div>
@@ -60,13 +59,14 @@
             size="small"
             @click="automaticDiagnosis"
             class="btn-auto"
+            :loading="loading"
             >诊断</el-button
           >
         </div>
 
         <div class="Btn">
           <div style="height: 200px">
-            <bing :result="result"> </bing>
+            <bingTwo :statistics="statistics"> </bingTwo>
           </div>
 
           <div class="minp">
@@ -77,89 +77,41 @@
             </p>
 
             <h4>诊断步骤:</h4>
-            <p>1、选择振动测点与起止时间,点击“查询;</p>
+            <p>1、选择振动测点与起止时间,点击“查询;</p>
             <p>2、对齿轮“参数设置”输入相关信息;</p>
-            <p>3、点击“诊断”输出最终轴承状态结果。</p>
+            <p>3、点击“诊断”输出最终齿轮状态结果。</p>
           </div>
         </div>
       </div>
     </div>
     <div class="bottomBox">
       <div class="BtLeft">
-        <h4>齿轮故障状态趋势图</h4>
+        <h4>齿轮状态趋势图</h4>
         <el-empty
           v-if="this.xData.length === 0 || this.yData.length === 0"
           description="暂无数据"
-          style="padding: 17px 0"
+          style="padding: 46px 0"
         ></el-empty>
         <Eecharts
           v-else
           style="height: 300px"
           :xData="xData"
           :yData="yData"
-          :yNames="['齿轮故障']"
+          :yNames="['齿轮磨损', '齿轮断齿']"
           yAxisName="齿轮故障状态"
         ></Eecharts>
       </div>
-
-      <el-dialog title="参数" :visible.sync="dialogVisible" width="50%">
-        <div class="BtRight">
-          <h4>参数设置</h4>
-          <div class="BtRightDiv">
-            <p class="BtRightP">
-              <span>发电机到齿轮测点的转速传动比</span>
-
-              <span
-                ><el-input
-                  v-model="transmissionRatio"
-                  size="small"
-                  v-number-only
-                ></el-input
-              ></span>
-            </p>
-
-            <h4>报警阈值输入</h4>
-            <div class="canshu">
-              <p class="BtRightP">
-                <span class="label-text">振动速度报警阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedAlarmThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-
-              <p class="BtRightP">
-                <span class="label-text">振动速度危险阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedDangerThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-            </div>
-          </div>
-        </div>
-        <div class="dialog-footer">
-          <el-button type="primary" size="small" @click="submit"
-            >确定</el-button
-          >
-        </div>
-      </el-dialog>
     </div>
   </div>
 </template>
 
 <script>
+import axios from "axios";
 import Eecharts from "./Eecharts.vue";
-import bing from "./bing.vue";
+import bingTwo from "./bingTwo.vue";
 import { cacheEntryPossiblyAdded } from "plotly.js-dist";
 export default {
-  components: { Eecharts, bing },
+  components: { Eecharts, bingTwo },
   props: {
     codedata: {
       type: Array,
@@ -173,6 +125,14 @@ export default {
       type: Number,
       default: 0,
     },
+    fieldCode: {
+      type: String,
+      default: "",
+    },
+    windTurbineNumber: {
+      type: String,
+      default: "",
+    },
   },
   data() {
     return {
@@ -204,6 +164,8 @@ export default {
       hasError: false, // 标志是否已经显示过错误提示
       result: {},
       dialogVisible: false,
+      loading: false, // 控制加载状态
+      statistics: {},
     };
   },
   created() {},
@@ -232,113 +194,86 @@ export default {
     },
     handleCurrentChange(val) {
       console.log(`当前页: ${val}`);
-
+      setTimeout(() => {
+        this.automaticDiagnosis();
+      }, 500);
       this.currentPage = val; // 子组件内部更新当前页
       this.$emit("updatePage", this.currentPage); // 通知父组件,把当前页传出去
     },
+
     automaticDiagnosis() {
-      this.dialogVisible = true;
-    },
-    submit() {
-      // 验证必填项
-      const requiredFields = [
-        { field: this.transmissionRatio, name: "发动机到轴承测点转速传动比" },
-        { field: this.bearingPitchDiameter, name: "轴承节圆直径D(mm)" },
-        { field: this.rollingElementDiameter, name: "滚动体直径d(mm)" },
-        { field: this.rollingElementCount, name: "滚动体个数Z(个)" },
-        { field: this.contactAngle, name: "接触角α(°)" },
-        {
-          field: this.vibrationSpeedAlarmThreshold,
-          name: "振动速度报警阈值(mm/s)",
-        },
-        {
-          field: this.vibrationSpeedDangerThreshold,
-          name: "振动速度危险阈值(mm/s)",
-        },
-        {
-          field: this.envelopeTotalAlarmThreshold,
-          name: "包络总值报警阈值(gE)",
-        },
-        {
-          field: this.envelopeTotalDangerThreshold,
-          name: "包络总值危险阈值(gE)",
-        },
-      ];
-
-      // 记录是否已弹出过错误提示
-      let hasError = false;
-
-      // 只检查必填项的字段是否为空
-      // for (const { field, name } of requiredFields) {
-      //   if (!field && !hasError) {
-      //     // 弹出提示并标记已经出现错误提示
-      //     this.$message.error(`${name} 是必填项`);
-      //     hasError = true;  // 标记已经弹出过错误提示
-      //     return;  // 停止执行后续逻辑
-      //   }
-      // }
-
-      // 如果验证通过,继续执行后续逻辑
-      const newProps = this.tableData.map(() => ({
-        innerRingFault: Math.floor(Math.random() * 3).toString(),
-        outerRingFault: Math.floor(Math.random() * 3).toString(),
-        // rollingElementFault: Math.floor(Math.random() * 3).toString(),
-        // cageFault: Math.floor(Math.random() * 3).toString(),
-      }));
-
-      this.tableData.forEach((row, index) => {
-        this.$set(this.tableData, index, {
-          ...row,
-          ...newProps[index], // 用每一行自己生成的随机数
-        });
-      });
+      this.loading = true;
+      const ids = this.tableData
+        .map((item) => item.id)
+        .filter((id) => id !== undefined);
 
-      const faultValues = [
-        ...this.tableData.map((record) => record.innerRingFault),
-        ...this.tableData.map((record) => record.outerRingFault),
-        // ...this.tableData.map((record) => record.rollingElementFault),
-        // ...this.tableData.map((record) => record.cageFault),
-      ];
-
-      // 统计各个值出现的次数
-      const counter = faultValues.reduce((acc, value) => {
-        acc[value] = (acc[value] || 0) + 1;
-        return acc;
-      }, {});
-
-      // 构造统计结果对象
-      this.result = {
-        1: counter["0"] || 0,
-        2: counter["1"] || 0,
-        3: counter["2"] || 0,
+      const params = {
+        windCode: this.fieldCode,
+        engine_code: this.windTurbineNumber,
+        autodiagType: "Gear",
+        ids,
       };
 
-      // 更新颜色状态
-      const fields = [
-        { key: "innerRingFault", colorKey: "innerRing" },
-        { key: "outerRingFault", colorKey: "outerRing" },
-        // { key: "rollingElementFault", colorKey: "rollingElement" },
-        // { key: "cageFault", colorKey: "cage" },
-      ];
-
-      fields.forEach(({ key, colorKey }) => {
-        const values = newProps.map((item) => Number(item[key]));
-        const maxVal = Math.max(...values);
-        let color = "#80808057"; // 默认灰色
-        if (maxVal === 0) color = "#8AE359"; // 无故障
-        else if (maxVal === 1) color = "#EECB5F"; // 警告
-        else if (maxVal === 2) color = "#F7715F"; // 危险
-
-        this.bearingStateColors[colorKey] = color; // 更新颜色
+      const autodiagType = params.autodiagType || "Gear";
+
+      const loadingInstance = this.$loading({
+        lock: true,
+        text: "自动诊断中...",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
       });
 
-      // 更新趋势图数据
-      // 更新趋势图数据(用tableData,不是newProps)
-      this.xData = this.tableData.map((item) => item.timeStamp);
-      this.yData = fields.map(({ key }) =>
-        this.tableData.map((item) => Number(item[key]))
-      );
-      this.dialogVisible = false;
+      axios
+        .post(`/WJJdiag/autodiag/${autodiagType}`, params)
+        .then((res) => {
+        if (res.data.code === 400) {
+    this.$message({
+          message: '当前测点无法进行齿轮箱诊断',
+          type: 'warning'
+        });
+          
+        }else{
+ const result = res.data.results || {};
+          this.statistics = res.data.statistics || {};
+          // x轴数据,时间戳
+          this.xData = this.tableData.map((item) => item.timeStamp);
+          // y轴数据,状态码二维数组
+          this.yData = [
+            result.crack?.status_codes || [],
+            result.wear?.status_codes || [],
+          ];
+          // 设置颜色函数(根据 max_status)
+          const setColor = (status) => {
+            switch (status) {
+              case 0:
+                return "#8ae359"; // 正常
+              case 1:
+                return "#eecb5f"; // 报警
+              case 2:
+                return "#f7715f"; // 危险
+              default:
+                return "#80808057"; // 未知或缺失
+            }
+          }
+
+          // 根据 max_status 设置颜色
+          this.bearingStateColors.innerRing = setColor(
+            result.crack?.max_status ?? -1
+          );
+          this.bearingStateColors.outerRing = setColor(
+            result.wear?.max_status ?? -1
+          );
+
+        }
+         
+        })
+        .catch((err) => {
+          console.error("诊断失败:", err);
+        })
+        .finally(() => {
+          loadingInstance.close();
+          this.loading = false;
+        });
     },
   },
 };
@@ -349,22 +284,28 @@ h4 {
   margin-bottom: 5px;
   font-weight: 600;
 }
+
 .TopBox {
   height: 280px;
   display: flex;
   justify-content: space-around;
+
   .leftdiv {
     width: 50%;
     display: flex;
     justify-content: space-around;
+
     .stateBox {
       .state {
         display: flex;
         flex-direction: column;
-        justify-content: center; /* 整体居中 */
+        justify-content: center;
+        /* 整体居中 */
         align-items: center;
         height: 200px;
-        gap: 20px; /* 控制间距 */
+        gap: 20px;
+
+        /* 控制间距 */
         p {
           width: 150px;
           height: 40px;
@@ -375,18 +316,24 @@ h4 {
           font-weight: 600;
         }
       }
+
       .btn-auto {
         margin-top: 10px;
         width: 100%;
       }
     }
+
     .Btn {
       width: 50%;
       display: flex;
-      flex-direction: column; /* 垂直排列 */
-      justify-content: space-between; /* 顶部和底部对齐 */
-      min-height: 100px; /* 确保容器有足够高度 */
+      flex-direction: column;
+      /* 垂直排列 */
+      justify-content: space-between;
+      /* 顶部和底部对齐 */
+      min-height: 100px;
+      /* 确保容器有足够高度 */
       margin: 10px 0;
+
       .PText {
         display: flex;
         justify-content: space-around;
@@ -394,37 +341,47 @@ h4 {
         span {
           display: flex;
           align-items: center;
+
           i {
             width: 30px;
             height: 15px;
             margin-right: 5px;
           }
+
           .color1 {
             background-color: #8ae359;
           }
+
           .color2 {
             background-color: #eecb5f;
           }
+
           .color3 {
             background-color: #f7715f;
           }
         }
       }
+
       margin: 10px 0;
+
       .minp {
         font-size: 12px;
-        margin-top: auto; /* 自动推到最底部 */
+        margin-top: auto;
+        /* 自动推到最底部 */
       }
     }
   }
+
   .rightdiv {
     width: 50%;
+
     .fenye {
       display: flex;
       justify-content: space-between;
       margin: 5px 0;
       font-size: 11px;
       line-height: 30px;
+
       span {
         font-weight: 600;
       }
@@ -436,36 +393,44 @@ h4 {
   display: flex;
   justify-content: space-around;
   margin-top: 10px;
+
   .BtLeft {
     border: 1px solid rgb(231, 231, 231);
     width: 100%;
     padding: 10px;
   }
+
   .BtRight {
-    // width: 49%;
     border: 1px solid rgb(231, 231, 231);
     padding: 10px;
+
     .BtRightDiv {
       padding: 0 10px;
+
       h4 {
         font-size: 14px;
       }
+
       .BtRightP {
         line-height: 30px;
         font-size: 12px;
         display: flex;
         margin-bottom: 5px;
         width: 50%;
+
         span {
           margin-left: 10px;
+
           .el-input {
             width: 100px;
           }
         }
+
         .label-text {
           width: 140px;
         }
       }
+
       .canshu {
         display: flex;
         flex-wrap: wrap;
@@ -473,11 +438,13 @@ h4 {
       }
     }
   }
+
   .dialog-footer {
     margin-top: 20px;
     text-align: right;
   }
 }
+
 ::v-deep .el-table__cell {
   padding: 2px 0;
   font-size: 12px;

+ 82 - 179
src/views/health/components/malfunction/loose.vue

@@ -31,7 +31,7 @@
           </el-table-column>
         </el-table>
         <div class="fenye">
-          <p><span>故障状态码说明:</span>0代表正常,1代表报警,2代表危险</p>
+          <p><span>状态码说明:</span>0正常,1报警,2危险,-1未定义</p>
 
           <el-pagination
             small
@@ -57,13 +57,14 @@
             size="small"
             @click="automaticDiagnosis"
             class="btn-auto"
+            :loading="loading"
             >诊断</el-button
           >
         </div>
 
         <div class="Btn">
           <div style="height: 200px">
-            <bing :result="result"> </bing>
+            <bingTwo :statistics="statistics"> </bingTwo>
           </div>
 
           <div class="minp">
@@ -75,23 +76,13 @@
 
             <h4>诊断步骤:</h4>
             <p>1、选择振动测点与起止时间,点击“查询;</p>
-            <p>2、对松动“参数设置”输入相关信息;</p>
-            <p>3、点击“诊断”输出最终轴承状态结果。</p>
+            <p>2、点击“诊断”输出最终轴承状态结果。</p>
           </div>
         </div>
       </div>
     </div>
     <div class="bottomBox">
       <div class="BtLeft">
-        <h4>测点基础信息</h4>
-        <el-empty
-          :image="kfImg"
-          description="功能开发中"
-          style="padding: 48px 0"
-        />
-      </div>
-
-      <div class="BtLeft">
         <h4>松动故障状态趋势图</h4>
         <el-empty
           v-if="this.xData.length === 0 || this.yData.length === 0"
@@ -100,73 +91,25 @@
         ></el-empty>
         <Eecharts
           v-else
-          style="height: 300px"
+          style="height: 310px"
           :xData="xData"
-          :yData="yData"
+          :yData="[yData]"
           :yNames="['松动故障']"
           yAxisName="松动故障状态"
+   
         ></Eecharts>
       </div>
-
-      <el-dialog title="参数" :visible.sync="dialogVisible" width="50%">
-        <div class="BtRight">
-          <h4>参数设置</h4>
-          <div class="BtRightDiv">
-            <p class="BtRightP">
-              <span>发电机到松动测点的转速传动比</span>
-
-              <span
-                ><el-input
-                  v-model="transmissionRatio"
-                  size="small"
-                  v-number-only
-                ></el-input
-              ></span>
-            </p>
-
-            <h4>报警阈值输入</h4>
-            <div class="canshu">
-              <p class="BtRightP">
-                <span class="label-text">振动速度报警阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedAlarmThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-
-              <p class="BtRightP">
-                <span class="label-text">振动速度危险阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedDangerThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-            </div>
-          </div>
-        </div>
-        <div class="dialog-footer">
-          <el-button type="primary" size="small" @click="submit"
-            >确定</el-button
-          >
-        </div>
-      </el-dialog>
     </div>
   </div>
 </template>
 
 <script>
-import kfImg from "@/assets/KF.png";
+import axios from "axios";
 import Eecharts from "./Eecharts.vue";
-import bing from "./bing.vue";
-import { cacheEntryPossiblyAdded } from "plotly.js-dist";
+import bingTwo from "./bingTwo.vue";
+import { cacheEntryPossiblyAdded, log10, promisify } from "plotly.js-dist";
 export default {
-  components: { Eecharts, bing },
+  components: { Eecharts, bingTwo },
   props: {
     codedata: {
       type: Array,
@@ -180,10 +123,17 @@ export default {
       type: Number,
       default: 0,
     },
+    fieldCode: {
+      type: String,
+      default: "",
+    },
+    windTurbineNumber: {
+      type: String,
+      default: "",
+    },
   },
   data() {
     return {
-      kfImg: kfImg,
       tableData: [],
       // 添加新的数据属性用于绑定输入框的值
       transmissionRatio: "",
@@ -210,8 +160,10 @@ export default {
         cage: "#80808057",
       },
       hasError: false, // 标志是否已经显示过错误提示
-      result: {},
+      statistics: {},
       dialogVisible: false,
+      results: [],
+      loading: false, // 控制加载状态
     };
   },
   created() {},
@@ -240,113 +192,74 @@ export default {
     },
     handleCurrentChange(val) {
       console.log(`当前页: ${val}`);
+      setTimeout(() => {
+        this.automaticDiagnosis();
+      },500);
 
       this.currentPage = val; // 子组件内部更新当前页
       this.$emit("updatePage", this.currentPage); // 通知父组件,把当前页传出去
     },
     automaticDiagnosis() {
-      this.dialogVisible = true;
-    },
-    submit() {
-      // 验证必填项
-      const requiredFields = [
-        { field: this.transmissionRatio, name: "发动机到轴承测点转速传动比" },
-        { field: this.bearingPitchDiameter, name: "轴承节圆直径D(mm)" },
-        { field: this.rollingElementDiameter, name: "滚动体直径d(mm)" },
-        { field: this.rollingElementCount, name: "滚动体个数Z(个)" },
-        { field: this.contactAngle, name: "接触角α(°)" },
-        {
-          field: this.vibrationSpeedAlarmThreshold,
-          name: "振动速度报警阈值(mm/s)",
-        },
-        {
-          field: this.vibrationSpeedDangerThreshold,
-          name: "振动速度危险阈值(mm/s)",
-        },
-        {
-          field: this.envelopeTotalAlarmThreshold,
-          name: "包络总值报警阈值(gE)",
-        },
-        {
-          field: this.envelopeTotalDangerThreshold,
-          name: "包络总值危险阈值(gE)",
-        },
-      ];
-
-      // 记录是否已弹出过错误提示
-      let hasError = false;
-
-      // 只检查必填项的字段是否为空
-      // for (const { field, name } of requiredFields) {
-      //   if (!field && !hasError) {
-      //     // 弹出提示并标记已经出现错误提示
-      //     this.$message.error(`${name} 是必填项`);
-      //     hasError = true;  // 标记已经弹出过错误提示
-      //     return;  // 停止执行后续逻辑
-      //   }
-      // }
-
-      // 如果验证通过,继续执行后续逻辑
-      const newProps = this.tableData.map(() => ({
-        innerRingFault: Math.floor(Math.random() * 3).toString(),
-        // outerRingFault: Math.floor(Math.random() * 3).toString(),
-        // rollingElementFault: Math.floor(Math.random() * 3).toString(),
-        // cageFault: Math.floor(Math.random() * 3).toString(),
-      }));
-
-      this.tableData.forEach((row, index) => {
-        this.$set(this.tableData, index, {
-          ...row,
-          ...newProps[index], // 用每一行自己生成的随机数
-        });
-      });
-
-      const faultValues = [
-        ...this.tableData.map((record) => record.innerRingFault),
-        // ...this.tableData.map((record) => record.outerRingFault),
-        // ...this.tableData.map((record) => record.rollingElementFault),
-        // ...this.tableData.map((record) => record.cageFault),
-      ];
-
-      // 统计各个值出现的次数
-      const counter = faultValues.reduce((acc, value) => {
-        acc[value] = (acc[value] || 0) + 1;
-        return acc;
-      }, {});
-
-      // 构造统计结果对象
-      this.result = {
-        1: counter["0"] || 0,
-        2: counter["1"] || 0,
-        3: counter["2"] || 0,
+      this.loading = true;
+      const ids = this.tableData
+        .map((item) => item.id)
+        .filter((id) => id !== undefined);
+      const params = {
+        windCode: this.fieldCode,
+        engine_code: this.windTurbineNumber,
+        autodiagType: "Looseness",
+        ids: ids,
       };
+      const autodiagType = params.autodiagType || "Looseness";
 
-      // 更新颜色状态
-      const fields = [
-        { key: "innerRingFault", colorKey: "innerRing" },
-        // { key: "outerRingFault", colorKey: "outerRing" },
-        // { key: "rollingElementFault", colorKey: "rollingElement" },
-        // { key: "cageFault", colorKey: "cage" },
-      ];
+      const loadingInstance = this.$loading({
+        lock: true,
+        text: "自动诊断中...",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
 
-      fields.forEach(({ key, colorKey }) => {
-        const values = newProps.map((item) => Number(item[key]));
-        const maxVal = Math.max(...values);
-        let color = "#80808057"; // 默认灰色
-        if (maxVal === 0) color = "#8AE359"; // 无故障
-        else if (maxVal === 1) color = "#EECB5F"; // 警告
-        else if (maxVal === 2) color = "#F7715F"; // 危险
+      axios
+        .post(`/WJJdiag/autodiag/${autodiagType}`, params)
+        .then((res) => {
+          this.statistics = res.data.statistics;
+          this.$set(this, "yData", [...res.data.results]);
+          this.$set(
+            this,
+            "xData",
+            this.tableData.map((item) => item.timeStamp)
+          );
+          console.log(this.yData, "yData11");
+          console.log(this.xData, "xData22");
 
-        this.bearingStateColors[colorKey] = color; // 更新颜色
-      });
+          const maxStatus = res.data.statistics.max_status;
+          if (maxStatus === 0) {
+            this.bearingStateColors.innerRing = "#8ae359";
+          } else if (maxStatus === 1) {
+            this.bearingStateColors.innerRing = "#eecb5f";
+          } else if (maxStatus === 2) {
+            this.bearingStateColors.innerRing = "#f7715f";
+          } else {
+            this.bearingStateColors.innerRing = "#80808057";
+          }
 
-      // 更新趋势图数据
-      // 更新趋势图数据(用tableData,不是newProps)
-      this.xData = this.tableData.map((item) => item.timeStamp);
-      this.yData = fields.map(({ key }) =>
-        this.tableData.map((item) => Number(item[key]))
-      );
-      this.dialogVisible = false;
+          this.$message.success({
+            message: "诊断完成",
+            duration: 1000, // 1秒后自动关闭
+          });
+        })
+        .catch((error) => {
+          console.error("自动诊断失败:", error);
+          this.bearingStateColors.innerRing = "#80808057";
+          this.$message.error({
+            message: "诊断失败",
+            duration: 1000, // 1秒后自动关闭
+          });
+        })
+        .finally(() => {
+          loadingInstance.close();
+          this.loading = false;
+        });
     },
   },
 };
@@ -442,13 +355,12 @@ h4 {
 
 .bottomBox {
   display: flex;
-  justify-content: space-between;
+  justify-content: space-around;
   margin-top: 10px;
   .BtLeft {
     border: 1px solid rgb(231, 231, 231);
-    width: 49.5%;
+    width: 100%;
     padding: 10px;
-    
   }
   .BtRight {
     // width: 49%;
@@ -491,13 +403,4 @@ h4 {
   padding: 2px 0;
   font-size: 12px;
 }
-.el-empty {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    flex-direction: column;
-    text-align: center;
-    box-sizing: border-box;
-    // padding: 40px 0;
-    height: 310px;}
 </style>

+ 81 - 157
src/views/health/components/malfunction/misalignment.vue

@@ -31,7 +31,7 @@
           </el-table-column>
         </el-table>
         <div class="fenye">
-          <p><span>故障状态码说明:</span>0代表正常,1代表报警,2代表危险</p>
+          <p><span>状态码说明:</span>0正常,1报警,2危险,-1未定义</p>
 
           <el-pagination
             small
@@ -57,13 +57,14 @@
             size="small"
             @click="automaticDiagnosis"
             class="btn-auto"
+            :loading="loading"
             >诊断</el-button
           >
         </div>
 
         <div class="Btn">
           <div style="height: 200px">
-            <bing :result="result"> </bing>
+            <bingTwo :statistics="statistics"> </bingTwo>
           </div>
 
           <div class="minp">
@@ -75,8 +76,7 @@
 
             <h4>诊断步骤:</h4>
             <p>1、选择振动测点与起止时间,点击“查询;</p>
-            <p>2、对不平衡“参数设置”输入相关信息;</p>
-            <p>3、点击“诊断”输出最终轴承状态结果。</p>
+            <p>2、点击“诊断”输出最终轴承状态结果。</p>
           </div>
         </div>
       </div>
@@ -87,76 +87,29 @@
         <el-empty
           v-if="this.xData.length === 0 || this.yData.length === 0"
           description="暂无数据"
-          style="padding: 17px 0"
+          style="padding: 48px 0"
         ></el-empty>
         <Eecharts
           v-else
-          style="height: 300px"
+          style="height: 310px"
           :xData="xData"
-          :yData="yData"
+          :yData="[yData]"
           :yNames="['不平衡故障']"
           yAxisName="不平衡故障状态"
+   
         ></Eecharts>
       </div>
-
-      <el-dialog title="参数" :visible.sync="dialogVisible" width="50%">
-        <div class="BtRight">
-          <h4>参数设置</h4>
-          <div class="BtRightDiv">
-            <p class="BtRightP">
-              <span>发电机到不平衡测点的转速传动比</span>
-
-              <span
-                ><el-input
-                  v-model="transmissionRatio"
-                  size="small"
-                  v-number-only
-                ></el-input
-              ></span>
-            </p>
-
-            <h4>报警阈值输入</h4>
-            <div class="canshu">
-              <p class="BtRightP">
-                <span class="label-text">振动速度报警阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedAlarmThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-
-              <p class="BtRightP">
-                <span class="label-text">振动速度危险阈值(mm/s)</span>
-                <span
-                  ><el-input
-                    v-model="vibrationSpeedDangerThreshold"
-                    size="small"
-                    v-number-only
-                  ></el-input
-                ></span>
-              </p>
-            </div>
-          </div>
-        </div>
-        <div class="dialog-footer">
-          <el-button type="primary" size="small" @click="submit"
-            >确定</el-button
-          >
-        </div>
-      </el-dialog>
     </div>
   </div>
 </template>
 
 <script>
+import axios from "axios";
 import Eecharts from "./Eecharts.vue";
-import bing from "./bing.vue";
-import { cacheEntryPossiblyAdded } from "plotly.js-dist";
+import bingTwo from "./bingTwo.vue";
+import { cacheEntryPossiblyAdded, log10, promisify } from "plotly.js-dist";
 export default {
-  components: { Eecharts, bing },
+  components: { Eecharts, bingTwo },
   props: {
     codedata: {
       type: Array,
@@ -170,6 +123,14 @@ export default {
       type: Number,
       default: 0,
     },
+    fieldCode: {
+      type: String,
+      default: "",
+    },
+    windTurbineNumber: {
+      type: String,
+      default: "",
+    },
   },
   data() {
     return {
@@ -199,8 +160,10 @@ export default {
         cage: "#80808057",
       },
       hasError: false, // 标志是否已经显示过错误提示
-      result: {},
+      statistics: {},
       dialogVisible: false,
+      results: [],
+      loading: false, // 控制加载状态
     };
   },
   created() {},
@@ -229,113 +192,74 @@ export default {
     },
     handleCurrentChange(val) {
       console.log(`当前页: ${val}`);
+      setTimeout(() => {
+        this.automaticDiagnosis();
+      },500);
 
       this.currentPage = val; // 子组件内部更新当前页
       this.$emit("updatePage", this.currentPage); // 通知父组件,把当前页传出去
     },
     automaticDiagnosis() {
-      this.dialogVisible = true;
-    },
-    submit() {
-      // 验证必填项
-      const requiredFields = [
-        { field: this.transmissionRatio, name: "发动机到轴承测点转速传动比" },
-        { field: this.bearingPitchDiameter, name: "轴承节圆直径D(mm)" },
-        { field: this.rollingElementDiameter, name: "滚动体直径d(mm)" },
-        { field: this.rollingElementCount, name: "滚动体个数Z(个)" },
-        { field: this.contactAngle, name: "接触角α(°)" },
-        {
-          field: this.vibrationSpeedAlarmThreshold,
-          name: "振动速度报警阈值(mm/s)",
-        },
-        {
-          field: this.vibrationSpeedDangerThreshold,
-          name: "振动速度危险阈值(mm/s)",
-        },
-        {
-          field: this.envelopeTotalAlarmThreshold,
-          name: "包络总值报警阈值(gE)",
-        },
-        {
-          field: this.envelopeTotalDangerThreshold,
-          name: "包络总值危险阈值(gE)",
-        },
-      ];
-
-      // 记录是否已弹出过错误提示
-      let hasError = false;
-
-      // 只检查必填项的字段是否为空
-      // for (const { field, name } of requiredFields) {
-      //   if (!field && !hasError) {
-      //     // 弹出提示并标记已经出现错误提示
-      //     this.$message.error(`${name} 是必填项`);
-      //     hasError = true;  // 标记已经弹出过错误提示
-      //     return;  // 停止执行后续逻辑
-      //   }
-      // }
-
-      // 如果验证通过,继续执行后续逻辑
-      const newProps = this.tableData.map(() => ({
-        innerRingFault: Math.floor(Math.random() * 3).toString(),
-        // outerRingFault: Math.floor(Math.random() * 3).toString(),
-        // rollingElementFault: Math.floor(Math.random() * 3).toString(),
-        // cageFault: Math.floor(Math.random() * 3).toString(),
-      }));
-
-      this.tableData.forEach((row, index) => {
-        this.$set(this.tableData, index, {
-          ...row,
-          ...newProps[index], // 用每一行自己生成的随机数
-        });
-      });
-
-      const faultValues = [
-        ...this.tableData.map((record) => record.innerRingFault),
-        // ...this.tableData.map((record) => record.outerRingFault),
-        // ...this.tableData.map((record) => record.rollingElementFault),
-        // ...this.tableData.map((record) => record.cageFault),
-      ];
-
-      // 统计各个值出现的次数
-      const counter = faultValues.reduce((acc, value) => {
-        acc[value] = (acc[value] || 0) + 1;
-        return acc;
-      }, {});
-
-      // 构造统计结果对象
-      this.result = {
-        1: counter["0"] || 0,
-        2: counter["1"] || 0,
-        3: counter["2"] || 0,
+      this.loading = true;
+      const ids = this.tableData
+        .map((item) => item.id)
+        .filter((id) => id !== undefined);
+      const params = {
+        windCode: this.fieldCode,
+        engine_code: this.windTurbineNumber,
+        autodiagType: "Unbalance",
+        ids: ids,
       };
+      const autodiagType = params.autodiagType || "Unbalance";
 
-      // 更新颜色状态
-      const fields = [
-        { key: "innerRingFault", colorKey: "innerRing" },
-        // { key: "outerRingFault", colorKey: "outerRing" },
-        // { key: "rollingElementFault", colorKey: "rollingElement" },
-        // { key: "cageFault", colorKey: "cage" },
-      ];
+      const loadingInstance = this.$loading({
+        lock: true,
+        text: "自动诊断中...",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
 
-      fields.forEach(({ key, colorKey }) => {
-        const values = newProps.map((item) => Number(item[key]));
-        const maxVal = Math.max(...values);
-        let color = "#80808057"; // 默认灰色
-        if (maxVal === 0) color = "#8AE359"; // 无故障
-        else if (maxVal === 1) color = "#EECB5F"; // 警告
-        else if (maxVal === 2) color = "#F7715F"; // 危险
+      axios
+        .post(`/WJJdiag/autodiag/${autodiagType}`, params)
+        .then((res) => {
+          this.statistics = res.data.statistics;
+          this.$set(this, "yData", [...res.data.results]);
+          this.$set(
+            this,
+            "xData",
+            this.tableData.map((item) => item.timeStamp)
+          );
+          console.log(this.yData, "yData11");
+          console.log(this.xData, "xData22");
 
-        this.bearingStateColors[colorKey] = color; // 更新颜色
-      });
+          const maxStatus = res.data.statistics.max_status;
+          if (maxStatus === 0) {
+            this.bearingStateColors.innerRing = "#8ae359";
+          } else if (maxStatus === 1) {
+            this.bearingStateColors.innerRing = "#eecb5f";
+          } else if (maxStatus === 2) {
+            this.bearingStateColors.innerRing = "#f7715f";
+          } else {
+            this.bearingStateColors.innerRing = "#80808057";
+          }
 
-      // 更新趋势图数据
-      // 更新趋势图数据(用tableData,不是newProps)
-      this.xData = this.tableData.map((item) => item.timeStamp);
-      this.yData = fields.map(({ key }) =>
-        this.tableData.map((item) => Number(item[key]))
-      );
-      this.dialogVisible = false;
+          this.$message.success({
+            message: "诊断完成",
+            duration: 1000, // 1秒后自动关闭
+          });
+        })
+        .catch((error) => {
+          console.error("自动诊断失败:", error);
+          this.bearingStateColors.innerRing = "#80808057";
+          this.$message.error({
+            message: "诊断失败",
+            duration: 1000, // 1秒后自动关闭
+          });
+        })
+        .finally(() => {
+          loadingInstance.close();
+          this.loading = false;
+        });
     },
   },
 };

+ 176 - 226
src/views/health/components/malfunction/temperature.vue

@@ -1,5 +1,5 @@
 <template>
-  <div>
+  <div class="MAXdiv">
     <div class="TopBox">
       <div class="rightdiv">
         <el-table
@@ -9,29 +9,24 @@
           style="width: 100%"
           height="250"
         >
-          <!-- <el-table-column fixed type="selection" width="55"> </el-table-column> -->
-          <el-table-column prop="timeStamp" label="时间" align="center">
-          </el-table-column>
-
-          <el-table-column prop="" label="部件名称" align="center">
-          </el-table-column>
+          <el-table-column prop="time_stamp" label="时间" align="center" />
           <el-table-column
-            prop="innerRingFault"
-            label="温度状态"
+            prop="temp_channel"
+            label="部件名称"
             align="center"
-          >
-          </el-table-column>
+          />
+          <el-table-column prop="status" label="温度状态" align="center" />
         </el-table>
-        <div class="fenye">
-          <p><span>故障状态代码说明:</span>0代表正常,1代表异常</p>
 
+        <div class="fenye">
+                    <p><span>状态码说明:</span>0正常,1报警,2危险,-1未定义</p>
           <el-pagination
             @current-change="handleCurrentChange"
             :current-page="currentPage"
             layout="total, prev, pager, next, jumper"
             :total="totalCount"
-            :page-size="10"
-          ></el-pagination>
+            :page-size="500"
+          />
         </div>
       </div>
 
@@ -39,68 +34,56 @@
         <div class="stateBox">
           <h4>温度状态</h4>
           <div class="state">
-            <p :style="{ backgroundColor: bearingStateColors.innerRing }">
+            <p :style="{ backgroundColor: getStatusColor('主轴承温度') }">
               主轴承温度
             </p>
-            <p :style="{ backgroundColor: bearingStateColors.outerRing }">
-              齿轮箱温
+            <p :style="{ backgroundColor: getStatusColor('齿轮箱油温') }">
+              齿轮箱
             </p>
-            <p :style="{ backgroundColor: bearingStateColors.rollingElement }">
-              发电机驱动侧温度
+            <p
+              :style="{
+                backgroundColor: getStatusColor('发电机驱动端轴承温度'),
+              }"
+            >
+              发电机驱动端轴承温度
             </p>
-            <p :style="{ backgroundColor: bearingStateColors.cage }">
-              发电机非驱动侧温度
+            <p
+              :style="{
+                backgroundColor: getStatusColor('发电机非驱动端轴承温度'),
+              }"
+            >
+              发电机非驱动端轴承温度
             </p>
           </div>
-          <el-button
-            type="primary"
-            size="small"
-            @click="automaticDiagnosis"
-            class="btn-auto"
-            >诊断</el-button
-          >
         </div>
 
         <div class="Btn">
           <div style="height: 200px">
-            <bing :result="result"> </bing>
+            <bing :result="result" />
           </div>
-
           <div class="minp">
             <p class="PText">
-              <span><i class="color1"></i>正常</span
-              ><span><i class="color2"></i>报警</span
-              >
+              <span><i class="color1"></i>正常</span>
+              <span><i class="color2"></i>危险</span>
             </p>
-
             <h4>诊断步骤:</h4>
-            <p>1、选择振动测点与起止时间,点击“查询”;</p>
-            <p>2、对轴承“参数设置”输入相关信息;</p>
-            <p>3、点击“诊断”输出最终轴承状态结果。</p>
+            <p>1、选择风场风机与起止时间,点击“查询”;</p>
+            <p>2、点击“查询”输出最终温度状态结果。</p>
           </div>
         </div>
       </div>
     </div>
+
     <div class="bottomBox">
-      <div class="tu">
-        <zhexian
-          title="主轴承温度特征值"
-          lineType="line"
-          lineColor="#02aae9"
-        ></zhexian>
-      </div>
-      <div class="tu">
-        <zhexian title="驱动侧发电机轴承温度"></zhexian>
-      </div>
-      <div class="tu">
+      <div class="tu" v-for="(item, index) in chartList" :key="index">
+        <el-empty v-if="!hasData(item.data)" description="暂无数据" />
         <zhexian
-          title="齿轮箱油温"
-          lineType="line"
-          lineColor="#02aae9"
-        ></zhexian>
-      </div>
-      <div class="tu">
-        <zhexian title="驱动侧非发电机轴承温度"></zhexian>
+          v-else
+          :title="item.title"
+          :lineType="item.lineType"
+          :lineColor="item.lineColor"
+          :chartData="item.data"
+        />
       </div>
     </div>
   </div>
@@ -109,11 +92,20 @@
 <script>
 import Eecharts from "./Eecharts.vue";
 import bing from "./bing.vue";
-import { cacheEntryPossiblyAdded } from "plotly.js-dist";
 import Zhexian from "./zhexian.vue";
+
 export default {
   components: { Eecharts, bing, Zhexian },
   props: {
+    echartsdata: {
+      type: Object,
+      default: () => ({
+        main_bearing: [],
+        generator_drive_end: [],
+        gearbox_oil: [],
+        generator_nondrive_end: [],
+      }),
+    },
     codedata: {
       type: Array,
       default: () => [],
@@ -130,168 +122,159 @@ export default {
   data() {
     return {
       tableData: [],
-      // 添加新的数据属性用于绑定输入框的值
-      transmissionRatio: "",
-      bearingPitchDiameter: "",
-      rollingElementDiameter: "",
-      rollingElementCount: "",
-      contactAngle: "",
-      vibrationSpeedAlarmThreshold: "",
-      vibrationSpeedDangerThreshold: "",
-      envelopeTotalAlarmThreshold: "",
-      envelopeTotalDangerThreshold: "",
-      // 分页
-
       currentPage: 1,
       total: 1,
-
-      xData: [],
-      yData: [],
-      // 颜色判断
+      result: {},
       bearingStateColors: {
         innerRing: "#80808057",
         outerRing: "#80808057",
         rollingElement: "#80808057",
         cage: "#80808057",
       },
-      hasError: false, // 标志是否已经显示过错误提示
-      result: {},
     };
   },
-  created() {},
-  watch: {
-    codedata: {
-      handler(newVal) {
-        this.tableData = newVal;
-      },
-      immediate: true, // 组件创建时立刻执行一次
-      deep: true, // 如果 codedata 是复杂对象,建议加上
-    },
-  },
-
-  methods: {
-    toggleSelection(rows) {
-      if (rows) {
-        rows.forEach((row) => {
-          this.$refs.multipleTable.toggleRowSelection(row);
-        });
-      } else {
-        this.$refs.multipleTable.clearSelection();
-      }
-    },
-    handleSelectionChange(val) {
-      this.multipleSelection = val;
-    },
-    handleCurrentChange(val) {
-      console.log(`当前页: ${val}`);
-
-      this.currentPage = val; // 子组件内部更新当前页
-      this.$emit("updatePage", this.currentPage); // 通知父组件,把当前页传出去
-    },
-    automaticDiagnosis() {
-      // 验证必填项
-      const requiredFields = [
-        { field: this.transmissionRatio, name: "发电机到轴承测点转速传动比" },
-        { field: this.bearingPitchDiameter, name: "轴承节圆直径D(mm)" },
-        { field: this.rollingElementDiameter, name: "滚动体直径d(mm)" },
-        { field: this.rollingElementCount, name: "滚动体个数Z(个)" },
-        { field: this.contactAngle, name: "接触角α(°)" },
+  computed: {
+    chartList() {
+      const list = [
         {
-          field: this.vibrationSpeedAlarmThreshold,
-          name: "振动速度报警阈值(mm/s)",
+          title: "主轴承温度趋势图",
+          data: this.echartsdata.main_bearing,
+          lineType: "line",
+          lineColor: "#02aae9",
         },
         {
-          field: this.vibrationSpeedDangerThreshold,
-          name: "振动速度危险阈值(mm/s)",
+          title: "驱动侧发电机轴承温度趋势图",
+          data: this.echartsdata.generator_drive_end,
         },
         {
-          field: this.envelopeTotalAlarmThreshold,
-          name: "包络总值报警阈值(gE)",
+          title: "齿轮箱油温趋势图",
+          data: this.echartsdata.gearbox_oil,
+          lineType: "line",
+          lineColor: "#02aae9",
         },
         {
-          field: this.envelopeTotalDangerThreshold,
-          name: "包络总值危险阈值(gE)",
+          title: "驱动侧非发电机轴承温度趋势图",
+          data: this.echartsdata.generator_nondrive_end,
         },
       ];
+      return list.slice().sort((a, b) => {
+        const hasData = (d) =>
+          Array.isArray(d)
+            ? d.length
+            : typeof d === "object" && Object.keys(d).length;
+        return hasData(b.data) - hasData(a.data);
+      });
+    },
+  },
+  watch: {
+    codedata: {
+      handler(newVal) {
+        this.tableData = newVal;
+        this.updateBearingStateColors();
+        this.updateStatusCount(); // 统计调用
+      },
+      immediate: true,
+      deep: true,
+    },
+  },
+  methods: {
+    updateBearingStateColors() {
+      // 四个温度类型对应状态颜色key
+      const statusMap = {
+        主轴承温度: "innerRing",
+        齿轮箱油温: "outerRing",
+        发电机驱动端轴承温度: "rollingElement", // 改成“驱动端”对应数据字段
+        发电机非驱动端轴承温度: "cage", // 改成“非驱动端”对应数据字段
+      };
 
-      // 记录是否已弹出过错误提示
-      let hasError = false;
-
-      // 只检查必填项的字段是否为空
-      // for (const { field, name } of requiredFields) {
-      //   if (!field && !hasError) {
-      //     // 弹出提示并标记已经出现错误提示
-      //     this.$message.error(`${name} 是必填项`);
-      //     hasError = true;  // 标记已经弹出过错误提示
-      //     return;  // 停止执行后续逻辑
-      //   }
-      // }
+      // 颜色映射,正常绿,异常黄,无数据灰
+      const colorMap = {
+        normal: "#8ae359",
+        danger: "#eecb5f",
+        unknown: "#80808057",
+      };
 
-      // 如果验证通过,继续执行后续逻辑
-      const newProps = this.tableData.map(() => ({
-        innerRingFault: Math.floor(Math.random() * 2).toString(),
-        // outerRingFault: Math.floor(Math.random() * 3).toString(),
-        // rollingElementFault: Math.floor(Math.random() * 3).toString(),
-        // cageFault: Math.floor(Math.random() * 3).toString(),
-      }));
+      const updatedColors = {};
 
-      this.tableData.forEach((row, index) => {
-        this.$set(this.tableData, index, {
-          ...row,
-          ...newProps[index], // 用每一行自己生成的随机数
-        });
-      });
+      // 遍历四个温度类型,分别判断它们对应的tableData是否有异常或报警
+      for (const [label, key] of Object.entries(statusMap)) {
+        const items = this.tableData.filter(
+          (item) => item.temp_channel === label
+        );
+        if (items.length === 0) {
+          updatedColors[key] = colorMap.unknown; // 无数据,灰色
+        } else {
+          const hasDanger = items.some(
+            (item) => item.status === "异常" || item.status === "危险"
+          );
+          updatedColors[key] = hasDanger ? colorMap.danger : colorMap.normal;
+        }
+      }
 
-      const faultValues = [
-        ...this.tableData.map((record) => record.innerRingFault),
-        ...this.tableData.map((record) => record.outerRingFault),
-        ...this.tableData.map((record) => record.rollingElementFault),
-        ...this.tableData.map((record) => record.cageFault),
-      ];
+      // 合并更新状态颜色对象
+      this.bearingStateColors = {
+        ...this.bearingStateColors,
+        ...updatedColors,
+      };
+    },
+    updateStatusCount() {
+      let normalCount = 0;
+      let dangerCount = 0;
 
-      // 统计各个值出现的次数
-      const counter = faultValues.reduce((acc, value) => {
-        acc[value] = (acc[value] || 0) + 1;
-        return acc;
-      }, {});
+      this.tableData.forEach((item) => {
+        if (item.status === "正常") {
+          normalCount++;
+        } else if (
+          item.status === "异常" ||
+          item.status === "危险" ||
+          item.status === "报警"
+        ) {
+          dangerCount++;
+        }
+      });
 
-      // 构造统计结果对象
       this.result = {
-        1: counter["0"] || 0,
-        2: counter["1"] || 0,
-        // 3: counter["2"] || 0,
+        normal: normalCount,
+        danger: dangerCount,
       };
+    },
 
-      // 更新颜色状态
-      const fields = [
-        { key: "innerRingFault", colorKey: "innerRing" },
-        { key: "outerRingFault", colorKey: "outerRing" },
-        { key: "rollingElementFault", colorKey: "rollingElement" },
-        { key: "cageFault", colorKey: "cage" },
-      ];
+    getStatusColor(tempName) {
+      const map = {
+        主轴承温度: "innerRing",
+        齿轮箱油温: "outerRing",
+        发电机驱动端轴承温度: "rollingElement",
+        发电机非驱动端轴承温度: "cage",
+      };
+      // 根据tempName返回对应颜色
+      return this.bearingStateColors[map[tempName]] || "#80808057";
+    },
 
-      fields.forEach(({ key, colorKey }) => {
-        const values = newProps.map((item) => Number(item[key]));
-        const maxVal = Math.max(...values);
-        let color = "#80808057"; // 默认灰色
-        if (maxVal === 0) color = "#8AE359"; // 无故障
-        else if (maxVal === 1) color = "#EECB5F"; // 警告
-        // else if (maxVal === 2) color = "#F7715F"; // 危险
+    hasData(data) {
+      if (!data) return false;
 
-        this.bearingStateColors[colorKey] = color; // 更新颜色
-      });
+      // 检查是否是特定结构 { timestamps: [], values: [] }
+      if (Array.isArray(data.timestamps) && Array.isArray(data.values)) {
+        return data.timestamps.length > 0 || data.values.length > 0;
+        // 或者如果要求两个都不为空:
+        // return data.timestamps.length > 0 && data.values.length > 0;
+      }
+
+      // 原有的检查逻辑
+      if (Array.isArray(data)) return data.length > 0;
+      if (typeof data === "object") return Object.keys(data).length > 0;
+      return false;
+    },
 
-      // 更新趋势图数据
-      // 更新趋势图数据(用tableData,不是newProps)
-      this.xData = this.tableData.map((item) => item.timeStamp);
-      this.yData = fields.map(({ key }) =>
-        this.tableData.map((item) => Number(item[key]))
-      );
+    handleCurrentChange(val) {
+      this.currentPage = val;
+      this.$emit("updatePage", this.currentPage);
     },
   },
 };
 </script>
 
+
 <style lang="scss" scoped>
 h4 {
   margin-bottom: 5px;
@@ -314,7 +297,7 @@ h4 {
         height: 200px;
         gap: 20px; /* 控制间距 */
         p {
-          width: 150px;
+          width: 200px;
           height: 40px;
           background: rgb(227, 227, 227);
           color: rgb(50, 50, 50);
@@ -369,7 +352,8 @@ h4 {
     width: 50%;
     .fenye {
       display: flex;
-      justify-content: space-between;
+      //justify-content: center;
+           justify-content: space-between;
       margin: 5px 0;
       font-size: 12px;
       line-height: 30px;
@@ -385,56 +369,22 @@ h4 {
   display: flex;
   flex-wrap: wrap;
   justify-content: space-around;
-  overflow: hidden;
-  overflow-y: auto;
-  height: 350px;
+
   border: 1px solid rgb(231, 231, 231);
   padding: 10px;
   .tu {
     width: 49%;
     height: 350px;
   }
-  // margin-top: 10px;
-  // .BtLeft {
-  //   border: 1px solid rgb(231, 231, 231);
-  //   width: 49%;
-  //   padding: 10px;
-  // }
-  // .BtRight {
-  //   width: 49%;
-  //   border: 1px solid rgb(231, 231, 231);
-  //   padding: 10px;
-  //   .BtRightDiv {
-  //     padding: 0 10px;
-  //     h4 {
-  //       font-size: 14px;
-  //     }
-  //     .BtRightP {
-  //       line-height: 30px;
-  //       font-size: 12px;
-  //       display: flex;
-  //       margin-bottom: 5px;
-  //       width: 50%;
-  //       span {
-  //         margin-left: 10px;
-  //         .el-input {
-  //           width: 100px;
-  //         }
-  //       }
-  //       .label-text {
-  //         width: 140px;
-  //       }
-  //     }
-  //     .canshu {
-  //       display: flex;
-  //       flex-wrap: wrap;
-  //       justify-content: space-between;
-  //     }
-  //   }
-  // }
 }
 ::v-deep .el-table__cell {
   padding: 2px 0;
   font-size: 12px;
 }
+
+.MAXdiv {
+  overflow: hidden;
+  overflow-y: auto;
+  height: 70vh;
+}
 </style>

+ 71 - 59
src/views/health/components/malfunction/zhexian.vue

@@ -3,111 +3,123 @@
 </template>
 
 <script>
-import * as echarts from 'echarts'
+import * as echarts from "echarts";
 
 export default {
-  name: 'LargeAreaChart',
+  name: "LargeAreaChart",
   props: {
     title: {
       type: String,
-      default: 'Large Area Chart'
+      default: "Large Area Chart",
     },
     lineType: {
       type: String,
-      default: 'line' // 可选:line, bar 等
+      default: "line", // 可选:line, bar 等
     },
     lineColor: {
       type: String,
-      default: '#5470C6' // 默认 ECharts 主色
-    }
+      default: "#5470C6", // 默认 ECharts 主色
+    },
+    chartData: {
+      type: Object,
+      default: () => ({
+        timestamps: [],
+        values: [],
+      }),
+    },
   },
   data() {
     return {
-      myChart: null
-    }
+      myChart: null,
+    };
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler() {
+        this.updateChart();
+      },
+    },
   },
   mounted() {
-    this.initChart()
+    this.initChart();
   },
   beforeUnmount() {
     if (this.myChart) {
-      this.myChart.dispose()
+      this.myChart.dispose();
     }
   },
   methods: {
     initChart() {
-      this.myChart = echarts.init(this.$refs.chartRef)
+      this.myChart = echarts.init(this.$refs.chartRef);
+      this.updateChart();
+    },
+    updateChart() {
+      if (!this.myChart || !this.chartData.timestamps.length) return;
 
-      let base = +new Date(2024, 1, 3)
-      let oneDay = 24 * 360 * 100
-      let data = [[base, Math.random() * 300]]
-      for (let i = 1; i < 20000; i++) {
-        let now = new Date((base += oneDay))
-        data.push([
-          +now,
-          Math.round((Math.random() - 0.5) * 20 + data[i - 1][1])
-        ])
-      }
+      const data = this.chartData.timestamps.map((t, i) => [
+        t,
+        this.chartData.values[i],
+      ]);
 
       const option = {
         tooltip: {
-          trigger: 'axis',
-          position: pt => [pt[0], '10%']
+          trigger: "axis",
+          position: (pt) => [pt[0], "10%"],
         },
         title: {
-          left: 'center',
-          text: this.title
+          left: "center",
+          text: this.title,
         },
         toolbox: {
           feature: {
-            dataZoom: { yAxisIndex: 'none' },
+            dataZoom: { yAxisIndex: "none" },
             restore: {},
-            saveAsImage: {}
-          }
+            saveAsImage: {},
+          },
         },
         xAxis: {
-          type: 'time',
-          boundaryGap: false
+          type: "time",
+          boundaryGap: false,
+          axisLabel: {
+            formatter: (value) => {
+              const date = new Date(value);
+              const m = String(date.getMonth() + 1).padStart(2, "0");
+              const d = String(date.getDate()).padStart(2, "0");
+              return `${m}-${d} `;
+            },
+            rotate: 0, // 倾斜以防止重叠
+            hideOverlap: true,
+          },
         },
         yAxis: {
-          type: 'value',
-          boundaryGap: [0, '100%']
+          type: "value",
+          max: 1, // 👈 固定最大值
+          boundaryGap: [0, "100%"],
         },
         dataZoom: [
-          {
-            type: 'inside',
-            start: 0,
-            end: 20
-          },
-          {
-            start: 0,
-            end: 20
-          }
+          { type: "inside", start: 0, end: 20 },
+          { start: 0, end: 20 },
         ],
         series: [
           {
-            name: '温度',
+            name: "特征值",
             type: this.lineType,
             smooth: true,
-            symbol: 'none',
-            areaStyle: this.lineType === 'line' ? {} : undefined,
-            itemStyle: {
-              color: this.lineColor
-            },
-            lineStyle: {
-              color: this.lineColor
-            },
-            data
-          }
-        ]
-      }
+            symbol: "none",
+            areaStyle: this.lineType === "line" ? {} : undefined,
+            itemStyle: { color: this.lineColor },
+            lineStyle: { color: this.lineColor },
+            data,
+          },
+        ],
+      };
 
-      this.myChart.setOption(option)
-    }
-  }
-}
+      this.myChart.setOption(option);
+    },
+  },
+};
 </script>
 
 <style scoped>
-/* 可以按需添加样式 */
 </style>

+ 4 - 0
src/views/health/components/timedomaincharts.vue

@@ -249,6 +249,10 @@ export default {
         .post("/WJapi/analysis/time", params)
         .then((res) => {
           this.timeList = JSON.parse(res.data);
+
+
+          console.log(this.timeList, "timeList");
+          
         })
         .catch((error) => {})
         .finally(() => {

+ 4 - 1
src/views/health/index.vue

@@ -161,6 +161,8 @@ export default {
       timevalue: [],
       ListData: [],
       loading: false, // ✅ 加载状态
+
+  
     };
   },
   computed: {
@@ -231,7 +233,7 @@ export default {
       const start = performance.now(); // ⏱️ 请求开始时间
 
       axios
-        .post(`/WJJapi/health_assess`, parms)
+        .post(`/WJJhealth/health_assess`, parms)
         .then((res) => {
           this.ListData = res.data;
 
@@ -388,6 +390,7 @@ export default {
   color: var(--header-bg);
 }
 .kuang {
+  min-height: 79vh;
   height: 680px;
   position: relative;
   overflow: hidden;

+ 502 - 0
src/views/health/malfunction copy.vue

@@ -0,0 +1,502 @@
+<template>
+  <div class="global-variable">
+    <!-- tab 切换 -->
+    <el-tabs v-model="activeName" @tab-click="handleClick">
+      <el-tab-pane
+        v-for="item in menuItems"
+        :key="item.component"
+        :label="item.name"
+        :name="item.component"
+      />
+    </el-tabs>
+
+    <!-- 查询条件 -->
+    <div class="searchbox">
+      <p>
+        单位:
+        <selecttree
+          size="small"
+          style="width: 180px"
+          placeholder="请选择所属公司"
+          :list="tabConditions[activeTab].parentOpt"
+          type="1"
+          v-model="tabConditions[activeTab].companyCode"
+          @change="parentChange"
+          :defaultParentProps="{
+            children: 'children',
+            label: 'companyName',
+            value: 'codeNumber',
+          }"
+        />
+      </p>
+      <p>
+        风机:
+        <el-select
+          size="small"
+          style="width: 150px"
+          v-model="tabConditions[activeTab].unitvalue"
+          @change="getchedian"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in tabConditions[activeTab].unitoptions"
+            :key="item.engineCode"
+            :label="item.engineName"
+            :value="item.engineCode"
+          />
+        </el-select>
+      </p>
+      <p>
+        测点:
+        <el-select
+          v-model="tabConditions[activeTab].monitoringvalue"
+          size="small"
+          clearable
+          placeholder="请选择"
+          :disabled="activeTab === 'Temperature'"
+        >
+          <el-option
+            v-for="item in tabConditions[activeTab].monitoringoptions"
+            :key="item.itemKey"
+            :label="item.itemValue"
+            :value="item.itemKey"
+          />
+        </el-select>
+      </p>
+
+      <p>
+        采样频率:
+        <el-select
+          v-model="tabConditions[activeTab].frequencyvalue"
+          size="small"
+          clearable
+          placeholder="请选择"
+          :disabled="activeTab === 'Temperature'"
+        >
+          <el-option
+            v-for="item in tabConditions[activeTab].frequencyoptions"
+            :key="item"
+            :label="item"
+            :value="item"
+          />
+        </el-select>
+      </p>
+      <p>
+        时间:
+        <el-date-picker
+          size="small"
+          v-model="tabConditions[activeTab].timevalue"
+          type="datetimerange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        />
+      </p>
+      <el-button
+        type="primary"
+        size="small"
+        @click="conditions(1)"
+        class="search-btn"
+        >查询</el-button
+      >
+    </div>
+
+    <!-- 动态组件内容 -->
+    <div class="main-body">
+      <keep-alive>
+        <component
+          :is="activeTab"
+          :codedata="tabData[activeTab].codedata"
+          v-bind="
+            activeTab === 'Temperature'
+              ? { echartsdata: tabData.Temperature.echartsdata }
+              : {}
+          "
+          :totalCount="tabData[activeTab].totalCount"
+          :totalPage="tabData[activeTab].totalPage"
+          @updatePage="handlePageChange"
+        />
+      </keep-alive>
+    </div>
+  </div>
+</template>
+
+<script>
+import * as FileSaver from "file-saver";
+import * as XLSX from "xlsx";
+import {
+  getSysOrganizationAuthTreeByRoleId,
+  windEngineGrouPage,
+  queryDetectionDic,
+} from "@/api/ledger.js";
+import selecttree from "../../components/selecttree.vue";
+import Bearing from "./components/malfunction/bearing.vue";
+import Dissymmetry from "./components/malfunction/dissymmetry.vue";
+import Gear from "./components/malfunction/gear.vue";
+import Loose from "./components/malfunction/loose.vue";
+import Misalignment from "./components/malfunction/misalignment.vue";
+import Temperature from "./components/malfunction/temperature.vue";
+import axios from "axios";
+
+export default {
+  components: {
+    selecttree,
+    Bearing,
+    Dissymmetry,
+    Gear,
+    Loose,
+    Misalignment,
+    Temperature,
+  },
+  data() {
+    return {
+      activeTab: "Temperature",
+      activeName: "Temperature",
+      menuItems: [
+        {
+          name: "轴承诊断",
+          icon: require("@/assets/img/ZC.png"),
+          component: "Bearing",
+        },
+        {
+          name: "齿轮诊断",
+          icon: require("@/assets/img/SZ.png"),
+          component: "Gear",
+        },
+        {
+          name: "不对中诊断",
+          icon: require("@/assets/img/DZ.png"),
+          component: "Dissymmetry",
+        },
+        {
+          name: "不平衡诊断",
+          icon: require("@/assets/img/DC.png"),
+          component: "Misalignment",
+        },
+        {
+          name: "松动诊断",
+          icon: require("@/assets/img/SD.png"),
+          component: "Loose",
+        },
+        {
+          name: "温度诊断",
+          icon: require("@/assets/img/WD.png"),
+          component: "Temperature",
+        },
+      ],
+      tabConditions: {
+        Bearing: {},
+        Gear: {},
+        Dissymmetry: {},
+        Misalignment: {},
+        Loose: {},
+        Temperature: {},
+      },
+      tabData: {
+        Bearing: { codedata: [], totalCount: 0, totalPage: 0 },
+        Gear: { codedata: [], totalCount: 0, totalPage: 0 },
+        Dissymmetry: { codedata: [], totalCount: 0, totalPage: 0 },
+        Misalignment: { codedata: [], totalCount: 0, totalPage: 0 },
+        Loose: { codedata: [], totalCount: 0, totalPage: 0 },
+        Temperature: {
+          codedata: [],
+          totalCount: 0,
+          totalPage: 0,
+          echartsdata: {},
+        },
+      },
+    };
+  },
+  created() {
+    for (const key in this.tabConditions) {
+      this.tabConditions[key] = this.defaultCondition();
+    }
+    this.GETtree();
+  },
+  methods: {
+    defaultCondition() {
+      return {
+        unitvalue: "",
+        unitoptions: [],
+        companyCode: "",
+        parentOpt: [],
+        timevalue: [],
+        monitoringvalue: "",
+        monitoringoptions: [],
+        frequencyvalue: "",
+        frequencyoptions: [],
+      };
+    },
+    handleClick(tab) {
+      this.activeTab = tab.name;
+    },
+    async GETtree() {
+      const res = await getSysOrganizationAuthTreeByRoleId();
+      const treedata = res.data;
+      const processed = this.processTreeData(treedata);
+
+      for (const key in this.tabConditions) {
+        this.tabConditions[key].parentOpt = processed;
+      }
+    },
+    parentChange(data) {
+      const condition = this.tabConditions[this.activeTab];
+
+      if (!data?.codeNumber) return;
+
+      condition.unitvalue = "";
+      condition.monitoringvalue = "";
+      condition.frequencyvalue = "";
+
+      windEngineGrouPage({
+        fieldCode: data.codeNumber,
+        pageNum: 1,
+        pageSize: 99,
+      }).then((res) => {
+        condition.unitoptions = res.data.list;
+      });
+
+      axios
+        .get(`/ETLapi/waveData/getAllSamplingFrequency/${data.codeNumber}`)
+        .then((res) => {
+          condition.frequencyoptions = res.data.datas;
+        });
+
+      condition.companyCode = data.codeNumber;
+    },
+    getchedian(value) {
+      const condition = this.tabConditions[this.activeTab];
+      const companyCode = condition.companyCode;
+
+      axios
+        .post(`/ETLapi/waveData/getAllMesurePointName/${companyCode}/${value}`)
+        .then((res) => {
+          condition.monitoringvalue = "";
+          if (res.data.code === 500) {
+            condition.monitoringoptions = [];
+            this.$message({
+              message: res.data.message || "未知错误",
+              type: "warning",
+            });
+            return;
+          }
+          if (res.data.code === 200) {
+            const datas = Array.isArray(res.data.datas) ? res.data.datas : [];
+            condition.monitoringoptions = datas;
+            if (datas.length === 0) {
+              this.$message({ message: "暂无数据", type: "warning" });
+            }
+          }
+        })
+        .catch((err) => {
+          console.error("测点请求失败:", err);
+          condition.monitoringoptions = [];
+        });
+    },
+    processTreeData(treeData) {
+      const processedData = [];
+      function processNode(node) {
+        if (node.codeType === "field") {
+          node.companyName = node.fieldName;
+        }
+        if (node.children && node.children.length > 0) {
+          node.children.forEach(processNode);
+        }
+      }
+      treeData.forEach((root) => {
+        processNode(root);
+        processedData.push(root);
+      });
+      return processedData;
+    },
+    handlePageChange(page) {
+      this.conditions(page);
+    },
+    conditions(page) {
+      const tab = this.activeTab;
+      const condition = this.tabConditions[tab];
+
+      const params = {
+        samplingFrequency: condition.frequencyvalue,
+        windCode: condition.companyCode,
+        windTurbineNumberList: [condition.unitvalue],
+        mesureNameList: [condition.monitoringvalue],
+        startTime: this.$formatDateTWO(condition.timevalue[0]),
+        endTime: this.$formatDateTWO(condition.timevalue[1]),
+        pageNo: page,
+        pageSize: 10,
+      };
+
+      if (tab === "Temperature") {
+        const temperature = {
+          windCode: "WOF046400029",
+          windTurbineNumberList: ["WOG01312"],
+          startTime: "2023-10-01 00:00",
+          endTime: "2023-10-07 00:00",
+          pageNo: page,
+          pageSize: 500,
+        };
+
+        const loading = this.$loading({
+          lock: true,
+          text: "温度诊断数据加载中,请稍候…",
+          spinner: "el-icon-loading",
+          background: "rgba(0, 0, 0, 0.8)", // 稍浅一些,更柔和
+          customClass: "custom-loading-style", // 可选:如果你有样式可以加类名
+        });
+
+        const thresholdReq = axios
+          .post("/WJJdiag/temperature/threshold", temperature)
+          .then((res) => {
+            const data = res.data.data.records || [];
+            this.tabData[tab].codedata = data;
+            this.tabData[tab].totalCount = res.data.data.totalSize || 0;
+            console.log("温度诊断总数:", res.data.data.totalSize);
+          })
+          .catch((err) => {
+            console.error("温度诊断请求失败:", err);
+            this.$message.error("温度诊断数据请求失败,请稍后再试");
+          });
+
+        const trendReq = axios
+          .post("/WJJdiag/SPRT/trend", temperature)
+          .then((res) => {
+            const echartsdata = res.data.data || {};
+            this.tabData[tab].echartsdata = echartsdata;
+            console.log("趋势图数据:", echartsdata);
+          })
+          .catch((err) => {
+            console.error("趋势图请求失败:", err);
+            this.$message.error("温度趋势图数据请求失败,请稍后再试");
+          });
+
+        // 所有请求完成后关闭 loading
+        Promise.allSettled([thresholdReq, trendReq]).finally(() => {
+          loading.close();
+        });
+      } else {
+        // 默认其他组件逻辑
+        axios
+          .post("/ETLapi/waveData/getMesureDataWithSF", params)
+          .then((res) => {
+            const data = res.data || {};
+            this.tabData[tab].codedata = data.datas || [];
+            this.tabData[tab].totalCount = data.totalCount || 0;
+            this.tabData[tab].totalPage = data.totalPage || 0;
+          });
+      }
+    },
+  },
+};
+</script>
+
+
+
+  <style lang="scss" scoped>
+.global-variable {
+  padding: 10px;
+}
+.head {
+  padding: 5px 0;
+  display: flex;
+  justify-content: space-between;
+
+  ul {
+    display: flex;
+    width: 500px;
+    height: 65px;
+    justify-content: space-between;
+    li {
+      cursor: pointer;
+      padding: 8px 12px 0 12px;
+      border-radius: 4px;
+      transition: all 0.3s;
+
+      &:hover {
+        background-color: #f0f0f0;
+      }
+
+      &.active {
+        background-color: #e6f7ff;
+        border-bottom: 2px solid var(--header-bg);
+
+        span {
+          color: var(--header-bg);
+          font-weight: bold;
+        }
+      }
+
+      .Simg {
+        width: 30px;
+        height: 30px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin: 0 auto;
+
+        img {
+          max-width: 100%;
+          max-height: 100%;
+        }
+      }
+
+      span {
+        display: block;
+        font-size: 12px;
+        font-weight: 600;
+        text-align: center;
+        margin-top: 5px;
+      }
+    }
+  }
+}
+.searchbox {
+  display: flex;
+  margin-bottom: 10px;
+  align-items: center;
+  flex-wrap: wrap;
+  // padding-top: 10px;
+  p {
+    margin-right: 10px;
+    margin-bottom: 0;
+    margin-top: 10px;
+    display: flex;
+    align-items: center;
+
+    .el-select,
+    .el-date-picker {
+      margin-left: 10px;
+    }
+  }
+
+  .el-select {
+    width: 180px;
+  }
+  .search-btn {
+    margin-top: 10px;
+  }
+}
+.main-body {
+  margin-top: 10px;
+  // border: 1px solid #ebeef5;
+  border-radius: 4px;
+  padding: 10px;
+  background: #fff;
+}
+
+.el-range-editor.el-input__inner {
+  width: 370px;
+}
+
+/* 放在你的组件 <style scoped> 或全局样式里 */
+.custom-loading-style .el-loading-spinner i {
+  font-size: 26px;
+  color: #409eff; /* Element UI 主色调,更柔和 */
+}
+
+.custom-loading-style .el-loading-text {
+  font-size: 14px;
+  color: #303133;
+  letter-spacing: 0.5px;
+}
+</style>

+ 249 - 142
src/views/health/malfunction.vue

@@ -7,8 +7,7 @@
         :key="item.component"
         :label="item.name"
         :name="item.component"
-      >
-      </el-tab-pane>
+      />
     </el-tabs>
 
     <!-- 查询条件 -->
@@ -19,9 +18,9 @@
           size="small"
           style="width: 180px"
           placeholder="请选择所属公司"
-          :list="parentOpt"
+          :list="tabConditions[activeTab].parentOpt"
           type="1"
-          v-model="companyCode"
+          v-model="tabConditions[activeTab].companyCode"
           @change="parentChange"
           :defaultParentProps="{
             children: 'children',
@@ -35,12 +34,12 @@
         <el-select
           size="small"
           style="width: 150px"
-          v-model="unitvalue"
+          v-model="tabConditions[activeTab].unitvalue"
           @change="getchedian"
           placeholder="请选择"
         >
           <el-option
-            v-for="item in unitoptions"
+            v-for="item in tabConditions[activeTab].unitoptions"
             :key="item.engineCode"
             :label="item.engineName"
             :value="item.engineCode"
@@ -50,29 +49,32 @@
       <p>
         测点:
         <el-select
-          v-model="monitoringvalue"
+          v-model="tabConditions[activeTab].monitoringvalue"
           size="small"
           clearable
           placeholder="请选择"
+          :disabled="activeTab === 'Temperature'"
         >
           <el-option
-            v-for="item in monitoringoptions"
+            v-for="item in tabConditions[activeTab].monitoringoptions"
             :key="item.itemKey"
             :label="item.itemValue"
             :value="item.itemKey"
           />
         </el-select>
       </p>
+
       <p>
         采样频率:
         <el-select
-          v-model="frequencyvalue"
+          v-model="tabConditions[activeTab].frequencyvalue"
           size="small"
           clearable
           placeholder="请选择"
+          :disabled="activeTab === 'Temperature'"
         >
           <el-option
-            v-for="item in frequencyoptions"
+            v-for="item in tabConditions[activeTab].frequencyoptions"
             :key="item"
             :label="item"
             :value="item"
@@ -83,17 +85,18 @@
         时间:
         <el-date-picker
           size="small"
-          v-model="timevalue"
+          v-model="tabConditions[activeTab].timevalue"
           type="datetimerange"
           range-separator="至"
           start-placeholder="开始日期"
           end-placeholder="结束日期"
         />
+        <!-- :picker-options="datePickerOptions" -->
       </p>
       <el-button
         type="primary"
         size="small"
-        @click="conditions(1)"
+        @click="onSearchClick"
         class="search-btn"
         >查询</el-button
       >
@@ -104,9 +107,16 @@
       <keep-alive>
         <component
           :is="activeTab"
-          :codedata="codedata"
-          :totalCount="totalCount"
-          :totalPage="totalPage"
+          :codedata="tabData[activeTab].codedata"
+          v-bind="
+            activeTab === 'Temperature'
+              ? { echartsdata: tabData.Temperature.echartsdata }
+              : {}
+          "
+          :totalCount="tabData[activeTab].totalCount"
+          :totalPage="tabData[activeTab].totalPage"
+          :fieldCode="tabConditions[activeTab].companyCode"
+          :windTurbineNumber="tabConditions[activeTab].unitvalue"
           @updatePage="handlePageChange"
         />
       </keep-alive>
@@ -144,8 +154,7 @@ export default {
   data() {
     return {
       activeTab: "Bearing",
-      activeName: "Bearing", // el-tabs 控制当前 tab
-
+      activeName: "Bearing",
       menuItems: [
         {
           name: "轴承诊断",
@@ -178,102 +187,129 @@ export default {
           component: "Temperature",
         },
       ],
-
-      unitvalue: "",
-      unitoptions: [],
-      companyCode: "",
-      parentOpt: [],
-      timevalue: [],
-      startTime: "",
-      endTime: "",
-      monitoringvalue: "",
-      monitoringoptions: [],
-      frequencyvalue: "",
-      frequencyoptions: [],
-      codedata: [],
-      totalCount: 0,
-      totalPage: 0,
-      page: "",
+      tabConditions: {
+        Bearing: {},
+        Gear: {},
+        Dissymmetry: {},
+        Misalignment: {},
+        Loose: {},
+        Temperature: {},
+      },
+      tabData: {
+        Bearing: { codedata: [], totalCount: 0, totalPage: 0 },
+        Gear: { codedata: [], totalCount: 0, totalPage: 0 },
+        Dissymmetry: { codedata: [], totalCount: 0, totalPage: 0 },
+        Misalignment: { codedata: [], totalCount: 0, totalPage: 0 },
+        Loose: { codedata: [], totalCount: 0, totalPage: 0 },
+        Temperature: {
+          codedata: [],
+          totalCount: 0,
+          totalPage: 0,
+          echartsdata: {},
+        },
+      },
+      datePickerOptions: {
+        onPick: ({ minDate, maxDate }) => {
+          if (minDate && !maxDate) {
+            const maxTime = new Date(
+              minDate.getTime() + 30 * 24 * 60 * 60 * 1000
+            );
+            this.datePickerOptions.disabledDate = (time) => {
+              return (
+                time.getTime() < minDate.getTime() ||
+                time.getTime() > maxTime.getTime()
+              );
+            };
+          } else {
+            this.datePickerOptions.disabledDate = () => false;
+          }
+        },
+        disabledDate: () => false,
+      },
     };
   },
   created() {
+    for (const key in this.tabConditions) {
+      this.tabConditions[key] = this.defaultCondition();
+    }
     this.GETtree();
   },
   methods: {
+    defaultCondition() {
+      return {
+        unitvalue: "",
+        unitoptions: [],
+        companyCode: "",
+        parentOpt: [],
+        timevalue: [],
+        monitoringvalue: "",
+        monitoringoptions: [],
+        frequencyvalue: "",
+        frequencyoptions: [],
+      };
+    },
     handleClick(tab) {
       this.activeTab = tab.name;
     },
     async GETtree() {
       const res = await getSysOrganizationAuthTreeByRoleId();
       const treedata = res.data;
-      const processedData = this.processTreeData(treedata);
-      this.parentOpt = processedData;
-      this.defaultdata = res.data[0];
-    },
-    parentChange(data) {
-      this.maplist = data;
-      this.maplistArr = data;
+      const processed = this.processTreeData(treedata);
 
-      if (!this.maplist?.codeNumber) {
-        console.error("codeNumber 不存在!");
-        return;
+      for (const key in this.tabConditions) {
+        this.tabConditions[key].parentOpt = processed;
       }
+    },
+    parentChange(data) {
+      const condition = this.tabConditions[this.activeTab];
+      if (!data?.codeNumber) return;
+      condition.unitvalue = "";
+      condition.monitoringvalue = "";
+      condition.frequencyvalue = "";
 
-      const paramsData = {
-        fieldCode: this.maplist.codeNumber,
+      windEngineGrouPage({
+        fieldCode: data.codeNumber,
         pageNum: 1,
         pageSize: 99,
-      };
-
-      this.unitvalue = "";
-      this.monitoringvalue = "";
-      this.frequencyvalue = "";
+      }).then((res) => {
+        condition.unitoptions = res.data.list;
+      });
 
-      windEngineGrouPage(paramsData)
+      axios
+        .get(`/ETLapi/waveData/getAllSamplingFrequency/${data.codeNumber}`)
         .then((res) => {
-          this.unitoptions = res.data.list;
-          this.windCode = this.companyCode;
-        })
-        .catch((err) => {
-          console.error("windEngineGrouPage 失败:", err);
+          condition.frequencyoptions = res.data.datas;
         });
 
-      let shouldSkip = false;
-      try {
-        if (data.codeType === "field") {
-          if (
-            this.parseCoordinates(data.longitudeAndLatitudeString).length > 0
-          ) {
-            shouldSkip = true;
-          }
-        } else {
-          data.children?.forEach((element) => {
-            if (
-              element.codeType === "field" &&
-              this.parseCoordinates(element.longitudeAndLatitudeString).length >
-                0
-            ) {
-              shouldSkip = true;
-            }
-          });
-        }
-      } catch (err) {
-        console.error("解析坐标出错:", err);
-      }
-
-      if (shouldSkip) {
-        console.log("坐标已存在,跳过部分逻辑");
-      }
+      condition.companyCode = data.codeNumber;
+    },
+    getchedian(value) {
+      const condition = this.tabConditions[this.activeTab];
+      const companyCode = condition.companyCode;
 
       axios
-        .get(
-          `/ETLapi/waveData/getAllSamplingFrequency/${this.maplist.codeNumber}`
-        )
+        .post(`/ETLapi/waveData/getAllMesurePointName/${companyCode}/${value}`)
         .then((res) => {
-          this.frequencyoptions = res.data.datas;
+          condition.monitoringvalue = "";
+          if (res.data.code === 500) {
+            condition.monitoringoptions = [];
+            this.$message({
+              message: "当前风场不存在测点和采样频率数据" || "未知错误",
+              type: "warning",
+            });
+            return;
+          }
+          if (res.data.code === 200) {
+            const datas = Array.isArray(res.data.datas) ? res.data.datas : [];
+            condition.monitoringoptions = datas;
+            if (datas.length === 0) {
+              this.$message({ message: "暂无数据", type: "warning" });
+            }
+          }
         })
         .catch((err) => {
-          console.error("第二个请求失败:", err);
+          console.error("测点请求失败:", err);
+          condition.monitoringoptions = [];
         });
     },
     processTreeData(treeData) {
@@ -283,9 +319,7 @@ export default {
           node.companyName = node.fieldName;
         }
         if (node.children && node.children.length > 0) {
-          node.children.forEach((child) => {
-            processNode(child);
-          });
+          node.children.forEach(processNode);
         }
       }
       treeData.forEach((root) => {
@@ -294,69 +328,130 @@ export default {
       });
       return processedData;
     },
-    parseCoordinates(input) {
-      if (input && typeof input === "string") {
-        return input.split(",").map(Number);
-      }
-      return [];
+    onSearchClick() {
+      this.conditions(1, false); // 主动查询,第一页,非分页触发
     },
-    getchedian(value) {
-      axios
-        .post(
-          `/ETLapi/waveData/getAllMesurePointName/${this.companyCode}/${value}`
-        )
+    handlePageChange(page) {
+      this.conditions(page, true); // true 表示分页触发
+    },
+
+    conditions(page, isPageChange = false) {
+      const tab = this.activeTab;
+      const condition = this.tabConditions[tab];
+
+    if (tab === "Temperature") {
+      const temperature = {
+        windCode: condition.companyCode,
+        windTurbineNumberList: [condition.unitvalue],
+        startTime: this.$formatDateTWO(condition.timevalue[0]),
+        endTime: this.$formatDateTWO(condition.timevalue[1]),
+        pageNo: page,
+        pageSize: 500,
+      }
+
+      const loading = this.$loading({
+        lock: true,
+        text: "温度诊断数据加载中,请稍候…",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.8)",
+      })
+
+      const emptyEchartsData = {
+        gearbox_oil: { timestamps: [], values: [] },
+        generator_drive_end: { timestamps: [], values: [] },
+        generator_nondrive_end: { timestamps: [], values: [] },
+        main_bearing: { timestamps: [], values: [] },
+      }
+
+      const trendRequest = () => {
+        const trendStart = performance.now()
+        return axios
+          .post("/WJJdiag/SPRT/trend", temperature)
+          .then((res) => {
+            const trendEnd = performance.now()
+            console.log(
+              `温度诊断 trend 接口耗时: ${(
+                (trendEnd - trendStart) /
+                1000
+              ).toFixed(2)}s`
+            )
+            const echartsdata = res.data.data || {}
+            this.tabData[tab].echartsdata = echartsdata
+          })
+          .catch((err) => {
+            console.error("趋势图请求失败:", err)
+            this.$message.error("温度趋势图数据请求失败,请稍后再试")
+          })
+      }
+
+      const thresholdStart = performance.now()
+      const thresholdReq = axios
+        .post("/WJJdiag/temperature/threshold", temperature)
         .then((res) => {
-          this.monitoringvalue = "";
-          if (res.data.code === 500) {
-            this.monitoringoptions = []; // 清空旧数据
-            this.$message({
-              message: res.data.message || "未知错误",
-              type: "warning",
-            });
-            return;
-          }
+          const thresholdEnd = performance.now()
+          console.log(
+            `温度诊断 threshold 接口耗时: ${(
+              (thresholdEnd - thresholdStart) /
+              1000
+            ).toFixed(2)}s`
+          )
 
-          if (res.data.code === 200) {
-            const datas = Array.isArray(res.data.datas) ? res.data.datas : [];
-            this.monitoringoptions = datas;
-            if (datas.length === 0) {
-              this.$message({
-                message: "暂无数据",
-                type: "warning",
-              });
-            }
+          const data = res.data.data.records || []
+          this.tabData[tab].codedata = data
+          this.tabData[tab].totalCount = res.data.data.totalSize || 0
+
+          if (!data.length) {
+            this.$message.warning("暂无诊断数据")
+            // 清空echartsdata为固定空结构
+            this.tabData[tab].echartsdata = emptyEchartsData
+            return Promise.resolve("skip trend")
           }
+
+          // 有数据时,根据是否分页决定是否请求趋势图
+          return isPageChange ? Promise.resolve() : trendRequest()
         })
         .catch((err) => {
-          console.error("请求失败", err);
-          this.monitoringoptions = []; // 防止报错后保持旧数据
-        });
-    },
-    handlePageChange(page) {
-      this.conditions(page);
-    },
-    conditions(page) {
-      const params = {
-        samplingFrequency: this.frequencyvalue,
-        windCode: this.maplist.codeNumber,
-        windTurbineNumberList: [this.unitvalue],
-        mesureNameList: [this.monitoringvalue],
-        startTime: this.$formatDateTWO(this.timevalue[0]),
-        endTime: this.$formatDateTWO(this.timevalue[1]),
-        pageNo: page,
-        pageSize: 10,
-      };
+          console.error("温度诊断请求失败:", err)
+          this.$message.error("温度诊断数据请求失败,请稍后再试")
+        })
 
-      axios.post(`/ETLapi/waveData/getMesureDataWithSF`, params).then((res) => {
-        this.codedata = res.data.datas;
-        this.totalCount = res.data.totalCount;
-        this.totalPage = res.data.totalPage;
-      });
+      Promise.resolve(thresholdReq).finally(() => {
+        loading.close()
+      })
+    } else {
+        const params = {
+          samplingFrequency: condition.frequencyvalue,
+          windCode: condition.companyCode,
+          windTurbineNumberList: [condition.unitvalue],
+          mesureNameList: [condition.monitoringvalue],
+          startTime: this.$formatDateTWO(condition.timevalue[0]),
+          endTime: this.$formatDateTWO(condition.timevalue[1]),
+          pageNo: page,
+          pageSize: 10,
+        };
+
+        const startTime = performance.now();
+        axios
+          .post("/ETLapi/waveData/getMesureDataWithSF", params)
+          .then((res) => {
+            const endTime = performance.now();
+            console.log(
+              `其他 tab 接口请求耗时: ${(endTime - startTime).toFixed(2)}ms`
+            );
+
+            const data = res.data || {};
+            this.tabData[tab].codedata = data.datas || [];
+            this.tabData[tab].totalCount = data.totalCount || 0;
+            this.tabData[tab].totalPage = data.totalPage || 0;
+          });
+      }
     },
   },
 };
 </script>
-  
+
+
+
   <style lang="scss" scoped>
 .global-variable {
   padding: 10px;
@@ -452,4 +547,16 @@ export default {
 .el-range-editor.el-input__inner {
   width: 370px;
 }
+
+/* 放在你的组件 <style scoped> 或全局样式里 */
+.custom-loading-style .el-loading-spinner i {
+  font-size: 26px;
+  color: #409eff; /* Element UI 主色调,更柔和 */
+}
+
+.custom-loading-style .el-loading-text {
+  font-size: 14px;
+  color: #303133;
+  letter-spacing: 0.5px;
+}
 </style>

+ 1 - 1
src/views/home/Index.vue

@@ -52,7 +52,7 @@ export default {
   data() {
     return {
       loading: false,
-      isShowHd: false, //true 则展示华电的菜单样式,false 则展示默认的左侧边栏菜单
+      isShowHd: true, //true 则展示华电的菜单样式,false 则展示默认的左侧边栏菜单
     };
   },
   methods: {

+ 2 - 2
src/views/home/components/MenuHD.vue

@@ -379,7 +379,7 @@ export default {
 </style>
 
 <!-- /* 华电时的菜单打开这个 */ -->
-<!-- <style lang="scss" >
+<style lang="scss" >
 .el-menu--popup {
   width: 100% !important;
     min-width: 120px !important;
@@ -390,4 +390,4 @@ export default {
     padding: 0 5px !important;
   }
 }
-</style> -->
+</style>

+ 15 - 9
vue.config.js

@@ -66,8 +66,8 @@ module.exports = {
         // target: "http://192.168.5.4:16200", // 石月
         // target: "http://192.168.50.235:16200", // 内网
         // target: "http://192.168.5.15:16200",
-        target: "http://192.168.50.235:16500", //演示环境
-        // target: "http://106.120.102.238:26500", //外网演示环境
+        // target: "http://192.168.50.235:16500", //演示环境
+        target: "http://106.120.102.238:26500", //外网演示环境
         // target: "http://106.120.102.238:16700", // 外网16700  生产16600
         // target: "http://10.96.137.5",
         changeOrigin: true,
@@ -113,17 +113,23 @@ module.exports = {
         },
       },
 
-      // 王娇娇
-      "/WJJapi": {
-        // target: "http://192.168.50.235:8888", // WZLapi 内网 目标地址
-        target: "http://106.120.102.238:18777", // WZLapi/ 内网 目标地址
+      // 王娇娇健康评估
+      "/WJJhealth": {
+        target: "http://106.120.102.238:28999/WJJhealth/api/health", // WZLapi/ 内网 目标地址
         changeOrigin: true,
         pathRewrite: {
-          "^/WJJapi": "", // 去掉 /WZLapi 前缀
+          "^/WJJhealth": "", // 去掉 /WZLapi 前缀
         },
-        onProxyReq(proxyReq, req, res) {
-          console.log("Proxying /sAlgorithm request to:", proxyReq.path); // 打印代理请求路径
+    
+      },
+      // 故障诊断
+      "/WJJdiag": {
+        target: "http://106.120.102.238:28999/WJJdiag", // WZLapi/ 内网 目标地址
+        changeOrigin: true,
+        pathRewrite: {
+          "^/WJJdiag": "", // 去掉 /WZLapi 前缀
         },
+
       },
 
       // 数据转换亮亮