Przeglądaj źródła

加入告警历史的筛选

valentichu 1 rok temu
rodzic
commit
d4c50cea9f

Plik diff jest za duży
+ 0 - 0
lib/index.js


+ 32 - 31
src/App.jsx

@@ -7,44 +7,45 @@ function Home(props) {
 
   return (
     <>
-      <div style={{ padding: "0px 30px" }}>
-        <Alarm.ComplexConfig
-          ref={compRef}
-          editId={-1}
-        ></Alarm.ComplexConfig>
-      </div>
-      {/* <Alarm.DetailModal
+      {/* <div style={{ padding: "0px 30px" }}>
+        <Alarm.ComplexConfig ref={compRef} editId={-1}></Alarm.ComplexConfig>
+      </div> */}
+      <Alarm.DetailModal
         open={open}
         onCancel={() => setOpen(false)}
-        // options={{ ruleId: 69 }}
         options={{
-          detail: {
-            id: 275575,
-            name: "测试",
-            rule_id: 69,
-            type: 1,
-            sub_type: 13,
-            status: 1,
-            point_id: "",
-            point_name: "",
-            alarm_level: 1,
-            op_status: 1,
-            created_time: "2024-09-25 15:06:00",
-            duration: 1704255,
-            confirmed_time: "2024-09-25 16:03:15",
-            confirmed_oper_id: 14,
-            confirmed_oper_name: "郭红阳",
-            recovery_time: "",
-            remark: "ccc",
-            value: 0,
-            unit: "",
-            group_name: "",
-          },
+          group: [6],
+          diagramId: "ZjdhOGJiZGQtNjkyZi00NjU0LWFmMTctNjM3YzYxNTEwYzA0",
         }}
+        noSettings
+        // options={{
+        //   detail: {
+        //     id: 275575,
+        //     name: "测试",
+        //     rule_id: 69,
+        //     type: 1,
+        //     sub_type: 13,
+        //     status: 1,
+        //     point_id: "",
+        //     point_name: "",
+        //     alarm_level: 1,
+        //     op_status: 1,
+        //     created_time: "2024-09-25 15:06:00",
+        //     duration: 1704255,
+        //     confirmed_time: "2024-09-25 16:03:15",
+        //     confirmed_oper_id: 14,
+        //     confirmed_oper_name: "郭红阳",
+        //     recovery_time: "",
+        //     remark: "ccc",
+        //     value: 0,
+        //     unit: "",
+        //     group_name: "",
+        //   },
+        // }}
         // // options={{
         // //   pointId: "ABC123_AAA_chr1_AEff_MIN_H",
         // // }}
-      ></Alarm.DetailModal> */}
+      ></Alarm.DetailModal>
       {/* <Alarm.ComplexConfig
         ref={compRef}
         editId={-1}

+ 38 - 4
src/api/alarm.js

@@ -23,20 +23,52 @@ export async function searchPoint(data) {
   return res.statusText ? res.data : res;
 }
 
-export async function getAlarmHistory(page, rule_ids, size = 15) {
+export async function getAlarmHistory({
+  page,
+  rule_ids,
+  size = 15,
+  key = "",
+  begin,
+  end,
+  status,
+  op_status,
+  group_ids,
+  isExport,
+  export_name,
+  diagram_uuid,
+}) {
   const res = await axios.post(
     "/api/unialarm/get_alarm_history",
     {
       rule_ids,
       page_num: page,
-      page_size: size,
+      page_size: isExport ? 999999 : size,
       types: [1],
+      key_word: key,
+      op_status,
+      status,
+      begin,
+      end,
+      group_ids,
+      export: isExport,
+      export_name,
+      diagram_uuid,
     },
     config
   );
   return res.statusText ? res.data : res;
 }
 
+export async function download(url) {
+  const newConfig = {
+    baseURL: config.baseURL,
+    noNeedInterceptor: true,
+    responseType: "blob",
+  };
+  const res = await axios.get(url, newConfig);
+  return res;
+}
+
 export async function getRuleIdByPointId(point_id) {
   const res = await axios.post(
     "/api/unialarm/get_rule_with_point",
@@ -94,8 +126,8 @@ export async function getRuleList(point_id) {
   return res.statusText ? res.data : res;
 }
 
-export async function getGroupList(data) {
-  const res = await axios.post("/api/unialarm/get_group_list", data, config);
+export async function getGroupList() {
+  const res = await axios.post("/api/unialarm/get_group_list", {}, config);
   return res.statusText ? res.data : res;
 }
 
@@ -109,4 +141,6 @@ export default {
   confirmAlarm,
   getAlarmPointData,
   getRuleList,
+  getGroupList,
+  download,
 };

+ 184 - 30
src/pages/Alarm/components/components/AlarmHistory/index.jsx

@@ -3,8 +3,8 @@ import React, {
   useState,
   forwardRef,
   useImperativeHandle,
+  useCallback,
 } from "react";
-import { Tooltip, Space, Pagination, Button } from "antd";
 import { Table } from "antd";
 import styles from "./index.module.less";
 import { useMemoizedFn } from "ahooks";
@@ -13,6 +13,18 @@ import _ from "lodash";
 import dayjs from "dayjs";
 import API from "../../../../../api/alarm";
 import AlarmConfirm from "../AlarmConfirm";
+import { useDebounceFn } from "ahooks";
+import { SearchOutlined } from "@ant-design/icons";
+import {
+  Tooltip,
+  Space,
+  Pagination,
+  Button,
+  Select,
+  Input,
+  DatePicker,
+} from "antd";
+const { RangePicker } = DatePicker;
 
 function TranslateText(arr) {
   const dtLanguage = localStorage.getItem("dtLanguage");
@@ -86,6 +98,28 @@ const alarmStatusMap = {
 
 const showTotal = (total) => `共${total}条`;
 
+const alarmStatusOptions = [
+  {
+    label: TranslateText(["进行中", "In progress"]),
+    value: 1,
+  },
+  {
+    label: TranslateText(["已结束", "Ended"]),
+    value: 2,
+  },
+];
+
+const periodOptions = [
+  {
+    label: TranslateText(["未确认", "Unconfirmed"]),
+    value: 2,
+  },
+  {
+    label: TranslateText(["已确认", "Confirmed"]),
+    value: 1,
+  },
+];
+
 const Index = (props) => {
   const [tags, setTags] = useState([{ name: "详情1", id: "1" }]);
   const [current, setCurrent] = useState("history");
@@ -95,14 +129,82 @@ const Index = (props) => {
   const [page, setPage] = useState(1);
   const [currentAlarm, setCurrentAlarm] = useState({});
   const [showConfirm, setShowConfirm] = useState(false);
+  const [keyword, setKeyword] = useState("");
+  const [status, setStatus] = useState(1);
+  const [opStatus, setOpStatus] = useState(2);
+  const [range, setRange] = useState(null);
 
   const fetchData = useMemoizedFn(async () => {
-    if (props.ruleId === -1) return;
-    const res = await API.getAlarmHistory(page, props.ruleId);
+    if (!props.ruleId && !props.group) return;
+
+    const res = range
+      ? await API.getAlarmHistory({
+          page,
+          rule_ids: props.ruleId,
+          key: keyword,
+          status,
+          op_status: opStatus,
+          group_ids: props.group,
+          begin: range[0].unix(),
+          end: range[1].unix(),
+          diagram_uuid: props.diagramId,
+        })
+      : await API.getAlarmHistory({
+          page,
+          rule_ids: props.ruleId,
+          key: keyword,
+          status,
+          op_status: opStatus,
+          group_ids: props.group,
+          diagram_uuid: props.diagramId,
+        });
     setData(res?.data?.history);
     setTotal(res?.data?.total);
   });
 
+  const onExport = useMemoizedFn(async () => {
+    const response = range
+      ? await API.getAlarmHistory({
+          page,
+          rule_ids: props.ruleId,
+          key: keyword,
+          status,
+          op_status: opStatus,
+          group_ids: props.group,
+          begin: range[0].unix(),
+          end: range[1].unix(),
+          isExport: true,
+          export_name: "告警记录",
+          diagram_uuid: props.diagramId,
+        })
+      : await API.getAlarmHistory({
+          page,
+          rule_ids: props.ruleId,
+          key: keyword,
+          status,
+          op_status: opStatus,
+          group_ids: props.group,
+          isExport: true,
+          export_name: "告警记录",
+          diagram_uuid: props.diagramId,
+        });
+
+    if (response.data?.download_url) {
+      let res = await API.download(response.data?.download_url);
+      const blob = new Blob([res], {
+        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+      });
+      const objectURL = URL.createObjectURL(blob);
+      const anchor = document.createElement("a");
+      anchor.href = objectURL;
+      anchor.download = true;
+      anchor.click();
+      URL.revokeObjectURL(objectURL);
+    }
+  });
+
+  const { run } = useDebounceFn(fetchData, { wait: 500 });
+
   const onConfirm = (record) => {
     if (record.op_status === 1) return;
     setCurrentAlarm(record);
@@ -110,7 +212,7 @@ const Index = (props) => {
   };
   useEffect(() => {
     fetchData();
-  }, [page, props.ruleId, fetchData]);
+  }, [page, props.ruleId, fetchData, props.group]);
   const columns = [
     // {
     //   title: '序号',
@@ -122,6 +224,7 @@ const Index = (props) => {
       title: TranslateText(["告警时间", "Alarm time"]),
       width: 180,
       dataIndex: "created_time",
+      fixed: "left",
       render: (text, record) =>
         text ? dayjs(text).format("YYYY-MM-DD HH:mm:ss") : "暂无",
     },
@@ -130,17 +233,10 @@ const Index = (props) => {
       dataIndex: "name",
       ellipsis: true,
       width: 400,
-      render: (text, record) => {
-        return <Tooltip title={text}>{text}</Tooltip>;
-      },
     },
     {
       title: () => {
-        return (
-          <Tooltip title={TranslateText(["级别", "Level"])}>
-            <span>{TranslateText(["级别", "Level"])}</span>
-          </Tooltip>
-        );
+        return <span>{TranslateText(["级别", "Level"])}</span>;
       },
       onHeaderCell: () => ({
         style: {
@@ -160,13 +256,6 @@ const Index = (props) => {
         );
       },
     },
-    {
-      title: TranslateText(["恢复时间", "Recovery time"]),
-      dataIndex: "recovery_time",
-      width: 180,
-      render: (text, record) =>
-        text ? dayjs(text).format("YYYY-MM-DD HH:mm:ss") : "-",
-    },
     {
       title: TranslateText(["持续时间", "duration"]),
       dataIndex: "duration",
@@ -237,15 +326,6 @@ const Index = (props) => {
       render: (text, record) =>
         text ? dayjs(text).format("YYYY-MM-DD HH:mm:ss") : "-",
     },
-    {
-      title: TranslateText(["备注", "Remarks"]),
-      dataIndex: "remark",
-      width: 120,
-      ellipsis: "true",
-      render: (text, record) => {
-        return <div title={text}>{text}</div>;
-      },
-    },
     {
       title: TranslateText(["操作", "Operation"]),
       dataIndex: "action",
@@ -268,8 +348,82 @@ const Index = (props) => {
       ),
     },
   ];
+  const disabledDate = useCallback((current) => {
+    // Can not select days after today
+    return current && current > dayjs().endOf("day");
+  }, []);
   return (
     <>
+      <div className={styles.toolbox}>
+        <div>
+          <Input
+            value={keyword}
+            onChange={(e) => {
+              setKeyword(e.target.value);
+              setPage(1);
+              run();
+            }}
+            placeholder="请输入告警名称"
+            style={{
+              width: 240,
+              marginLeft: 16,
+            }}
+            suffix={
+              <SearchOutlined
+                style={{
+                  fontSize: 16,
+                  color: "var(--dt-fill-color6)",
+                }}
+              />
+            }
+          ></Input>
+          <Select
+            value={status}
+            onChange={(s) => {
+              setStatus(s);
+              setPage(1);
+              setTimeout(fetchData, 100);
+            }}
+            style={{
+              width: 120,
+              marginLeft: 16,
+            }}
+            options={alarmStatusOptions}
+          ></Select>
+          <Select
+            value={opStatus}
+            onChange={(s) => {
+              setOpStatus(s);
+              setPage(1);
+              setTimeout(fetchData, 100);
+            }}
+            style={{
+              width: 120,
+              marginLeft: 16,
+            }}
+            options={periodOptions}
+          ></Select>
+          <RangePicker
+            value={range}
+            onChange={(r) => {
+              setRange(r);
+              setPage(1);
+              setTimeout(fetchData, 100);
+            }}
+            style={{
+              width: 260,
+              marginLeft: 16,
+            }}
+            allowClear={true}
+            disabledDate={disabledDate}
+          />
+        </div>
+        <div>
+          <Button type="primary" onClick={onExport}>
+            导出
+          </Button>
+        </div>
+      </div>
       <Table
         className={styles.table}
         loading={loading}
@@ -279,8 +433,8 @@ const Index = (props) => {
         pagination={false}
         size="middle"
         scroll={{
-          x: 1160,
-          y: "calc(90vh - 250px)",
+          x: 1200,
+          y: "calc(80vh - 322px)",
         }}
       />
       <div className={styles.page}>

+ 11 - 0
src/pages/Alarm/components/components/AlarmHistory/index.module.less

@@ -38,9 +38,20 @@
     .scroll_bar_restyle::-webkit-scrollbar-track {
       background-color: initial;
     }
+
+    .ant-table-placeholder {
+      height: calc(80vh - 360px);
+    }
   }
 }
 
+.toolbox {
+  display: flex;
+  align-items: center;
+  margin-bottom: 20px;
+  justify-content: space-between;
+}
+
 .page {
   margin-top: 16px;
   display: flex;

+ 24 - 7
src/pages/Alarm/components/detail.jsx

@@ -20,7 +20,7 @@ const Detail = (props) => {
   const { options, isDiagram } = props;
   const [tags, setTags] = useState([]);
   const [current, setCurrent] = useState("history");
-  const [ruleId, setRuleId] = useState(-1);
+  const [ruleId, setRuleId] = useState(undefined);
   const [showConfirm, setShowConfirm] = useState(false);
   // const [showAlarmConfig, setShowAlarmConfig] = useState(false);
   const getRuleIdByPointId = useMemoizedFn(async (ruleId, pointId) => {
@@ -37,7 +37,11 @@ const Detail = (props) => {
     setTags([]);
   });
   useEffect(() => {
-    if (options.ruleId || options.pointId) {
+    if (options.group) {
+      setCurrent("history");
+      setTags([]);
+      setRuleId(undefined);
+    } else if (options.ruleId || options.pointId) {
       getRuleIdByPointId(options.ruleId, options.pointId);
     } else if (options.detail) {
       setRuleId([options.detail.rule_id]);
@@ -49,7 +53,13 @@ const Detail = (props) => {
       ]);
       setCurrent(options.detail.id);
     }
-  }, [options.detail, options.ruleId, options.pointId]);
+  }, [
+    options.detail,
+    options.ruleId,
+    options.pointId,
+    options.group,
+    getRuleIdByPointId,
+  ]);
   const currentData = tags.find((item) => item.id === current) ?? {};
   const onRemove = (index) => {
     const newTags = _.cloneDeep(tags);
@@ -92,7 +102,7 @@ const Detail = (props) => {
           top: 50,
         }}
         bodyStyle={{
-          height: "calc(90vh - 80px)",
+          height: "calc(80vh - 80px)",
           display: "flex",
           flexDirection: "column",
         }}
@@ -102,7 +112,9 @@ const Detail = (props) => {
             <div className={styles.header}>
               <div
                 className={`${styles.tags} ${
-                  current !== "history" ? styles.nobutton : ""
+                  current !== "history" || props.noSettings
+                    ? styles.nobutton
+                    : ""
                 }`}
               >
                 <Tabs
@@ -168,7 +180,7 @@ const Detail = (props) => {
                     {currentData?.data?.op_status === 1 ? "已确认" : "确认"}
                   </Button>
                 )} */}
-                {current === "history" && (
+                {current === "history" && !props.noSettings && (
                   <Button onClick={props?.onSetting} style={{ marginLeft: 10 }}>
                     告警配置
                   </Button>
@@ -177,7 +189,12 @@ const Detail = (props) => {
             </div>
 
             {current === "history" && (
-              <AlarmHistory onSelect={onSelect} ruleId={ruleId}></AlarmHistory>
+              <AlarmHistory
+                onSelect={onSelect}
+                ruleId={ruleId}
+                group={options?.group}
+                diagramId={options?.diagramId}
+              ></AlarmHistory>
             )}
             {current !== "history" && (
               <AlarmDetail

+ 0 - 1
src/pages/Alarm/components/detail.module.less

@@ -13,7 +13,6 @@
 .header {
   align-items: center;
   display: flex;
-  margin-bottom: 16px;
   margin-top: 32px;
 }
 .tags {

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików