Bladeren bron

feat: 功能调用

Wzyyy98 3 jaren geleden
bovenliggende
commit
3dc88c7c56

+ 119 - 0
src/pages/rule-engine/Scene/Save/action/DeviceOutput/actions/TypeModel.tsx

@@ -0,0 +1,119 @@
+import ParamsSelect, { ItemProps } from '@/pages/rule-engine/Scene/Save/components/ParamsSelect';
+import { useEffect, useState } from 'react';
+import { DataNode } from 'antd/es/tree';
+import { Input, InputNumber, Tree } from 'antd';
+import MTimePicker from '../../../components/ParamsSelect/components/MTimePicker';
+
+interface Props {
+  value: any;
+  type: string;
+  onChange?: (data: any) => void;
+}
+
+export default (props: Props) => {
+  const [value, setValue] = useState<any>(null);
+  const treeData: DataNode[] = [
+    {
+      title: 'parent 1',
+      key: '0-0',
+      children: [
+        {
+          title: 'parent 1-0',
+          key: '0-0-0',
+          children: [
+            {
+              title: 'leaf',
+              key: '0-0-0-0',
+            },
+            {
+              title: 'leaf',
+              key: '0-0-0-1',
+            },
+          ],
+        },
+        {
+          title: 'parent 1-1',
+          key: '0-0-1',
+          children: [{ title: 'sss', key: '0-0-1-0' }],
+        },
+      ],
+    },
+  ];
+  const [showValue, setShowValue] = useState<any>('');
+
+  const renderNode = (type: string) => {
+    switch (type) {
+      case 'int':
+      case 'long':
+      case 'float':
+      case 'double':
+        return (
+          <InputNumber
+            value={value}
+            onChange={(e: any) => {
+              setShowValue(e);
+              setValue(e);
+            }}
+            style={{ width: '100%' }}
+            placeholder={'请输入'}
+          />
+        );
+      case 'date':
+        return (
+          <MTimePicker
+            value={value}
+            onChange={(time: any, timeString: string) => {
+              setShowValue(timeString);
+              setValue(time);
+            }}
+          />
+        );
+      default:
+        return <Input value={value} placeholder={'请输入' + name} />;
+    }
+  };
+
+  const itemList: ItemProps[] = [
+    {
+      label: `手动输入`,
+      key: 'manual',
+      content: renderNode(props.type),
+    },
+    {
+      label: `内置参数`,
+      key: 'built-in',
+      content: (
+        <Tree
+          treeData={treeData}
+          height={300}
+          defaultExpandAll
+          onSelect={(selectedKeys) => {
+            setValue(selectedKeys[0]);
+            setShowValue(selectedKeys[0]);
+          }}
+        />
+      ),
+    },
+  ];
+
+  useEffect(() => {
+    setShowValue(value);
+  }, [props.value]);
+
+  return (
+    <div>
+      <ParamsSelect
+        style={{ width: '100%', height: '100%' }}
+        inputProps={{
+          placeholder: '请选择',
+        }}
+        tabKey={'manual'}
+        itemList={itemList}
+        value={showValue}
+        onChange={(val: any) => {
+          setValue(val);
+        }}
+      />
+    </div>
+  );
+};

+ 123 - 0
src/pages/rule-engine/Scene/Save/action/DeviceOutput/actions/functionCall.tsx

