Browse Source

增加报警查询和预警查询页面

baiyanting 1 năm trước cách đây
mục cha
commit
62fe4b59ff

+ 24 - 2
src/router/index.js

@@ -565,12 +565,34 @@ export const asyncRoutes = [
         },
         children: [
           {
-            path: "realwarning", // 基础矩阵
+            path: "realwarning", // 综合报警
             name: "realwarning",
             component: () => import("@/views/IntegratedAlarm/safe/realWarning"),
             meta: {
               title: "综合报警",
-              icon: "svg-matrix",
+              icon: "",
+              permissions: ["jn_jcjz"],
+            },
+          },
+          {
+            path: "historyWarning", // 报警查询
+            name: "historyWarning",
+            component: () =>
+              import("@/views/IntegratedAlarm/safe/historyWarning"),
+            meta: {
+              title: "报警查询",
+              icon: "",
+              permissions: ["jn_jcjz"],
+            },
+          },
+          {
+            path: "customWarning", // 预警查询
+            name: "customWarning",
+            component: () =>
+              import("@/views/IntegratedAlarm/safe/customWarning"),
+            meta: {
+              title: "预警查询",
+              icon: "",
               permissions: ["jn_jcjz"],
             },
           },

+ 5 - 1
src/views/IntegratedAlarm/index.vue

@@ -8,4 +8,8 @@ export default {
 };
 </script>
 
-<style></style>
+<style scoped lang="less">
+.search-item {
+  display: flex;
+}
+</style>

+ 745 - 0
src/views/IntegratedAlarm/safe/customWarning/index.vue

@@ -0,0 +1,745 @@
+<template>
+  <div class="custom-warning">
+    <div class="form-wrapper">
+      <div class="search-wrapper">
+        <div class="search-item">
+          <span class="label">类型:</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.typeVal"
+              clearable
+              size="mini"
+             
+              placeholder="全部"
+              popper-class="select"
+              @change="
+                () => {
+                  getStationList();
+                  typechange();
+                }
+              "
+            >
+              <el-option
+                v-for="item in state.typeList"
+                :key="item.value"
+                :value="item.value"
+                :label="item.label"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item">
+          <span class="label">{{
+            state.isshowwindturbineName ? "场站:" : "升压站:"
+          }}</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.stationId"
+              clearable
+              size="mini"
+              placeholder="全部"
+              popper-class="select"
+              @change="getWindturbineList"
+            >
+              <el-option
+                v-for="item in stationList"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              ></el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item" v-if="state.isshowwindturbineName">
+          <span class="label">机组:</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.deviceId"
+              clearable
+              size="mini"
+              placeholder="全部"
+              popper-class="select"
+            >
+              <el-option
+                v-for="item in state.windturbineList"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item" v-if="state.isshowwindturbineName">
+          <span class="label">型号:</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.modelId"
+              clearable
+              size="mini"
+              placeholder="全部"
+              popper-class="select"
+            >
+              <el-option
+                v-for="item in modelList"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item" v-if="state.isshowwindturbineName">
+          <span class="label">部件:</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.components"
+              clearable
+              size="mini"
+              placeholder="全部"
+              popper-class="select"
+            >
+              <el-option
+                v-for="item in componentList"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item">
+          <span class="label">描述:</span>
+          <div class="search-content">
+            <el-input
+              v-model="state.description"
+              size="mini"
+              placeholder="请输入..."
+            ></el-input>
+          </div>
+        </div>
+        <div class="search-item">
+          <span class="label">日期:</span>
+          <div class="search-content">
+            <el-date-picker
+              v-model="state.dateTime"
+              size="mini"
+              type="datetimerange"
+              range-separator="-"
+              format="YYYY-MM-DD HH:mm:ss"
+              value-format="YYYY-MM-DD HH:mm:ss"
+              start-placeholder="开始"
+              end-placeholder="结束"
+            >
+            </el-date-picker>
+          </div>
+        </div>
+      </div>
+      <div class="btns">
+        <el-button class="buttons" size="mini" @click="getAlarmHistoryt"
+          >查询</el-button
+        >
+        <el-button
+          size="mini"
+          class="buttons"
+          @click="export2Excel"
+          :disabled="state.tableData?.length == 0 ? true : false"
+        >
+          导出</el-button
+        >
+        <el-button
+          class="buttons"
+          size="mini"
+          :disabled="!state.tableData?.length"
+          @click="confirmItem(state.tableData)"
+          >确认本页</el-button
+        >
+      </div>
+    </div>
+
+    <div class="table-wrapper">
+      <div class="leftContent">
+        <span>{{ pageTitle }}</span>
+      </div>
+      <el-table
+        size="mini"
+        :data="state.tableData"
+        height="calc(100% - 35px - 55px)"
+        style="width: 100%"
+        stripe
+      >
+        <template v-if="state.isshowwindturbineName">
+          <el-table-column
+            v-for="item in state.tableHeader"
+            :label="item.title"
+            :prop="item.code"
+            :key="item.code"
+            :width="item.width || ''"
+            show-overflow-tooltip
+            header-align="center"
+          >
+            <template #default="scope">
+              <p :style="item.style && item.style(scope.row)">
+                <span v-if="item.code == 'rank'">
+                  {{ tableFilter(scope.row.rank) }}
+                </span>
+                <span v-else-if="item.code == 'ts'">
+                  {{ formatTime(scope.row.ts) }}
+                </span>
+                <span
+                  :style="`color:${
+                    scope.row.confirmed ? '#05bb4c' : 'var(--el-color-danger)'
+                  }`"
+                  v-else-if="item.code == 'confirmed'"
+                >
+                  {{ scope.row.confirmed ? "是" : "否" }}
+                </span>
+                <span v-else>
+                  {{
+                    scope.row[item.code] != "NULL" ? scope.row[item.code] : "--"
+                  }}
+                </span>
+              </p>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="操作"
+            width="100"
+            header-align="center"
+            align="center"
+            
+          >
+            <template #default="scope">
+              <el-button
+                style="color: #05bb4c"
+                type="text"
+                @click="confirmItem([scope.row])"
+                >确认本条</el-button
+              >
+            </template>
+          </el-table-column>
+        </template>
+        <template v-else>
+          <el-table-column
+            v-for="item in state.tableHeader1"
+            :label="item.title"
+            :prop="item.code"
+            :key="item.code"
+            :width="item.width || ''"
+            show-overflow-tooltip
+            header-align="center"
+          >
+            <template #default="scope">
+              <p :style="item.style && item.style(scope.row)">
+                <span v-if="item.code == 'rank'">
+                  {{ tableFilter(scope.row.rank) }}
+                </span>
+                <span v-else-if="item.code == 'ts'">
+                  {{ formatTime(scope.row.ts) }}
+                </span>
+                <span
+                  :style="`color:${
+                    scope.row.confirmed ? '#05bb4c' : 'var(--el-color-danger)'
+                  }`"
+                  v-else-if="item.code == 'confirmed'"
+                >
+                  {{ scope.row.confirmed ? "是" : "否" }}
+                </span>
+                <span v-else>
+                  {{
+                    scope.row[item.code] != "NULL" ? scope.row[item.code] : "--"
+                  }}
+                </span>
+              </p>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="操作"
+            width="100"
+            header-align="center"
+            align="center"
+        
+          >
+            <template #default="scope">
+              <el-button
+                style="color: #05bb4c"
+                type="text"
+                @click="confirmItem([scope.row])"
+                >确认本条</el-button
+              >
+            </template>
+          </el-table-column>
+        </template>
+      </el-table>
+      <div class="pagination-wrapper">
+        <el-pagination
+          layout="total, sizes, prev, pager, next"
+          :current-page="query.page"
+          :page-size="query.limit"
+          :page-sizes="[20, 100, 500, 1000]"
+          :total="query.pageTotal"
+          @size-change="
+            (value) => {
+              query.page = 1;
+              query.limit = value;
+              getAlarmHistoryt();
+            }
+          "
+          @current-change="handlePageChange"
+        ></el-pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import {
+  watch,
+  reactive,
+  nextTick,
+  computed,
+  onMounted,
+  ref,
+  onActivated,
+  onUpdated,
+} from "vue";
+import { useRouter, useRoute } from "vue-router";
+import dayjs from "dayjs";
+import {
+  alarm_history,
+  new_alarm_history,
+  fetchWindturbineList,
+  fetchModel,
+  fetchRelatePartAndAlarmType,
+  getWpList,
+  confirmAlart,
+} from "@/api/zhbj/index.js";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { outExportExcel } from "@/tools/excel/exportExcel.js"; //引入文件
+import { useStore } from "vuex";
+const pageTitle = "预警查询";
+const store = useStore();
+const route = useRoute();
+
+onMounted(() => {
+  state.dateTime = [
+    dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss"),
+    dayjs().format("YYYY-MM-DD HH:mm:ss"),
+  ];
+  state.deviceId = route.params.deviceId || "";
+  state.alarmId = route.params.alarmId || "";
+  getStationList();
+  getequipmentmodel_list();
+  getfetchRelatePart();
+});
+
+// 机型
+const getequipmentmodel_list = async () => {
+  const { data } = await fetchModel();
+  state.modelListAll = data;
+};
+//所属部件
+const getfetchRelatePart = async () => {
+  const { data } = await fetchRelatePartAndAlarmType();
+  state.fetchListAll = data;
+};
+
+const confirmItem = (alarmItem) => {
+  ElMessageBox("您确定要执行此操作吗?", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  })
+    .then(() => {
+      confirmAlart(alarmItem)
+        .then((res) => {
+          if (res.code === 200) {
+            ElMessage.success("确认成功");
+            store.commit("removeWarning", alarmItem);
+            getAlarmHistoryt();
+          }
+        })
+        .catch(() => {
+          ElMessage.error("确认失败,请重试");
+        });
+    })
+    .catch(() => {});
+};
+
+const getColumnStyle = (columnItem) => {
+  let style = "color:";
+  if (columnItem.endts) {
+    style += "#05bb4c";
+  } else {
+    style += "var(--el-color-danger)";
+  }
+  return style;
+};
+
+const state = reactive({
+  typeList: [
+    // {
+    //   label: "升压站",
+    //   value: "booststation",
+    // },
+    // {
+    //   label: "自定义",
+    //   value: "custom",
+    // },
+    {
+      label: "风机",
+      value: "windturbine",
+    },
+    {
+      label: "光伏",
+      value: "inverter",
+    },
+  ],
+  c: "windturbine",
+  stationId: "",
+  alarmId: "",
+  typeVal: "windturbine",
+  windturbineList: [],
+  deviceId: "",
+  modelListAll: {},
+  fetchListAll: {},
+  modelId: "", //型号
+  components: "", //部件
+  description: "", //描述
+  dateTime: [],
+  startDate: null,
+  endDate: null,
+  tableData: [],
+  isshowwindturbineName: true,
+  tableHeader: [
+    { title: "时间", code: "ts", width: "150" },
+    { title: "场站", code: "stationname", width: "150" },
+    { title: "机组", code: "devicename", width: "150" },
+    { title: "报警信息", code: "description", width: "250" },
+    { title: "故障原因", code: "faultCause" },
+    // { title: "故障编码", code: "nemCode", width: "100" },
+    // { title: "故障解决方法", code: "resolvent" },
+    // { title: "级别", code: "rank", width: "80" },
+    { title: "报警解除时间", code: "endtsName", width: "150" },
+    {
+      title: "状态",
+      code: "isCloseName",
+      width: "80",
+      style: getColumnStyle,
+      //   width: 100,
+    },
+    { title: "是否确认", code: "confirmed", width: "100" },
+    { title: "类型", code: "deviceTypeName", width: "80" },
+  ],
+  tableHeader1: [
+    { title: "时间", code: "ts", width: "150" },
+    { title: "升压站", code: "stationname", width: "150" },
+    { title: "报警信息", code: "description", width: "250" },
+    // { title: "级别", code: "rank", width: "80" },
+    { title: "报警解除时间", code: "endtsName", width: "150" },
+    {
+      title: "状态",
+      code: "isCloseName",
+      style: getColumnStyle,
+      //   width: 100,
+      width: "80",
+    },
+    { title: "是否确认", code: "confirmed", width: "100" },
+    { title: "类型", code: "deviceTypeName", width: "80" },
+  ],
+});
+// 场站列表/升压站列表
+const stationList = ref([]);
+
+const getStationList = async () => {
+  const { data } = await getWpList(state.typeVal);
+  stationList.value = data;
+  if (state.deviceId) {
+    let station = data.find((i) => {
+      let st = i.id.split("_")[2];
+      let dt = state.deviceId.split("_")[2];
+      if (st == dt) {
+        return i;
+      }
+    });
+    state.stationId = station?.id;
+  } else {
+    state.stationId =
+      state.typeVal == "windturbine" ? "SXJ_KGDL_DJY_FDC_STA" : data[0]?.id;
+  }
+  if (stationList.value.length) {
+    await getWindturbineList();
+    await getAlarmHistoryt();
+  }
+};
+
+// watch(
+//   () => stationList,
+//   (val, old) => {
+//     val?.value?.length &&
+//       nextTick(async () => {
+//         await getWindturbineList();
+//         await getAlarmHistoryt();
+//       });
+//   },
+//   {
+//     deep: true,
+//     immediate: true,
+//   }
+// );
+watch(
+  () => route,
+  (val, old) => {
+    state.deviceId = route.params.deviceId || "";
+    state.alarmId = route.params.alarmId || "";
+    // nextTick(async () => {
+    //   if (route.params.deviceId && route.params.alarmId) {
+    //     await getAlarmHistoryt();
+    //   }
+    // });
+  },
+  {
+    deep: true,
+    immediate: true,
+  }
+);
+//型号列表
+const modelList = computed(() => {
+  if (state.stationId == "") {
+    return [];
+  } else {
+    state.modelId = route.params.deviceId
+      ? ""
+      : state.modelListAll[state.stationId]?.[0]?.id || "";
+    return state.modelListAll[state.stationId];
+  }
+});
+//部件列表
+const componentList = computed(() => {
+  if (state.stationId == "") {
+    return [];
+  } else {
+    if (state.stationId.includes("FDC")) {
+      return state.fetchListAll?.fjbj;
+    } else {
+      return state.fetchListAll?.gfbj;
+    }
+  }
+});
+//get 风机
+const getWindturbineList = async () => {
+  const { data } = await fetchWindturbineList(state.stationId);
+  state.windturbineList = data;
+};
+const query = reactive({
+  page: 1,
+  limit: 20,
+  pageTotal: null,
+});
+
+// 获取历史记录表
+const getAlarmHistoryt = async () => {
+  //   if (route.params.deviceId && route.params.alarmId) {
+  //     state.stationId = "";
+  //   }
+  let params = {
+    pageNum: query.page,
+    pageSize: query.limit,
+    alarmId: state.alarmId,
+    alarmType: "custom",
+    deviceType: state.typeVal,
+    stationid: state.stationId,
+    deviceid:
+      state.deviceId || (state.typeVal == "booststation" ? "" : state.deviceId),
+    modelId: state.typeVal == "booststation" ? "" : state.modelId,
+    components: state.components,
+    description: state.description,
+    begin: state.dateTime[0],
+    end: state.dateTime[1],
+  };
+  const { data } = await alarm_history(params);
+  query.pageTotal = data?.total;
+  data?.ls?.forEach((ele) => {
+    ele.isCloseName = ele.endts ? "已解除" : "未解除";
+    ele.deviceTypeName = tableFilter(ele.deviceType);
+    ele.endtsName = ele.endts > 0 ? formatTime(ele.endts) : "";
+  });
+  state.tableData = data?.ls;
+};
+//报警类型变化
+const typechange = () => {
+  state.alarmId = "";
+  state.deviceId = "";
+  state.isshowwindturbineName = state.typeVal == "booststation" ? false : true;
+};
+
+// 批量导出
+const export2Excel = async () => {
+  let params = {
+    pageNum: query.page,
+    pageSize: query.pageTotal,
+    alarmType: state.typeVal,
+    stationid: state.stationId,
+    deviceid: state.typeVal == "booststation" ? "" : state.deviceId,
+    modelId: state.modelId,
+    components: state.components,
+    description: state.description,
+    begin: state.dateTime[0],
+    end: state.dateTime[1],
+  };
+
+  if (state.dateTime[1] - state.dateTime[0] > 6 * 24 * 60 * 60 * 1000) {
+    this.$message({
+      message: "导出时间范围不能大于7天",
+      type: "warning",
+    });
+  } else {
+    let tableHeader = [];
+    let tableKey = [];
+    const { data } = await alarm_history(params);
+    if (state.isshowwindturbineName) {
+      tableHeader = state.tableHeader.map((item) => item.title);
+      tableKey = state.tableHeader.map((item) => item.code);
+    } else {
+      tableHeader = state.tableHeader1.map((item) => item.title);
+      tableKey = state.tableHeader1.map((item) => item.code);
+    }
+    const stationName = stationList.value.find((ele) => {
+      return ele.id === state.stationId;
+    }).name;
+    const fileName = `${stationName} ${state.dateTime[0]} ~ ${state.dateTime[1]} 数据表`;
+
+    outExportExcel(
+      tableHeader,
+      tableKey,
+      data.ls.map((item) => {
+        return {
+          ...item,
+          ts: formatTime(item.ts),
+          rank: tableFilter(item.rank),
+          deviceType: tableFilter(item.deviceType),
+        };
+      }),
+      fileName
+    );
+    ElMessage.success(`导出成功!`);
+  }
+};
+// 分页导航
+const handlePageChange = (val) => {
+  query.page = val;
+  getAlarmHistoryt();
+};
+// 时间格式化
+const formatTime = (val) => {
+  return dayjs(val).format("YYYY-MM-DD HH:mm:ss");
+};
+// 格式化
+const obj = {
+  1: "低级",
+  2: "低中级",
+  3: "中级",
+  4: "中高级",
+  5: "高级",
+  booststation: "升压站",
+  custom: "自定义",
+  windturbine: "风机",
+  inverter: "光伏",
+};
+const messageTypeObj = {
+  1: "触发",
+  3: "解除",
+};
+const tableFilter = (val) => {
+  return obj[val];
+};
+const messageTypeFilter = (val) => {
+  return messageTypeObj[val];
+};
+</script>
+
+<style scoped lang="scss">
+p {
+  padding: 0;
+  margin: 0;
+}
+.custom-warning {
+  height: 100%;
+  width: 100%;
+  padding: 0 20px;
+  padding-bottom: 10px;
+  .form-wrapper ::v-deep {
+    display: flex;
+    flex-direction: column;
+    padding-top: 10px;
+    .search-wrapper {
+      display: flex;
+      align-items: center;
+      font-size: 14px;
+      font-family: Microsoft YaHei;
+      font-weight: 400;
+      color: #b3b3b3;
+      margin-bottom: 10px;
+      .search-item {
+        display: flex;
+        margin-right: 10px;
+        max-width: 220px;
+        align-items: center;
+        .label {
+          margin-right: 10px;
+          text-align: right;
+          white-space: nowrap;
+          // width: 60px;
+        }
+        .search-content {
+          flex: 1;
+        }
+      }
+    }
+
+    .btns {
+      display: flex;
+      justify-content: flex-end;
+      margin-right: 10px;
+    }
+
+    .buttons {
+      background-color: rgba(5, 187, 76, 0.2);
+      border: 1px solid #3b6c53;
+      color: #b3b3b3;
+      font-size: 14px;
+
+      &:hover {
+        background-color: rgba(5, 187, 76, 0.5);
+        color: #ffffff;
+      }
+    }
+  }
+  .table-wrapper {
+    height: calc(100% - 82px);
+    width: 100%;
+    .leftContent {
+      width: 242px;
+      height: 41px;
+      display: flex;
+      align-items: center;
+      background: url("~@/assets/imgs/title_left_bg1.png") no-repeat;
+
+      span {
+        font-size: 16px;
+        font-family: Microsoft YaHei;
+        font-weight: 400;
+        color: #05bb4c;
+        margin-left: 25px;
+      }
+    }
+    .pagination-wrapper :deep {
+      text-align: right;
+      margin-top: 10px;
+    }
+  }
+}
+</style>

+ 786 - 0
src/views/IntegratedAlarm/safe/historyWarning/index.vue

@@ -0,0 +1,786 @@
+<template>
+  <div
+    class="history-warning"
+    v-loading="tableLoading"
+    element-loading-text="加载中..."
+    element-loading-background="rgba(4, 12, 11, 0.8)"
+  >
+    <div class="form-wrapper">
+      <div class="search-wrapper">
+        <div class="search-item">
+          <span class="label">类型:</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.typeVal"
+              clearable
+              size="mini"
+              placeholder="全部"
+              popper-class="select"
+              @change="
+                () => {
+                  getStationList();
+                  typechange();
+                }
+              "
+            >
+              <el-option
+                v-for="item in state.typeList"
+                :key="item.value"
+                :value="item.value"
+                :label="item.label"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item">
+          <span class="label">{{
+            state.isshowwindturbineName ? "场站:" : "升压站:"
+          }}</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.stationId"
+              clearable
+              size="mini"
+              placeholder="全部"
+              popper-class="select"
+              @change="getWindturbineList"
+            >
+              <el-option
+                v-for="item in stationList"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              ></el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item" v-if="state.isshowwindturbineName">
+          <span class="label">机组:</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.deviceId"
+              clearable
+              size="mini"
+              placeholder="全部"
+              popper-class="select"
+            >
+              <el-option
+                v-for="item in state.windturbineList"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item" v-if="state.isshowwindturbineName">
+          <span class="label">型号:</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.modelId"
+              clearable
+              size="mini"
+              placeholder="全部"
+              popper-class="select"
+            >
+              <el-option
+                v-for="item in modelList"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item" v-if="state.isshowwindturbineName">
+          <span class="label">部件:</span>
+          <div class="search-content">
+            <el-select
+              v-model="state.components"
+              clearable
+              size="mini"
+              placeholder="全部"
+              popper-class="select"
+            >
+              <el-option
+                v-for="item in componentList"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="search-item">
+          <span class="label">描述:</span>
+          <div class="search-content"></div>
+          <el-input
+            v-model="state.description"
+            placeholder="请输入..."
+            size="mini"
+          ></el-input>
+        </div>
+        <div class="search-item">
+          <span class="label">日期:</span>
+          <div class="search-content">
+            <el-date-picker
+              v-model="state.dateTime"
+              size="mini"
+              type="datetimerange"
+              range-separator="-"
+              format="YYYY-MM-DD HH:mm:ss"
+              value-format="YYYY-MM-DD HH:mm:ss"
+              start-placeholder="开始"
+              end-placeholder="结束"
+            >
+            </el-date-picker>
+          </div>
+        </div>
+      </div>
+      <div class="btns">
+        <el-button class="buttons" size="mini" @click="getAlarmHistoryt"
+          >查询</el-button
+        >
+        <el-button
+          size="mini"
+          class="buttons"
+          @click="export2Excel"
+          :disabled="state.tableData?.length == 0 ? true : false"
+        >
+          导出</el-button
+        >
+        <el-button
+          class="buttons"
+          size="mini"
+          :disabled="!state.tableData?.length"
+          @click="confirmItem(state.tableData)"
+          >确认本页</el-button
+        >
+      </div>
+    </div>
+
+    <div class="table-wrapper">
+      <div class="leftContent">
+        <span>{{ pageTitle }}</span>
+      </div>
+      <el-table
+        size="mini"
+        :data="state.tableData"
+        height="calc(100% - 35px - 55px)"
+        style="width: 100%"
+        stripe
+      >
+        <template v-if="state.isshowwindturbineName">
+          <el-table-column
+            v-for="item in state.tableHeader"
+            :label="item.title"
+            :prop="item.code"
+            :key="item.code"
+            :width="item.width || ''"
+            show-overflow-tooltip
+            header-align="center"
+          >
+            <template #default="scope">
+              <p :style="item.style && item.style(scope.row)">
+                <span v-if="item.code == 'rank'">
+                  {{ tableFilter(scope.row.rank) }}
+                </span>
+                <span v-else-if="item.code == 'alarmtype'">
+                  {{ tableFilter(scope.row.alarmtype) }}
+                </span>
+                <span v-else-if="item.code == 'ts'">
+                  {{ formatTime(scope.row.ts) }}
+                </span>
+                <span
+                  :style="`color:${
+                    scope.row.confirmed ? '#05bb4c' : 'var(--el-color-danger)'
+                  }`"
+                  v-else-if="item.code == 'confirmed'"
+                >
+                  {{ scope.row.confirmed ? "是" : "否" }}
+                </span>
+                <span v-else>
+                  {{
+                    scope.row[item.code] != "NULL" ? scope.row[item.code] : "--"
+                  }}
+                </span>
+              </p>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="操作"
+            width="100"
+            header-align="center"
+            align="center"
+          >
+            <template #default="scope">
+              <el-button
+                type="text"
+                style="color: #05bb4c"
+                @click="confirmItem([scope.row])"
+                >确认本条</el-button
+              >
+            </template>
+          </el-table-column>
+        </template>
+        <template v-else>
+          <el-table-column
+            v-for="item in state.tableHeader1"
+            :label="item.title"
+            :prop="item.code"
+            :key="item.code"
+            :width="item.width || ''"
+            show-overflow-tooltip
+            header-align="center"
+          >
+            <template #default="scope">
+              <p :style="item.style && item.style(scope.row)">
+                <span v-if="item.code == 'rank'">
+                  {{ tableFilter(scope.row.rank) }}
+                </span>
+                <span v-else-if="item.code == 'alarmtype'">
+                  {{ tableFilter(scope.row.alarmtype) }}
+                </span>
+                <span v-else-if="item.code == 'ts'">
+                  {{ formatTime(scope.row.ts) }}
+                </span>
+                <span
+                  :style="`color:${
+                    scope.row.confirmed ? '#05bb4c' : 'var(--el-color-danger)'
+                  }`"
+                  v-else-if="item.code == 'confirmed'"
+                >
+                  {{ scope.row.confirmed ? "是" : "否" }}
+                </span>
+                <span v-else>
+                  {{
+                    scope.row[item.code] != "NULL" ? scope.row[item.code] : "--"
+                  }}
+                </span>
+              </p>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="操作"
+            width="100"
+            header-align="center"
+            align="center"
+            fixed="right"
+          >
+            <template #default="scope">
+              <el-button  type="text" style="color: #05bb4c" @click="confirmItem([scope.row])"
+                >确认本条</el-button
+              >
+            </template>
+          </el-table-column>
+        </template>
+      </el-table>
+      <div class="pagination-wrapper">
+        <el-pagination
+          layout="total, sizes, prev, pager, next"
+          :current-page="query.page"
+          :page-size="query.limit"
+          :page-sizes="[20, 100, 500, 1000]"
+          :total="query.pageTotal"
+          @size-change="
+            (value) => {
+              query.page = 1;
+              query.limit = value;
+              getAlarmHistoryt();
+            }
+          "
+          @current-change="handlePageChange"
+        ></el-pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup name="historyWarning">
+import { watch, reactive, nextTick, computed, onMounted, ref } from "vue";
+import { useRouter, useRoute } from "vue-router";
+
+import dayjs from "dayjs";
+import {
+  alarm_history,
+  new_alarm_history,
+  fetchWindturbineList,
+  fetchModel,
+  fetchRelatePartAndAlarmType,
+  getWpList,
+  confirmAlart,
+} from "@/api/zhbj/index.js";
+import { ElMessageBox, ElMessage } from "element-plus";
+import { outExportExcel } from "@/tools/excel/exportExcel.js"; //引入文件
+import { useStore } from "vuex";
+const pageTitle = "报警查询";
+const store = useStore();
+
+const route = useRoute();
+const tableLoading = ref(false);
+onMounted(() => {
+  state.dateTime = [
+    dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss"),
+    dayjs().format("YYYY-MM-DD HH:mm:ss"),
+  ];
+  if (route.params.typeVal != "booststation") {
+    state.deviceId = route.params.deviceId || "";
+    state.alarmId = route.params.alarmId || "";
+    state.typeVal = route.params.typeVal || "windturbine";
+  } else {
+    state.stationName = route.params.deviceId;
+    state.deviceId = "";
+    state.alarmId = route.params.alarmId || "";
+    state.typeVal = route.params.typeVal || "booststation";
+  }
+  state.isshowwindturbineName = state.typeVal == "booststation" ? false : true;
+  if (route.params.ts) {
+    state.dateTime = [
+      `${dayjs(Number(route.params.ts)).format("YYYY-MM-DD")} 00:00:00`,
+      dayjs(Number(route.params.ts)).format("YYYY-MM-DD HH:mm:ss"),
+    ];
+  }
+  //   getStationList(); //场站
+  getequipmentmodel_list(); //机型
+  getfetchRelatePart(); //部件
+});
+// 机型
+const getequipmentmodel_list = async () => {
+  const { data } = await fetchModel();
+  state.modelListAll = data;
+};
+//所属部件
+const getfetchRelatePart = async () => {
+  const { data } = await fetchRelatePartAndAlarmType();
+  state.fetchListAll = data;
+};
+
+const confirmItem = (alarmItem) => {
+  ElMessageBox("您确定要执行此操作吗?", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  })
+    .then(() => {
+      confirmAlart(alarmItem)
+        .then((res) => {
+          if (res.code === 200) {
+            ElMessage.success("确认成功");
+            store.commit("removeWarning", alarmItem);
+            getAlarmHistoryt();
+          }
+        })
+        .catch(() => {
+          ElMessage.error("确认失败,请重试");
+        });
+    })
+    .catch(() => {});
+};
+
+const getColumnStyle = (columnItem) => {
+  let style = "color:";
+  if (columnItem.endts) {
+    style += " #05bb4c";
+  } else {
+    style += "var(--el-color-danger)";
+  }
+  return style;
+};
+
+const state = reactive({
+  typeList: [
+    {
+      label: "升压站",
+      value: "booststation",
+    },
+    // {
+    //   label: "自定义",
+    //   value: "custom",
+    // },
+    {
+      label: "风机",
+      value: "windturbine",
+    },
+    {
+      label: "光伏",
+      value: "inverter",
+    },
+  ],
+  typeVal: "windturbine",
+  stationId: "",
+  stationName: "",
+  alarmId: "",
+  windturbineList: [],
+  deviceId: "",
+  modelListAll: {},
+  fetchListAll: {},
+  modelId: "", //型号
+  components: "", //部件
+  description: "", //描述
+  dateTime: [],
+  startDate: null,
+  endDate: null,
+  tableData: [],
+  isshowwindturbineName: true,
+  ts: "",
+  tableHeader: [
+    { title: "时间", code: "ts", width: "150" },
+    { title: "场站", code: "stationname", width: "150" },
+    { title: "机组", code: "devicename", width: "150" },
+    { title: "报警信息", code: "description", width: "180" },
+    { title: "故障原因", code: "faultCause" },
+    // { title: "级别", code: "rank", width: "80" },
+    { title: "故障编码", code: "nemCode", width: "100" },
+    // { title: "故障解决方法", code: "resolvent" },
+    { title: "报警解除时间", code: "endtsName", width: "150" },
+    {
+      title: "状态",
+      code: "isCloseName",
+      //   width: "80",
+      style: getColumnStyle,
+      width: 100,
+    },
+    { title: "是否确认", code: "confirmed", width: "100" },
+    { title: "类型", code: "alarmTypeName", width: "80" },
+  ],
+  tableHeader1: [
+    { title: "时间", code: "ts", width: "150" },
+    { title: "升压站", code: "stationname", width: "150" },
+    { title: "报警信息", code: "description" },
+    // { title: "级别", code: "rank", width: "80" },
+    { title: "报警解除时间", code: "endtsName", width: "150" },
+    {
+      title: "状态",
+      code: "isCloseName",
+      style: getColumnStyle,
+      width: 100,
+      //   width: "80",
+    },
+    { title: "是否确认", code: "confirmed", width: "100" },
+    { title: "类型", code: "alarmTypeName", width: "80" },
+  ],
+});
+// 场站列表/升压站列表
+const stationList = ref([]);
+//获取场站列表
+const getStationList = async () => {
+  const { data } = await getWpList(state.typeVal);
+  stationList.value = data;
+  if (state.deviceId && state.typeVal != "booststation") {
+    let station = data.find((i) => {
+      let st = i.id.split("_")[2];
+      let dt = state.deviceId.split("_")[2];
+      if (st == dt) {
+        return i;
+      }
+    });
+    state.stationId = station?.id;
+  } else if (state.typeVal == "booststation") {
+    let station = data.find((i) => i.name == state.stationName);
+    state.stationId = station ? station?.id : data[0]?.id;
+  } else {
+    state.stationId = data[0]?.id;
+  }
+
+  state.stationId = route.params.stationId || state.stationId;
+  route.params.stationId
+    ? (state.modelId = modelList.value?.[0]?.id || "")
+    : "";
+  if (stationList.value.length) {
+    getWindturbineList();
+  }
+};
+
+// watch(
+//   () => stationList,
+//   (val, old) => {
+//     val?.value?.length &&
+//       nextTick(async () => {
+//         await getWindturbineList();
+//       });
+//   },
+//   {
+//     deep: true,
+//     immediate: true,
+//   }
+// );
+watch(
+  () => route,
+  (val, old) => {
+    if (route.params.typeVal != "booststation") {
+      state.deviceId = route.params.deviceId || "";
+      state.alarmId = route.params.alarmId || "";
+      state.typeVal = route.params.typeVal || "windturbine";
+    } else {
+      state.stationName = route.params.deviceId;
+      state.stationId = route.params.stationId;
+      state.deviceId = "";
+      state.alarmId = route.params.alarmId || "";
+      state.typeVal = route.params.typeVal || "booststation";
+    }
+    state.isshowwindturbineName =
+      state.typeVal == "booststation" ? false : true;
+    getStationList();
+  },
+  {
+    deep: true,
+    immediate: true,
+  }
+);
+//型号列表
+const modelList = computed(() => {
+  if (state.typeVal == "windturbine") {
+    if (state.stationId == "") {
+      return [];
+    } else {
+      state.modelId = route.params.deviceId
+        ? ""
+        : state.modelListAll[state.stationId]?.[0]?.id || "";
+      return state.modelListAll[state.stationId];
+    }
+  } else {
+    return [];
+  }
+});
+//部件列表
+const componentList = computed(() => {
+  if (state.typeVal == "windturbine") {
+    if (state.stationId == "") {
+      return [];
+    } else {
+      if (state.stationId.includes("FDC")) {
+        return state.fetchListAll?.fjbj;
+      } else {
+        return state.fetchListAll?.gfbj;
+      }
+    }
+  } else {
+    return [];
+  }
+});
+//get 风机
+const getWindturbineList = async () => {
+  const { data } = await fetchWindturbineList(state.stationId);
+  state.windturbineList = data;
+  state.modelId = modelList.value?.[0]?.id || "";
+  await getAlarmHistoryt();
+};
+const query = reactive({
+  page: 1,
+  limit: 20,
+  pageTotal: null,
+});
+
+// 获取历史记录表
+const getAlarmHistoryt = async () => {
+  //   if (route.params.deviceId && route.params.alarmId) {
+  //     state.stationId = "";
+  //   }
+  tableLoading.value = true;
+  let params = {
+    pageNum: query.page,
+    pageSize: query.limit,
+    alarmId: state.alarmId,
+    alarmType: state.typeVal,
+    stationid: state.stationId,
+    deviceid: state.typeVal == "booststation" ? "" : state.deviceId,
+    modelId: state.typeVal == "booststation" ? "" : state.modelId,
+    components: state.components,
+    description: state.description,
+    begin: state.dateTime[0],
+    end: state.dateTime[1],
+  };
+  const { data } = await alarm_history(params);
+  tableLoading.value = false;
+  query.pageTotal = data?.total;
+  data?.ls?.forEach((ele) => {
+    ele.isCloseName = ele.endts ? "已解除" : "未解除";
+    ele.alarmTypeName =
+      ele.alarmType === "booststation"
+        ? "升压站"
+        : ele.alarmType === "windturbine"
+        ? "风机"
+        : ele.alarmType === "inverter"
+        ? "光伏"
+        : "";
+    ele.endtsName = ele.endts > 0 ? formatTime(ele.endts) : "";
+  });
+  state.tableData = data?.ls;
+};
+//报警类型变化
+const typechange = () => {
+  state.alarmId = "";
+  state.deviceId = "";
+  state.isshowwindturbineName = state.typeVal == "booststation" ? false : true;
+};
+
+// 批量导出
+const export2Excel = async () => {
+  let params = {
+    pageNum: query.page,
+    pageSize: query.pageTotal,
+    alarmType: state.typeVal,
+    stationid: state.stationId,
+    deviceid: state.typeVal == "booststation" ? "" : state.deviceId,
+    modelId: state.modelId,
+    components: state.components,
+    description: state.description,
+    begin: state.dateTime[0],
+    end: state.dateTime[1],
+  };
+
+  if (state.dateTime[1] - state.dateTime[0] > 6 * 24 * 60 * 60 * 1000) {
+    this.$message({
+      message: "导出时间范围不能大于7天",
+      type: "warning",
+    });
+  } else {
+    let tableHeader = [];
+    let tableKey = [];
+    const { data } = await alarm_history(params);
+    if (state.isshowwindturbineName) {
+      tableHeader = state.tableHeader.map((item) => item.title);
+      tableKey = state.tableHeader.map((item) => item.code);
+    } else {
+      tableHeader = state.tableHeader1.map((item) => item.title);
+      tableKey = state.tableHeader1.map((item) => item.code);
+    }
+    const stationName = stationList.value.find((ele) => {
+      return ele.id === state.stationId;
+    }).name;
+    const fileName = `${stationName} ${state.dateTime[0]} ~ ${state.dateTime[1]} 数据表`;
+
+    outExportExcel(
+      tableHeader,
+      tableKey,
+      data.ls.map((item) => {
+        return {
+          ...item,
+          ts: formatTime(item.ts),
+          rank: tableFilter(item.rank),
+          alarmtype: tableFilter(item.alarmtype),
+        };
+      }),
+      fileName
+    );
+    ElMessage.success(`导出成功!`);
+  }
+};
+// 分页导航
+const handlePageChange = (val) => {
+  query.page = val;
+  getAlarmHistoryt();
+};
+// 时间格式化
+const formatTime = (val) => {
+  return dayjs(val).format("YYYY-MM-DD HH:mm:ss");
+};
+// 格式化
+const obj = {
+  1: "低级",
+  2: "低中级",
+  3: "中级",
+  4: "中高级",
+  5: "高级",
+  booststation: "升压站",
+  custom: "自定义",
+  windturbine: "风机",
+};
+const messageTypeObj = {
+  1: "触发",
+  3: "解除",
+};
+const tableFilter = (val) => {
+  return obj[val];
+};
+const messageTypeFilter = (val) => {
+  return messageTypeObj[val];
+};
+</script>
+
+<style scoped lang="less">
+p {
+  padding: 0;
+  margin: 0;
+}
+.history-warning {
+  height: 100%;
+  width: 100%;
+  padding: 0 20px;
+  padding-bottom: 10px;
+  .form-wrapper ::v-deep {
+    display: flex;
+    flex-direction: column;
+    padding-top: 10px;
+    .search-wrapper {
+      display: flex;
+      align-items: center;
+      font-size: 14px;
+      font-family: Microsoft YaHei;
+      font-weight: 400;
+      color: #b3b3b3;
+      margin-bottom: 10px;
+      .search-item {
+        display: flex;
+        margin-right: 10px;
+        max-width: 220px;
+        align-items: center;
+        .label {
+          margin-right: 10px;
+          text-align: right;
+          white-space: nowrap;
+          // width: 60px;
+        }
+        .search-content {
+          flex: 1;
+        }
+      }
+    }
+
+    .btns {
+      display: flex;
+      justify-content: flex-end;
+      margin-right: 10px;
+    }
+
+    .buttons {
+      background-color: rgba(5, 187, 76, 0.2);
+      border: 1px solid #3b6c53;
+      color: #b3b3b3;
+      font-size: 14px;
+
+      &:hover {
+        background-color: rgba(5, 187, 76, 0.5);
+        color: #ffffff;
+      }
+    }
+  }
+  .table-wrapper {
+    height: calc(100% - 82px);
+    width: 100%;
+    .leftContent {
+      width: 242px;
+      height: 41px;
+      display: flex;
+      align-items: center;
+      background: url("~@/assets/imgs/title_left_bg1.png") no-repeat;
+
+      span {
+        font-size: 16px;
+        font-family: Microsoft YaHei;
+        font-weight: 400;
+        color: #05bb4c;
+        margin-left: 25px;
+      }
+    }
+    .pagination-wrapper :deep {
+      text-align: right;
+      margin-top: 10px;
+    }
+  }
+}
+</style>

+ 2 - 1
src/views/IntegratedAlarm/safe/index.vue

@@ -8,4 +8,5 @@ export default {
 };
 </script>
 
-<style></style>
+<style scoped lang="less">
+</style>