瀏覽代碼

常规上传

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 1 月之前
父節點
當前提交
3cfcfd63c4

+ 25 - 7
src/App.vue

@@ -249,7 +249,7 @@ export default {
           break;
         case 5:
           // this.agcDisplay = true;
-           this.$router.push({
+          this.$router.push({
             path: "/agcDetail",
           });
           break;
@@ -302,25 +302,43 @@ export default {
       this.stateDisplay = false;
       switch (val) {
         case "fault":
-          this.faultDisplay = true;
+          // this.faultDisplay = true;
+          this.$router.push({
+            path: "/fault",
+          });
           break;
         case "warning":
-          this.warningDisplay = true;
+          // this.warningDisplay = true;
+          this.$router.push({
+            path: "/warning",
+          });
           break;
         case "status":
-          this.statusDisplay = true;
+          // this.statusDisplay = true;
+          this.$router.push({
+            path: "/status",
+          });
           break;
         case "action":
-          this.actionDisplay = true;
+          // this.actionDisplay = true;
+          this.$router.push({
+            path: "/action",
+          });
           break;
         case "calendar":
           this.calendarDisplay = true;
           break;
         case "record":
-          this.recordDisplay = true;
+          // this.recordDisplay = true;
+          this.$router.push({
+            path: "/record",
+          });
           break;
         case "changeState":
-          this.stateDisplay = true;
+          // this.stateDisplay = true;
+          this.$router.push({
+            path: "/changeState",
+          });
           break;
         default:
           break;

+ 909 - 0
src/components/action/index.vue

@@ -0,0 +1,909 @@
+<template>
+  <div class="body">
+    <div class="bodyDetial">
+      <!-- <div style="width: 50%;height:200px;background-color:red;"></div>
+      <div style="width: 50%;height:200px;background-color:yellow;"></div> -->
+      <div class="left-item">
+        <el-scrollbar>
+          <el-input placeholder="输入关键字进行过滤" v-model="filterText">
+          </el-input>
+          <el-tree
+            class="filter-tree"
+            :data="showData"
+            :props="defaultProps"
+            :filter-node-method="filterNode"
+            node-key="id"
+            :default-expanded-keys="[0]"
+            ref="tree"
+            @node-click="handleChange"
+          >
+          </el-tree>
+        </el-scrollbar>
+      </div>
+      <div class="right-item">
+        <div class="dateBar">
+          <el-date-picker
+            class="pickers"
+            @change="changes"
+            v-model="timeValue"
+            type="datetimerange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+          >
+          </el-date-picker>
+          <div
+            class="buttons"
+            @click="
+              () => {
+                getControlRecord();
+                getControlStatistics();
+              }
+            "
+          >
+            查询
+          </div>
+        </div>
+        <el-scrollbar style="height: 94%">
+          <div class="tables">
+            <el-table
+              :data="recordData"
+              class="table"
+              style="width: 100%"
+              height="75vh"
+              :header-cell-style="{
+                background: 'rgb(30,30,30)',
+                color: 'rgb(220,220,220)',
+                padding: '4px',
+                fontSize: '14px',
+                'border-bottom': 'solid 1px rgba(77, 77, 77, 1)',
+              }"
+              :cell-style="{
+                height: '40px',
+                background: 'rgb(30,30,30)',
+                color: 'rgb(220,220,220)',
+                padding: '3px',
+                fontSize: '12px',
+                'border-bottom': '1px solid #000000',
+              }"
+              @cell-dblclick="cellDbClick"
+            >
+              <el-table-column
+                prop="time"
+                label="日期"
+                width="120"
+                align="center"
+              >
+              </el-table-column>
+              <el-table-column
+                prop="code"
+                label="风机号"
+                width="120"
+                align="center"
+              >
+              </el-table-column>
+              <el-table-column
+                prop="controls"
+                label="控制命令"
+                width="100"
+                align="center"
+              >
+              </el-table-column>
+              <el-table-column prop="result" label="操作结果" align="center">
+              </el-table-column>
+              <el-table-column
+                prop="userName"
+                label="操作人"
+                width="160"
+                align="center"
+              >
+              </el-table-column>
+              <el-table-column
+                prop="windSpeed"
+                label="风速(m/s)"
+                width="160"
+                align="center"
+              >
+              </el-table-column>
+              <el-table-column
+                prop="statusChanged"
+                label="状态转换"
+                width="160"
+                align="center"
+              >
+              </el-table-column>
+              <el-table-column
+                prop="statusChangeInterval"
+                label="状态转换时间(s)"
+                width="160"
+                align="center"
+              >
+              </el-table-column>
+            </el-table>
+            <div class="titleinfoall" v-if="showControlStatistics">
+              <div class="titleinfo">
+                <span class="showTitle fontSty1">启动:</span>
+                <span class="showvalue">
+                  {{ controlStatisticsInfo.startSuccessCount }}/{{
+                    controlStatisticsInfo.startCount
+                  }}
+                </span>
+                <span class="showTitle fontSty">次</span>
+              </div>
+              <div class="titleinfo">
+                <span class="showTitle fontSty1">停机:</span>
+                <span class="showvalue">
+                  {{ controlStatisticsInfo.stopSuccessCount }}/{{
+                    controlStatisticsInfo.stopCount
+                  }}
+                </span>
+                <span class="showTitle fontSty">次</span>
+              </div>
+              <div class="titleinfo">
+                <span class="showTitle fontSty1">维护:</span>
+                <span class="showvalue">
+                  {{ controlStatisticsInfo.maintenanceSuccessCount }}/{{
+                    controlStatisticsInfo.maintenanceCount
+                  }}
+                </span>
+                <span class="showTitle fontSty">次</span>
+              </div>
+              <div class="titleinfo">
+                <span class="showTitle fontSty1">解除维护:</span>
+                <span class="showvalue">
+                  {{ controlStatisticsInfo.unMaintenanceSuccessCount }}/{{
+                    controlStatisticsInfo.unMaintenanceCount
+                  }}
+                </span>
+                <span class="showTitle fontSty">次</span>
+              </div>
+              <div class="titleinfo">
+                <span class="showTitle fontSty1">多发电量:</span>
+                <span class="showvalue">
+                  {{ controlStatisticsInfo.powerGeneration?.toFixed(2) || 0 }}
+                </span>
+                <span class="showTitle fontSty">kwh</span>
+              </div>
+              <div class="titleinfo">
+                <span class="showTitle fontSty1">节约电量:</span>
+                <span class="showvalue">
+                  {{ controlStatisticsInfo.powerSaving?.toFixed(2) || 0 }}
+                </span>
+                <span class="showTitle fontSty">kwh</span>
+              </div>
+              <div class="titleinfo">
+                <span class="showTitle fontSty1">维护时长:</span>
+                <span class="showvalue">
+                  {{ controlStatisticsInfo.maintenanceTime?.toFixed(2) || 0 }}
+                </span>
+                <span class="showTitle fontSty">分钟</span>
+              </div>
+              <div class="titleinfo">
+                <span class="showTitle fontSty1">提前时间:</span>
+                <span class="showvalue">
+                  {{ controlStatisticsInfo.advanceTime?.toFixed(2) || 0 }}
+                </span>
+                <span class="showTitle fontSty">分钟</span>
+              </div>
+            </div>
+          </div>
+        </el-scrollbar>
+        <div class="paginations">
+          <el-pagination
+            :hide-on-single-page="true"
+            :page-size="currentPage"
+            background
+            layout="prev, pager, next"
+            :total="total"
+            @current-change="handleCurrentChange"
+          />
+        </div>
+      </div>
+    </div>
+  </div>
+  <el-dialog
+    class="dialogs"
+    custom-class="currentBorder"
+    width="70%"
+    top="50px"
+    :show-close="true"
+    append-to-body
+    v-model="showStartDialog"
+  >
+    <div id="chart" style="width: 100%; height: 500px" />
+    <el-card class="otherContentBox" v-if="otherContentInfo.success">
+      <el-descriptions title="控制评分">
+        <el-descriptions-item label="控制时间">{{
+          otherContentInfo.operationRecordTs || "---"
+        }}</el-descriptions-item>
+        <el-descriptions-item label="并网开始时间">{{
+          otherContentInfo.onLineStartTs || "---"
+        }}</el-descriptions-item>
+        <el-descriptions-item label="并网结束时间">{{
+          otherContentInfo.onLineEndTs || "---"
+        }}</el-descriptions-item>
+        <el-descriptions-item label="并网时长">
+          {{ otherContentInfo.onLineDuration || "---" }}
+        </el-descriptions-item>
+        <el-descriptions-item label="并网期间发电量">{{
+          otherContentInfo.onLinePowerGeneration
+        }}</el-descriptions-item>
+        <el-descriptions-item label="单位时间内发电量">{{
+          otherContentInfo.powerGenerationPerHour
+        }}</el-descriptions-item>
+        <el-descriptions-item label="并网期间耗电量">{{
+          otherContentInfo.powerConsumption
+        }}</el-descriptions-item>
+        <!-- <el-descriptions-item label="风能利用百分比">{{
+            otherContentInfo.windUseRate
+          }}</el-descriptions-item> -->
+        <el-descriptions-item label="评分">
+          <el-rate
+            style="display: inline-block"
+            v-model="otherContentInfo.score"
+            allow-half
+            disabled
+          />
+          <span>{{ otherContentInfo.score * 2 }}&nbsp;/&nbsp;10&nbsp;分</span>
+        </el-descriptions-item>
+      </el-descriptions>
+    </el-card>
+    <el-card class="otherContentBox" v-else>
+      <div
+        style="
+          width: 100%;
+          height: 140px;
+          color: #eee;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          font-size: 18px;
+        "
+      >
+        <el-empty class="empSvg" :image-size="100" description="暂无控制评分" />
+      </div>
+    </el-card>
+  </el-dialog>
+</template>
+
+<script>
+import dayjs from "dayjs";
+import api from "api/index";
+import * as echarts from "echarts";
+export default {
+  props: {},
+  updated() {
+    if (this.timeValue.length === 0) {
+      let date = new Date();
+      this.timeValue[0] = date.getTime() - 28800000;
+      this.timeValue[1] = date.getTime() + 3600000;
+    }
+  },
+  mounted() {},
+  data() {
+    return {
+      statname: "",
+      currentPage: 20,
+      filterText: "",
+      pageIndex: 1,
+      station: [],
+      datas: {},
+      chooseStation: {},
+      timeValue: [],
+      showData: [
+        {
+          id: 0,
+          code: "全部",
+          stationId: "",
+          children: [],
+        },
+      ],
+      defaultProps: {
+        children: "children",
+        label: "code",
+      },
+      recordData: [
+        {
+          time: "2025-05-28",
+          code: "#001",
+          controls: "指令1",
+          result: "结果1",
+          userName: "张三",
+          windSpeed: 3.5,
+          statusChanged: "状态1",
+          statusChangeInterval: "10:17:37",
+        },
+        {
+          time: "2025-05-28",
+          code: "#001",
+          controls: "指令1",
+          result: "结果1",
+          userName: "张三",
+          windSpeed: 3.5,
+          statusChanged: "状态1",
+          statusChangeInterval: "10:17:37",
+        },
+        {
+          time: "2025-05-28",
+          code: "#001",
+          controls: "指令1",
+          result: "结果1",
+          userName: "张三",
+          windSpeed: 3.5,
+          statusChanged: "状态1",
+          statusChangeInterval: "10:17:37",
+        },
+        {
+          time: "2025-05-28",
+          code: "#001",
+          controls: "指令1",
+          result: "结果1",
+          userName: "张三",
+          windSpeed: 3.5,
+          statusChanged: "状态1",
+          statusChangeInterval: "10:17:37",
+        },
+        {
+          time: "2025-05-28",
+          code: "#001",
+          controls: "指令1",
+          result: "结果1",
+          userName: "张三",
+          windSpeed: 3.5,
+          statusChanged: "状态1",
+          statusChangeInterval: "10:17:37",
+        },
+      ],
+      total: "",
+      controlErorCodes: [
+        "控制成功",
+        "控制命令发送失败",
+        "无效的控制地址",
+        "被控设备异常",
+        "无效的控制功能",
+        "网络连接错误,检查场站通信",
+        "控制结果读取超时",
+        "未知错误",
+        "控制命令错误",
+        "收到无法识别数据",
+        "未读取到数据包",
+        "未知错误",
+        "风机操作过频繁",
+        "风机被挂牌",
+        "风机操作与风机状态不符",
+        "需要登录",
+      ],
+      showStartDialog: false,
+      rateValue: 4.5,
+      otherContentInfo: {
+        score: 0,
+      },
+      showControlStatistics: false,
+      controlStatisticsInfo: {},
+    };
+  },
+  methods: {
+    // getWindturbineFdc() {
+    //   api.getWindturbineFdc().then((res) => {
+    //     this.station = res.data;
+    //     this.getControlRecord();
+    //   });
+    // },
+    dataDeal() {
+      let stationList = this.$store.state.stationList;
+      this.showData[0].children = [
+        // {
+        //   id : 1,
+        // code : "风机全部",
+        // stationId : "WIND_ALL",
+        // children : [],
+        // }
+      ];
+      stationList.forEach((item, index) => {
+        if (item.type === 1) {
+          let obj = {};
+          obj.id = index + 1;
+          obj.code = item.name;
+          obj.stationId = item.id;
+          obj.children = [];
+          this.showData[0].children.push(obj);
+          // console.log(123,obj.stationId);
+        }
+      });
+      this.datas = this.$store.state.windturbinelist
+        ? this.$store.state.windturbinelist
+        : {};
+      let arr = Object.keys(this.datas).sort();
+      for (let id of arr) {
+        let item = this.datas[id];
+        this.showData[0].children
+          .filter((val) => val.stationId === item.stationId)[0]
+          ?.children.push(item);
+      }
+    },
+    handleChange(value) {
+      // console.log(111,value);
+      this.statname = value.stationId;
+      this.chooseStation = value;
+      this.pageIndex = 1;
+      this.getControlRecord(value);
+      this.getControlStatistics();
+    },
+    closed() {
+      this.pageIndex = 1;
+      this.chooseStation = {};
+      this.showData = [
+        {
+          id: 0,
+          code: "全部",
+          stationId: "",
+          children: [],
+        },
+      ];
+      let stationList = this.$store.state.stationList;
+      stationList.forEach((item, index) => {
+        let obj = {};
+        obj.id = index + 1;
+        obj.code = item.name;
+        obj.stationId = item.id;
+        obj.children = [];
+        this.showData[0].children.push(obj);
+      });
+
+      this.$emit("closed");
+    },
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.code.indexOf(value) !== -1;
+    },
+    handleCurrentChange(val) {
+      this.pageIndex = val;
+      this.getControlRecord();
+    },
+    opened() {
+      let date = new Date();
+      this.timeValue[0] = date.getTime() - 28800000;
+      this.timeValue[1] = date.getTime() + 3600000;
+      this.dataDeal();
+      this.getControlRecord();
+    },
+
+    getControlStatistics() {
+      this.showControlStatistics = false;
+      this.controlStatisticsInfo = {};
+      const stTs = this.timeValue[0];
+      const endTs = this.timeValue[1];
+      const stationId = this.statname;
+      api
+        .getControlStatistics(
+          new Date(stTs).getTime(),
+          new Date(endTs).getTime(),
+          stationId
+        )
+        .then((res) => {
+          this.showControlStatistics = true;
+          // console.log(999,res);
+          this.controlStatisticsInfo = {
+            advanceTime: res.data.advanceTime,
+            maintenanceCount: res.data.maintenanceCount,
+            maintenanceSuccessCount: res.data.maintenanceSuccessCount,
+            powerGeneration: res.data.powerGeneration,
+            powerSaving: res.data.powerSaving,
+            startCount: res.data.startCount,
+            startSuccessCount: res.data.startSuccessCount,
+            stopSuccessCount: res.data.stopSuccessCount,
+            stopCount: res.data.stopCount,
+            unMaintenanceCount: res.data.unMaintenanceCount,
+            unMaintenanceSuccessCount: res.data.unMaintenanceSuccessCount,
+            maintenanceTime: res.data.maintenanceTime,
+          };
+        });
+    },
+    getControlRecord() {
+      api
+        .controlRecord({
+          stationId: this.chooseStation.stationId
+            ? this.chooseStation.stationId
+            : "",
+          userName: "",
+          windturbineId:
+            String(this.chooseStation?.id)?.length < 2
+              ? ""
+              : this.chooseStation.stationId
+              ? this.chooseStation.windturbineId
+              : "",
+          startTime: dayjs(this.timeValue[0]).format("YYYY/MM/DD HH:mm:ss"),
+          endTime: dayjs(this.timeValue[1]).format("YYYY/MM/DD HH:mm:ss"),
+          pageSize: this.currentPage,
+          pageIndex: this.pageIndex,
+        })
+        .then((res) => {
+          console.log(123, res);
+          if (res) {
+            let types = {
+              Start: "启动",
+              Stop: "停止",
+              Reset: "复位",
+              Maintain: "维护",
+              UnMaintain: "取消维护",
+              Lock: "挂牌",
+              UnLock: "取消挂牌",
+            };
+            // console.log(666,res);
+            res.data.dataList.forEach((item) => {
+              item.time = dayjs(item.time).format("MM-DD HH:mm:ss");
+              item.result = this.controlErorCodes[item.errorCode];
+              item.controls = types[item.controlType];
+              item.showName = item.windturbineId;
+              item.windSpeed = item.windSpeed.toFixed(2);
+              if (item.statusChanged == false) {
+                item.statusChanged = "";
+              } else {
+                item.statusChanged = "成功";
+              }
+            });
+            this.total = res.data.total;
+            this.recordData = res.data.dataList;
+            console.log(666, res.data.dataList);
+          }
+        });
+    },
+
+    cellDbClick(row) {
+      const controlType = row.controlType || "";
+      if (controlType === "Start") {
+        this.initEcharts(row.id);
+      }
+    },
+
+    initEcharts(id) {
+      api.getEvaluationData(id).then((res) => {
+        var data = res.data.datas;
+        var statistics = res.data.statistics;
+        var marks = new Array();
+        if (Array.isArray(statistics.mark)) {
+          for (var j = 0; j < statistics.mark.length; ++j) {
+            marks.push({ xAxis: statistics.mark[j] });
+          }
+        }
+
+        var ser = new Array();
+        var isFirst = true;
+        for (var i = 0; i < data.length; ++i) {
+          var s = {
+            data: data[i].values.map((item) => {
+              return item.value;
+            }),
+            type: "line",
+            name: data[i].name,
+            symbol: "none",
+            yAxisIndex: /功率/g.test(data[i].name) ? 1 : 0,
+          };
+          if (isFirst) {
+            s.markLine = {
+              symbol: ["none", "none"],
+              label: { show: false },
+              data: marks,
+            };
+          }
+          ser.push(s);
+          isFirst = false;
+        }
+
+        var option = {
+          tooltip: {
+            trigger: "axis",
+          },
+          legend: {
+            show: true,
+            textStyle: {
+              color: "#eee", //字体颜色
+            },
+            data: data.map((item) => {
+              return item.name;
+            }),
+          },
+          xAxis: {
+            type: "category",
+            data: data[0].values.map((item) => {
+              return new Date(item.ts).toLocaleString();
+            }),
+            axisLabel: {
+              show: true,
+              textStyle: {
+                color: "#eee",
+              },
+            },
+          },
+          yAxis: [
+            {
+              type: "value",
+              name: "风速(m/s)",
+              nameTextStyle: {
+                color: "#fff",
+              },
+              axisLabel: {
+                textStyle: {
+                  color: "#eee",
+                },
+              },
+              splitLine: {
+                lineStyle: {
+                  color: ["#878787"],
+                },
+              },
+            },
+            {
+              type: "value",
+              name: "功率(kw)",
+              nameTextStyle: {
+                color: "#fff",
+              },
+              axisLabel: {
+                textStyle: {
+                  color: "#eee",
+                },
+              },
+              splitLine: {
+                show: false,
+              },
+            },
+          ],
+          dataZoom: [
+            {
+              type: "inside",
+              start: 0,
+              end: 100,
+            },
+          ],
+          series: ser,
+        };
+
+        if (res.data.statistics.success) {
+          this.otherContentInfo = {
+            operationRecordTs: this.formatDate(
+              new Date(res.data.statistics.allTime.operationRecordTs)
+            ),
+            onLineStartTs: this.formatDate(
+              new Date(res.data.statistics.allTime.onlineStartTs)
+            ),
+            onLineEndTs: this.formatDate(
+              new Date(res.data.statistics.allTime.onlineEndTs)
+            ),
+            onLineDuration: `${res.data.statistics.allTime.onLineDuration.toFixed(
+              2
+            )} h`,
+            onLinePowerGeneration: `${res.data.statistics.onLinePowerGeneration.toFixed(
+              2
+            )} kwh`,
+            powerGenerationPerHour: `${res.data.statistics.powerGenerationPerHour.toFixed(
+              2
+            )} kwh`,
+            powerConsumption: `${res.data.statistics.powerConsumption.toFixed(
+              2
+            )} kwh`,
+            windUseRate: `${res.data.statistics.windUseRate.toFixed(2)} %`,
+            score: res.data.statistics.score / 2,
+            success: res.data.statistics.success,
+          };
+        } else {
+          this.otherContentInfo = {};
+        }
+
+        this.showStartDialog = true;
+
+        this.$nextTick(() => {
+          let chartDom = document.getElementById("chart");
+          chartDom.innerHTML = "";
+          chartDom?.removeAttribute("_echarts_instance_");
+          let chart = echarts.init(chartDom, null, { renderer: "svg" });
+          chart.setOption(option);
+        });
+      });
+    },
+
+    formatDate(value) {
+      var date = new Date(value);
+      var y = date.getFullYear(),
+        m = date.getMonth() + 1,
+        d = date.getDate(),
+        h = date.getHours(),
+        i = date.getMinutes(),
+        s = date.getSeconds();
+      if (m < 10) {
+        m = "0" + m;
+      }
+      if (d < 10) {
+        d = "0" + d;
+      }
+      if (h < 10) {
+        h = "0" + h;
+      }
+      if (i < 10) {
+        i = "0" + i;
+      }
+      if (s < 10) {
+        s = "0" + s;
+      }
+      var t = y + "-" + m + "-" + d + " " + h + ":" + i + ":" + s;
+      return t;
+    },
+  },
+  watch: {
+    filterText(val) {
+      this.$refs.tree.filter(val);
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.body {
+  background-color: #000000;
+  height: 90vh;
+  width: 97%;
+  padding-left: 3%;
+  padding-top: 2%;
+}
+.searchTitle {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+.bodyDetial {
+  display: flex;
+  flex-direction: row;
+  margin-left: 3vw;
+  padding-top: 10px;
+  color: #ffffff;
+  height: 98%;
+}
+
+.left-item {
+  width: 20%;
+  height: 100%;
+  background-color: rgba(77, 77, 77, 1);
+  border-right: 2px solid #000000;
+}
+
+.right-item {
+  width: 80%;
+  height: 100%;
+  background-color: rgba(77, 77, 77, 1);
+}
+
+.el-tree {
+  color: #ffffff !important;
+  background-color: rgba(77, 77, 77, 1) !important;
+}
+
+.el-tree-node:focus > .el-tree-node__content {
+  background-color: #000000 !important;
+}
+
+.el-tree-node__content:hover {
+  background-color: #000000 !important;
+}
+
+.dateBar {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: space-between;
+  margin-left: 20px;
+}
+
+.pickers {
+  margin-left: 20px;
+}
+
+.tables {
+  margin-top: 20px;
+  width: 95%;
+  margin-left: 3%;
+  position: relative;
+}
+
+.table {
+  background-color: rgba(77, 77, 77, 1) !important;
+}
+
+.el-table td,
+.el-table th.is-leaf {
+  border-bottom: 1px solid rgba(77, 77, 77, 1) !important;
+}
+
+.el-table__header {
+  width: 100% !important;
+}
+
+.el-table__body-wrapper {
+  background-color: rgba(77, 77, 77, 1) !important;
+}
+
+.el-table::before {
+  width: 0;
+}
+
+tr {
+  line-height: 1.5;
+  background: #1e1e1e;
+  margin-bottom: 2px;
+  border-radius: 5px;
+}
+
+.table-main {
+  font-size: 14px;
+  width: 600px;
+  text-align: center;
+  background: #000000;
+  margin: 5px;
+  border-collapse: separate;
+  border-spacing: 0px 5px;
+}
+
+.paginations {
+  display: flex;
+  flex-direction: row-reverse;
+}
+
+.titleinfoall {
+  display: flex;
+  position: absolute;
+  left: 10px;
+  bottom: 10px;
+}
+
+.showTitle {
+  color: #ffffff;
+  margin-right: 10px;
+}
+.fontSty {
+  font-size: 12px;
+}
+.fontSty1 {
+  font-weight: bold;
+}
+
+.showvalue {
+  color: #ffffff;
+  font-size: 14px;
+  font-weight: bold;
+  margin-right: 10px;
+}
+</style>
+
+<style lang="less">
+.el-dialog.currentBorder {
+  border: 1px solid #eee;
+}
+
+.el-card.otherContentBox {
+  background: rgb(36, 36, 36);
+
+  .el-descriptions__header {
+    color: #fff;
+  }
+
+  .el-descriptions__cell {
+    white-space: nowrap;
+  }
+
+  .el-descriptions__body {
+    color: #eee;
+    background: rgb(36, 36, 36);
+  }
+
+  .empSvg {
+    .el-empty__image {
+      opacity: 0.9;
+    }
+
+    .el-empty__description {
+      p {
+        color: #eee;
+      }
+    }
+  }
+}
+</style>

+ 292 - 0
src/components/changeState/index.vue

@@ -0,0 +1,292 @@
+<template>
+  <div class="body">
+    <div class="searchTitle">
+      <div class="search">
+        <div class="date">风场:</div>
+        <el-select
+          @change="listedChange(selectValue)"
+          class="inputs"
+          v-model="selectValue"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in stationList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search">
+        <div class="date">风机名称:</div>
+        <el-select
+          class="inputs"
+          v-model="selectWind"
+          @change="handleChange"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in windturbinelist"
+            :key="item.id"
+            :label="item.id"
+            :value="item.id"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search">
+        <div class="date">日期:</div>
+        <el-date-picker
+          class="pickers"
+          @change="changes"
+          v-model="timeValue"
+          type="datetimerange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        >
+        </el-date-picker>
+      </div>
+
+      <div class="buttons" @click="getData()">查询</div>
+    </div>
+    <div class="tables">
+      <el-table
+        :data="stateList"
+        class="table"
+        style="width: 100%"
+        height="75vh"
+        :header-cell-style="{
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '4px',
+          fontSize: '14px',
+          'border-bottom': 'solid 1px rgba(77, 77, 77, 1)',
+        }"
+        :cell-style="{
+          height: '40px',
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '3px',
+          fontSize: '12px',
+          'border-bottom': '1px solid #000000',
+        }"
+      >
+        <el-table-column prop="ts" label="动作时间" align="center">
+        </el-table-column>
+        <el-table-column prop="code" label="风机名称" align="center">
+        </el-table-column>
+        <el-table-column prop="status" label="动作编号" align="center">
+        </el-table-column>
+        <el-table-column prop="statusName" label="动作信息" align="center">
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="paginations">
+      <el-pagination
+        :hide-on-single-page="true"
+        :page-size="1"
+        background
+        layout="prev, pager, next"
+        :total="total"
+        @current-change="handleCurrentChange"
+      >
+      </el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+import api from "api/index";
+import dayjs from "dayjs";
+export default {
+  components: {},
+  data() {
+    return {
+      timeValue: [],
+      selectValue: "",
+      stationList: [],
+      selectWind: "",
+      windturbinelist: [],
+      pagesize: 20,
+      pagenum: 1,
+      total: 20,
+      stateList: [
+        {
+          ts: "2025-05-28 10:34:22",
+          code: "#01",
+          status: "00001",
+          statusName: "动作描述",
+        },
+        {
+          ts: "2025-05-28 10:34:22",
+          code: "#01",
+          status: "00001",
+          statusName: "动作描述",
+        },
+        {
+          ts: "2025-05-28 10:34:22",
+          code: "#01",
+          status: "00001",
+          statusName: "动作描述",
+        },
+        {
+          ts: "2025-05-28 10:34:22",
+          code: "#01",
+          status: "00001",
+          statusName: "动作描述",
+        },
+        {
+          ts: "2025-05-28 10:34:22",
+          code: "#01",
+          status: "00001",
+          statusName: "动作描述",
+        },
+      ],
+    };
+  },
+  created() {},
+  mounted() {},
+  methods: {
+    opened() {
+      // let date = new Date();
+      this.timeValue[0] =
+        new Date(new Date().toLocaleDateString()).getTime() - 86400000;
+      this.timeValue[1] = new Date(new Date().toLocaleDateString()).getTime();
+      //   let stationList = this.$store.state.stationList;
+      let stationArr = [];
+      this.$store.state.stationList.forEach((item) => {
+        if (item.name.indexOf("全部") === -1) {
+          stationArr.push(item);
+        }
+      });
+      let stationList = stationArr;
+      this.selectValue = stationList[0].id;
+      this.stationList = stationList;
+      this.listedChange(this.selectValue);
+      this.getData();
+    },
+    closed() {
+      this.pagenum = 1;
+    },
+    listedChange(value) {
+      this.windturbinelist = [];
+      let windturbinelist = this.$store.state.windturbinelist;
+      let arr = Object.keys(windturbinelist).sort();
+      let windturbine = [];
+      for (const key of arr) {
+        let wind = windturbinelist[key];
+        if (wind.stationId === value) {
+          windturbine.push(wind);
+        }
+      }
+      this.selectWind = windturbine[0]?.id || "";
+      this.windturbineId = windturbine[0]?.windturbineId;
+      this.windturbinelist = windturbine;
+    },
+    getData() {
+      api
+        .statusChange({
+          pagesize: this.pagesize,
+          pagenum: this.pagenum,
+          startTs: new Date(this.timeValue[0]).getTime(),
+          endTs: new Date(this.timeValue[1]).getTime(),
+          windturbineid: this.selectWind,
+        })
+        .then((res) => {
+          if (res.data) {
+            this.total = Number(res.data.totalPages);
+            res.data.content.forEach((item) => {
+              item.recommendedDate = dayjs(item.ts).format(
+                "YYYY-MM-DD HH:mm:ss"
+              );
+            });
+            this.stateList = res.data.content;
+          }
+        });
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.body {
+  display: flex;
+  flex-direction: column;
+  background-color: #000000;
+  height: 90vh;
+  width: 97%;
+  padding-left: 3%;
+  padding-top: 2%;
+  overflow-y: auto;
+}
+
+.body::-webkit-scrollbar {
+  /*隐藏滚轮*/
+  display: none;
+}
+.searchTitle {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-left: 3vw;
+  padding-top: 10px;
+  color: #ffffff;
+}
+
+.search {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-right: 50px;
+}
+
+.date {
+  margin-right: 10px;
+  font-size: 16px;
+}
+
+.tables {
+  margin-left: 3vw;
+  padding-top: 10px;
+}
+
+.lable {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  flex-wrap: wrap;
+  width: 100%;
+  margin-left: 75px;
+  padding-top: 10px;
+}
+
+.lable-item {
+  font-size: 16px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  width: 16%;
+  color: #ffffff;
+  margin-bottom: 10px;
+}
+
+.el-table {
+  position: static;
+  background-color: #141414;
+}
+
+.inputs {
+  border: none;
+  width: 174px !important;
+  background-color: #292929;
+  height: 40px;
+  color: #ffffff;
+}
+
+.paginations {
+  display: flex;
+  flex-direction: row-reverse;
+}
+</style>
+  

+ 413 - 0
src/components/fault/index.vue

@@ -0,0 +1,413 @@
+<template>
+  <div class="body">
+    <div class="searchTitle">
+      <div class="search">
+        <div class="date">风场:</div>
+        <el-select
+          @change="listedChange(selectValue)"
+          class="inputs"
+          v-model="selectValue"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in stationList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search">
+        <div class="date">日期:</div>
+        <el-date-picker
+          class="pickers"
+          @change="changes"
+          v-model="timeValue"
+          type="datetimerange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        >
+        </el-date-picker>
+      </div>
+      <div class="search">
+        <div class="date">风机名称:</div>
+        <el-select
+          class="inputs"
+          v-model="selectWind"
+          @change="handleChange"
+          placeholder="请选择"
+          clearable
+        >
+          <el-option
+            v-for="item in windturbinelist"
+            :key="item.code"
+            :label="item.code"
+            :value="item.code"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search">
+        <div class="date">关键字:</div>
+        <el-input
+          class="inputs"
+          placeholder="请输入"
+          v-model="inputVlaues"
+        ></el-input>
+      </div>
+
+      <div class="buttons" @click="getWarning()">查询</div>
+    </div>
+    <!-- <div class="lable">
+        <div class="lable-item" v-for="(item, index) in lableList" :key="index">
+          <div>{{item.name}}:</div>
+          <div style="margin-left: 10px;color:red;">{{item.value}}</div>
+        </div>
+      </div> -->
+    <div class="tables">
+      <el-table
+        :data="warningList"
+        class="table"
+        style="width: 100%"
+        height="75vh"
+        :header-cell-style="{
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '4px',
+          fontSize: '14px',
+          'border-bottom': 'solid 1px rgba(77, 77, 77, 1)',
+        }"
+        :cell-style="{
+          height: '40px',
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '3px',
+          fontSize: '12px',
+          'border-bottom': '1px solid #000000',
+        }"
+      >
+        <el-table-column
+          prop="alertTime"
+          label="发生时间"
+          width="150"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="stationName"
+          label="风场名称"
+          width="120"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="windturbineName"
+          label="风机名称"
+          width="120"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="rank"
+          label="报警等级"
+          width="100"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column label="状态" width="120" align="center">
+          <template #default="scope">
+            <span>
+              {{ scope.row.messageType === 1 ? "触发" : "已解除" }}
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          prop="snapId"
+          label="故障编号"
+          width="240"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column prop="alertText" label="故障信息" align="center">
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="paginations">
+      <el-pagination
+        :hide-on-single-page="true"
+        :page-size="currentPage"
+        background
+        layout="prev, pager, next"
+        :total="total"
+        @current-change="handleCurrentChange"
+      >
+      </el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+import dayjs from "dayjs";
+import api from "api/index";
+export default {
+  data() {
+    return {
+      current: 0,
+      pagenum: 1,
+      total: "",
+      timeValue: [],
+      selectValue: "",
+      inputVlaues: "",
+      stationList: [],
+      selectWind: "",
+      windturbineId: "",
+      windturbinelist: [],
+      warningList: [
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+      ],
+      currentPage: 20,
+      lableList: [
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+      ],
+    };
+  },
+  methods: {
+    ChangeBar(values) {
+      this.current = values;
+    },
+    opened() {
+      let date = new Date();
+      this.timeValue[0] =
+        new Date(new Date().toLocaleDateString()).getTime() - 86400000;
+      this.timeValue[1] = new Date(new Date().toLocaleDateString()).getTime();
+      let stationArr = [
+        {
+          name: "全部",
+          id: "",
+        },
+      ];
+      this.$store.state.stationList.forEach((item) => {
+        if (item.name.indexOf("全部") === -1) {
+          stationArr.push(item);
+        }
+      });
+      let stationList = stationArr;
+      this.selectValue = stationList[1].id;
+      this.stationList = stationList;
+      this.listedChange(this.selectValue);
+      this.getWarning();
+    },
+    closed() {
+      this.pagenum = 1;
+    },
+    getWarning() {
+      api
+        .getWindturbineWarning({
+          pagesize: this.currentPage,
+          pagenum: this.pagenum,
+          stationid: this.selectValue === "WIND_ALL" ? "" : this.selectValue,
+          windturbineid: this.windturbineId,
+          starttime: dayjs(this.timeValue[0]).format("YYYY-MM-DD HH:mm:ss"),
+          endtime: dayjs(this.timeValue[1]).format("YYYY-MM-DD HH:mm:ss"),
+          keyword: this.inputVlaues,
+          category1: "windturbine,SYZ,GF",
+        })
+        .then((msg) => {
+          if (msg.data) {
+            this.total = msg.data.total;
+            msg.data.records.forEach((item) => {
+              item.alertTime = dayjs(item.alertTime).format("MM-DD HH:mm:ss");
+            });
+            this.warningList = msg.data.records;
+          }
+        });
+    },
+    handleCurrentChange(val) {
+      this.pagenum = val;
+      this.getWarning();
+    },
+    listedChange(value) {
+      this.windturbinelist = [];
+      let windturbinelist = this.$store.state.windturbinelist;
+      let arr = Object.keys(windturbinelist).sort();
+      let windturbine = [];
+      for (const key of arr) {
+        let wind = windturbinelist[key];
+        if (wind.stationId === value) {
+          windturbine.push(wind);
+        }
+      }
+      // this.selectWind = windturbine[0]?.code || "";
+      // this.windturbineId = windturbine[0]?.windturbineId
+      this.windturbinelist = windturbine;
+    },
+    handleChange(val) {
+      if (val) {
+        this.windturbineId = this.windturbinelist.filter(
+          (item) => item.code === val
+        )[0].windturbineId;
+      } else {
+        this.windturbineId = "";
+      }
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.body {
+  background-color: #000000;
+  height: 89vh;
+  width: 97%;
+  padding-left: 3%;
+  padding-top: 2%;
+}
+.searchTitle {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-left: 3vw;
+  padding-top: 10px;
+  color: #ffffff;
+}
+.search {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-right: 50px;
+}
+.date {
+  margin-right: 10px;
+  font-size: 16px;
+  white-space: nowrap;
+}
+.tables {
+  margin-left: 3vw;
+  padding-top: 10px;
+}
+.lable {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  flex-wrap: wrap;
+  width: 100%;
+  margin-left: 75px;
+  padding-top: 10px;
+}
+.lable-item {
+  font-size: 16px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  width: 16%;
+  color: #ffffff;
+  margin-bottom: 10px;
+}
+.el-table {
+  position: static;
+  background-color: #141414;
+}
+.inputs {
+  border: none;
+  width: 174px !important;
+  background-color: #292929;
+  height: 40px;
+  color: #ffffff;
+}
+.paginations {
+  display: flex;
+  flex-direction: row-reverse;
+}
+</style>

+ 373 - 0
src/components/record/index.vue

@@ -0,0 +1,373 @@
+<template>
+  <div class="body">
+    <div class="searchTitle">
+      <div class="search">
+        <div class="date">风场:</div>
+        <el-select
+          @change="listedChange(selectValue)"
+          class="inputs"
+          v-model="selectValue"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in stationList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search">
+        <div class="date">风机名称:</div>
+        <el-select
+          class="inputs"
+          v-model="selectWind"
+          @change="handleChange"
+          placeholder="请选择"
+          clearable
+        >
+          <el-option
+            v-for="item in windturbinelist"
+            :key="item.id"
+            :label="item.id"
+            :value="item.id"
+          >
+          </el-option>
+        </el-select>
+      </div>
+
+      <div class="buttons" @click="getData()">查询</div>
+    </div>
+    <div class="tables">
+      <el-table
+        :data="recordList"
+        class="table"
+        style="width: 100%"
+        height="75vh"
+        :header-cell-style="{
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '4px',
+          fontSize: '14px',
+          'border-bottom': 'solid 1px rgba(77, 77, 77, 1)',
+        }"
+        :cell-style="{
+          height: '40px',
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '3px',
+          fontSize: '12px',
+          'border-bottom': '1px solid #000000',
+        }"
+      >
+        <el-table-column
+          prop="recommendedDate"
+          label="推荐时间"
+          width="150"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column prop="stationId" label="场站" align="center">
+        </el-table-column>
+        <el-table-column prop="windturbineId" label="风机" align="center">
+        </el-table-column>
+        <el-table-column prop="windSpeed" label="推荐时风速" align="center">
+        </el-table-column>
+        <el-table-column
+          prop="averageWindSpeed5"
+          label="推荐时五分钟平均风速"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column label="推荐操作" align="center">
+          <template #default="scope">
+            <span>
+              {{ controlType[scope.row?.controlType] }}
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          prop="rollSpeed"
+          label="推荐时发电机转速"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column prop="power" label="推荐时功率" align="center">
+        </el-table-column>
+        <el-table-column
+          prop="theoreticalPower"
+          label="推荐时理论功率"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="healthIndex"
+          label="推荐时健康指数"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column prop="cause" label="推荐原因" align="center">
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="paginations">
+      <el-pagination
+        :hide-on-single-page="true"
+        :page-size="1"
+        background
+        layout="prev, pager, next"
+        :total="total"
+        @current-change="handleCurrentChange"
+      >
+      </el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+import api from "api/index";
+import dayjs from "dayjs";
+export default {
+  components: {},
+  data() {
+    return {
+      selectValue: "",
+      stationList: [],
+      selectWind: "",
+      windturbinelist: [],
+      pagesize: 20,
+      pagenum: 1,
+      total: "",
+      recordList: [
+        {
+          recommendedDate: "2025-05-28 10:26:45",
+          stationId: "XX场站",
+          windturbineId: "#01",
+          windSpeed: 3.5,
+          averageWindSpeed5: 3.5,
+          controlType: "Start",
+          rollSpeed: 1000,
+          power: 1000,
+          theoreticalPower: 1000,
+          healthIndex: 100,
+          cause: "强的不行",
+        },
+        {
+          recommendedDate: "2025-05-28 10:26:45",
+          stationId: "XX场站",
+          windturbineId: "#01",
+          windSpeed: 3.5,
+          averageWindSpeed5: 3.5,
+          controlType: "Start",
+          rollSpeed: 1000,
+          power: 1000,
+          theoreticalPower: 1000,
+          healthIndex: 100,
+          cause: "强的不行",
+        },
+        {
+          recommendedDate: "2025-05-28 10:26:45",
+          stationId: "XX场站",
+          windturbineId: "#01",
+          windSpeed: 3.5,
+          averageWindSpeed5: 3.5,
+          controlType: "Start",
+          rollSpeed: 1000,
+          power: 1000,
+          theoreticalPower: 1000,
+          healthIndex: 100,
+          cause: "强的不行",
+        },
+        {
+          recommendedDate: "2025-05-28 10:26:45",
+          stationId: "XX场站",
+          windturbineId: "#01",
+          windSpeed: 3.5,
+          averageWindSpeed5: 3.5,
+          controlType: "Start",
+          rollSpeed: 1000,
+          power: 1000,
+          theoreticalPower: 1000,
+          healthIndex: 100,
+          cause: "强的不行",
+        },
+        {
+          recommendedDate: "2025-05-28 10:26:45",
+          stationId: "XX场站",
+          windturbineId: "#01",
+          windSpeed: 3.5,
+          averageWindSpeed5: 3.5,
+          controlType: "Start",
+          rollSpeed: 1000,
+          power: 1000,
+          theoreticalPower: 1000,
+          healthIndex: 100,
+          cause: "强的不行",
+        },
+      ],
+      controlType: {
+        Nothing: "不推荐 ",
+        Start: "推荐启动 ",
+        Stop: "推荐停机",
+        Maintain: "推荐维护",
+        UnMaintain: "取消维护",
+        Lock: "挂牌",
+        UnLock: "取消挂牌 ",
+      },
+    };
+  },
+  created() {},
+  mounted() {},
+  methods: {
+    opened() {
+      //   let stationList = this.$store.state.stationList;
+      let stationArr = [
+        {
+          name: "全部",
+          id: "",
+        },
+      ];
+      this.$store.state.stationList.forEach((item) => {
+        if (item.name.indexOf("全部") === -1) {
+          stationArr.push(item);
+        }
+      });
+      let stationList = stationArr;
+      this.selectValue = stationList[0].id;
+      this.stationList = stationList;
+      this.listedChange(this.selectValue);
+      this.getData();
+    },
+    closed() {
+      this.pagenum = 1;
+    },
+    listedChange(value) {
+      this.windturbinelist = [];
+      let windturbinelist = this.$store.state.windturbinelist;
+      let arr = Object.keys(windturbinelist).sort();
+      let windturbine = [];
+      for (const key of arr) {
+        let wind = windturbinelist[key];
+        if (wind.stationId === value) {
+          windturbine.push(wind);
+        }
+      }
+      this.selectWind = windturbine[0]?.id || "";
+      this.windturbineId = windturbine[0]?.windturbineId;
+      this.windturbinelist = windturbine;
+    },
+    getData() {
+      api
+        .recommended({
+          pagesize: this.pagesize,
+          pagenum: this.pagenum,
+          stationid: this.selectValue === "WIND_ALL" ? "" : this.selectValue,
+          windturbineid: this.selectWind,
+        })
+        .then((res) => {
+          if (res.data) {
+            this.total = Number(res.data.totalPages);
+            res.data.content.forEach((item) => {
+              item.recommendedDate = dayjs(item.recommendedDate).format(
+                "YYYY-MM-DD HH:mm:ss"
+              );
+              item.power = item.power.toFixed(2);
+              item.rollSpeed = item.rollSpeed.toFixed(2);
+              item.theoreticalPower = item.theoreticalPower.toFixed(2);
+              item.windSpeed = item.windSpeed.toFixed(2);
+              item.averageWindSpeed5 = item.averageWindSpeed5.toFixed(2);
+            });
+            this.recordList = res.data.content;
+          }
+        });
+    },
+    handleCurrentChange(val) {
+      this.pagenum = val;
+      this.getData();
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.body {
+  display: flex;
+  flex-direction: column;
+  background-color: #000000;
+  height: 90vh;
+  width: 97%;
+  padding-left: 3%;
+  padding-top: 2%;
+  overflow-y: auto;
+}
+
+.body::-webkit-scrollbar {
+  /*隐藏滚轮*/
+  display: none;
+}
+
+.searchTitle {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-left: 3vw;
+  padding-top: 10px;
+  color: #ffffff;
+}
+
+.search {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-right: 50px;
+}
+
+.date {
+  margin-right: 10px;
+  font-size: 16px;
+}
+
+.tables {
+  margin-left: 3vw;
+  padding-top: 10px;
+}
+
+.lable {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  flex-wrap: wrap;
+  width: 100%;
+  margin-left: 75px;
+  padding-top: 10px;
+}
+
+.lable-item {
+  font-size: 16px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  width: 16%;
+  color: #ffffff;
+  margin-bottom: 10px;
+}
+
+.el-table {
+  position: static;
+  background-color: #141414;
+}
+
+.inputs {
+  border: none;
+  width: 174px !important;
+  background-color: #292929;
+  height: 40px;
+  color: #ffffff;
+}
+
+.paginations {
+  display: flex;
+  flex-direction: row-reverse;
+}
+</style>
+  

+ 261 - 0
src/components/status/index.vue

@@ -0,0 +1,261 @@
+<template>
+  <div class="body">
+    <div class="searchTitle">
+      <div class="search">
+        <div class="date">风场:</div>
+        <el-select class="inputs" v-model="selectValue" placeholder="请选择">
+          <el-option
+            v-for="item in stationList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search">
+        <div class="date">日期:</div>
+        <el-date-picker
+          class="pickers"
+          @change="changes"
+          v-model="timeValue"
+          type="datetimerange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        >
+        </el-date-picker>
+      </div>
+      <div class="buttons" @click="getData()">查询</div>
+    </div>
+    <div class="tables">
+      <el-table
+        :data="StatusList"
+        class="table"
+        style="width: 100%"
+        height="75vh"
+        :header-cell-style="{
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '4px',
+          fontSize: '14px',
+          'border-bottom': 'solid 1px rgba(77, 77, 77, 1)',
+        }"
+        :cell-style="{
+          height: '40px',
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '3px',
+          fontSize: '12px',
+          'border-bottom': '1px solid #000000',
+        }"
+      >
+        <el-table-column
+          prop="code"
+          label="风机名称"
+          width="150"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="averageWindSpeedDay"
+          label="平均风速(m/s)"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="actualpowerday"
+          label="发电量(Kwh)"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column prop="powerfactor" label="功率因数" align="center">
+        </el-table-column>
+        <el-table-column
+          prop="onlinehours"
+          label="并网运行时间(H)"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="maintainhours"
+          label="风机维护时间(H)"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="faulthours"
+          label="风机故障时间(H)"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="standbyhours"
+          label="待机时间(H)"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="offlinehours"
+          label="离线时间(H)"
+          align="center"
+        >
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import api from "api/index";
+export default {
+  data() {
+    return {
+      timeValue: [],
+      stationList: [],
+      selectValue: "",
+      StatusList: [
+        {
+          code: "#01",
+          averageWindSpeedDay: 3.5,
+          actualpowerday: 1000,
+          powerfactor: 0,
+          onlinehours: 10,
+          maintainhours: 10,
+          faulthours: 10,
+          standbyhours: 10,
+          offlinehours: 10,
+        },
+        {
+          code: "#01",
+          averageWindSpeedDay: 3.5,
+          actualpowerday: 1000,
+          powerfactor: 0,
+          onlinehours: 10,
+          maintainhours: 10,
+          faulthours: 10,
+          standbyhours: 10,
+          offlinehours: 10,
+        },
+        {
+          code: "#01",
+          averageWindSpeedDay: 3.5,
+          actualpowerday: 1000,
+          powerfactor: 0,
+          onlinehours: 10,
+          maintainhours: 10,
+          faulthours: 10,
+          standbyhours: 10,
+          offlinehours: 10,
+        },
+        {
+          code: "#01",
+          averageWindSpeedDay: 3.5,
+          actualpowerday: 1000,
+          powerfactor: 0,
+          onlinehours: 10,
+          maintainhours: 10,
+          faulthours: 10,
+          standbyhours: 10,
+          offlinehours: 10,
+        },
+        {
+          code: "#01",
+          averageWindSpeedDay: 3.5,
+          actualpowerday: 1000,
+          powerfactor: 0,
+          onlinehours: 10,
+          maintainhours: 10,
+          faulthours: 10,
+          standbyhours: 10,
+          offlinehours: 10,
+        },
+      ],
+    };
+  },
+  methods: {
+    opened() {
+      let date = new Date();
+      this.timeValue[0] =
+        new Date(new Date().toLocaleDateString()).getTime() - 86400000;
+      this.timeValue[1] = new Date(new Date().toLocaleDateString()).getTime();
+      //   let stationList = this.$store.state.stationList;
+      let stationArr = [
+        {
+          name: "全部",
+          id: "",
+        },
+      ];
+      this.$store.state.stationList.forEach((item) => {
+        if (item.name.indexOf("全部") === -1) {
+          stationArr.push(item);
+        }
+      });
+      let stationList = stationArr;
+      this.selectValue = stationList[0].id;
+      this.stationList = stationList;
+      this.getData();
+    },
+    getData() {
+      api
+        .statusTime({
+          stationid: this.selectValue === "WIND_ALL" ? "" : this.selectValue,
+          startTs: this.timeValue[0],
+          endTs: this.timeValue[1],
+        })
+        .then((res) => {
+          res.data.forEach((item) => {
+            for (const key in item) {
+              if (typeof item[key] === "number") {
+                item[key] = item[key].toFixed(2);
+              }
+            }
+          });
+          this.StatusList = res.data;
+        });
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.body {
+  background-color: #000000;
+  height: 90vh;
+  width: 97%;
+  padding-left: 3%;
+  padding-top: 2%;
+}
+.searchTitle {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-left: 3vw;
+  padding-top: 10px;
+  color: #ffffff;
+}
+.search {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-right: 50px;
+}
+.date {
+  margin-right: 10px;
+  font-size: 16px;
+}
+.tables {
+  margin-left: 3vw;
+  padding-top: 10px;
+}
+.el-table {
+  position: static;
+  background-color: #141414;
+}
+.inputs {
+  border: none;
+  width: 174px !important;
+  background-color: #292929;
+  height: 40px;
+  color: #ffffff;
+}
+</style>

+ 390 - 0
src/components/warningNotDia/index.vue

@@ -0,0 +1,390 @@
+<template>
+  <div class="body">
+    <div class="searchTitle">
+      <div class="search">
+        <div class="date">风场:</div>
+        <el-select
+          @change="listedChange(selectValue)"
+          class="inputs"
+          v-model="selectValue"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in stationList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search">
+        <div class="date">日期:</div>
+        <el-date-picker
+          class="pickers"
+          @change="changes"
+          v-model="timeValue"
+          type="datetimerange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        >
+        </el-date-picker>
+      </div>
+      <div class="search">
+        <div class="date">关键字:</div>
+        <el-input
+          class="inputs"
+          placeholder="请输入"
+          v-model="inputVlaues"
+        ></el-input>
+      </div>
+
+      <div class="buttons" @click="getWarning()">查询</div>
+    </div>
+    <!-- <div class="lable">
+        <div class="lable-item" v-for="(item, index) in lableList" :key="index">
+          <div>{{item.name}}:</div>
+          <div style="margin-left: 10px;color:red;">{{item.value}}</div>
+        </div>
+      </div> -->
+    <div class="tables">
+      <el-table
+        stripe="true"
+        :data="warningList"
+        class="table"
+        style="width: 100%"
+        height="75vh"
+        :header-cell-style="{
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '4px',
+          fontSize: '14px',
+          'border-bottom': 'solid 1px rgba(77, 77, 77, 1)',
+        }"
+        :cell-style="{
+          height: '40px',
+          background: 'rgb(30,30,30)',
+          color: 'rgb(220,220,220)',
+          padding: '3px',
+          fontSize: '12px',
+          'border-bottom': '1px solid #000000',
+        }"
+      >
+        <el-table-column
+          prop="alertTime"
+          label="发生时间"
+          width="150"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="stationName"
+          label="风场名称"
+          width="120"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="windturbineName"
+          label="风机名称"
+          width="120"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="rank"
+          label="报警等级"
+          width="100"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column label="状态" width="120" align="center">
+          <template #default="scope">
+            <span>
+              {{ scope.row.messageType === 1 ? "触发" : "已解除" }}
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          prop="snapId"
+          label="故障编号"
+          width="240"
+          align="center"
+        >
+        </el-table-column>
+        <el-table-column prop="alertText" label="故障信息" align="center">
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="paginations">
+      <el-pagination
+        :hide-on-single-page="true"
+        :page-size="currentPage"
+        background
+        layout="prev, pager, next"
+        :total="total"
+        @current-change="handleCurrentChange"
+      >
+      </el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+import dayjs from "dayjs";
+import api from "api/index";
+export default {
+  data() {
+    return {
+      current: 0,
+      pagenum: 1,
+      total: "",
+      timeValue: [],
+      selectValue: "",
+      inputVlaues: "",
+      stationList: [],
+      windturbineId: "",
+      windturbinelist: [],
+      warningList: [
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+        {
+          alertTime: "2025-05-28 09:55:55",
+          stationName: "XX场站",
+          windturbineName: "***风机",
+          rank: "1",
+          messageType: "1",
+          snapId: "00000001",
+          alertText: "设备发生故障",
+        },
+      ],
+      currentPage: 20,
+      lableList: [
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+        {
+          name: "偏航系统故障",
+          value: "6996",
+        },
+      ],
+    };
+  },
+  methods: {
+    ChangeBar(values) {
+      this.current = values;
+    },
+    opened() {
+      let date = new Date();
+      this.timeValue[0] =
+        new Date(new Date().toLocaleDateString()).getTime() - 86400000;
+      this.timeValue[1] = new Date(new Date().toLocaleDateString()).getTime();
+      //   let stationList = this.$store.state.stationList;
+      let stationArr = [
+        {
+          name: "全部",
+          id: "",
+        },
+      ];
+      this.$store.state.stationList.forEach((item) => {
+        if (item.name.indexOf("全部") === -1) {
+          stationArr.push(item);
+        }
+      });
+      let stationList = stationArr;
+      this.selectValue = stationList[1].id;
+      this.stationList = stationList;
+      this.listedChange(this.selectValue);
+      this.getWarning();
+    },
+    closed() {
+      this.pagenum = 1;
+    },
+    getWarning() {
+      api
+        .getWindturbineWarning({
+          pagesize: this.currentPage,
+          pagenum: this.pagenum,
+          stationid: this.selectValue === "WIND_ALL" ? "" : this.selectValue,
+          windturbineid: "",
+          starttime: dayjs(this.timeValue[0]).format("YYYY-MM-DD HH:mm:ss"),
+          endtime: dayjs(this.timeValue[1]).format("YYYY-MM-DD HH:mm:ss"),
+          keyword: this.inputVlaues,
+          category1: "custom",
+        })
+        .then((msg) => {
+          if (msg.data) {
+            this.total = msg.data.total;
+            msg.data.records.forEach((item) => {
+              item.alertTime = dayjs(item.alertTime).format("MM-DD HH:mm:ss");
+            });
+            this.warningList = msg.data.records;
+          }
+        });
+    },
+    handleCurrentChange(val) {
+      this.pagenum = val;
+      this.getWarning();
+    },
+    listedChange(value) {
+      this.windturbinelist = [];
+      let windturbinelist = this.$store.state.windturbinelist;
+      let arr = Object.keys(windturbinelist).sort();
+      let windturbine = [];
+      for (const key of arr) {
+        let wind = windturbinelist[key];
+        if (wind.stationId === value) {
+          windturbine.push(wind);
+        }
+      }
+      this.windturbineId = windturbine[0]?.windturbineId;
+      this.windturbinelist = windturbine;
+    },
+    handleChange(val) {
+      this.windturbineId = this.windturbinelist.filter(
+        (item) => item.code === val
+      )[0].windturbineId;
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.body {
+  background-color: #000000;
+  height: 89vh;
+  width: 97%;
+  padding-left: 3%;
+  padding-top: 2%;
+}
+.searchTitle {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-left: 3vw;
+  padding-top: 10px;
+  color: #ffffff;
+}
+.search {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-right: 50px;
+}
+.date {
+  margin-right: 10px;
+  font-size: 16px;
+}
+.tables {
+  margin-left: 3vw;
+  padding-top: 10px;
+}
+.lable {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  flex-wrap: wrap;
+  width: 100%;
+  margin-left: 75px;
+  padding-top: 10px;
+}
+.lable-item {
+  font-size: 16px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  width: 16%;
+  color: #ffffff;
+  margin-bottom: 10px;
+}
+.el-table {
+  position: static;
+  background-color: #141414;
+}
+.inputs {
+  border: none;
+  width: 174px !important;
+  background-color: #292929;
+  height: 40px;
+  color: #ffffff;
+}
+.paginations {
+  display: flex;
+  flex-direction: row-reverse;
+}
+</style>

+ 30 - 0
src/router/index.js

@@ -28,6 +28,36 @@ const routes = [
         component: () => import('components/focus/syzDetailsNoDia.vue')
     },
     {
+        path: '/fault',
+        name: 'fault',
+        component: () => import('components/fault/index.vue')
+    },
+    {
+        path: '/warning',
+        name: 'warning',
+        component: () => import('components/warningNotDia/index.vue')
+    },
+    {
+        path: '/status',
+        name: 'status',
+        component: () => import('components/status/index.vue')
+    },
+    {
+        path: '/action',
+        name: 'action',
+        component: () => import('components/action/index.vue')
+    },
+    {
+        path: '/record',
+        name: 'record',
+        component: () => import('components/record/index.vue')
+    },
+    {
+        path: '/changeState',
+        name: 'changeState',
+        component: () => import('components/changeState/index.vue')
+    },
+    {
         path: '/ManualPage',
         name: 'ManualPage',
         component: () => import('views/ManualPage.vue')