@@ -0,0 +1,123 @@
+import type { ProColumns } from '@jetlinks/pro-table';
+import { EditableProTable } from '@jetlinks/pro-table';
+import React, { useEffect, useRef, useState } from 'react';
+import type { ProFormInstance } from '@ant-design/pro-form';
+import ProForm from '@ant-design/pro-form';
+import TypeModel from './TypeModel';
+
+type FunctionTableDataType = {
+  id: string;
+  name: string;
+  type: string;
+};
+
+interface FunctionCallProps {
+  functionData: any[];
+  value?: any;
+  onChange?: (data: any) => void;
+  name?: string;
+  productId?: string;
+}
+
+export default (props: FunctionCallProps) => {
+  const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
+  const formRef = useRef<ProFormInstance<any>>();
+
+  useEffect(() => {
+    if (props.functionData && props.functionData.length) {
+      setEditableRowKeys(props.functionData.map((d) => d.id));
+      if (props.value) {
+        console.log(props.functionData, 11111111111);
+        const tableData = props.functionData.map((item: any) => {
+          const oldValue = props.value.find((oldItem: any) => oldItem.name === item.id);
+          if (oldValue) {
+            return {
+              ...item,
+              value: oldValue.value,
+            };
+          }
+          return item;
+        });
+        formRef.current?.setFieldsValue({
+          table: tableData,
+        });
+      } else {
+        formRef.current?.setFieldsValue({
+          table: props.functionData,
+        });
+      }
+    } else {
+      formRef.current?.setFieldsValue({
+        table: [],
+      });
+    }
+  }, [props.value, props.functionData]);
+
+  useEffect(() => {
+    if (props.productId && props.onChange) {
+      props.onChange([]);
+    }
+  }, [props.productId]);
+
+  const getItemNode = (record: any) => {
+    const type = record.type;
+    return <TypeModel value={record.value} type={type} onChange={() => {}} />;
+  };
+
+  const columns: ProColumns<FunctionTableDataType>[] = [
+    {
+      dataIndex: 'name',
+      title: '参数名称',
+      width: 200,
+      editable: false,
+    },
+    {
+      dataIndex: 'type',
+      title: '类型',
+      width: 200,
+      editable: false,
+    },
+    {
+      title: '值',
+      dataIndex: 'value',
+      align: 'center',
+      width: 260,
+      renderFormItem: (_, row) => {
+        return getItemNode(row.record);
+      },
+    },
+  ];
+
+  return (
+    <ProForm<{ table: FunctionTableDataType[] }>
+      formRef={formRef}
+      name={props.name || 'proForm'}
+      submitter={false}
+      onValuesChange={() => {
+        const values = formRef.current?.getFieldsValue();
+        console.log(values, 'values');
+        if (props.onChange) {
+          props.onChange(
+            values.table.map((item: any) => ({
+              name: item.id,
+              value: item.value,
+            })),
+          );
+        }
+      }}
+    >
+      <EditableProTable
+        rowKey="id"
+        name={'table'}
+        recordCreatorProps={false}
+        columns={columns}
+        size={'small'}
+        editable={{
+          type: 'multiple',
+          editableKeys,
+          onChange: setEditableRowKeys,
+        }}
+      />
+    </ProForm>
+  );
+};

+ 61 - 6
src/pages/rule-engine/Scene/Save/action/DeviceOutput/actions/index.tsx

@@ -4,6 +4,7 @@ import { useEffect, useState } from 'react';
 import ReadProperty from '../../device/readProperty';
 import ReadProperty from '../../device/readProperty';
 import TopCard from '../device/TopCard';
 import TopCard from '../device/TopCard';
 import DeviceModel from '../model';
 import DeviceModel from '../model';
