Procházet zdrojové kódy

feat(alarm): alarm scene

lind před 3 roky
rodič
revize
08d2ab37c7

+ 161 - 0
src/components/FTermArrayCards/index.tsx

@@ -0,0 +1,161 @@
+import React from 'react';
+import { Card, Empty, Select } from 'antd';
+import { CardProps } from 'antd/lib/card';
+import { ArrayField } from '@formily/core';
+import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
+import cls from 'classnames';
+import { ISchema } from '@formily/json-schema';
+import { usePrefixCls } from '@formily/antd/lib/__builtins__';
+import { ArrayBase, ArrayBaseMixins } from '@formily/antd';
+
+type ComposedArrayCards = React.FC<CardProps> & ArrayBaseMixins;
+
+const isAdditionComponent = (schema: ISchema) => {
+  return schema['x-component']?.indexOf('Addition') > -1;
+};
+
+const isIndexComponent = (schema: ISchema) => {
+  return schema['x-component']?.indexOf('Index') > -1;
+};
+
+const isRemoveComponent = (schema: ISchema) => {
+  return schema['x-component']?.indexOf('Remove') > -1;
+};
+
+const isMoveUpComponent = (schema: ISchema) => {
+  return schema['x-component']?.indexOf('MoveUp') > -1;
+};
+
+const isMoveDownComponent = (schema: ISchema) => {
+  return schema['x-component']?.indexOf('MoveDown') > -1;
+};
+
+const isOperationComponent = (schema: ISchema) => {
+  return (
+    isAdditionComponent(schema) ||
+    isRemoveComponent(schema) ||
+    isMoveDownComponent(schema) ||
+    isMoveUpComponent(schema)
+  );
+};
+
+export const FTermArrayCards: ComposedArrayCards = observer((props) => {
+  const field = useField<ArrayField>();
+  const schema = useFieldSchema();
+  const dataSource = Array.isArray(field.value) ? field.value : [];
+  const prefixCls = usePrefixCls('formily-array-cards', props);
+
+  if (!schema) throw new Error('can not found schema object');
+
+  const renderItems = () => {
+    return dataSource?.map((item, index) => {
+      const items = Array.isArray(schema.items)
+        ? schema.items[index] || schema.items[0]
+        : schema.items;
+      const title = (
+        <span>
+          <RecursionField
+            schema={items!}
+            name={index}
+            filterProperties={(schema4) => {
+              if (!isIndexComponent(schema4)) return false;
+              return true;
+            }}
+            onlyRenderProperties
+          />
+          {props.title || field.title}
+        </span>
+      );
+      const extra = (
+        <span>
+          <RecursionField
+            schema={items!}
+            name={index}
+            filterProperties={(schema1) => {
+              if (!isOperationComponent(schema1)) return false;
+              return true;
+            }}
+            onlyRenderProperties
+          />
+          {props.extra}
+        </span>
+      );
+      const content = (
+        <RecursionField
+          schema={items!}
+          name={index}
+          filterProperties={(schema2) => {
+            if (isIndexComponent(schema2)) return false;
+            if (isOperationComponent(schema2)) return false;
+            return true;
+          }}
+        />
+      );
+      console.log(index, 'index');
+      return (
+        ArrayBase.Item && (
+          <ArrayBase.Item key={index} index={index} record={item}>
+            {index > 0 && (
+              <div style={{ margin: 10, display: 'flex', justifyContent: 'center' }}>
+                <Select
+                  value="or"
+                  style={{ width: '200px' }}
+                  options={[
+                    { label: '或者', value: 'or' },
+                    { label: '并且', value: 'and' },
+                  ]}
+                />
+              </div>
+            )}
+            <Card
+              {...props}
+              onChange={() => {}}
+              className={cls(`${prefixCls}-item`, props.className)}
+              title={title}
+              extra={extra}
+            >
+              {content}
+            </Card>
+          </ArrayBase.Item>
+        )
+      );
+    });
+  };
+
+  const renderAddition = () => {
+    return schema.reduceProperties((addition, schema3, key) => {
+      if (isAdditionComponent(schema3)) {
+        return <RecursionField schema={schema3} name={key} />;
+      }
+      return addition;
+    }, null);
+  };
+
+  const renderEmpty = () => {
+    if (dataSource?.length) return;
+    return (
+      <Card
+        {...props}
+        onChange={() => {}}
+        className={cls(`${prefixCls}-item`, props.className)}
+        title={props.title || field.title}
+      >
+        <Empty />
+      </Card>
+    );
+  };
+
+  return (
+    <ArrayBase>
+      {renderEmpty()}
+      {renderItems()}
+      {renderAddition()}
+    </ArrayBase>
+  );
+});
+
+FTermArrayCards.displayName = 'FTermArrayCards';
+
+ArrayBase.mixin!(FTermArrayCards);
+
+export default FTermArrayCards;

