Переглянути джерело

feat(metadata): add event/function metadata form

Lind 4 роки тому
батько
коміт
9ce069cf58

+ 6 - 2
src/components/Metadata/JsonParam/index.tsx

@@ -13,7 +13,11 @@ import { DataTypeList } from '@/pages/device/data';
 import { Store } from 'jetlinks-store';
 
 // 不算是自定义组件。只是抽离了JSONSchema
-const JsonParam = () => {
+interface Props {
+  keys?: string;
+}
+
+const JsonParam = (props: Props) => {
   const SchemaField = createSchemaField({
     components: {
       FormItem,
@@ -29,7 +33,7 @@ const JsonParam = () => {
   const schema: ISchema = {
     type: 'object',
     properties: {
-      properties: {
+      [props?.keys || 'properties']: {
         type: 'array',
         'x-component': 'ArrayItems',
         'x-decorator': 'FormItem',

+ 233 - 246
src/pages/device/Product/Detail/Metadata/Base/Edit/index.tsx

@@ -47,6 +47,33 @@ const Edit = () => {
     initialValues: MetadataModel.item as Record<string, unknown>,
   });
 
+  const schemaTitleMapping = {
+    properties: {
+      title: intl.formatMessage({
+        id: 'pages.device.productDetail.metadata.dataType',
+        defaultMessage: '数据类型',
+      }),
+    },
+    events: {
+      title: intl.formatMessage({
+        id: 'pages.device.productDetail.metadata.inputParameter',
+        defaultMessage: '输出参数',
+      }),
+    },
+    functions: {
+      title: intl.formatMessage({
+        id: 'pages.device.productDetail.metadata.inputParameter',
+        defaultMessage: '输出参数',
+      }),
+    },
+    tags: {
+      title: intl.formatMessage({
+        id: 'pages.device.productDetail.metadata.dataType',
+        defaultMessage: '数据类型',
+      }),
+    },
+  };
+
   const param = useParams<{ id: string }>();
   const SchemaField = createSchemaField({
     components: {
@@ -97,207 +124,221 @@ const Edit = () => {
 
   const [units, setUnits] = useState<{ label: string; value: string }[]>();
 
-  const propertySchema: ISchema = {
+  const valueTypeConfig = {
     type: 'object',
+    'x-index': 4,
     properties: {
-      id: {
-        title: intl.formatMessage({
-          id: 'pages.device.productDetail.metadata.key',
-          defaultMessage: '标识',
-        }),
+      type: {
+        title: schemaTitleMapping[MetadataModel.type].title,
         required: true,
         'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        'x-disabled': MetadataModel.action === 'edit',
+        'x-component': 'Select',
+        enum: DataTypeList,
       },
-      name: {
+      unit: {
         title: intl.formatMessage({
-          id: 'pages.table.name',
-          defaultMessage: '名称',
+          id: 'pages.device.instanceDetail.metadata.unit',
+          defaultMessage: '单位',
         }),
-        required: true,
         'x-decorator': 'FormItem',
-        'x-component': 'Input',
-      },
-      valueType: {
-        type: 'object',
-        properties: {
-          type: {
-            title: intl.formatMessage({
-              id: 'pages.device.productDetail.metadata.dataType',
-              defaultMessage: '数据类型',
-            }),
-            required: true,
-            'x-decorator': 'FormItem',
-            'x-component': 'Select',
-            enum: DataTypeList,
+        'x-component': 'Select',
+        'x-visible': false,
+        enum: units,
+        'x-reactions': {
+          dependencies: ['.type'],
+          fulfill: {
+            state: {
+              visible: "{{['int','float','long','double'].includes($deps[0])}}",
+            },
           },
-          unit: {
-            title: intl.formatMessage({
-              id: 'pages.device.instanceDetail.metadata.unit',
-              defaultMessage: '单位',
-            }),
-            'x-decorator': 'FormItem',
-            'x-component': 'Select',
-            'x-visible': false,
-            enum: units,
-            'x-reactions': {
-              dependencies: ['.type'],
-              fulfill: {
-                state: {
-                  visible: "{{['int','float','long','double'].includes($deps[0])}}",
-                },
-              },
+        },
+      },
+      scale: {
+        title: intl.formatMessage({
+          id: 'pages.device.productDetail.metadata.accuracy',
+          defaultMessage: '精度',
+        }),
+        'x-decorator': 'FormItem',
+        'x-component': 'NumberPicker',
+        'x-reactions': {
+          dependencies: ['.type'],
+          fulfill: {
+            state: {
+              visible: "{{['float','double'].includes($deps[0])}}",
             },
           },
-          scale: {
-            title: intl.formatMessage({
-              id: 'pages.device.productDetail.metadata.accuracy',
-              defaultMessage: '精度',
-            }),
-            'x-decorator': 'FormItem',
-            'x-component': 'NumberPicker',
-            'x-reactions': {
-              dependencies: ['.type'],
-              fulfill: {
-                state: {
-                  visible: "{{['float','double'].includes($deps[0])}}",
-                },
-              },
+        },
+      },
+      booleanConfig: {
+        title: intl.formatMessage({
+          id: 'pages.device.productDetail.metadata.boolean',
+          defaultMessage: '布尔值',
+        }),
+        type: 'void',
+        'x-decorator': 'FormItem',
+        'x-component': 'BooleanEnum',
+        'x-reactions': {
+          dependencies: ['.type'],
+          fulfill: {
+            state: {
+              visible: "{{['boolean'].includes($deps[0])}}",
             },
           },
-          booleanConfig: {
-            title: intl.formatMessage({
-              id: 'pages.device.productDetail.metadata.boolean',
-              defaultMessage: '布尔值',
-            }),
-            type: 'void',
-            'x-decorator': 'FormItem',
-            'x-component': 'BooleanEnum',
-            'x-reactions': {
-              dependencies: ['.type'],
-              fulfill: {
-                state: {
-                  visible: "{{['boolean'].includes($deps[0])}}",
-                },
-              },
+        },
+      },
+      format: {
+        title: intl.formatMessage({
+          id: 'pages.device.productDetail.metadata.timeFormat',
+          defaultMessage: '时间格式',
+        }),
+        'x-decorator': 'FormItem',
+        'x-component': 'Select',
+        enum: DateTypeList,
+        'x-reactions': {
+          dependencies: ['.type'],
+          fulfill: {
+            state: {
+              visible: "{{['date'].includes($deps[0])}}",
             },
           },
-          format: {
-            title: intl.formatMessage({
-              id: 'pages.device.productDetail.metadata.timeFormat',
-              defaultMessage: '时间格式',
-            }),
-            'x-decorator': 'FormItem',
-            'x-component': 'Select',
-            enum: DateTypeList,
-            'x-reactions': {
-              dependencies: ['.type'],
-              fulfill: {
-                state: {
-                  visible: "{{['date'].includes($deps[0])}}",
-                },
-              },
+        },
+      },
+      enumConfig: {
+        title: intl.formatMessage({
+          id: 'pages.device.productDetail.metadata.enum',
+          defaultMessage: '枚举项',
+        }),
+        type: 'void',
+        'x-decorator': 'FormItem',
+        'x-component': 'EnumParam',
+        'x-reactions': {
+          dependencies: ['.type'],
+          fulfill: {
+            state: {
+              visible: "{{['enum'].includes($deps[0])}}",
             },
           },
-          enumConfig: {
+        },
+      },
+      expands: {
+        type: 'object',
+        properties: {
+          maxLength: {
             title: intl.formatMessage({
-              id: 'pages.device.productDetail.metadata.enum',
-              defaultMessage: '枚举项',
+              id: 'pages.device.productDetail.metadata.maxLength',
+              defaultMessage: '最大长度',
             }),
-            type: 'void',
             'x-decorator': 'FormItem',
-            'x-component': 'EnumParam',
+            'x-component': 'NumberPicker',
+            'x-decorator-props': {
+              tooltip: intl.formatMessage({
+                id: 'pages.device.productDetail.metadata.maxLength.byte',
+                defaultMessage: '字节',
+              }),
+            },
             'x-reactions': {
-              dependencies: ['.type'],
+              dependencies: ['..type'],
               fulfill: {
                 state: {
-                  visible: "{{['enum'].includes($deps[0])}}",
-                },
-              },
-            },
-          },
-          expands: {
-            type: 'object',
-            properties: {
-              maxLength: {
-                title: intl.formatMessage({
-                  id: 'pages.device.productDetail.metadata.maxLength',
-                  defaultMessage: '最大长度',
-                }),
-                'x-decorator': 'FormItem',
-                'x-component': 'NumberPicker',
-                'x-decorator-props': {
-                  tooltip: intl.formatMessage({
-                    id: 'pages.device.productDetail.metadata.maxLength.byte',
-                    defaultMessage: '字节',
-                  }),
-                },
-                'x-reactions': {
-                  dependencies: ['..type'],
-                  fulfill: {
-                    state: {
-                      visible: "{{['string','password'].includes($deps[0])}}",
-                    },
-                  },
+                  visible: "{{['string','password'].includes($deps[0])}}",
                 },
               },
             },
           },
-          elementType: {
-            title: intl.formatMessage({
-              id: 'pages.device.productDetail.metadata.elementConfiguration',
-              defaultMessage: '元素配置',
-            }),
-            'x-decorator': 'FormItem',
-            'x-component': 'ArrayParam',
-            'x-reactions': {
-              dependencies: ['.type'],
-              fulfill: {
-                state: {
-                  visible: "{{['array'].includes($deps[0])}}",
-                },
-              },
+        },
+      },
+      elementType: {
+        title: intl.formatMessage({
+          id: 'pages.device.productDetail.metadata.elementConfiguration',
+          defaultMessage: '元素配置',
+        }),
+        'x-decorator': 'FormItem',
+        'x-component': 'ArrayParam',
+        'x-reactions': {
+          dependencies: ['.type'],
+          fulfill: {
+            state: {
+              visible: "{{['array'].includes($deps[0])}}",
             },
           },
-          jsonConfig: {
-            title: intl.formatMessage({
-              id: 'pages.device.productDetail.metadata.jsonObject',
-              defaultMessage: 'JSON对象',
-            }),
-            type: 'void',
-            'x-decorator': 'FormItem',
-            'x-component': 'JsonParam',
-            'x-reactions': {
-              dependencies: ['.type'],
-              fulfill: {
-                state: {
-                  visible: "{{['object'].includes($deps[0])}}",
-                },
-              },
+        },
+      },
+      jsonConfig: {
+        title: intl.formatMessage({
+          id: 'pages.device.productDetail.metadata.jsonObject',
+          defaultMessage: 'JSON对象',
+        }),
+        type: 'void',
+        'x-decorator': 'FormItem',
+        'x-component': 'JsonParam',
+        'x-reactions': {
+          dependencies: ['.type'],
+          fulfill: {
+            state: {
+              visible: "{{['object'].includes($deps[0])}}",
             },
           },
-          fileType: {
-            title: intl.formatMessage({
-              id: 'pages.device.productDetail.metadata.fileType',
-              defaultMessage: '文件类型',
-            }),
-            'x-decorator': 'FormItem',
-            'x-component': 'Select',
-            'x-visible': false,
-            enum: FileTypeList,
-            'x-reactions': {
-              dependencies: ['.type'],
-              fulfill: {
-                state: {
-                  visible: "{{['file'].includes($deps[0])}}",
-                },
-              },
+        },
+      },
+      fileType: {
+        title: intl.formatMessage({
+          id: 'pages.device.productDetail.metadata.fileType',
+          defaultMessage: '文件类型',
+        }),
+        'x-decorator': 'FormItem',
+        'x-component': 'Select',
+        'x-visible': false,
+        enum: FileTypeList,
+        'x-reactions': {
+          dependencies: ['.type'],
+          fulfill: {
+            state: {
+              visible: "{{['file'].includes($deps[0])}}",
             },
           },
         },
       },
+    },
+  } as any;
+  const commonConfig = {
+    id: {
+      title: intl.formatMessage({
+        id: 'pages.device.productDetail.metadata.key',
+        defaultMessage: '标识',
+      }),
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Input',
+      'x-disabled': MetadataModel.action === 'edit',
+      'x-index': 0,
+    },
+    name: {
+      title: intl.formatMessage({
+        id: 'pages.table.name',
+        defaultMessage: '名称',
+      }),
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Input',
+      'x-index': 1,
+    },
+    description: {
+      title: intl.formatMessage({
+        id: 'pages.device.productDetail.metadata.describe',
+        defaultMessage: '描述',
+      }),
+      'x-decorator': 'FormItem',
+      'x-component': 'Input.TextArea',
+      'x-index': 100,
+    },
+  } as any;
+  const propertySchema: ISchema = {
+    type: 'object',
+    properties: {
+      ...commonConfig,
+      valueType: valueTypeConfig,
       expands: {
+        'x-index': 5,
         type: 'object',
         properties: {
           source: {
@@ -349,40 +390,12 @@ const Edit = () => {
           },
         },
       },
-
-      description: {
-        title: intl.formatMessage({
-          id: 'pages.device.productDetail.metadata.describe',
-          defaultMessage: '描述',
-        }),
-        'x-decorator': 'FormItem',
-        'x-component': 'Input.TextArea',
-      },
     },
   };
-
   const functionSchema: ISchema = {
     type: 'object',
     properties: {
-      id: {
-        title: intl.formatMessage({
-          id: 'pages.device.productDetail.metadata.key',
-          defaultMessage: '标识',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        'x-disabled': MetadataModel.action === 'edit',
-      },
-      name: {
-        title: intl.formatMessage({
-          id: 'pages.table.name',
-          defaultMessage: '名称',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-      },
+      ...commonConfig,
       async: {
         title: intl.formatMessage({
           id: 'pages.device.productDetail.metadata.whetherAsync',
@@ -407,78 +420,52 @@ const Edit = () => {
             value: false,
           },
         ],
+        'x-index': 2,
       },
-      inputParams: {
+      inputs: {
+        type: 'void',
+        'x-index': 3,
         title: intl.formatMessage({
           id: 'pages.device.productDetail.metadata.inputParameter',
           defaultMessage: '输入参数',
         }),
-        required: true,
         'x-decorator': 'FormItem',
-        'x-component': 'Input',
-      },
-      outputParams: {
-        title: intl.formatMessage({
-          id: 'pages.device.productDetail.metadata.outputParameters',
-          defaultMessage: '输出参数',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-      },
-      description: {
-        title: intl.formatMessage({
-          id: 'pages.device.productDetail.metadata.describe',
-          defaultMessage: '描述',
-        }),
-        'x-decorator': 'FormItem',
-        'x-component': 'Input.TextArea',
+        'x-component': 'JsonParam',
+        'x-reactions': (field) => {
+          field.setComponentProps({ keys: 'inputs' });
+        },
       },
+      output: valueTypeConfig,
     },
   };
-
   const eventSchema: ISchema = {
     type: 'object',
     properties: {
-      id: {
-        title: intl.formatMessage({
-          id: 'pages.device.productDetail.metadata.key',
-          defaultMessage: '标识',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        'x-disabled': MetadataModel.action === 'edit',
-      },
-      name: {
-        title: intl.formatMessage({
-          id: 'pages.table.name',
-          defaultMessage: '名称',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-      },
-      'expands.level': {
-        title: intl.formatMessage({
-          id: 'pages.device.productDetail.metadata.level',
-          defaultMessage: 'level',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Select',
-        enum: EventLevel,
+      ...commonConfig,
+      expands: {
+        type: 'object',
+        'x-index': 2,
+        properties: {
+          level: {
+            title: intl.formatMessage({
+              id: 'pages.device.productDetail.metadata.level',
+              defaultMessage: 'level',
+            }),
+            required: true,
+            'x-decorator': 'FormItem',
+            'x-component': 'Select',
+            enum: EventLevel,
+          },
+        },
       },
+      valueType: valueTypeConfig,
     },
   };
-
-  // 标签与属性表单相同,仅没有是否只读
   const createTagSchema = () => {
     const temp = _.cloneDeep(propertySchema) as any;
     delete temp.properties?.expands.properties.readOnly;
     return temp;
   };
-
   const metadataTypeMapping: Record<string, { name: string; schema: ISchema }> = {
     properties: {
       name: '属性',

+ 1 - 1
src/pages/device/Product/typings.d.ts

@@ -75,7 +75,7 @@ type FunctionMetadata = {
   id: string;
   name: string;
   async: boolean;
-  output: Record<any, any>;
+  output: Record<string, unknown>;
   inputs: ({
     id: string;
     name: string;

+ 2 - 2
src/pages/device/data.ts

@@ -93,8 +93,8 @@ export const EventLevel: { label: string; value: string }[] = [
     value: 'warn',
   },
   {
-    label: 'urgent',
-    value: '紧急',
+    value: 'urgent',
+    label: '紧急',
   },
 ];