lind 3 лет назад
Родитель
Сommit
f3e263a5d6

+ 39 - 0
src/components/ProTableCard/CardItems/AlarmConfig.tsx

@@ -0,0 +1,39 @@
+import React from 'react';
+import { TableCard } from '@/components';
+import '@/style/common.less';
+import '../index.less';
+
+export interface AlarmConfigProps extends TemplateItem {
+  detail?: React.ReactNode;
+  actions?: React.ReactNode[];
+  avatarSize?: number;
+}
+
+export const aliyunSms = require('/public/images/notice/sms.png');
+
+export default (props: AlarmConfigProps) => {
+  return (
+    <TableCard actions={props.actions} showStatus={false} detail={props.detail} showMask={false}>
+      <div className={'pro-table-card-item'}>
+        <div className={'card-item-avatar'}>
+          <img width={88} height={88} src={aliyunSms} alt={props.type} />
+        </div>
+        <div className={'card-item-body'}>
+          <div className={'card-item-header'}>
+            <span className={'card-item-header-name ellipsis'}>{props.name}</span>
+          </div>
+          <div className={'card-item-content'}>
+            <div>
+              <label>告警名称</label>
+              <div className={'ellipsis'}>{props.name}</div>
+            </div>
+            <div>
+              <label>说明</label>
+              <div className={'ellipsis'}>{props.description}</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </TableCard>
+  );
+};

+ 102 - 75
src/components/SearchComponent/index.tsx

@@ -100,6 +100,10 @@ const SchemaField = createSchemaField({
   },
 });
 