+ 8 - 0
src/components/FTermArrayCards/style.less

@@ -0,0 +1,8 @@
+@root-entry-name: 'default';
+@import (reference) '~antd/es/style/themes/index.less';
+
+@array-cards-prefix-cls: ~'@{ant-prefix}-formily-array-cards';
+
+.@{array-cards-prefix-cls}-item {
+  margin-bottom: 10px !important;
+}

+ 4 - 0
src/components/FTermArrayCards/style.ts

@@ -0,0 +1,4 @@
+import 'antd/lib/card/style/index';
+import 'antd/lib/empty/style/index';
+import 'antd/lib/button/style/index';
+import './style.less';

+ 18 - 0
src/components/FTermTypeSelect/index.tsx

@@ -0,0 +1,18 @@
+import { ArrayItems, Select } from '@formily/antd';
+
+const FTermTypeSelect = () => {
+  const index = ArrayItems.useIndex!();
+  return index > 0 ? (
+    <div style={{ width: '100%', marginBottom: 15, display: 'flex', justifyContent: 'center' }}>
+      <Select
+        style={{ width: '200px' }}
+        value="or"
+        options={[
+          { label: '并且', value: 'and' },
+          { label: '或者', value: 'or' },
+        ]}
+      />
+    </div>
+  ) : null;
+};
+export default FTermTypeSelect;

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

@@ -6,10 +6,10 @@ import Import from './Import';
 import type { ReactNode } from 'react';
 import { useState } from 'react';
 import Cat from './Cat';
-// import Service from '@/pages/device/components/Metadata/service';
+import Service from '@/pages/device/components/Metadata/service';
 import { InfoCircleOutlined } from '@ant-design/icons';
 import styles from './index.less';
-import { InstanceModel, service } from '@/pages/device/Instance';
+import { InstanceModel, service as instanceService } from '@/pages/device/Instance';
 import { PermissionButton } from '@/components';
 import { Store } from 'jetlinks-store';
 import SystemConst from '@/utils/const';
@@ -21,7 +21,7 @@ interface Props {
   independentMetadata?: boolean;
 }
 
