xieyonghong 3 лет назад
Родитель
Сommit
328feee6ee

BIN
public/images/scene/action-bind-icon.png


BIN
public/images/scene/action-delay-icon.png


BIN
public/images/scene/action-device-icon.png


BIN
public/images/scene/action-notify-icon.png


BIN
public/images/scene/action-unbind-icon.png


+ 24 - 9
src/components/ProTableCard/CardItems/Scene/index.tsx

@@ -200,8 +200,20 @@ const deviceRender = (data: ActionsType | undefined) => {
     case 'relation':
       return (
         <div>
-          {data?.options?.type || ''}
-          与【触发设备】具有相同【关系名称】的【产品名称】设备的【属性/功能】
+          {data?.options?.type || ''}与
+          <span className={styles['notify-text-highlight']}>{data?.options?.deviceName || ''}</span>
+          具有相同
+          <span className={styles['notify-text-highlight']}>
+            {data?.options?.relationName || ''}
+          </span>
+          的
+          <span className={styles['notify-text-highlight']}>
+            {data?.options?.productName || ''}
+          </span>
+          设备的
+          <span className={styles['notify-text-highlight']}>
+            {data?.options?.propertyName || data?.options?.functionName || ''}
+          </span>
         </div>
       );
     case 'tag':
@@ -221,11 +233,12 @@ const deviceRender = (data: ActionsType | undefined) => {
     default:
       return (
         <div>
-          {data?.options?.type || ''}
-          <span className={styles['notify-text-highlight']}>{data?.options?.deviceName || ''}</span>
-          <span className={styles['notify-text-highlight']}>
-            {data?.options?.propertyName || data?.options?.functionName || ''}
-          </span>
+          {/*{data?.options?.type || ''}*/}
+          {/*<span className={styles['notify-text-highlight']}>{data?.options?.deviceName || ''}</span>*/}
+          {/*<span className={styles['notify-text-highlight']}>*/}
+          {/*  {data?.options?.propertyName || data?.options?.functionName || ''}*/}
+          {/*</span>*/}
+          打开空调动作1执行结果=成功并且 湿度24
         </div>
       );
   }
@@ -297,8 +310,10 @@ const branchesActionRender = (actions: any[]) => {
   if (actions && actions?.length) {
     const list: any[] = [];
     actions.map((item, index) => {
-      list.push(actionRender(item, index));
+      const dt = actionRender(item, index);
+      list.push(dt);
     });
+
     return list.map((item, index) => (
       <div className={styles['right-item-right-item-contents-item']}>
         <div style={{ minWidth: 40 }}>动作{index + 1}</div>
@@ -308,6 +323,7 @@ const branchesActionRender = (actions: any[]) => {
   }
   return '';
 };
+
 const ContentRender = (data: SceneCardProps) => {
   const [visible, setVisible] = useState<boolean>(false);
   const type = data.triggerType;
@@ -411,7 +427,6 @@ const ContentRender = (data: SceneCardProps) => {
                     <div className={styles['card-item-content-action-item-right-item']}>
                       <div className={styles['right-item-right']}>
                         {(item?.then || []).map((i: BranchesThen, _index: number) => {
-                          console.log(i);
                           return (
                             <div key={i?.key || _index} className={styles['right-item-right-item']}>
                               <div className={styles['trigger-ways']}>

+ 5 - 4
src/pages/rule-engine/Scene/Save/action/DeviceOutput/actions/TypeModel.tsx

@@ -44,13 +44,10 @@ export default (props: Props) => {
   };
 
   useEffect(() => {
-    if (props.onChange) {
-      props.onChange(value, source);
-    }
     if (source === 'upper') {
       sourceChangeEvent();
     }
-  }, [source, value]);
+  }, [source]);
 
   const renderNode = (type: string) => {
     switch (type) {
@@ -198,8 +195,12 @@ export default (props: Props) => {
         itemList={itemList}
         value={value}
         onChange={(val: any, tabKey: any) => {
+          // console.log(val,tabKey)
           setValue(val);
           setSource(tabKey);
+          if (props.onChange) {
+            props.onChange(val, tabKey);
+          }
         }}
         type={props.type}
       />

+ 245 - 0
src/pages/rule-engine/Scene/Save/action/DeviceOutput/device/Tag.tsx

@@ -0,0 +1,245 @@
+import { Button, Col, DatePicker, Input, InputNumber, Row, Select, Space } from 'antd';
+import { useEffect, useState } from 'react';
+import moment from 'moment';
+import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
+
+interface TagModalProps {
+  tagData: any[];
+  value?: any[];
+  onChange?: (value: any[]) => void;
+  id?: string;
+}
+
+/**
+ * 数据格式 [{"value":{"key":"value"},"name":"标签名称"}]
+ * @param props
+ */
+export default (props: TagModalProps) => {
+  const [tagList, setTagList] = useState<any[]>([{}]);
+  const [options, setOptions] = useState<any[]>([]);
+
+  const handleItem = (data: any) => {
+    return {
+      ...data,
+      valueType: data.valueType ? data.valueType.type : '-',
+      format: data.valueType ? data.valueType.format : undefined,
+      options: data.valueType ? data.valueType.elements : undefined,
+      value: data.value,
+    };
+  };
+
+  const onChange = () => {
+    const newValue = tagList
+      .filter((item) => !!item.value)
+      .map((item: any) => {
+        return {
+          column: item.id,
+          type: item.type,
+          value: item.value,
+        };
+      });
+    console.log();
+    if (props.onChange) {
+      props.onChange([{ value: newValue, name: '标签' }]);
+    }
+  };
+
+  useEffect(() => {
+    setOptions(
+      props.tagData?.map((item: any) => {
+        return { label: item.name, value: item.id, ...item };
+      }),
+    );
+  }, [props.tagData]);
+
+  useEffect(() => {
+    if (
+      props.value &&
+      props.value[0] &&
+      props.value[0].name &&
+      props.tagData &&
+      props.tagData.length
+    ) {
+      const names: string[] = [];
+      const newTagList = props.value[0].value
+        .filter((valueItem: any) => {
+          return props.tagData.some((item) => valueItem.column === item.id);
+        })
+        .map((valueItem: any) => {
+          const oldItem = props.tagData.find((item) => item.id === valueItem.column);
+          if (oldItem) {
+            names.push(oldItem.name);
+            return {
+              ...handleItem(oldItem),
+              value: valueItem.value,
+              type: valueItem.type,
+            };
+          }
+          return valueItem;
+        });
+      //   setNameList(names);
+      setTagList(newTagList);
+    } else {
+      setTagList([{}]);
+    }
+  }, [props.value, props.tagData]);
+
+  const getItemNode = (record: any) => {
+    const type = record.valueType;
+    const name = record.name;
+
+    switch (type) {
+      case 'enum':
+        return (
+          <Select
+            value={record.value}
+            style={{ width: '100%', textAlign: 'left' }}
+            options={record.options}
+            fieldNames={{ label: 'text', value: 'value' }}
+            placeholder={'请选择' + name}
+            onChange={(key) => {
+              record.value = key;
+            }}
+          />
+        );
+      case 'boolean':
+        return (
+          <Select
+            value={record.value}
+            style={{ width: '100%', textAlign: 'left' }}
+            options={[
+              { label: 'true', value: true },
+              { label: 'false', value: false },
+            ]}
+            placeholder={'请选择' + name}
+            onChange={(key) => {
+              record.value = key;
+            }}
+          />
+        );
+      case 'int':
+      case 'long':
+      case 'float':
+      case 'double':
+        return (
+          <InputNumber
+            value={record.value}
+            style={{ width: '100%' }}
+            placeholder={'请输入' + name}
+            onChange={(key) => {
+              record.value = key;
+            }}
+          />
+        );
+      case 'date':
+        return (
+          <>
+            {
+              // @ts-ignore
+              <DatePicker
+                value={record.value && moment(record.value, 'YYYY-MM-DD HH:mm:ss')}
+                format={record.format || 'YYYY-MM-DD HH:mm:ss'}
+                style={{ width: '100%' }}
+                onChange={(_, date) => {
+                  record.value = date;
+                }}
+              />
+            }
+          </>
+        );
+      default:
+        return (
+          <Input
+            value={record.value}
+            placeholder={'请输入标签值'}
+            onChange={(e) => {
+              record.value = e.target.value;
+            }}
+          />
+        );
+    }
+  };
+
+  return (
+    <>
+      <div
+        onChange={() => {
+          onChange();
+        }}
+      >
+        {tagList.map((tag, index) => (
+          <Row gutter={12} key={tag.id || index} style={{ marginBottom: 12 }}>
+            <Col span={4}>
+              {index === 0 ? (
+                <span>标签选择</span>
+              ) : (
+                <Select
+                  value={tag.type}
+                  options={[
+                    { label: '并且', value: 'and' },
+                    { label: '或者', value: 'or' },
+                  ]}
+                  style={{ width: '100%' }}
+                  onSelect={(key: string) => {
+                    const indexItem = tagList[index];
+                    indexItem.type = key;
+                    tagList[index] = indexItem;
+                    setTagList([...tagList]);
+                  }}
+                />
+              )}
+            </Col>
+            <Col span={16}>
+              <Row gutter={12}>
+                <Col flex="120px">
+                  <Select
+                    value={tag.id}
+                    style={{ width: '120px' }}
+                    options={options}
+                    onSelect={(_: any, data: any) => {
+                      const newList = [...tagList];
+                      const indexType = newList[index].type;
+                      newList.splice(
+                        index,
+                        1,
+                        handleItem({ ...data, value: undefined, type: indexType }),
+                      );
+                      setTagList(newList);
+                    }}
+                    placeholder={'请选择标签'}
+                  />
+                </Col>
+                <Col flex={'auto'}>{getItemNode(tag)}</Col>
+              </Row>
+            </Col>
+            <Col span={4}>
+              <Space>
+                <Button
+                  style={{ padding: '0 8px' }}
+                  onClick={() => {
+                    setTagList([...tagList, { type: 'and' }]);
+                  }}
+                >
+                  <PlusOutlined />
+                </Button>
+                {tagList.length !== 1 && (
+                  <Button
+                    style={{ padding: '0 8px' }}
+                    onClick={() => {
+                      const newTagList = [...tagList];
+                      newTagList.splice(index, 1);
+                      setTagList(newTagList);
+                    }}
+                    danger
+                  >
+                    <DeleteOutlined />
+                  </Button>
+                )}
+              </Space>
+            </Col>
+          </Row>
+        ))}
+      </div>
+    </>
+  );
+};

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

@@ -18,6 +18,9 @@ import { ExclamationCircleOutlined } from '@ant-design/icons';
 import { FormModel } from '../../..';
 import { BuiltInParamsHandleTreeData } from '@/pages/rule-engine/Scene/Save/components/BuiltInParams';
 import { queryBuiltInParams } from '@/pages/rule-engine/Scene/Save/action/service';
+import RelationSelect from '../../device/relationSelect';
+import { getRelations } from '@/pages/rule-engine/Scene/Save/action/service';
+import Tag from './Tag';
 
 interface Props {
   name: number;
@@ -28,17 +31,31 @@ export default observer((props: Props) => {
   const intl = useIntl();
   const [searchParam, setSearchParam] = useState({});
   const [form] = Form.useForm();
-  const [type, setType] = useState<string>('');
   const [builtInList, setBuiltInList] = useState<any[]>([]);
+  const selector = Form.useWatch('selector', form);
+  const [tagList, setTagList] = useState([]);
+  const [list, setList] = useState<any>([]);
 
   const TypeList = [
     {
       label: '自定义',
-      value: 'custom',
+      value: 'fixed',
       image: require('/public/images/scene/device-custom.png'),
       tip: '自定义选择当前产品下的任意设备',
     },
     {
+      label: '按关系',
+      value: 'relation',
+      image: require('/public/images/scene/device-custom.png'),
+      tip: '选择与触发设备具有相同关系的设备',
+    },
+    {
+      label: '按标签',
+      value: 'tag',
+      image: require('/public/images/scene/device-custom.png'),
+      tip: '按标签选择产品下具有特定标签的设备',
+    },
+    {
       label: '按变量',
       value: 'variable',
       image: require('/public/images/scene/device-variable.png'),
@@ -216,9 +233,9 @@ export default observer((props: Props) => {
             paging: false,
           })
           .then((resp) => {
-            const formatValue = (list: any[]) => {
+            const formatValue = (lists: any[]) => {
               const _list: any[] = [];
-              list.forEach((item) => {
+              lists.forEach((item) => {
                 if (item.children) {
                   item.children = formatValue(item.children);
                 }
@@ -271,107 +288,209 @@ export default observer((props: Props) => {
         const _data = BuiltInParamsHandleTreeData(res.result);
         const array = filterTree(_data);
         setBuiltInList(array);
-        // console.log(array)
       }
     });
   };
+  const filterType = async () => {
+    console.log(FormModel);
+    if (FormModel.trigger?.type === 'device') {
+      const res = await getRelations();
+      if (res.status === 200 && res.result.length === 0) {
+        const array = TypeList.filter((item) => item.value !== 'relation');
+        setList(array);
+      } else {
+        setList(TypeList);
+      }
+      const tag = JSON.parse(DeviceModel.productDetail?.metadata || '{}')?.tags;
+      console.log(tag, 'tag');
+      if (!tag) {
+        const array = TypeList.filter((item) => item.value !== 'tag');
+        setList(array);
+      } else {
+        setList(TypeList);
+      }
+    } else {
+      const arr = TypeList.filter((item) => item.value !== 'relation' && item.value !== 'tag');
+      const arr1 = TypeList.filter((item) => item.value === 'fixed');
+      // isParallel()? setList(arr1):setList(arr)
+      if (isParallel()) {
+        setList(arr1);
+      } else {
+        setList(arr);
+      }
+    }
+  };
 
-  useEffect(() => {
-    // console.log(FormModel, isParallel())
-    sourceChangeEvent();
-    setType('custom');
-  }, []);
-
-  return (
-    <div>
-      <div className="device-title">
-        <ExclamationCircleOutlined className="device-title-icon" />
-        <span>自定义选择当前产品下的任意设备</span>
-      </div>
-      {isParallel() && (
-        <Form form={form} layout={'vertical'}>
-          <Form.Item name="type" label="选择方式" required>
-            <TopCard
-              typeList={TypeList}
-              value={'custom'}
+  const contentRender = (type?: string) => {
+    switch (type) {
+      //自定义
+      case 'fixed':
+        return (
+          <>
+            <SearchComponent
+              field={columns}
+              model={'simple'}
+              enableSave={false}
+              onSearch={async (data) => {
+                actionRef.current?.reset?.();
+                setSearchParam(data);
+              }}
+              target="device"
+              defaultParam={[
+                {
+                  terms: [
+                    {
+                      column: 'productId',
+                      value: DeviceModel.productId,
+                    },
+                  ],
+                },
+              ]}
+            />
+            <div>
+              <ProTableCard<DeviceInstance>
+                actionRef={actionRef}
+                columns={columns}
+                rowKey="id"
+                search={false}
+                gridColumn={2}
+                columnEmptyText={''}
+                onlyCard={true}
+                tableAlertRender={false}
+                rowSelection={{
+                  type: 'radio',
+                  selectedRowKeys: [DeviceModel.deviceId],
+                  onChange: (_, selectedRows) => {
+                    if (selectedRows.length) {
+                      const item = selectedRows?.[0];
+                      DeviceModel.deviceId = item.id;
+                      DeviceModel.selectorValues = [
+                        { value: DeviceModel.deviceId, name: item.name },
+                      ];
+                    } else {
+                      DeviceModel.deviceId = '';
+                      DeviceModel.selectorValues = [];
+                    }
+                  },
+                }}
+                request={(params) =>
+                  service.query({
+                    ...params,
+                    sorts: [{ name: 'createTime', order: 'desc' }],
+                  })
+                }
+                params={searchParam}
+                cardRender={(record) => (
+                  <SceneDeviceCard showBindBtn={false} showTool={false} {...record} />
+                )}
+                height={'none'}
+              />
+            </div>
+          </>
+        );
+      case 'relation':
+        return (
+          <Form.Item
+            name="selectorValues"
+            label="关系"
+            rules={[{ required: true, message: '请选择关系人' }]}
+          >
+            <RelationSelect
+              onChange={(value, options) => {
+                // console.log(value,options)
+                if (value) {
+                  DeviceModel.deviceId = 'deviceId';
+                  DeviceModel.source = 'upper';
+                  DeviceModel.selectorValues = value;
+                  DeviceModel.upperKey = 'deviceId';
+                  DeviceModel.relationName = options.label;
+                }
+              }}
+            />
+          </Form.Item>
+        );
+      case 'tag':
+        return (
+          <Form.Item
+            name="selectorValues"
+            // label='标签'
+            rules={[{ required: true, message: '请选择标签' }]}
+          >
+            <Tag
+              tagData={tagList}
               onChange={(value) => {
-                setType(value);
+                console.log(value);
+                if (value) {
+                  DeviceModel.deviceId = 'deviceId';
+                  DeviceModel.source = 'fixed';
+                  DeviceModel.selectorValues = value;
+                }
               }}
             />
           </Form.Item>
-          {type === 'variable' && (
-            <Form.Item name="deviceId" label="变量" required>
+        );
+      default:
+        return (
+          <>
+            <Form.Item name="selectorValues" label="变量" required>
               <TreeSelect
                 style={{ width: '100%', height: '100%' }}
                 treeData={builtInList}
                 fieldNames={{ label: 'name', value: 'id' }}
                 placeholder={'请选择参数'}
                 onSelect={(value: any, node: any) => {
-                  // console.log(value,node)
-                  DeviceModel.deviceId = [value];
+                  console.log(value, node);
+                  DeviceModel.deviceId = value;
                   DeviceModel.deviceDetail = node;
+                  DeviceModel.selectorValues = [{ value: value, name: node.description }];
                 }}
               />
             </Form.Item>
-          )}
+          </>
+        );
+    }
+  };
+
+  useEffect(() => {
+    if (form) {
+      form.setFieldsValue({ selector: DeviceModel.selector });
+    }
+    sourceChangeEvent();
+  }, []);
+
+  useEffect(() => {
+    if (DeviceModel.productDetail) {
+      const metadata = JSON.parse(DeviceModel.productDetail?.metadata || '{}');
+      setTagList(metadata.tags);
+      // console.log(metadata.tags)
+      filterType();
+    }
+  }, [DeviceModel.productDetail]);
+
+  useEffect(() => {
+    DeviceModel.selector = selector;
+  }, [selector]);
+
+  return (
+    <div>
+      <div className="device-title">
+        <ExclamationCircleOutlined className="device-title-icon" />
+        <span>自定义选择当前产品下的任意设备</span>
+      </div>
+
+      {/* {isParallel() && (
+        <Form form={form} layout={'vertical'}>
+          <Form.Item name="selector" label="选择方式" required>
+            <TopCard typeList={TypeList} />
+          </Form.Item>
         </Form>
-      )}
-      {type === 'custom' && (
-        <>
-          <SearchComponent
-            field={columns}
-            model={'simple'}
-            enableSave={false}
-            onSearch={async (data) => {
-              actionRef.current?.reset?.();
-              setSearchParam(data);
-            }}
-            target="device"
-            defaultParam={[
-              {
-                terms: [
-                  {
-                    column: 'productId',
-                    value: DeviceModel.productId[0],
-                  },
-                ],
-              },
-            ]}
-          />
-          <div>
-            <ProTableCard<DeviceInstance>
-              actionRef={actionRef}
-              columns={columns}
-              rowKey="id"
-              search={false}
-              gridColumn={2}
-              columnEmptyText={''}
-              onlyCard={true}
-              tableAlertRender={false}
-              rowSelection={{
-                type: 'radio',
-                selectedRowKeys: DeviceModel.deviceId,
-                onChange: (selectedRowKeys, selectedRows) => (
-                  // console.log(selectedRowKeys)
-                  (DeviceModel.deviceId = selectedRowKeys),
-                  (DeviceModel.deviceDetail = selectedRows?.[0])
-                ),
-              }}
-              request={(params) =>
-                service.query({
-                  ...params,
-                  sorts: [{ name: 'createTime', order: 'desc' }],
-                })
-              }
-              params={searchParam}
-              cardRender={(record) => (
-                <SceneDeviceCard showBindBtn={false} showTool={false} {...record} />
-              )}
-              height={'none'}
-            />
-          </div>
-        </>
-      )}
+      )} */}
+      <Form form={form} layout={'vertical'}>
+        <Form.Item name="selector" label="选择方式" required>
+          <TopCard typeList={list} />
+        </Form.Item>
+        {contentRender(selector)}
+      </Form>
     </div>
   );
 });

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

@@ -9,6 +9,7 @@ import './index.less';
 import DeviceModel from './model';
 import { onlyMessage } from '@/utils/util';
 import { ActionsDeviceProps } from '../../../typings';
+// import { FormModel } from '../..';
 
 export const service = new Service<any>('');
 
@@ -48,16 +49,6 @@ export default observer((props: Props) => {
       ),
     },
   ];
-
-  // const handleOptions = ()=>{
-  //   const _options: any = {
-  //     name: '', // 名称
-  //     onlyName: false,
-  //     type: '', // 触发类型
-  //     action: DeviceModel.options.action,
-  //   };
-  // }
-
   const next = () => {
     if (
       (DeviceModel.current === 0 && DeviceModel.productId.length !== 0) ||
@@ -78,16 +69,11 @@ export default observer((props: Props) => {
   const save = async () => {
     const value = await formRef.current?.validateFields();
     const item = {
-      selector: 'fixed',
-      source: 'fixed',
-      selectorValues: [
-        {
-          value: DeviceModel.deviceDetail.id,
-          name: DeviceModel.deviceDetail.name,
-        },
-      ],
-      productId: DeviceModel.productId[0],
-      message: value,
+      selector: DeviceModel.selector,
+      source: DeviceModel.source,
+      selectorValues: DeviceModel.selectorValues,
+      productId: DeviceModel.productId,
+      message: value.device.message,
     };
     console.log(item, value);
 
@@ -95,6 +81,10 @@ export default observer((props: Props) => {
       name: '', //设备名称
       type: '', //类型
       properties: '', //属性功能
+      selector: DeviceModel.selector, //选择器标识
+      productName: DeviceModel.productDetail.name,
+      relationName: DeviceModel.relationName,
+      taglist: [],
     };
     _options.name = DeviceModel.deviceDetail.name;
     const _type = value.device.message.messageType;
@@ -110,9 +100,19 @@ export default observer((props: Props) => {
       _options.type = '设置';
       _options.properties = Object.keys(value.device.message.properties)?.[0];
     }
-    console.log(_options);
-    console.log('device', item);
+    if (_options.selector === 'tag') {
+      _options.taglist = DeviceModel.selectorValues?.[0]?.value.map((it: any) => ({
+        name: it.column || it.name,
+        type: it.type ? (it.type === 'and' ? '并且' : '或者') : '',
+        value: it.value,
+      }));
+      // console.log(_options.taglist, 'taglist')
+    }
+    // console.log(_options);
+    // console.log('device', item);
     props.save(item, _options);
+    // FormModel.actions[props.name].options = _options;
+    DeviceModel.current = 0;
   };
 
   useEffect(() => {

+ 14 - 4
src/pages/rule-engine/Scene/Save/action/DeviceOutput/model.ts

@@ -10,23 +10,33 @@ type ModelType = {
     content: React.ReactNode;
   }[];
   current: number;
-  productId: string[];
-  deviceId: any[];
+  productId: string;
+  deviceId: string;
   productDetail: ProductItem | any;
   device: Partial<ActionsDeviceProps>;
   deviceDetail: any;
   options: any;
+  selector: string;
+  selectorValues: any;
+  upperKey: string;
+  source: string;
+  relationName: string;
 };
 
 const DeviceModel = model<ModelType>({
   steps: [],
   current: 0,
-  productId: [],
-  deviceId: [],
+  productId: '',
+  deviceId: '',
   productDetail: {},
   device: {},
   deviceDetail: {},
   options: {},
+  selector: 'fixed',
+  selectorValues: [],
+  upperKey: '',
+  source: 'fixed',
+  relationName: '',
 });
 
 export default DeviceModel;

+ 2 - 2
src/pages/rule-engine/Scene/Save/action/DeviceOutput/product/index.tsx

@@ -218,10 +218,10 @@ export default observer(() => {
           tableAlertRender={false}
           rowSelection={{
             type: 'radio',
-            selectedRowKeys: DeviceModel.productId,
+            selectedRowKeys: [DeviceModel.productId],
             onChange: (selectedRowKeys, selectedRows) => {
               // console.log(selectedRowKeys,selectedRows)
-              DeviceModel.productId = selectedRows.map((item) => item.id);
+              DeviceModel.productId = selectedRows.map((item) => item.id)?.[0];
               DeviceModel.productDetail = selectedRows?.[0];
             },
           }}

+ 77 - 13
src/pages/rule-engine/Scene/Save/action/ListItem/Item.tsx

@@ -144,7 +144,46 @@ export default (props: ItemProps) => {
     }
   };
 
+  const deviceRender = (data: ActionsType | undefined) => {
+    switch (data?.device?.selector) {
+      case 'fixed':
+        return (
+          <div>
+            {data?.options?.type}
+            <span>{data?.options?.name}</span>
+            {data?.options?.properties}
+          </div>
+        );
+      case 'tag':
+        return (
+          <div>
+            {data?.options?.type}
+            {data.options?.taglist.map((item: any) => (
+              <span>
+                {item.type}
+                {item.name}
+                {item.value}
+              </span>
+            ))}
+            {data?.options?.productName}
+            {data?.options?.properties}
+          </div>
+        );
+      case 'relation':
+        return (
+          <div>
+            {data?.options?.type}与<span>{data?.options?.name}</span>具有相同
+            {data?.options?.relationName}的{data?.options?.productName}设备的
+            {data?.options?.properties}
+          </div>
+        );
+      default:
+        return null;
+    }
+  };
+
   const contentRender = () => {
+    // console.log('props.data', props.data)
     if (props?.data?.alarm?.mode === 'trigger') {
       return (
         <div>
@@ -160,7 +199,12 @@ export default (props: ItemProps) => {
       );
     } else if (props?.data?.alarm?.mode === 'relieve') {
       return (
-        <div>
+        <div
+          className={'item-options-content'}
+          onClick={() => {
+            setVisible(true);
+          }}
+        >
           满足条件后将解除关联
           <a
             onClick={() => {
@@ -172,11 +216,38 @@ export default (props: ItemProps) => {
         </div>
       );
     } else if (props?.data?.executor === 'notify') {
-      return notifyRender(props?.data);
+      return (
+        <div
+          className={'item-options-content'}
+          onClick={() => {
+            setVisible(true);
+          }}
+        >
+          {notifyRender(props?.data)}
+        </div>
+      );
     } else if (props?.data?.executor === 'delay') {
-      return <div> {props.options.name}</div>;
+      return (
+        <div
+          className={'item-options-content'}
+          onClick={() => {
+            setVisible(true);
+          }}
+        >
+          {props.options.name}
+        </div>
+      );
     } else if (props.data?.executor === 'device') {
-      return <div></div>;
+      return (
+        <div
+          className={'item-options-content'}
+          onClick={() => {
+            setVisible(true);
+          }}
+        >
+          {deviceRender(props?.data)}
+        </div>
+      );
     }
     return (
       <AddButton
@@ -195,20 +266,13 @@ export default (props: ItemProps) => {
         <div className="item-options-warp">
           <div className="item-options-type">
             <img
-              style={{ width: 48 }}
+              style={{ width: 18 }}
               src={iconMap.get(
                 props?.data.executor === 'alarm' ? props?.data?.alarm?.mode : props?.data.executor,
               )}
             />
           </div>
-          <div
-            className={'item-options-content'}
-            onClick={() => {
-              setVisible(true);
-            }}
-          >
-            {contentRender()}
-          </div>
+          {contentRender()}
         </div>
         <div className="item-number">{props.name + 1}</div>
         <div className="item-delete" onClick={props.onDelete}>

+ 1 - 0
src/pages/rule-engine/Scene/Save/action/ListItem/List.tsx

@@ -66,6 +66,7 @@ export default (props: ListProps) => {
             console.log(data);
 
             const { type, ...extra } = data;
+            console.log('list', data);
             const item: ActionsType = {
               ...extra,
               executor: data.type === 'trigger' || data.type === 'relieve' ? 'alarm' : data.type,

+ 3 - 2
src/pages/rule-engine/Scene/Save/action/ListItem/index.less

@@ -27,15 +27,16 @@
       align-items: center;
       justify-content: center;
       width: 48px;
+      height: 48px;
       margin-right: 8px;
-      background: rgba(47, 84, 235, 0.08);
+      background-color: #fafafa;
     }
 
     .item-options-content {
       display: flex;
       align-items: center;
       padding: 0 8px;
-      background: rgba(47, 84, 235, 0.08);
+      background: #fafafa;
       cursor: pointer;
       div {
         padding: 6px 10px;

+ 19 - 2
src/pages/rule-engine/Scene/Save/action/Modal/add.tsx

@@ -34,8 +34,25 @@ export default (props: Props) => {
             value={props.data?.device}
             save={(data: any, options: any) => {
               setActionType('');
-              console.log(data, options);
-              props.save(data, options);
+              // console.log(data, options);
+              // props.save(data, options);
+              // console.log('device-------------', {
+              //   type: 'device',
+              //   key: props.data.key || `action_${props.name}`,
+              //   device: {
+              //     ...data,
+              //   },
+              // });
+              props.save(
+                {
+                  type: 'device',
+                  key: props.data.key || `action_${props.name}`,
+                  device: {
+                    ...data,
+                  },
+                },
+                options,
+              );
             }}
             name={props.name}
             cancel={() => {

+ 12 - 9
src/pages/rule-engine/Scene/Save/action/device/relationSelect.tsx

@@ -4,7 +4,7 @@ import { getRelations } from '@/pages/rule-engine/Scene/Save/action/service';
 
 interface RelationProps {
   value?: any;
-  onChange?: (value?: any) => void;
+  onChange?: (value?: any, options?: any) => void;
   id?: string;
 }
 
@@ -33,16 +33,19 @@ export default (props: RelationProps) => {
       options={options}
       style={{ width: '100%' }}
       value={props.value ? props.value[0]?.value?.relation : undefined}
-      onSelect={(key: string) => {
+      onSelect={(key: string, option: any) => {
         if (props.onChange) {
-          props.onChange([
-            {
-              value: {
-                objectType: 'user',
-                relation: key,
+          props.onChange(
+            [
+              {
+                value: {
+                  objectType: 'user',
+                  relation: key,
+                },
               },
-            },
-          ]);
+            ],
+            option,
+          );
         }
       }}
       placeholder={'请选择关系'}

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

@@ -56,7 +56,6 @@ export default (props: ActionsProps) => {
               <Observer>
                 {() => {
                   const parallelThens = props.thenOptions.filter((item) => !item.parallel);
-
                   return (
                     <List
                       thenName={props.name}
@@ -64,7 +63,7 @@ export default (props: ActionsProps) => {
                       parallel={false}
                       actions={parallelThens.length ? parallelThens[0].actions : []}
                       onAdd={(actionItem) => {
-                        console.log(parallelThens);
+                        // console.log(parallelThens);
                         if (parallelThens[0]) {
                           if (
                             parallelThens[0].actions.some((aItem) => aItem.key === actionItem.key)

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

@@ -103,6 +103,7 @@ export default (props: Props) => {
                     )}
                     onClick={() => {
                       setTabKey(item.key);
+                      props.onChange(value, item.key);
                     }}
                   >
                     {item.label}