+/**
+ * 搜索字段排序
+ * @param field
+ */
 const sortField = (field: ProColumns[]) => {
   let _temp = false;
   field.forEach((item) => {
@@ -124,11 +128,21 @@ const sortField = (field: ProColumns[]) => {
   return _.sortBy(field, (i) => i.index);
 };
 
+// 保存历史记录
+// 过滤不参与搜索的列数据 ==> 字段排序
+
+// 场景一:简单模式
+// 默认搜索参数,根据Index 来判断,或者默认name为第一组条件
+
+// 场景二:高级模式
+// 默认六组搜索条件。根据字段index排序
+
 const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
   const { field, target, onSearch, defaultParam, enableSave = true, initParam } = props;
 
   /**
-   * 过滤不参与搜索的数据
+   * 过滤不参与搜索的数据 ?
+   * TODO Refactor 依赖透明?
    */
   const filterSearchTerm = (): ProColumns<T>[] =>
     field
@@ -136,6 +150,17 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
       .filter((item) => !item.hideInSearch)
       .filter((item) => !['index', 'option'].includes(item.dataIndex as string));
 
+  /**
+   * 根据dataIndex 过滤不参与查询的参数
+   *
+   * @param _field 查询的列
+   * @param excludes 过滤的字段名称
+   */
+  // const filterSearchTerm2 = (_field: ProColumns<T>[] = [], excludes: string[] = []) =>
+  //   _field.filter(item => item.dataIndex)
+  //     .filter(item => !item.hideInSearch)
+  //     .filter(item => !excludes.includes(item.dataIndex as string))
+
   // 处理后的搜索条件
   const processedField = sortField(filterSearchTerm());
   const defaultTerms = (index: number) =>
@@ -144,102 +169,104 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
       column: (processedField[index]?.dataIndex as string) || null,
       type: 'or',
     } as Partial<Term>);
+
   const intl = useIntl();
   const [expand, setExpand] = useState<boolean>(true);
   const initForm = server2Ui(initParam || [{ terms: [defaultTerms(0)] }]);
   const [aliasVisible, setAliasVisible] = useState<boolean>(false);
-
   const [initParams, setInitParams] = useState<SearchTermsUI>(initForm);
   const [history, setHistory] = useState([]);
   const [logVisible, setLogVisible] = useState<boolean>(false);
+  const uiParamRef = useRef(initParam);
+
   const form = useMemo(
     () =>
       createForm<SearchTermsUI>({
         validateFirst: true,
         initialValues: initParams,
         effects() {
-          // onFormInit((form1) => {
-          //   if (expand && !initParam) {
-          //     form1.setValues({
-          //       terms1: [{column: processedField[0]?.dataIndex, termType: 'like'}],
-          //     });
-          //   }
-          // });
           onFieldReact('*.*.column', async (typeFiled, f) => {
             const _column = (typeFiled as Field).value;
+
             const _field = field.find((item) => item.dataIndex === _column);
-            if (_field?.valueType === 'select') {
-              let option: { label: any; value: any }[] | FieldDataSource | undefined = [];
-              if (_field?.valueEnum) {
-                option = Object.values(_field?.valueEnum || {}).map((item) => ({
-                  label: item.text,
-                  value: item.status,
-                }));
-              } else if (_field?.request) {
-                option = await _field.request();
-              }
-              f.setFieldState(typeFiled.query('.termType'), async (state) => {
-                state.value = 'eq';
-              });
-              f.setFieldState(typeFiled.query('.value'), async (state) => {
-                state.componentType = 'Select';
-                // state.loading = true;
-                state.dataSource = option;
-                // state.loading = false;
-              });
-            } else if (_field?.valueType === 'treeSelect') {
-              let option: { label: any; value: any }[] | FieldDataSource | undefined = [];
-              if (_field?.valueEnum) {
-                option = Object.values(_field?.valueEnum || {}).map((item) => ({
-                  label: item.text,
-                  value: item.status,
-                }));
-              } else if (_field?.request) {
-                option = await _field.request();
-              }
-              f.setFieldState(typeFiled.query('.termType'), (_state) => {
-                _state.value = 'eq';
-              });
-              f.setFieldState(typeFiled.query('.value'), (state) => {
-                state.componentType = 'TreeSelect';
-                state.dataSource = option;
-                console.log(option, 'optin');
-                state.componentProps = {
-                  ..._field.fieldProps,
-                  treeNodeFilterProp: 'name',
-                  // filterOption: (input: string, option: any) =>
-                  //   option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0,
-                };
-              });
-            } else if (_field?.valueType === 'digit') {
-              f.setFieldState(typeFiled.query('.value'), async (state) => {
-                state.componentType = 'NumberPicker';
-              });
-              f.setFieldState(typeFiled.query('.termType'), async (state) => {
-                state.value = 'eq';
-              });
-            } else if (_field?.valueType === 'dateTime') {
-              f.setFieldState(typeFiled.query('.value'), async (state) => {
-                state.componentType = 'DatePicker';
-                state.componentProps = { showTime: true };
-              });
-              f.setFieldState(typeFiled.query('.termType'), async (state) => {
-                state.value = 'gte';
-              });
-            } else {
-              f.setFieldState(typeFiled.query('.value'), async (state) => {
-                state.componentType = 'Input';
-              });
-            }
             if (_column === 'id') {
               f.setFieldState(typeFiled.query('.termType'), async (state) => {
                 state.value = 'eq';
               });
+            } else {
+              switch (_field?.valueType) {
+                case 'select':
+                  let __option: { label: any; value: any }[] | FieldDataSource | undefined = [];
+                  if (_field?.valueEnum) {
+                    __option = Object.values(_field?.valueEnum || {}).map((item) => ({
+                      label: item.text,
+                      value: item.status,
+                    }));
+                  } else if (_field?.request) {
+                    __option = await _field.request();
+                  }
+                  f.setFieldState(typeFiled.query('.termType'), async (state) => {
+                    state.value = 'eq';
+                  });
+                  f.setFieldState(typeFiled.query('.value'), async (state) => {
+                    console.log(_field, 'productName');
+
+                    state.componentType = 'Select';
+                    // state.loading = true;
+                    state.dataSource = __option;
+                    // state.loading = false;
+                  });
+                  break;
+                case 'treeSelect':
+                  let _option: { label: any; value: any }[] | FieldDataSource | undefined = [];
+                  if (_field?.valueEnum) {
+                    _option = Object.values(_field?.valueEnum || {}).map((item) => ({
+                      label: item.text,
+                      value: item.status,
+                    }));
+                  } else if (_field?.request) {
+                    _option = await _field.request();
+                  }
+                  f.setFieldState(typeFiled.query('.termType'), (_state) => {
+                    _state.value = 'eq';
+                  });
+                  f.setFieldState(typeFiled.query('.value'), (state) => {
+                    state.componentType = 'TreeSelect';
+                    state.dataSource = _option;
+                    state.componentProps = {
+                      ..._field.fieldProps,
+                      treeNodeFilterProp: 'name',
+                    };
+                  });
+                  break;
+                case 'digit':
+                  f.setFieldState(typeFiled.query('.value'), async (state) => {
+                    state.componentType = 'NumberPicker';
+                  });
+                  f.setFieldState(typeFiled.query('.termType'), async (state) => {
+                    state.value = 'eq';
+                  });
+                  break;
+                case 'dateTime':
+                  f.setFieldState(typeFiled.query('.value'), async (state) => {
+                    state.componentType = 'DatePicker';
+                    state.componentProps = { showTime: true };
+                  });
+                  f.setFieldState(typeFiled.query('.termType'), async (state) => {
+                    state.value = 'gte';
+                  });
+                  break;
+                default:
+                  f.setFieldState(typeFiled.query('.value'), async (state) => {
+                    state.componentType = 'Input';
+                  });
+                  break;
+              }
             }
           });
           onFieldValueChange('*.*.column', (field1, form1) => {
             form1.setFieldState(field1.query('.value'), (state1) => {
-              state1.value = null;
+              state1.value = undefined;
             });
           });
         },
@@ -355,8 +382,6 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
     },
   };
 
-  const uiParamRef = useRef(initParam);
-
   const handleForm = (_expand?: boolean) => {
     const value = form.values;
     const __expand = _expand || expand;
@@ -398,12 +423,14 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
       handleExpand();
     }
   }, [initParam]);
