|
@@ -3,8 +3,8 @@ import React, {
|
|
|
useState,
|
|
useState,
|
|
|
forwardRef,
|
|
forwardRef,
|
|
|
useImperativeHandle,
|
|
useImperativeHandle,
|
|
|
|
|
+ useCallback,
|
|
|
} from "react";
|
|
} from "react";
|
|
|
-import { Tooltip, Space, Pagination, Button } from "antd";
|
|
|
|
|
import { Table } from "antd";
|
|
import { Table } from "antd";
|
|
|
import styles from "./index.module.less";
|
|
import styles from "./index.module.less";
|
|
|
import { useMemoizedFn } from "ahooks";
|
|
import { useMemoizedFn } from "ahooks";
|
|
@@ -13,6 +13,18 @@ import _ from "lodash";
|
|
|
import dayjs from "dayjs";
|
|
import dayjs from "dayjs";
|
|
|
import API from "../../../../../api/alarm";
|
|
import API from "../../../../../api/alarm";
|
|
|
import AlarmConfirm from "../AlarmConfirm";
|
|
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) {
|
|
function TranslateText(arr) {
|
|
|
const dtLanguage = localStorage.getItem("dtLanguage");
|
|
const dtLanguage = localStorage.getItem("dtLanguage");
|
|
@@ -86,6 +98,28 @@ const alarmStatusMap = {
|
|
|
|
|
|
|
|
const showTotal = (total) => `共${total}条`;
|
|
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 Index = (props) => {
|
|
|
const [tags, setTags] = useState([{ name: "详情1", id: "1" }]);
|
|
const [tags, setTags] = useState([{ name: "详情1", id: "1" }]);
|
|
|
const [current, setCurrent] = useState("history");
|
|
const [current, setCurrent] = useState("history");
|
|
@@ -95,14 +129,82 @@ const Index = (props) => {
|
|
|
const [page, setPage] = useState(1);
|
|
const [page, setPage] = useState(1);
|
|
|
const [currentAlarm, setCurrentAlarm] = useState({});
|
|
const [currentAlarm, setCurrentAlarm] = useState({});
|
|
|
const [showConfirm, setShowConfirm] = useState(false);
|
|
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 () => {
|
|
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);
|
|
setData(res?.data?.history);
|
|
|
setTotal(res?.data?.total);
|
|
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) => {
|
|
const onConfirm = (record) => {
|
|
|
if (record.op_status === 1) return;
|
|
if (record.op_status === 1) return;
|
|
|
setCurrentAlarm(record);
|
|
setCurrentAlarm(record);
|
|
@@ -110,7 +212,7 @@ const Index = (props) => {
|
|
|
};
|
|
};
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
fetchData();
|
|
fetchData();
|
|
|
- }, [page, props.ruleId, fetchData]);
|
|
|
|
|
|
|
+ }, [page, props.ruleId, fetchData, props.group]);
|
|
|
const columns = [
|
|
const columns = [
|
|
|
// {
|
|
// {
|
|
|
// title: '序号',
|
|
// title: '序号',
|
|
@@ -122,6 +224,7 @@ const Index = (props) => {
|
|
|
title: TranslateText(["告警时间", "Alarm time"]),
|
|
title: TranslateText(["告警时间", "Alarm time"]),
|
|
|
width: 180,
|
|
width: 180,
|
|
|
dataIndex: "created_time",
|
|
dataIndex: "created_time",
|
|
|
|
|
+ fixed: "left",
|
|
|
render: (text, record) =>
|
|
render: (text, record) =>
|
|
|
text ? dayjs(text).format("YYYY-MM-DD HH:mm:ss") : "暂无",
|
|
text ? dayjs(text).format("YYYY-MM-DD HH:mm:ss") : "暂无",
|
|
|
},
|
|
},
|
|
@@ -130,17 +233,10 @@ const Index = (props) => {
|
|
|
dataIndex: "name",
|
|
dataIndex: "name",
|
|
|
ellipsis: true,
|
|
ellipsis: true,
|
|
|
width: 400,
|
|
width: 400,
|
|
|
- render: (text, record) => {
|
|
|
|
|
- return <Tooltip title={text}>{text}</Tooltip>;
|
|
|
|
|
- },
|
|
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
title: () => {
|
|
title: () => {
|
|
|
- return (
|
|
|
|
|
- <Tooltip title={TranslateText(["级别", "Level"])}>
|
|
|
|
|
- <span>{TranslateText(["级别", "Level"])}</span>
|
|
|
|
|
- </Tooltip>
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ return <span>{TranslateText(["级别", "Level"])}</span>;
|
|
|
},
|
|
},
|
|
|
onHeaderCell: () => ({
|
|
onHeaderCell: () => ({
|
|
|
style: {
|
|
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"]),
|
|
title: TranslateText(["持续时间", "duration"]),
|
|
|
dataIndex: "duration",
|
|
dataIndex: "duration",
|
|
@@ -237,15 +326,6 @@ const Index = (props) => {
|
|
|
render: (text, record) =>
|
|
render: (text, record) =>
|
|
|
text ? dayjs(text).format("YYYY-MM-DD HH:mm:ss") : "-",
|
|
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"]),
|
|
title: TranslateText(["操作", "Operation"]),
|
|
|
dataIndex: "action",
|
|
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 (
|
|
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
|
|
<Table
|
|
|
className={styles.table}
|
|
className={styles.table}
|
|
|
loading={loading}
|
|
loading={loading}
|
|
@@ -279,8 +433,8 @@ const Index = (props) => {
|
|
|
pagination={false}
|
|
pagination={false}
|
|
|
size="middle"
|
|
size="middle"
|
|
|
scroll={{
|
|
scroll={{
|
|
|
- x: 1160,
|
|
|
|
|
- y: "calc(90vh - 250px)",
|
|
|
|
|
|
|
+ x: 1200,
|
|
|
|
|
+ y: "calc(80vh - 322px)",
|
|
|
}}
|
|
}}
|
|
|
/>
|
|
/>
|
|
|
<div className={styles.page}>
|
|
<div className={styles.page}>
|