Browse Source

fix: 修改记录

sun-chaochao 3 years ago
parent
commit
245320287c

+ 13 - 11
src/pages/account/NotificationSubscription/save/index.tsx

@@ -18,27 +18,29 @@ const Save = (props: Props) => {
   const [data, setDada] = useState<any>(props.data || {});
   const [dataList, setDataList] = useState<any[]>([]);
 
+  const form = useMemo(
+    () =>
+      createForm({
+        validateFirst: true,
+        initialValues: data,
+      }),
+    [],
+  );
+
   useEffect(() => {
     if (props.data?.topicConfig) {
-      setDada({
+      const param = {
         ...props.data,
         topicConfig: {
           alarmConfigId: props.data?.topicConfig?.alarmConfigId.split(','),
           alarmConfigName: props.data?.topicConfig?.alarmConfigName.split(','),
         },
-      });
+      };
+      setDada({ ...param });
+      form.setValues(param);
     }
   }, [props.data]);
 
-  const form = useMemo(
-    () =>
-      createForm({
-        validateFirst: true,
-        initialValues: data,
-      }),
-    [],
-  );
-
   const queryProvidersList = () => service.getProvidersList();
 
   const queryAlarmConfigList = () => {

+ 0 - 1
src/pages/device/Instance/Detail/Log/index.tsx

@@ -38,7 +38,6 @@ const Log = () => {
     {
       title: '内容',
       dataIndex: 'content',
-      valueType: 'option',
       ellipsis: true,
       render: (text, record) => <span>{String(record.content)}</span>,
     },

+ 26 - 3
src/pages/device/Instance/Detail/MetadataMap/EditableTable/index.tsx

@@ -1,7 +1,9 @@
 import React, { useContext, useEffect, useState } from 'react';
-import { Badge, Col, Form, Input, message, Pagination, Row, Select, Table } from 'antd';
+import { Badge, Col, Form, Input, message, Pagination, Row, Select, Table, Tooltip } from 'antd';
 import { service } from '@/pages/device/Instance';
 import './index.less';
+import { QuestionCircleOutlined } from '@ant-design/icons';
+// import { throttle } from 'lodash';
 
 const defaultImage = require('/public/images/metadata-map.png');
 
@@ -49,7 +51,7 @@ const EditableCell = ({
       const values = await form.validateFields();
       handleSave({
         ...record,
-        originalId: values?.originalId,
+        originalId: !!values?.originalId ? values?.originalId : record.metadataId,
         customMapping: values?.originalId !== '',
       });
     } catch (errInfo) {
@@ -69,6 +71,20 @@ const EditableCell = ({
   if (editable) {
     childNode = (
       <Form.Item style={{ margin: 0 }} name={dataIndex}>
+        {/* <AutoComplete onChange={throttle(save, 5000)}>
+          <AutoComplete.Option value={''}>使用物模型属性</AutoComplete.Option>
+          {record.customMapping && temp && (
+            <AutoComplete.Option value={record.originalId}>
+              {temp?.name}({temp?.id})
+            </AutoComplete.Option>
+          )}
+          {tempList.length > 0 &&
+            tempList.map((item: any) => (
+              <AutoComplete.Option key={item?.id} value={item?.id}>
+                {item?.name}({item?.id})
+              </AutoComplete.Option>
+            ))}
+        </AutoComplete> */}
         <Select
           onChange={save}
           showSearch
@@ -109,7 +125,14 @@ const EditableTable = (props: Props) => {
       render: (text: any, record: any) => <span>{`${record.name}(${record.id})`}</span>,
     },
     {
-      title: '设备上报属性',
+      title: (
+        <span>
+          设备上报属性
+          <Tooltip title="设备上报属性无法根据标识与物模型属性匹配时,默认使用物模型属性">
+            <QuestionCircleOutlined />
+          </Tooltip>
+        </span>
+      ),
       dataIndex: 'originalId',
       width: '30%',
       editable: true,

+ 1 - 1
src/pages/device/Instance/Export/index.tsx

@@ -116,7 +116,7 @@ const Export = (props: Props) => {
       onOk={downloadTemplate}
     >
       <Alert
-        message="不勾选产品,默认导出所有设备的基础数据,勾选单个产品可导出下属的详细数据"
+        message="选择单个产品时可导出其下属设备的详细数据,不选择产品时导出所有设备的基础数据"
         type="warning"
         showIcon
         closable

+ 1 - 0
src/pages/notice/Template/index.tsx

@@ -247,6 +247,7 @@ const Template = observer(() => {
             <Upload
               disabled={!templatePermission.import}
               key={'import'}
+              accept=".json"
               showUploadList={false}
               beforeUpload={(file) => {
                 const reader = new FileReader();

+ 181 - 0
src/pages/rule-engine/Alarm/Log/TabComponent/index copy.less

@@ -0,0 +1,181 @@
+@import '~antd/es/style/themes/default.less';
+
+@alarm-log-padding-left: 60px;
+
+.ellipsis {
+  width: 100%;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+
+.alarm-log-card {
+  .alarm-log-item {
+    display: flex;
+    margin-bottom: 20px;
+
+    .alarm-log-title {
+      position: relative;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      width: 15%;
+      padding: 10px;
+      overflow: hidden;
+      color: @primary-color;
+      background-color: #f0f2f3;
+      .alarm-log-level {
+        position: absolute;
+        top: 10px;
+        right: -12px;
+        display: flex;
+        justify-content: center;
+        width: 100px;
+        padding: 2px 0;
+        color: white;
+        background-color: red;
+        transform: skewX(45deg);
+        .alarm-log-text {
+          transform: skewX(-45deg);
+        }
+      }
+      .alarm-log-title-text {
+        margin: 0 10px;
+        .ellipsis();
+      }
+    }
+    .alarm-log-content {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      width: 87%;
+      padding: 20px;
+      background: url('/images/alarm/background.png') no-repeat;
+      background-size: 100% 100%;
+
+      .alarm-log-data {
+        display: flex;
+        align-items: center;
+        min-width: 60%;
+        max-width: 100%;
+
+        .alarm-log-image {
+          display: flex;
+          align-items: center;
+          padding-right: @alarm-log-padding-left;
+          border-right: 1px solid rgba(0, 0, 0, 0.09);
+
+          .alarm-type {
+            width: 40px;
+
+            .name {
+              color: #000;
+              font-size: 18px;
+            }
+
+            .text {
+              margin-top: 8px;
+              color: #666;
+              font-size: 14px;
+              .ellipsis();
+            }
+          }
+        }
+        .alarm-log-right {
+          display: flex;
+          justify-content: space-between;
+          width: 50%;
+          padding-left: @alarm-log-padding-left;
+
+          .alarm-log-time {
+            max-width: 165px;
+
+            .log-title {
+              margin-top: 8px;
+              color: #666;
+              font-size: 12px;
+            }
+
+            .context {
+              margin-top: 8px;
+              color: rgba(#000, 0.85);
+              font-size: 14px;
+              .ellipsis();
+            }
+          }
+
+          .alarm-log-status {
+            margin-left: @alarm-log-padding-left;
+          }
+        }
+      }
+      .alarm-log-actions {
+        .alarm-log-action {
+          display: flex;
+          justify-content: center;
+          width: 72px;
+          height: 72px;
+          background-color: #fff;
+          border: 1px solid @primary-color;
+
+          .btn {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            width: 72px;
+            height: 72px;
+            .icon {
+              margin-bottom: 5px;
+              color: @primary-color;
+              font-size: 25px;
+            }
+
+            div {
+              color: @primary-color;
+              font-size: 12px;
+            }
+          }
+        }
+
+        .alarm-log-action:hover {
+          background-color: @primary-color;
+
+          .icon,
+          div {
+            color: #fff;
+          }
+        }
+        .alarm-log-disabled {
+          display: flex;
+          justify-content: center;
+          width: 72px;
+          height: 72px;
+          border: 1px solid rgba(0, 0, 0, 0.25);
+          .btn {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            width: 72px;
+            height: 72px;
+            .icon {
+              margin-bottom: 5px;
+              color: rgba(0, 0, 0, 0.25);
+              font-size: 25px;
+            }
+
+            div {
+              color: rgba(0, 0, 0, 0.25);
+              font-size: 12px;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .alarm-log-item:hover {
+    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.1);
+  }
+}

+ 307 - 0
src/pages/rule-engine/Alarm/Log/TabComponent/index copy.tsx

@@ -0,0 +1,307 @@
+import SearchComponent from '@/components/SearchComponent';
+import { FileFilled, FileTextFilled, ToolFilled } from '@ant-design/icons';
+import type { ProColumns } from '@jetlinks/pro-table';
+import { Badge, Button, Card, Col, Empty, Pagination, Row, Space, Tooltip } from 'antd';
+import { useEffect, useState } from 'react';
+import './index.less';
+import SolveComponent from '../SolveComponent';
+import SolveLog from '../SolveLog';
+import { AlarmLogModel } from '../model';
+import moment from 'moment';
+import { observer } from '@formily/reactive-react';
+import { service } from '@/pages/rule-engine/Alarm/Log';
+import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
+import { useHistory } from 'umi';
+import PermissionButton from '@/components/PermissionButton';
+import classNames from 'classnames';
+
+interface Props {
+  type: string;
+}
+
+const imgMap = new Map();
+imgMap.set('product', require('/public/images/alarm/product.png'));
+imgMap.set('device', require('/public/images/alarm/device.png'));
+imgMap.set('other', require('/public/images/alarm/other.png'));
+imgMap.set('org', require('/public/images/alarm/org.png'));
+
+const titleMap = new Map();
+titleMap.set('product', '产品');
+titleMap.set('device', '设备');
+titleMap.set('other', '其他');
+titleMap.set('org', '部门');
+
+const colorMap = new Map();
+colorMap.set(1, '#E50012');
+colorMap.set(2, '#FF9457');
+colorMap.set(3, '#FABD47');
+colorMap.set(4, '#999999');
+colorMap.set(5, '#C4C4C4');
+
+const TabComponent = observer((props: Props) => {
+  const { permission } = PermissionButton.usePermission('rule-engine/Alarm/Log');
+  const columns: ProColumns<any>[] = [
+    {
+      title: '名称',
+      dataIndex: 'alarmName',
+    },
+    {
+      title: '最近告警时间',
+      dataIndex: 'alarmTime',
+      valueType: 'dateTime',
+    },
+    {
+      title: '状态',
+      dataIndex: 'state',
+      valueType: 'select',
+      valueEnum: {
+        warning: {
+          text: '告警中',
+          status: 'warning',
+        },
+        normal: {
+          text: '无告警',
+          status: 'normal',
+        },
+      },
+    },
+  ];
+
+  const [param, setParam] = useState<any>({ pageSize: 10, terms: [] });
+  const history = useHistory<Record<string, string>>();
+
+  const [dataSource, setDataSource] = useState<any>({
+    data: [],
+    pageSize: 10,
+    pageIndex: 0,
+    total: 0,
+  });
+
+  const handleSearch = (params: any) => {
+    setParam(params);
+    const terms = [...params.terms];
+    if (props.type !== 'all') {
+      terms.push({
+        termType: 'eq',
+        column: 'targetType',
+        value: props.type,
+        type: 'and',
+      });
+    }
+    service
+      .query({
+        ...params,
+        terms: [...terms],
+        sorts: [{ name: 'alarmTime', order: 'desc' }],
+      })
+      .then((resp) => {
+        if (resp.status === 200) {
+          setDataSource(resp.result);
+        }
+      });
+  };
+
+  useEffect(() => {
+    handleSearch(param);
+  }, [props.type]);
+
+  return (
+    <div className="alarm-log-card">
+      <SearchComponent<any>
+        field={columns}
+        target="alarm-log"
+        onSearch={(data) => {
+          const dt = {
+            pageSize: 10,
+            terms: [...data?.terms],
+          };
+          handleSearch(dt);
+        }}
+      />
+      <Card>
+        {dataSource?.data.length > 0 ? (
+          <Row gutter={24} style={{ marginTop: 10 }}>
+            {(dataSource?.data || []).map((item: any) => (
+              <Col key={item.id} span={24}>
+                <div className="alarm-log-item">
+                  <div className="alarm-log-title">
+                    <div
+                      className="alarm-log-level"
+                      style={{ backgroundColor: colorMap.get(item.level) }}
+                    >
+                      <div className="alarm-log-text">
+                        {AlarmLogModel.defaultLevel.find((i) => i.level === item.level)?.title ||
+                          item.level}
+                      </div>
+                    </div>
+                    <div className="alarm-log-title-text">
+                      <Tooltip placement="topLeft" title={item.alarmName}>
+                        {item.alarmName}
+                      </Tooltip>
+                    </div>
+                  </div>
+                  <div className="alarm-log-content">
+                    <div className="alarm-log-data">
+                      <div className="alarm-log-image">
+                        <img
+                          width={88}
+                          height={88}
+                          src={imgMap.get(props.type)}
+                          alt={''}
+                          style={{ marginRight: 20 }}
+                        />
+                        <div className="alarm-type">
+                          <div className="name">{titleMap.get(item.targetType)}</div>
+                          <div className="text">
+                            <Tooltip placement="topLeft" title={item.targetName}>
+                              {item.targetName}
+                            </Tooltip>
+                          </div>
+                        </div>
+                      </div>
+                      <div className="alarm-log-right">
+                        <div className="alarm-log-time">
+                          <div className="log-title">最近告警时间</div>
+                          <div className="context">
+                            {moment(item.alarmTime).format('YYYY-MM-DD HH:mm:ss')}
+                          </div>
+                        </div>
+                        <div
+                          className="alarm-log-time alarm-log-status"
+                          style={{ paddingLeft: 10 }}
+                        >
+                          <div className="log-title">状态</div>
+                          <div className="context">
+                            <Badge status={item.state.value === 'warning' ? 'error' : 'default'} />
+                            <span
+                              style={{
+                                color: item.state.value === 'warning' ? '#E50012' : 'black',
+                              }}
+                            >
+                              {item.state.text}
+                            </span>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <div className="alarm-log-actions">
+                      <Space>
+                        {item.state.value === 'warning' && (
+                          <div
+                            className={classNames(
+                              permission.action ? 'alarm-log-action' : 'alarm-log-disabled',
+                            )}
+                          >
+                            <Tooltip title={permission.action ? '' : '暂无权限,请联系管理员'}>
+                              <Button
+                                type={'link'}
+                                disabled={!permission.action}
+                                onClick={() => {
+                                  AlarmLogModel.solveVisible = true;
+                                  AlarmLogModel.current = item;
+                                }}
+                              >
+                                <div className="btn">
+                                  <ToolFilled className="icon" />
+                                  <div>告警处理</div>
+                                </div>
+                              </Button>
+                            </Tooltip>
+                          </div>
+                        )}
+                        <div className="alarm-log-action">
+                          <Button
+                            type={'link'}
+                            onClick={() => {
+                              AlarmLogModel.current = item;
+                              const url = getMenuPathByParams(
+                                MENUS_CODE['rule-engine/Alarm/Log/Detail'],
+                                item.id,
+                              );
+                              history.push(url);
+                            }}
+                          >
+                            <div className="btn">
+                              <FileFilled className="icon" />
+                              <div>告警日志</div>
+                            </div>
+                          </Button>
+                        </div>
+                        <div className="alarm-log-action">
+                          <Button
+                            type={'link'}
+                            onClick={() => {
+                              AlarmLogModel.logVisible = true;
+                              AlarmLogModel.current = item;
+                            }}
+                          >
+                            <div className="btn">
+                              <FileTextFilled className="icon" />
+                              <div>处理记录</div>
+                            </div>
+                          </Button>
+                        </div>
+                      </Space>
+                    </div>
+                  </div>
+                </div>
+              </Col>
+            ))}
+          </Row>
+        ) : (
+          <Empty />
+        )}
+        {dataSource.data.length > 0 && (
+          <div style={{ display: 'flex', marginTop: 20, justifyContent: 'flex-end' }}>
+            <Pagination
+              showSizeChanger
+              size="small"
+              className={'pro-table-card-pagination'}
+              total={dataSource?.total || 0}
+              current={dataSource?.pageIndex + 1}
+              onChange={(page, size) => {
+                handleSearch({
+                  ...param,
+                  pageIndex: page - 1,
+                  pageSize: size,
+                });
+              }}
+              pageSizeOptions={[10, 20, 50, 100]}
+              pageSize={dataSource?.pageSize}
+              showTotal={(num) => {
+                const minSize = dataSource?.pageIndex * dataSource?.pageSize + 1;
+                const MaxSize = (dataSource?.pageIndex + 1) * dataSource?.pageSize;
+                return `第 ${minSize} - ${MaxSize > num ? num : MaxSize} 条/总共 ${num} 条`;
+              }}
+            />
+          </div>
+        )}
+      </Card>
+      {AlarmLogModel.solveVisible && (
+        <SolveComponent
+          close={() => {
+            AlarmLogModel.solveVisible = false;
+            AlarmLogModel.current = {};
+          }}
+          reload={() => {
+            AlarmLogModel.solveVisible = false;
+            AlarmLogModel.current = {};
+            handleSearch(param);
+          }}
+          data={AlarmLogModel.current}
+        />
+      )}
+      {AlarmLogModel.logVisible && (
+        <SolveLog
+          close={() => {
+            AlarmLogModel.logVisible = false;
+            AlarmLogModel.current = {};
+          }}
+          data={AlarmLogModel.current}
+        />
+      )}
+    </div>
+  );
+});
+
+export default TabComponent;

+ 53 - 161
src/pages/rule-engine/Alarm/Log/TabComponent/index.less

@@ -1,181 +1,73 @@
 @import '~antd/es/style/themes/default.less';
 
-@alarm-log-padding-left: 60px;
+@card-content-padding-top: 30px;
 
-.ellipsis {
+.alarm-log-context {
+  display: flex;
+  align-items: center;
   width: 100%;
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-}
 
-.alarm-log-card {
-  .alarm-log-item {
+  .context-left {
     display: flex;
-    margin-bottom: 20px;
+    align-items: center;
+    justify-content: space-between;
+    width: calc(40% - 40px);
+    margin-right: 10%;
 
-    .alarm-log-title {
-      position: relative;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      width: 15%;
-      padding: 10px;
-      overflow: hidden;
-      color: @primary-color;
-      background-color: #f0f2f3;
-      .alarm-log-level {
-        position: absolute;
-        top: 10px;
-        right: -12px;
-        display: flex;
-        justify-content: center;
-        width: 100px;
-        padding: 2px 0;
-        color: white;
-        background-color: red;
-        transform: skewX(45deg);
-        .alarm-log-text {
-          transform: skewX(-45deg);
-        }
-      }
-      .alarm-log-title-text {
-        margin: 0 10px;
-        .ellipsis();
-      }
+    .context-img {
+      margin-right: 20px;
     }
-    .alarm-log-content {
-      display: flex;
-      align-items: center;
-      justify-content: space-between;
-      width: 87%;
-      padding: 20px;
-      background: url('/images/alarm/background.png') no-repeat;
-      background-size: 100% 100%;
-
-      .alarm-log-data {
-        display: flex;
-        align-items: center;
-        min-width: 60%;
-        max-width: 100%;
-
-        .alarm-log-image {
-          display: flex;
-          align-items: center;
-          padding-right: @alarm-log-padding-left;
-          border-right: 1px solid rgba(0, 0, 0, 0.09);
-
-          .alarm-type {
-            width: 40px;
-
-            .name {
-              color: #000;
-              font-size: 18px;
-            }
-
-            .text {
-              margin-top: 8px;
-              color: #666;
-              font-size: 14px;
-              .ellipsis();
-            }
-          }
-        }
-        .alarm-log-right {
-          display: flex;
-          justify-content: space-between;
-          width: 50%;
-          padding-left: @alarm-log-padding-left;
-
-          .alarm-log-time {
-            max-width: 165px;
 
-            .log-title {
-              margin-top: 8px;
-              color: #666;
-              font-size: 12px;
-            }
+    .left-item {
+      width: calc(100% - 90px);
 
-            .context {
-              margin-top: 8px;
-              color: rgba(#000, 0.85);
-              font-size: 14px;
-              .ellipsis();
-            }
-          }
-
-          .alarm-log-status {
-            margin-left: @alarm-log-padding-left;
-          }
-        }
+      .left-item-title {
+        font-size: 18px;
       }
-      .alarm-log-actions {
-        .alarm-log-action {
-          display: flex;
-          justify-content: center;
-          width: 72px;
-          height: 72px;
-          background-color: #fff;
-          border: 1px solid @primary-color;
-
-          .btn {
-            display: flex;
-            flex-direction: column;
-            align-items: center;
-            justify-content: center;
-            width: 72px;
-            height: 72px;
-            .icon {
-              margin-bottom: 5px;
-              color: @primary-color;
-              font-size: 25px;
-            }
-
-            div {
-              color: @primary-color;
-              font-size: 12px;
-            }
-          }
-        }
 
-        .alarm-log-action:hover {
-          background-color: @primary-color;
+      .left-item-value {
+        color: #666;
+        font-size: 14px;
+      }
+    }
+  }
 
-          .icon,
-          div {
-            color: #fff;
-          }
-        }
-        .alarm-log-disabled {
-          display: flex;
-          justify-content: center;
-          width: 72px;
-          height: 72px;
-          border: 1px solid rgba(0, 0, 0, 0.25);
-          .btn {
-            display: flex;
-            flex-direction: column;
-            align-items: center;
-            justify-content: center;
-            width: 72px;
-            height: 72px;
-            .icon {
-              margin-bottom: 5px;
-              color: rgba(0, 0, 0, 0.25);
-              font-size: 25px;
-            }
+  .context-right {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    width: 60%;
+    margin-right: 10px;
+    padding-left: 10%;
+    border-left: 1px solid rgba(0, 0, 0, 0.09);
+
+    .right-item {
+      .right-item-title {
+        color: #666;
+        font-size: 12px;
+      }
 
-            div {
-              color: rgba(0, 0, 0, 0.25);
-              font-size: 12px;
-            }
-          }
-        }
+      .right-item-value {
+        color: #000;
+        font-size: 14px;
       }
     }
   }
+}
 
-  .alarm-log-item:hover {
-    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.1);
+.alarm-log-state {
+  position: absolute;
+  top: @card-content-padding-top;
+  right: -12px;
+  display: flex;
+  justify-content: center;
+  width: 100px;
+  padding: 2px 0;
+  color: #fff;
+  background-color: rgba(#5995f5, 0.15);
+  transform: skewX(45deg);
+
+  .card-state-content {
+    transform: skewX(-45deg);
   }
 }

+ 124 - 123
src/pages/rule-engine/Alarm/Log/TabComponent/index.tsx

@@ -1,7 +1,7 @@
 import SearchComponent from '@/components/SearchComponent';
 import { FileFilled, FileTextFilled, ToolFilled } from '@ant-design/icons';
 import type { ProColumns } from '@jetlinks/pro-table';
-import { Badge, Button, Card, Col, Empty, Pagination, Row, Space, Tooltip } from 'antd';
+import { Badge, Button, Card, Col, Empty, Pagination, Row, Tooltip } from 'antd';
 import { useEffect, useState } from 'react';
 import './index.less';
 import SolveComponent from '../SolveComponent';
@@ -12,7 +12,6 @@ import { observer } from '@formily/reactive-react';
 import { service } from '@/pages/rule-engine/Alarm/Log';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { useHistory } from 'umi';
-import PermissionButton from '@/components/PermissionButton';
 import classNames from 'classnames';
 
 interface Props {
@@ -39,7 +38,6 @@ colorMap.set(4, '#999999');
 colorMap.set(5, '#C4C4C4');
 
 const TabComponent = observer((props: Props) => {
-  const { permission } = PermissionButton.usePermission('rule-engine/Alarm/Log');
   const columns: ProColumns<any>[] = [
     {
       title: '名称',
@@ -79,18 +77,19 @@ const TabComponent = observer((props: Props) => {
 
   const handleSearch = (params: any) => {
     setParam(params);
+    const terms = [...params.terms];
+    if (props.type !== 'all') {
+      terms.push({
+        termType: 'eq',
+        column: 'targetType',
+        value: props.type,
+        type: 'and',
+      });
+    }
     service
       .query({
         ...params,
-        terms: [
-          ...params.terms,
-          {
-            termType: 'eq',
-            column: 'targetType',
-            value: props.type,
-            type: 'and',
-          },
-        ],
+        terms: [...terms],
         sorts: [{ name: 'alarmTime', order: 'desc' }],
       })
       .then((resp) => {
@@ -104,6 +103,68 @@ const TabComponent = observer((props: Props) => {
     handleSearch(param);
   }, [props.type]);
 
+  const tools = (record: any) => [
+    <Button
+      type={'link'}
+      key={'solve'}
+      style={{ padding: 0 }}
+      disabled={record.state.value === 'normal'}
+      onClick={() => {
+        AlarmLogModel.solveVisible = true;
+        AlarmLogModel.current = record;
+      }}
+    >
+      <Tooltip title={record.state?.value === 'normal' ? '无告警' : ''}>
+        <ToolFilled />
+        告警处理
+      </Tooltip>
+    </Button>,
+    <Button
+      type={'link'}
+      style={{ padding: 0 }}
+      key={'log'}
+      onClick={() => {
+        AlarmLogModel.current = record;
+        const url = getMenuPathByParams(MENUS_CODE['rule-engine/Alarm/Log/Detail'], record.id);
+        history.push(url);
+      }}
+    >
+      <FileFilled />
+      告警日志
+    </Button>,
+    <Button
+      type={'link'}
+      style={{ padding: 0 }}
+      key={'detail'}
+      onClick={() => {
+        AlarmLogModel.logVisible = true;
+        AlarmLogModel.current = record;
+      }}
+    >
+      <FileTextFilled />
+      处理记录
+    </Button>,
+  ];
+
+  const getAction = (actions: React.ReactNode[]) => {
+    return actions
+      .filter((item) => item)
+      .map((item: any) => {
+        return (
+          <div
+            className={classNames('card-button', {
+              disabled: item.disabled,
+            })}
+            key={item.key}
+          >
+            {item}
+          </div>
+        );
+      });
+  };
+
+  const defaultImage = require('/public/images/device-access.png');
+
   return (
     <div className="alarm-log-card">
       <SearchComponent<any>
@@ -119,130 +180,70 @@ const TabComponent = observer((props: Props) => {
       />
       <Card>
         {dataSource?.data.length > 0 ? (
-          <Row gutter={24} style={{ marginTop: 10 }}>
+          <Row gutter={[24, 24]} style={{ marginTop: 10 }}>
             {(dataSource?.data || []).map((item: any) => (
-              <Col key={item.id} span={24}>
-                <div className="alarm-log-item">
-                  <div className="alarm-log-title">
-                    <div
-                      className="alarm-log-level"
-                      style={{ backgroundColor: colorMap.get(item.level) }}
-                    >
-                      <div className="alarm-log-text">
-                        {AlarmLogModel.defaultLevel.find((i) => i.level === item.level)?.title ||
-                          item.level}
+              <Col key={item.id} span={12}>
+                <div className={classNames('iot-card')}>
+                  <div className={'card-warp'}>
+                    <div className={classNames('card-content')}>
+                      <div
+                        style={{ fontSize: 20, fontWeight: 700, marginBottom: 20 }}
+                        className="ellipsis"
+                      >
+                        <Tooltip title={item.alarmName}>
+                          <a>{item.alarmName}</a>
+                        </Tooltip>
                       </div>
-                    </div>
-                    <div className="alarm-log-title-text">
-                      <Tooltip placement="topLeft" title={item.alarmName}>
-                        {item.alarmName}
-                      </Tooltip>
-                    </div>
-                  </div>
-                  <div className="alarm-log-content">
-                    <div className="alarm-log-data">
-                      <div className="alarm-log-image">
-                        <img
-                          width={88}
-                          height={88}
-                          src={imgMap.get(props.type)}
-                          alt={''}
-                          style={{ marginRight: 20 }}
-                        />
-                        <div className="alarm-type">
-                          <div className="name">{titleMap.get(item.targetType)}</div>
-                          <div className="text">
-                            <Tooltip placement="topLeft" title={item.targetName}>
-                              {item.targetName}
-                            </Tooltip>
+                      <div className="alarm-log-context">
+                        <div className="context-left">
+                          <div className="context-img">
+                            <img width={70} height={70} src={defaultImage} alt={''} />
                           </div>
-                        </div>
-                      </div>
-                      <div className="alarm-log-right">
-                        <div className="alarm-log-time">
-                          <div className="log-title">最近告警时间</div>
-                          <div className="context">
-                            {moment(item.alarmTime).format('YYYY-MM-DD HH:mm:ss')}
+                          <div className="left-item">
+                            <div className="left-item-title">{titleMap.get(item.targetType)}</div>
+                            <div className="left-item-value ellipsis">
+                              <Tooltip placement="topLeft" title={item.targetName}>
+                                {item.targetName}
+                              </Tooltip>
+                            </div>
                           </div>
                         </div>
-                        <div
-                          className="alarm-log-time alarm-log-status"
-                          style={{ paddingLeft: 10 }}
-                        >
-                          <div className="log-title">状态</div>
-                          <div className="context">
-                            <Badge status={item.state.value === 'warning' ? 'error' : 'default'} />
-                            <span
-                              style={{
-                                color: item.state.value === 'warning' ? '#E50012' : 'black',
-                              }}
-                            >
-                              {item.state.text}
-                            </span>
+                        <div className="context-right">
+                          <div className="right-item">
+                            <div className="right-item-title">最近告警时间</div>
+                            <div className="right-item-value ellipsis">
+                              {moment(item.alarmTime).format('YYYY-MM-DD HH:mm:ss')}
+                            </div>
                           </div>
-                        </div>
-                      </div>
-                    </div>
-                    <div className="alarm-log-actions">
-                      <Space>
-                        {item.state.value === 'warning' && (
-                          <div
-                            className={classNames(
-                              permission.action ? 'alarm-log-action' : 'alarm-log-disabled',
-                            )}
-                          >
-                            <Tooltip title={permission.action ? '' : '暂无权限,请联系管理员'}>
-                              <Button
-                                type={'link'}
-                                disabled={!permission.action}
-                                onClick={() => {
-                                  AlarmLogModel.solveVisible = true;
-                                  AlarmLogModel.current = item;
+                          <div className="right-item">
+                            <div className="right-item-title">状态</div>
+                            <div className="right-item-value">
+                              <Badge
+                                status={item.state.value === 'warning' ? 'error' : 'default'}
+                              />
+                              <span
+                                style={{
+                                  color: item.state.value === 'warning' ? '#E50012' : 'black',
                                 }}
                               >
-                                <div className="btn">
-                                  <ToolFilled className="icon" />
-                                  <div>告警处理</div>
-                                </div>
-                              </Button>
-                            </Tooltip>
-                          </div>
-                        )}
-                        <div className="alarm-log-action">
-                          <Button
-                            type={'link'}
-                            onClick={() => {
-                              AlarmLogModel.current = item;
-                              const url = getMenuPathByParams(
-                                MENUS_CODE['rule-engine/Alarm/Log/Detail'],
-                                item.id,
-                              );
-                              history.push(url);
-                            }}
-                          >
-                            <div className="btn">
-                              <FileFilled className="icon" />
-                              <div>告警日志</div>
+                                {item.state.text}
+                              </span>
                             </div>
-                          </Button>
+                          </div>
                         </div>
-                        <div className="alarm-log-action">
-                          <Button
-                            type={'link'}
-                            onClick={() => {
-                              AlarmLogModel.logVisible = true;
-                              AlarmLogModel.current = item;
-                            }}
-                          >
-                            <div className="btn">
-                              <FileTextFilled className="icon" />
-                              <div>处理记录</div>
-                            </div>
-                          </Button>
+                      </div>
+                      <div
+                        className={'alarm-log-state'}
+                        style={{ backgroundColor: colorMap.get(item.level) }}
+                      >
+                        <div className={'card-state-content'}>
+                          {AlarmLogModel.defaultLevel.find((i) => i.level === item.level)?.title ||
+                            item.level}
                         </div>
-                      </Space>
+                      </div>
                     </div>
                   </div>
+                  <div className={'card-tools'}>{getAction(tools(item))}</div>
                 </div>
               </Col>
             ))}

+ 4 - 0
src/pages/rule-engine/Alarm/Log/index.tsx

@@ -11,6 +11,10 @@ export const service = new Service('alarm/record');
 const Log = observer(() => {
   const list = [
     {
+      key: 'all',
+      tab: '全部',
+    },
+    {
       key: 'product',
       tab: '产品',
     },

+ 1 - 1
src/pages/rule-engine/Alarm/Log/model.ts

@@ -12,7 +12,7 @@ export const AlarmLogModel = model<{
   }[];
   columns: ProColumns<AlarmLogHistoryItem>[];
 }>({
-  tab: 'product',
+  tab: 'all',
   current: {},
   solveVisible: false,
   logVisible: false,