+import FunctionCall from './functionCall';
 import WriteProperty from './WriteProperty';
 import WriteProperty from './WriteProperty';
 
 
 interface Props {
 interface Props {
@@ -15,6 +16,9 @@ export default observer((props: Props) => {
   const [deviceMessageType, setDeviceMessageType] = useState('WRITE_PROPERTY');
   const [deviceMessageType, setDeviceMessageType] = useState('WRITE_PROPERTY');
   const [properties, setProperties] = useState([]); // 物模型-属性
   const [properties, setProperties] = useState([]); // 物模型-属性
   const [propertiesId, setPropertiesId] = useState<string | undefined>(''); // 物模型-属性ID,用于串行
   const [propertiesId, setPropertiesId] = useState<string | undefined>(''); // 物模型-属性ID,用于串行
+  const [functionList, setFunctionList] = useState<any>([]); // 物模型-功能
+  const [functionId, setFunctionId] = useState('');
+  const [functions, setFunctions] = useState([]);
 
 
   const TypeList = [
   const TypeList = [
     {
     {
@@ -41,18 +45,42 @@ export default observer((props: Props) => {
     if (DeviceModel.productDetail) {
     if (DeviceModel.productDetail) {
       const metadata = JSON.parse(DeviceModel.productDetail?.metadata || '{}');
       const metadata = JSON.parse(DeviceModel.productDetail?.metadata || '{}');
       setProperties(metadata.properties);
       setProperties(metadata.properties);
+      setFunctions(metadata.functions);
     }
     }
-  }, [DeviceModel.productDetail]);
+  }, [DeviceModel.productDetail, functionId]);
+
+  useEffect(() => {
+    if (functionId && functions.length !== 0) {
+      const functionItem: any = functions.find((item: any) => item.id === functionId);
+      if (functionItem) {
+        const item = functionItem.valueType
+          ? functionItem.valueType.properties
+          : functionItem.inputs;
+        const array = [];
+        for (const datum of item) {
+          array.push({
+            id: datum.id,
+            name: datum.name,
+            type: datum.valueType ? datum.valueType.type : '-',
+            format: datum.valueType ? datum.valueType.format : undefined,
+            options: datum.valueType ? datum.valueType.elements : undefined,
+            value: undefined,
+          });
+        }
+        setFunctionList(array);
+        console.log(propertiesId, 'array');
+      }
+    }
+  }, [functions, functionId]);
 
 
   useEffect(() => {
   useEffect(() => {
     props.get(form);
     props.get(form);
-    console.log(propertiesId);
   }, [form]);
   }, [form]);
 
 
   return (
   return (
     <div>
     <div>
       <Form form={form} layout={'vertical'}>
       <Form form={form} layout={'vertical'}>
-        <Form.Item name="messageType" label="动作类型" required>
+        <Form.Item name="messageType" label="动作类型" required initialValue="WRITE_PROPERTY">
           <TopCard
           <TopCard
             typeList={TypeList}
             typeList={TypeList}
             onChange={(value: string) => {
             onChange={(value: string) => {
@@ -61,9 +89,36 @@ export default observer((props: Props) => {
           />
           />
         </Form.Item>
         </Form.Item>
         {deviceMessageType === 'INVOKE_FUNCTION' && (
         {deviceMessageType === 'INVOKE_FUNCTION' && (
-          <Form.Item name={['device', 'message', 'inputs']} label="功能调用" required>
-            <Select></Select>
-          </Form.Item>
+          <>
+            <Form.Item
+              name={['device', 'message', 'functionId']}
+              label="功能调用"
+              rules={[{ required: true, message: '请选择功能' }]}
+            >
+              <Select
+                showSearch
+                allowClear
+                options={functions}
+                fieldNames={{ label: 'name', value: 'id' }}
+                style={{ width: '100%' }}
+                placeholder={'请选择功能'}
+                filterOption={(input: string, option: any) =>
+                  option.name.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                }
+                onChange={(value) => {
+                  setFunctionId(value);
+                }}
+              />
+            </Form.Item>
+            {functionId && (
+              <Form.Item
+                name={['device', 'message', 'inputs']}
+                rules={[{ required: true, message: '请输入功能值' }]}
+              >
+                <FunctionCall functionData={functionList} productId={DeviceModel.productId[0]} />
+              </Form.Item>
+            )}
+          </>
         )}
         )}
         {deviceMessageType === 'READ_PROPERTY' && (
         {deviceMessageType === 'READ_PROPERTY' && (
           <Form.Item
           <Form.Item

+ 1 - 1
src/pages/rule-engine/Scene/Save/action/DeviceOutput/device/index.tsx

@@ -275,7 +275,7 @@ export default observer(() => {
           tableAlertRender={false}
           tableAlertRender={false}
           rowSelection={{
           rowSelection={{
             type: 'radio',
             type: 'radio',
-            selectedRowKeys: DeviceModel.productId,
+            selectedRowKeys: DeviceModel.deviceId,
             onChange: (selectedRowKeys, selectedRows) => {
             onChange: (selectedRowKeys, selectedRows) => {
               DeviceModel.deviceId = selectedRows.map((item) => item.id);
               DeviceModel.deviceId = selectedRows.map((item) => item.id);
             },
             },

+ 1 - 1
src/pages/rule-engine/Scene/Save/components/ParamsSelect/index.less

@@ -1,7 +1,7 @@
 .select-wrapper {
 .select-wrapper {
   position: relative;
   position: relative;
   width: 100%;
   width: 100%;
-  margin-bottom: 20px;
+  // margin-bottom: 20px;
   .select-container {
   .select-container {
     position: absolute;
     position: absolute;
     top: 32px;
     top: 32px;

+ 3 - 0
src/pages/rule-engine/Scene/Save/components/ParamsSelect/index.tsx

@@ -73,6 +73,9 @@ export default (props: Props) => {
         suffix={<DownOutlined style={{ color: 'rgba(0, 0, 0, 0.25)' }} />}
         suffix={<DownOutlined style={{ color: 'rgba(0, 0, 0, 0.25)' }} />}
         {...props.inputProps}
         {...props.inputProps}
         value={value}
         value={value}
+        onChange={(e) => {
+          setValue(e.target.value);
+        }}
         onFocus={() => {
         onFocus={() => {
           setVisible(true);
           setVisible(true);
         }}
         }}