+
   const simpleSchema: ISchema = {
     type: 'object',
     properties: {
       terms1: createGroup('第一组'),
     },
   };
+
   const handleHistory = (item: SearchHistory) => {
     const log = JSON.parse(item.content) as SearchTermsUI;
     setLogVisible(false);

+ 0 - 4
src/pages/device/components/Metadata/Base/Edit/index.tsx

@@ -94,10 +94,6 @@ const Edit = observer((props: Props) => {
               }
             });
           });
-          /// 处理Boolean 类型
-          // expands.metrics.0.edit.space.value.0 路径
-          // const metricsPath = field.query('expands.metrics.value.0');
-          // form.setValuesIn('expands.metrics.value.0', 'testtttt')
         },
       }),
     [],

+ 22 - 7
src/pages/rule-engine/Alarm/Configuration/Save/index.tsx

@@ -10,10 +10,12 @@ import Service from '@/pages/rule-engine/Alarm/Configuration/service';
 import { useAsyncDataSource } from '@/utils/util';
 import styles from './index.less';
 import { service as ConfigService } from '../../Config';
+import { Store } from 'jetlinks-store';
 
 interface Props {
   visible: boolean;
   close: () => void;
+  data: any;
 }
 
 const alarm1 = require('/public/images/alarm/alarm1.png');