-// export const service = new Service();
+export const service = new Service();
 const Metadata = observer((props: Props) => {
   const intl = useIntl();
   const [visible, setVisible] = useState<boolean>(false);
@@ -33,7 +33,7 @@ const Metadata = observer((props: Props) => {
   const params = useParams<{ id: string }>();
 
   const resetMetadata = async () => {
-    const resp = await service.deleteMetadata(params.id);
+    const resp = await instanceService.deleteMetadata(params.id);
     if (resp.status === 200) {
       message.success('操作成功');
       Store.set(SystemConst.REFRESH_DEVICE, true);

+ 8 - 7
src/pages/notice/Config/Detail/index.tsx

@@ -63,15 +63,15 @@ const Detail = observer(() => {
       createForm({
         validateFirst: true,
         effects() {
-          onFieldValueChange('type', async (field, f) => {
+          onFieldValueChange('type', async (field) => {
             const type = field.value;
             if (!type) return;
-            f.setFieldState('provider', (state1) => {
-              state1.value = undefined;
-              // state.dataSource = providerRef.current
-              //   .find((item) => type === item.id)
-              //   ?.providerInfos.map((i) => ({ label: i.name, value: i.id }));
-            });
+            // f.setFieldState('provider', (state1) => {
+            // state1.value = undefined;
+            // state.dataSource = providerRef.current
+            //   .find((item) => type === item.id)
+            //   ?.providerInfos.map((i) => ({ label: i.name, value: i.id }));
+            // });
           });
           onFieldValueChange('provider', async (field) => {
             if (id === 'email') {
@@ -145,6 +145,7 @@ const Detail = observer(() => {
         required: true,
         'x-visible': typeList[id]?.length > 0,
         'x-hidden': id === 'email',
+        'x-value': typeList[id][0]?.value,
         enum: typeList[id] || [],
       },
       configuration: {

+ 4 - 2
src/pages/notice/Template/Detail/index.tsx

@@ -347,6 +347,7 @@ const Detail = observer(() => {
     }
   };
 
+  console.log(typeList[id][0]);
   const schema: ISchema = {
     type: 'object',
     properties: {
@@ -387,6 +388,7 @@ const Detail = observer(() => {
         required: true,
         'x-visible': typeList[id]?.length > 0,
         'x-hidden': id === 'email',
+        'x-value': typeList[id][0]?.value,
         enum: typeList[id] || [],
       },
       configId: {
@@ -653,11 +655,11 @@ const Detail = observer(() => {
                         'x-component': 'Select',
                         'x-decorator': 'FormItem',
                         'x-decorator-props': {
-                          tooltip: '请输入收信部门ID',
+                          tooltip: '收信部门ID',
                           gridSpan: 1,
                         },
                         'x-component-props': {
-                          placeholder: '请输入AgentID',
+                          placeholder: '请选择收信部门',
                         },
                         'x-reactions': {
                           dependencies: ['configId'],

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

@@ -56,7 +56,7 @@ export const typeList = {
   ],
   email: [
     {
-      value: 'email',
+      value: 'embedded',
       label: '默认',
     },
   ],

+ 0 - 26
src/pages/rule-engine/Scene/Save/action/index.tsx

@@ -1,26 +0,0 @@
-import ActionItem from './action';
-import './index.less';
-import { ProFormList } from '@ant-design/pro-form';
-
-export default () => {
-  return (
-    <div className={'actions-items'}>
-      <ProFormList
-        name={'actions'}
-        creatorButtonProps={{
-          creatorButtonText: '新增',
-        }}
-      >
-        {(meta, index, action) => {
-          return (
-            <ActionItem
-              onRemove={() => {
-                action.remove?.(index);
-              }}
-            />
-          );
-        }}
-      </ProFormList>
-    </div>
-  );
-};

+ 4 - 0
src/pages/rule-engine/Scene/Save/index.tsx

@@ -5,6 +5,7 @@ import { useEffect } from 'react';
 import { PermissionButton } from '@/components';
 import ActionItems from './action/action';
 import { PlusOutlined } from '@ant-design/icons';
+import TriggerTerm from '@/pages/rule-engine/Scene/TriggerTerm';
 
 export default () => {
   const location = useLocation();
@@ -62,6 +63,9 @@ export default () => {
           保存
         </PermissionButton>
       </Card>
+      <Card>
+        <TriggerTerm />
+      </Card>
     </PageContainer>
   );
 };

+ 7 - 0
src/pages/rule-engine/Scene/TriggerTerm/index.less

@@ -0,0 +1,7 @@
+.form {
+  :global {
+    .ant-formily-array-cards-item {
+      background-color: #f9f9f9;
+    }
+  }
+}

+ 165 - 0
src/pages/rule-engine/Scene/TriggerTerm/index.tsx

@@ -0,0 +1,165 @@
+import { createSchemaField } from '@formily/react';
+import {
+  ArrayCards,
+  ArrayItems,
+  Form,
+  FormGrid,
+  FormItem,
+  Input,
+  Select,
+  Space,
+} from '@formily/antd';
+import { ISchema } from '@formily/json-schema';
+import { createForm } from '@formily/core';
+import { useMemo } from 'react';
+import FTermArrayCards from '@/components/FTermArrayCards';
+import FTermTypeSelect from '@/components/FTermTypeSelect';
+import styles from './index.less';
+
+const TriggerTerm = () => {
+  const form = useMemo(() => createForm({}), []);
+  const SchemaField = createSchemaField({
+    components: {
+      FormItem,
+      Input,
+      Select,
+      ArrayCards,
+      FTermArrayCards,
+      ArrayItems,
+      Space,
+      FormGrid,
+      FTermTypeSelect,
+    },
+  });
+
+  const schema: ISchema = {
+    type: 'object',
+    properties: {
+      trigger: {
+        type: 'array',
+        'x-component': 'FTermArrayCards',
+        'x-decorator': 'FormItem',
+        'x-component-props': {
+          title: '分组',
+        },
+        items: {
+          type: 'object',
+          properties: {
+            index: {
+              type: 'void',
+              'x-component': 'FTermArrayCards.Index',
+            },
+            terms: {
+              type: 'array',
+              'x-component': 'ArrayItems',
+              'x-decorator': 'FormItem',
+              items: {
+                type: 'object',
+                properties: {
+                  termType: {
+                    type: 'string',
+                    // "x-decorator": 'FormItem',
+                    'x-component': 'FTermTypeSelect',
+                  },
+                  layout: {
+                    type: 'void',
+                    'x-component': 'FormGrid',
+                    'x-decorator-props': {
+                      maxColumns: 24,
+                      minColumns: 24,
+                    },
+                    properties: {
+                      params: {
+                        type: 'string',
+                        // title: '日期',
+                        'x-decorator': 'FormItem',
+                        'x-component': 'Input',
+                        'x-decorator-props': {
+                          gridSpan: 4,
+                        },
+                        'x-component-props': {
+                          placeholder: '请选择参数',
+                        },
+                      },
+                      operator: {
+                        type: 'string',
+                        // title: '输入框',
+                        'x-decorator': 'FormItem',
+                        'x-component': 'Select',
+                        'x-decorator-props': {
+                          gridSpan: 3,
+                        },
+                        'x-component-props': {
+                          placeholder: '操作符',
+                        },
+                      },
+                      type: {
+                        type: 'string',
+                        'x-decorator': 'FormItem',
+                        'x-component': 'Select',
+                        enum: [
+                          { label: '手动输入', value: 'sd' },
+                          { label: '指标', value: 'metrics' },
+                        ],
+                        'x-decorator-props': {
+                          gridSpan: 3,
+                        },
+                      },
+                      value: {
+                        type: 'string',
+                        enum: [
+                          { label: '高高值', value: 1 },
+                          { label: '低低值', value: 2 },
+                          { label: '高值', value: 3 },
+                          { label: '低值', value: 4 },
+                        ],
+                        'x-decorator': 'FormItem',
+                        'x-component': 'Select',
+                        'x-component-props': {},
+                        'x-decorator-props': {
+                          gridSpan: 3,
+                        },
+                      },
+                      remove: {
+                        type: 'void',
+                        'x-decorator': 'FormItem',
+                        'x-component': 'ArrayItems.Remove',
+                        'x-decorator-props': {
+                          gridSpan: 1,
+                        },
+                      },
+                    },
+                  },
+                },
+              },
+              properties: {
+                add: {
+                  type: 'void',
+                  title: '添加条件',
+                  'x-component': 'ArrayItems.Addition',
+                },
+              },
+            },
+            remove: {
+              type: 'void',
+              'x-component': 'FTermArrayCards.Remove',
+            },
+          },
+        },
+        properties: {
+          addition: {
+            type: 'void',
+            title: '添加分组',
+            'x-component': 'FTermArrayCards.Addition',
+          },
+        },
+      },
+    },
+  };
+  return (
+    <Form form={form} layout="vertical" className={styles.form}>
+      <SchemaField schema={schema} />
+    </Form>
+  );
+};
+export default TriggerTerm;

+ 60 - 16
src/pages/system/User/ResetPassword/index.tsx

@@ -51,18 +51,40 @@ const ResetPassword = (props: Props) => {
         ],
         name: 'password',
         'x-validator': [
-          {
-            max: 128,
-            message: '密码最多可输入128位',
-          },
-          {
-            min: 8,
-            message: '密码不能少于6位',
-          },
+          // {
+          //   max: 128,
+          //   message: '密码最多可输入128位',
+          // },
+          // {
+          //   min: 8,
+          //   message: '密码不能少于8位',
+          // },
           {
             required: true,
             message: '请输入密码',
           },
+          {
+            triggerType: 'onBlur',
+            validator: (value: string) => {
+              return new Promise((resolve) => {
+                service
+                  .validateField('password', value)
+                  .then((resp) => {
+                    if (resp.status === 200) {
+                      if (resp.result.passed) {
+                        resolve('');
+                      } else {
+                        resolve(resp.result.reason);
+                      }
+                    }
+                    resolve('');
+                  })
+                  .catch(() => {
+                    return '验证失败!';
+                  });
+              });
+            },
+          },
         ],
       },
       confirmPassword: {
@@ -78,18 +100,40 @@ const ResetPassword = (props: Props) => {
           placeholder: '请再次输入密码',
         },
         'x-validator': [
-          {
-            max: 128,
-            message: '密码最多可输入128位',
-          },
-          {
-            min: 8,
-            message: '密码不能少于8位',
-          },
+          // {
+          //   max: 128,
+          //   message: '密码最多可输入128位',
+          // },
+          // {
+          //   min: 8,
+          //   message: '密码不能少于8位',
+          // },
           {
             required: true,
             message: '请输入确认密码',
           },
+          {
+            triggerType: 'onBlur',
+            validator: (value: string) => {
+              return new Promise((resolve) => {
+                service
+                  .validateField('password', value)
+                  .then((resp) => {
+                    if (resp.status === 200) {
+                      if (resp.result.passed) {
+                        resolve('');
+                      } else {
+                        resolve(resp.result.reason);
+                      }
+                    }
+                    resolve('');
+                  })
+                  .catch(() => {
+                    return '验证失败!';
+                  });
+              });
+            },
+          },
         ],
         'x-reactions': [
           {

+ 41 - 16
src/pages/system/User/Save/index.tsx

@@ -214,14 +214,14 @@ const Save = (props: Props) => {
         ],
         name: 'password',
         'x-validator': [
-          {
-            max: 128,
-            message: '密码最多可输入128位',
-          },
-          {
-            min: 8,
-            message: '密码不能少于6位',
-          },
+          // {
+          //   max: 128,
+          //   message: '密码最多可输入128位',
+          // },
+          // {
+          //   min: 8,
+          //   message: '密码不能少于8位',
+          // },
           {
             required: model === 'add',
             message: '请输入密码',
@@ -242,19 +242,42 @@ const Save = (props: Props) => {
         },
         'x-visible': model === 'add',
         'x-validator': [
-          {
-            max: 128,
-            message: '密码最多可输入128位',
-          },
-          {
-            min: 8,
-            message: '密码不能少于6位',
-          },
+          // {
+          //   max: 128,
+          //   message: '密码最多可输入128位',
+          // },
+          // {
+          //   min: 8,
+          //   message: '密码不能少于6位',
+          // },
           {
             required: model === 'add',
             message: '请输入确认密码',
           },
+          {
+            triggerType: 'onBlur',
+            validator: (value: string) => {
+              return new Promise((resolve) => {
+                service
+                  .validateField('password', value)
+                  .then((resp) => {
+                    if (resp.status === 200) {
+                      if (resp.result.passed) {
+                        resolve('');
+                      } else {
+                        resolve(model === 'edit' ? '' : resp.result.reason);
+                      }
+                    }
+                    resolve('');
+                  })
+                  .catch(() => {
+                    return '验证失败!';
+                  });
+              });
+            },
+          },
         ],
+
         'x-reactions': [
           {
             dependencies: ['.password'],
@@ -368,6 +391,7 @@ const Save = (props: Props) => {
             title: '手机号',
             'x-decorator': 'FormItem',
             'x-component': 'Input',
+            'x-validator': 'phone',
             'x-decorator-props': {
               gridSpan: 1,
             },
@@ -376,6 +400,7 @@ const Save = (props: Props) => {
             title: '邮箱',
             'x-decorator': 'FormItem',
             'x-component': 'Input',
+            'x-validator': 'email',
             'x-decorator-props': {
               gridSpan: 1,
             },