@@ -48,7 +50,6 @@ const Save = (props: Props) => {
   const getLevel = () => {
     return ConfigService.queryLevel().then((resp) => {
       if (resp.status === 200) {
-        console.log(resp, 'resp');
         return resp.result?.levels?.map((item: { level: number; title: string }) => ({
           label: createImageLabel(LevelMap[item.level], item.title),
           value: item.level,
@@ -56,13 +57,21 @@ const Save = (props: Props) => {
       }
     });
   };
+
+  const getScene = () => {
+    return service.getScene().then((resp) => {
+      Store.set('scene-data', resp);
+      return resp;
+    });
+  };
   const form = useMemo(
     () =>
       createForm({
+        initialValues: props.data,
         validateFirst: true,
         effects() {},
       }),
-    [],
+    [props.data],
   );
 
   const getSupports = () => service.getTargetTypes();
@@ -78,11 +87,13 @@ const Save = (props: Props) => {
   });
 
   const handleSave = async () => {
-    const data: ConfigItem = await form.submit();
-    console.log(data, 'dat');
-    const resp: any = await service.update(data);
+    const data: any = await form.submit();
+    const list = Store.get('scene-data');
+    const scene = list.find((item: any) => item.value === data.sceneId);
+    const resp: any = await service.update({ ...data, sceneName: scene.label, state: 'disable' });
     if (resp.status === 200) {
       message.success('操作成功');
+      props.close();
     }
   };
 
@@ -109,7 +120,7 @@ const Save = (props: Props) => {
               placeholder: '请输入名称',
             },
           },
-          type: {
+          targetType: {
             title: '类型',
             'x-decorator': 'FormItem',
             'x-component': 'Select',
@@ -140,6 +151,7 @@ const Save = (props: Props) => {
         title: '关联触发场景',
         'x-decorator': 'FormItem',
         'x-component': 'Select',
+        'x-reactions': '{{useAsyncDataSource(getScene)}}',
         'x-decorator-props': {
           gridSpan: 1,
           addonAfter: (
@@ -194,7 +206,10 @@ const Save = (props: Props) => {
       title="新增告警"
     >
       <Form className={styles.form} form={form} layout="vertical">
-        <SchemaField schema={schema} scope={{ useAsyncDataSource, getSupports, getLevel }} />
+        <SchemaField
+          schema={schema}
+          scope={{ useAsyncDataSource, getSupports, getLevel, getScene }}
+        />
       </Form>
     </Modal>
   );

+ 53 - 4
src/pages/rule-engine/Alarm/Configuration/index.tsx

@@ -8,10 +8,16 @@ import { useRef, useState } from 'react';
 import { Space } from 'antd';
 import ProTableCard from '@/components/ProTableCard';
 import Save from './Save';
+import Service from '@/pages/rule-engine/Alarm/Configuration/service';
+import AlarmConfig from '@/components/ProTableCard/CardItems/AlarmConfig';
+
+const service = new Service('alarm/config');
 
 const Configuration = () => {
   const intl = useIntl();
+  const [visible, setVisible] = useState<boolean>(false);
 
+  const [current, setCurrent] = useState<any>();
   const columns: ProColumns<ConfigItem>[] = [
     {
       dataIndex: 'name',
@@ -32,6 +38,7 @@ const Configuration = () => {
     {
       title: '状态',
       dataIndex: 'state',
+      renderText: (state) => state.text,
     },
     {
       title: '说明',
@@ -44,20 +51,29 @@ const Configuration = () => {
       render: (_, record) => [
         <PermissionButton
           isPermission={true}
+          style={{ padding: 0 }}
           tooltip={{
             title: intl.formatMessage({
               id: 'pages.data.option.edit',
               defaultMessage: '编辑',
             }),
           }}
+          type="link"
           onClick={() => {
-            console.log(record);
+            setVisible(true);
+            setCurrent(record);
           }}
         >
           <EditOutlined />
         </PermissionButton>,
         <PermissionButton
+          type="link"
           isPermission={true}
+          style={{ padding: 0 }}
+          popConfirm={{
+            title: '确认删除?',
+            onConfirm: () => service.remove(record.id),
+          }}
           tooltip={{
             title: intl.formatMessage({
               id: 'pages.data.option.remove',
@@ -75,7 +91,6 @@ const Configuration = () => {
 
   const [param, setParam] = useState({});
 
-  const [visible, setVisible] = useState<boolean>(false);
   return (
     <PageContainer>
       <SearchComponent
@@ -85,17 +100,51 @@ const Configuration = () => {
           setParam(data);
         }}
       />
-      <ProTableCard<ConfigItem>
+      <ProTableCard<any>
         actionRef={actionRef}
         rowKey="id"
         search={false}
         params={param}
         columns={columns}
+        request={(params) => service.query(params)}
+        gridColumn={3}
+        cardRender={(record) => (
+          <AlarmConfig
+            {...record}
+            actions={[
+              <PermissionButton
+                isPermission={true}
+                key="edit"
+                onClick={() => {
+                  setCurrent(record);
+                  setVisible(true);
+                }}
+              >
+                <EditOutlined />
+                编辑
+              </PermissionButton>,
+              <PermissionButton
+                popConfirm={{
+                  title: '确认删除?',
+                  onConfirm: async () => {
+                    await service.remove(record.id);
+                    actionRef.current?.reset?.();
+                  },
+                }}
+                isPermission={true}
+                key="delete"
+              >
+                <DeleteOutlined />
+              </PermissionButton>,
+            ]}
+          />
+        )}
         headerTitle={
           <Space>
             <PermissionButton
               isPermission={true}
               onClick={() => {
+                setCurrent(undefined);
                 setVisible(true);
               }}
               key="button"
@@ -110,7 +159,7 @@ const Configuration = () => {
           </Space>
         }
       />
-      <Save visible={visible} close={() => setVisible(false)} />
+      <Save data={current} visible={visible} close={() => setVisible(false)} />
     </PageContainer>
   );
 };

+ 10 - 0
src/pages/rule-engine/Alarm/Configuration/service.ts

@@ -12,6 +12,16 @@ class Service extends BaseService<ConfigItem> {
         value: item.id,
       }));
     });
+
+  public getScene = () =>
+    request(`/${SystemConst.API_BASE}/scene/_query/no-paging?paging=false`, {
+      method: 'GET',
+    }).then((resp) => {
+      return resp.result.map((item: { id: string; name: string }) => ({
+        label: item.name,
+        value: item.id,
+      }));
+    });
 }
 
 export default Service;