Kaynağa Gözat

Merge xyh

Next xyh
XieYongHong 3 yıl önce
ebeveyn
işleme
ed9c56e5ec

+ 29 - 13
src/pages/rule-engine/Scene/Save/action/VariableItems/builtIn.tsx

@@ -1,9 +1,10 @@
 import { DatePicker, Input, InputNumber, Select } from 'antd';
 import { useCallback, useEffect, useState } from 'react';
-import { useRequest } from 'umi';
+import type { FormInstance } from 'antd';
 import { queryBuiltInParams } from '@/pages/rule-engine/Scene/Save/action/service';
 import { ItemGroup } from '@/pages/rule-engine/Scene/Save/components';
 import moment from 'moment';
+import { BuiltInParamsHandleTreeData } from '@/pages/rule-engine/Scene/Save/components/BuiltInParams';
 
 type ChangeType = {
   source?: string;
@@ -18,6 +19,9 @@ interface BuiltInProps {
   notifyType?: string;
   onChange?: (value: ChangeType) => void;
   trigger?: any;
+  parallel?: boolean;
+  form: FormInstance;
+  name: number;
 }
 
 export default (props: BuiltInProps) => {
@@ -25,22 +29,34 @@ export default (props: BuiltInProps) => {
   const [value, setValue] = useState(props.value?.value);
   const [upperKey, setUpperKey] = useState(props.value?.upperKey);
 
-  const [builtInList, setBuiltInList] = useState([]);
-
-  const { run: getBuiltInList } = useRequest(queryBuiltInParams, {
-    manual: true,
-    formatResult: (res) => res.result,
-    onSuccess: (res) => {
-      setBuiltInList(res);
-    },
-  });
+  const [builtInList, setBuiltInList] = useState<any[]>([]);
 
   useEffect(() => {
     console.log(props.trigger);
-    if (source === 'upper' && props.trigger) {
-      getBuiltInList({ ...props.trigger });
+    // if (source === 'upper' && props.trigger) {
+    //   getBuiltInList({ ...props.trigger });
+    // }
+    if (source === 'upper') {
+      if (props.parallel === false) {
+        const data = props.form.getFieldsValue();
+        const params = props.name - 1 >= 0 ? { action: props.name - 1 } : undefined;
+        queryBuiltInParams(data, params).then((res: any) => {
+          if (res.status === 200) {
+            const actionParams = res.result.filter(
+              (item: any) => item.id === `action_${props.name}`,
+            );
+            setBuiltInList(BuiltInParamsHandleTreeData(actionParams));
+          }
+        });
+      } else {
+        queryBuiltInParams({ ...props.trigger }).then((res: any) => {
+          if (res.status === 200) {
+            setBuiltInList(BuiltInParamsHandleTreeData(res.result));
+          }
+        });
+      }
     }
-  }, [source, props.trigger]);
+  }, [source, props.trigger, props.parallel]);
 
   useEffect(() => {
     setSource(props.value?.source);

+ 5 - 1
src/pages/rule-engine/Scene/Save/action/VariableItems/org.tsx

@@ -6,6 +6,7 @@ import {
 } from '@/pages/rule-engine/Scene/Save/action/service';
 
 type ChangeType = {
+  source?: string;
   value?: string[];
 };
 
@@ -54,7 +55,10 @@ export default (props: OrgProps) => {
       }}
       onChange={(key) => {
         if (props.onChange) {
-          props.onChange({ value: key });
+          props.onChange({
+            source: 'fixed',
+            value: key,
+          });
         }
       }}
       placeholder={'请选择部门'}

+ 33 - 20
src/pages/rule-engine/Scene/Save/action/VariableItems/user.tsx

@@ -8,7 +8,6 @@ import {
   queryRelationUsers,
   queryWechatUsers,
 } from '@/pages/rule-engine/Scene/Save/action/service';
-import { defer, filter, forkJoin, from, map } from 'rxjs';
 
 type ChangeType = {
   source?: string;
@@ -30,7 +29,6 @@ export default (props: UserProps) => {
   const [relationList, setRelationList] = useState([]);
   const [treeData, setTreeData] = useState([
     { name: '平台用户', id: 'p1', selectable: false, children: [] },
-    { name: '关系用户', id: 'p2', selectable: false, children: [] },
   ]);
 
   useEffect(() => {
@@ -52,25 +50,15 @@ export default (props: UserProps) => {
   }, [props.value]);
 
   const getPlatformUser = async () => {
-    forkJoin(
-      defer(() => from(queryPlatformUsers())).pipe(
-        filter((item) => item.status === 200),
-        map((resp) => resp.result),
-      ),
-      defer(() => from(queryRelationUsers())).pipe(
-        filter((item) => item.status === 200),
-        map((resp) => resp.result),
-      ),
-    ).subscribe((res) => {
-      const newTree = [...treeData];
-      res.forEach((item, index) => {
-        newTree[index].children = item;
-      });
-      setTreeData(newTree);
-    });
-  };
+    const newTree = [...treeData];
+    const platformResp = await queryPlatformUsers();
 
-  console.log('treeData', treeData);
+    if (platformResp.status === 200) {
+      newTree[0].children = platformResp.result;
+    }
+
+    setTreeData(newTree);
+  };
 
   const getRelationUsers = async (notifyType: string, configId: string) => {
     if (notifyType === 'dingTalk') {
@@ -175,6 +163,31 @@ export default (props: UserProps) => {
     }
   };
 
+  useEffect(() => {
+    if (props.type) {
+      const newTree = [...treeData];
+      if (props.type === 'device') {
+        queryRelationUsers().then((relationResp) => {
+          if (relationResp.status === 200) {
+            newTree.push({
+              name: '关系用户',
+              id: 'p2',
+              selectable: false,
+              children: relationResp.result,
+            });
+            setTreeData(newTree);
+          }
+        });
+      } else {
+        if (newTree.length > 1) {
+          newTree.splice(1, 1);
+          setTreeData(newTree);
+        }
+      }
+      onchange(props.value?.source, '');
+    }
+  }, [props.type]);
+
   const filterOption = (input: string, option: any) => {
     return option.name ? option.name.toLowerCase().includes(input.toLowerCase()) : false;
   };

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

@@ -1,5 +1,5 @@
 import type { FormInstance } from 'antd';
-import { Button, Col, Form, Row, Select } from 'antd';
+import { Button, Checkbox, Col, Form, Row, Select } from 'antd';
 import { useCallback, useEffect, useState } from 'react';
 import { useRequest } from 'umi';
 import {
@@ -16,6 +16,7 @@ import FunctionCall from './device/functionCall';
 import { InputNumber } from '../components';
 import { DeleteOutlined } from '@ant-design/icons';
 import { observer } from '@formily/reactive-react';
+import ConditionalFiltering from './device/ConditionalFiltering';
 
 interface ActionProps {
   restField: any;
@@ -26,6 +27,7 @@ interface ActionProps {
   onRemove: () => void;
   actionItemData?: any;
   trigger?: any;
+  parallel?: boolean;
 }
 
 export default observer((props: ActionProps) => {
@@ -41,6 +43,8 @@ export default observer((props: ActionProps) => {
   const [properties, setProperties] = useState([]); // 物模型-属性
   const [functionList, setFunctionList] = useState([]); // 物模型-功能
 
+  const [isFiltering, setIsFiltering] = useState(false);
+
   const { data: messageType, run: queryMessageTypes } = useRequest(queryMessageType, {
     manual: true,
     formatResult: (res) => res.result,
@@ -200,6 +204,22 @@ export default observer((props: ActionProps) => {
     </>
   );
 
+  const parallelNode = (
+    <Col span={2}>
+      {!props.parallel ? (
+        <Form.Item noStyle>
+          <Checkbox
+            onChange={(e) => {
+              setIsFiltering(e.target.checked);
+            }}
+          >
+            条件过滤
+          </Checkbox>
+        </Form.Item>
+      ) : null}
+    </Col>
+  );
+
   useEffect(() => {
     if (type1 === 'notify') {
       queryMessageTypes();
@@ -250,6 +270,7 @@ export default observer((props: ActionProps) => {
             onMessageTypeChange={setDeviceMessageType}
             onFunctionChange={setFunctionList}
             restField={props.restField}
+            parallel={props.parallel}
           />
         )}
         {type1 === 'delay' && (
@@ -270,30 +291,49 @@ export default observer((props: ActionProps) => {
           notifyType={notifyType}
           triggerType={props.triggerType}
           configId={configId}
+          parallel={props.parallel}
         />
       ) : null}
       {type1 === 'device' &&
       deviceMessageType === MessageTypeEnum.WRITE_PROPERTY &&
       properties.length ? (
-        <Form.Item
-          name={[name, 'device', 'message', 'properties']}
-          rules={[
-            {
-              validator: async (_: any, value: any) => {
-                if (value) {
-                  if (!Object.values(value)[0]) {
-                    return Promise.reject(new Error('请输入属性值'));
-                  }
-                } else {
-                  return Promise.reject(new Error('请选择属性'));
-                }
-                return Promise.resolve();
-              },
-            },
-          ]}
-        >
-          <WriteProperty properties={properties} type={props.triggerType} form={props.form} />
-        </Form.Item>
+        <>
+          <Row gutter={24}>
+            <Col span={18}>
+              <Form.Item
+                name={[name, 'device', 'message', 'properties']}
+                rules={[
+                  {
+                    validator: async (_: any, value: any) => {
+                      if (value) {
+                        if (!Object.values(value)[0]) {
+                          return Promise.reject(new Error('请输入属性值'));
+                        }
+                      } else {
+                        return Promise.reject(new Error('请选择属性'));
+                      }
+                      return Promise.resolve();
+                    },
+                  },
+                ]}
+              >
+                <WriteProperty
+                  name={name}
+                  properties={properties}
+                  type={props.triggerType}
+                  form={props.form}
+                  parallel={props.parallel}
+                />
+              </Form.Item>
+            </Col>
+            {parallelNode}
+          </Row>
+          {!props.parallel && isFiltering && (
+            <Row gutter={24}>
+              <ConditionalFiltering name={name} form={props.form} />
+            </Row>
+          )}
+        </>
       ) : null}
       {type1 === 'device' &&
       deviceMessageType === MessageTypeEnum.READ_PROPERTY &&
@@ -307,17 +347,29 @@ export default observer((props: ActionProps) => {
               <ReadProperty properties={properties} />
             </Form.Item>
           </Col>
+          {parallelNode}
+          {!props.parallel && isFiltering && (
+            <Row gutter={24}>
+              <ConditionalFiltering name={name} form={props.form} />
+            </Row>
+          )}
         </Row>
       ) : null}
       {type1 === 'device' &&
       deviceMessageType === MessageTypeEnum.INVOKE_FUNCTION &&
       functionList.length ? (
-        <Form.Item
-          name={[name, 'device', 'message', 'inputs']}
-          rules={[{ required: true, message: '请输入功能值' }]}
-        >
-          <FunctionCall functionData={functionList} />
-        </Form.Item>
+        <>
+          <Form.Item
+            name={[name, 'device', 'message', 'inputs']}
+            rules={[{ required: true, message: '请输入功能值' }]}
+          >
+            <FunctionCall functionData={functionList} />
+          </Form.Item>
+          <Row gutter={24}>
+            {parallelNode}
+            <ConditionalFiltering name={name} form={props.form} />
+          </Row>
+        </>
       ) : null}
     </div>
   );

+ 169 - 0
src/pages/rule-engine/Scene/Save/action/device/ConditionalFiltering.tsx

@@ -0,0 +1,169 @@
+import { Col, Form, Select, InputNumber, Input, DatePicker, Space, TreeSelect } from 'antd';
+import { ItemGroup } from '@/pages/rule-engine/Scene/Save/components';
+import type { FormInstance } from 'antd';
+import { useEffect, useState, useCallback } from 'react';
+import { queryBuiltInParams } from '@/pages/rule-engine/Scene/Save/action/service';
+
+interface ConditionalFilteringProps {
+  name: number;
+  form: FormInstance;
+}
+
+export default (props: ConditionalFilteringProps) => {
+  const [builtInList, setBuiltInList] = useState<any[]>([]);
+  const [source, setSource] = useState<any>('fixed');
+  const [type, setType] = useState('string');
+  const [termTypes, setTermTypes] = useState([]);
+
+  const valueTypeMap = (_type: string) => {
+    switch (_type) {
+      case 'init':
+      case 'float':
+      case 'double':
+      case 'long':
+        return <InputNumber />;
+      case 'date':
+        return (
+          <>
+            {
+              // @ts-ignore
+              <DatePicker />
+            }
+          </>
+        );
+      case 'boolean':
+        return (
+          <Select
+            options={[
+              { label: '是', value: 'true' },
+              { label: '否', value: 'false' },
+            ]}
+          />
+        );
+      default:
+        return <Input />;
+    }
+  };
+
+  const handleName = (data: any) => {
+    return (
+      <Space>
+        {data.name}
+        {data.description && (
+          <div style={{ color: 'grey', marginLeft: '5px' }}>({data.description})</div>
+        )}
+      </Space>
+    );
+  };
+
+  const handleTreeData = (data: any): any[] => {
+    if (data.length > 0) {
+      return data.map((item: any) => {
+        const name = handleName(item);
+        if (item.children) {
+          return { ...item, name, disabled: true, children: handleTreeData(item.children) };
+        }
+        return { ...item, name };
+      });
+    }
+    return [];
+  };
+
+  const getItemByChildren = (id: string, data: any[]) => {
+    let BuiltItem = undefined;
+    data.forEach((_item) => {
+      if (_item.id === id) {
+        BuiltItem = _item;
+      } else if (_item.children) {
+        BuiltItem = getItemByChildren(id, _item.children);
+      }
+    });
+    return BuiltItem;
+  };
+
+  const getBuiltItemById = useCallback(
+    (id: string) => {
+      const builtItem: any = getItemByChildren(id, builtInList);
+      console.log(builtItem, id);
+      if (builtItem) {
+        setType(builtItem.type);
+        setTermTypes(builtItem.termTypes);
+      }
+      return builtItem ? builtItem : {};
+    },
+    [builtInList],
+  );
+
+  useEffect(() => {
+    const data = props.form.getFieldsValue();
+    queryBuiltInParams(data, { action: props.name }).then((res: any) => {
+      if (res.status === 200) {
+        const actionParams = res.result.filter(
+          (item: any) => item.id === `action_${props.name + 1}`,
+        );
+        setBuiltInList(handleTreeData(actionParams));
+      }
+    });
+  }, []);
+
+  return (
+    <>
+      <Col span={4}>
+        <Form.Item name={[props.name, 'terms[0].column']}>
+          <TreeSelect
+            placeholder={'请选择参数'}
+            fieldNames={{
+              value: 'id',
+              label: 'name',
+            }}
+            treeData={builtInList}
+            onSelect={(v: any) => {
+              getBuiltItemById(v);
+              props.form.resetFields([props.name, 'terms[0].termType']);
+            }}
+          />
+        </Form.Item>
+      </Col>
+      <Col span={2}>
+        <Form.Item name={[props.name, 'terms[0].termType']}>
+          <Select
+            style={{ width: '100%' }}
+            options={termTypes}
+            fieldNames={{ value: 'id', label: 'name' }}
+            placeholder={'操作符'}
+          />
+        </Form.Item>
+      </Col>
+      <Col span={7}>
+        <Form.Item noStyle>
+          <ItemGroup>
+            <Form.Item name={[props.name, 'terms[0].value.source']}>
+              <Select
+                options={[
+                  { label: '手动输入', value: 'fixed' },
+                  { label: '内置参数', value: 'upper' },
+                ]}
+                style={{ width: 120 }}
+                onSelect={(v: any) => {
+                  setSource(v);
+                }}
+              />
+            </Form.Item>
+            <Form.Item name={[props.name, 'terms[0].value.value[0]']}>
+              {source === 'fixed' ? (
+                valueTypeMap(type)
+              ) : (
+                <TreeSelect
+                  placeholder={'请选择参数'}
+                  fieldNames={{ value: 'id', label: 'name' }}
+                  treeData={builtInList}
+                />
+              )}
+            </Form.Item>
+          </ItemGroup>
+        </Form.Item>
+      </Col>
+      <Col span={1}>不执行后续动作</Col>
+    </>
+  );
+};

+ 67 - 19
src/pages/rule-engine/Scene/Save/action/device/WriteProperty/index.tsx

@@ -1,9 +1,10 @@
-import { Col, DatePicker, FormInstance, Input, InputNumber, Row, Select } from 'antd';
+import { Col, DatePicker, Input, InputNumber, Row, Select, TreeSelect } from 'antd';
+import type { FormInstance } from 'antd';
 import { useCallback, useEffect, useState } from 'react';
-import { useRequest } from '@@/plugin-request/request';
 import { queryBuiltInParams } from '@/pages/rule-engine/Scene/Save/action/service';
 import moment from 'moment';
 import { ItemGroup } from '@/pages/rule-engine/Scene/Save/components';
+import { Space } from '@formily/antd';
 
 interface WritePropertyProps {
   properties: any[];
@@ -11,30 +12,65 @@ interface WritePropertyProps {
   form: FormInstance;
   value?: any;
   onChange?: (value?: any) => void;
+  parallel?: boolean;
+  name: number;
 }
 
 export default (props: WritePropertyProps) => {
   const [source, setSource] = useState('fixed');
-  const [builtInList, setBuiltInList] = useState([]);
+  const [builtInList, setBuiltInList] = useState<any[]>([]);
   const [propertiesKey, setPropertiesKey] = useState<string | undefined>(undefined);
   const [propertiesValue, setPropertiesValue] = useState(undefined);
   const [propertiesType, setPropertiesType] = useState('');
 
-  const { run: getBuiltInList } = useRequest(queryBuiltInParams, {
-    manual: true,
-    formatResult: (res) => res.result,
-    onSuccess: (res) => {
-      setBuiltInList(res);
-    },
-  });
+  const handleName = (data: any) => {
+    return (
+      <Space>
+        {data.name}
+        {data.description && (
+          <div style={{ color: 'grey', marginLeft: '5px' }}>({data.description})</div>
+        )}
+      </Space>
+    );
+  };
+
+  const handleTreeData = (data: any): any[] => {
+    if (data.length > 0) {
+      return data.map((item: any) => {
+        const name = handleName(item);
+        if (item.children) {
+          return { ...item, name, disabled: true, children: handleTreeData(item.children) };
+        }
+        return { ...item, name };
+      });
+    }
+    return [];
+  };
 
   useEffect(() => {
     if (source === 'upper') {
-      getBuiltInList({
-        trigger: { type: props.type },
-      });
+      if (props.parallel === false) {
+        const data = props.form.getFieldsValue();
+        const params = props.name - 1 >= 0 ? { action: props.name - 1 } : undefined;
+        queryBuiltInParams(data, params).then((res: any) => {
+          if (res.status === 200) {
+            const actionParams = res.result.filter(
+              (item: any) => item.id === `action_${props.name}`,
+            );
+            setBuiltInList(handleTreeData(actionParams));
+          }
+        });
+      } else {
+        queryBuiltInParams({
+          trigger: { type: props.type },
+        }).then((res: any) => {
+          if (res.status === 200) {
+            setBuiltInList(handleTreeData(res.result));
+          }
+        });
+      }
     }
-  }, [source, props.type]);
+  }, [source, props.type, props.parallel]);
 
   useEffect(() => {
     console.log('writeProperty', props.value);
@@ -121,7 +157,7 @@ export default (props: WritePropertyProps) => {
 
   return (
     <Row gutter={24}>
-      <Col span={4}>
+      <Col span={6}>
         <Select
           value={propertiesKey}
           options={props.properties.filter((item) => {
@@ -138,7 +174,7 @@ export default (props: WritePropertyProps) => {
           placeholder={'请选择属性'}
         ></Select>
       </Col>
-      <Col span={7}>
+      <Col span={16}>
         <ItemGroup compact>
           <Select
             value={source}
@@ -152,15 +188,27 @@ export default (props: WritePropertyProps) => {
             }}
           />
           {source === 'upper' ? (
-            <Select
-              options={builtInList}
-              fieldNames={{ label: 'name', value: 'id' }}
+            <TreeSelect
               placeholder={'请选择参数'}
+              fieldNames={{
+                value: 'id',
+                label: 'name',
+              }}
+              value={propertiesValue}
+              treeData={builtInList}
               onSelect={(value: any) => {
                 onChange(propertiesKey, value);
               }}
             />
           ) : (
+            // <Select
+            //   options={builtInList}
+            //   fieldNames={{ label: 'name', value: 'id' }}
+            //   placeholder={'请选择参数'}
+            //   onSelect={(value: any) => {
+            //     onChange(propertiesKey, value);
+            //   }}
+            // />
             <div>{inputNodeByType(propertiesType)}</div>
           )}
         </ItemGroup>

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

@@ -16,6 +16,7 @@ interface DeviceProps {
   onProperties: (data: any) => void;
   onMessageTypeChange: (type: string) => void;
   onFunctionChange: (functionItem: any) => void;
+  parallel?: boolean;
 }
 
 enum SourceEnum {
@@ -77,7 +78,6 @@ export default (props: DeviceProps) => {
   };
 
   useEffect(() => {
-    props.form?.resetFields([['actions', name, 'device', 'selector']]);
     if (props.triggerType === 'device') {
       setSourceList([
         ...DefaultSourceOptions,
@@ -87,6 +87,12 @@ export default (props: DeviceProps) => {
     } else {
       setSourceList(DefaultSourceOptions);
     }
+    props.form?.setFields([
+      {
+        name: ['actions', name, 'device', 'selector'],
+        value: SourceEnum.fixed,
+      },
+    ]);
   }, [props.triggerType]);
 
   useEffect(() => {

+ 8 - 1
src/pages/rule-engine/Scene/Save/action/messageContent.tsx

@@ -17,6 +17,7 @@ interface MessageContentProps {
   triggerType: string;
   configId: string;
   trigger?: any;
+  parallel?: boolean;
 }
 
 const rowGutter = 12;
@@ -148,7 +149,13 @@ export default (props: MessageContentProps) => {
                       ) : type === 'link' ? (
                         <Input placeholder={'请输入' + item.name} />
                       ) : (
-                        <BuiltIn type={props.triggerType} trigger={props.trigger} data={item} />
+                        <BuiltIn
+                          form={props.form}
+                          name={props.name}
+                          type={props.triggerType}
+                          trigger={props.trigger}
+                          data={item}
+                        />
                       )}
                     </Form.Item>
                   </Col>

+ 2 - 2
src/pages/rule-engine/Scene/Save/action/service.ts

@@ -31,8 +31,8 @@ export const queryDeviceSelector = () =>
   request(`${SystemConst.API_BASE}/scene/device-selectors`, { method: 'GET' });
 
 // 内置参数
-export const queryBuiltInParams = (data: any) =>
-  request(`${SystemConst.API_BASE}/scene/parse-variables`, { method: 'POST', data });
+export const queryBuiltInParams = (data: any, params?: any) =>
+  request(`${SystemConst.API_BASE}/scene/parse-variables`, { method: 'POST', data, params });
 
 // 平台用户
 export const queryPlatformUsers = () =>

+ 37 - 0
src/pages/rule-engine/Scene/Save/components/BuiltInParams.tsx

@@ -0,0 +1,37 @@
+import { Space } from 'antd';
+
+interface BuiltInParamsProps {
+  name: string;
+  description?: string;
+}
+
+const BuiltInParamsTitle = (props: BuiltInParamsProps) => {
+  return (
+    <Space>
+      {props.name}
+      {props.description && (
+        <div style={{ color: 'grey', marginLeft: '5px' }}>({props.description})</div>
+      )}
+    </Space>
+  );
+};
+
+export const BuiltInParamsHandleTreeData = (data: any): any[] => {
+  if (data.length > 0) {
+    return data.map((item: any) => {
+      const name = <BuiltInParamsTitle {...item} />;
+      if (item.children) {
+        return {
+          ...item,
+          name,
+          disabled: true,
+          children: BuiltInParamsHandleTreeData(item.children),
+        };
+      }
+      return { ...item, name };
+    });
+  }
+  return [];
+};
+
+export default BuiltInParamsTitle;

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

@@ -6,6 +6,7 @@
   > * {
     &:last-child {
       flex: 1;
+      width: 0;
     }
   }
 

+ 8 - 38
src/pages/rule-engine/Scene/Save/index.tsx

@@ -202,16 +202,21 @@ export default () => {
     <PageContainer>
       <Card>
         <Form
+          scrollToFirstError
           form={form}
           colon={false}
           name="basicForm"
           layout={'vertical'}
           preserve={false}
           className={'scene-save'}
+          initialValues={{
+            actions: [undefined],
+          }}
           onValuesChange={(changeValue, allValues) => {
             if (changeValue.trigger) {
               if (changeValue.trigger.device) {
                 if (
+                  changeValue.trigger.device.productId ||
                   changeValue.trigger.device.selectorValues ||
                   (changeValue.trigger.device.operation &&
                     hasKeyInObject(
@@ -258,7 +263,6 @@ export default () => {
                 }),
               },
             ]}
-            required
           >
             <Input placeholder={'请输入名称'} />
           </Form.Item>
@@ -321,21 +325,6 @@ export default () => {
               </Form.Item>
             )}
             {triggerType === TriggerWayType.device && (
-              // <Form.Item
-              //   name={['trigger', 'device']}
-              //   rules={[
-              //     {
-              //       validator: async (_: any, value: any) => {
-              //         if (!value) {
-              //           return Promise.reject(new Error('请选择产品'));
-              //         }
-              //         return Promise.resolve();
-              //       },
-              //     },
-              //   ]}
-              // >
-              //   <TriggerDevice className={'trigger-type-content'} />
-              // </Form.Item>
               <TriggerDevice value={triggerDatas} className={'trigger-type-content'} form={form} />
             )}
           </Form.Item>
@@ -352,15 +341,7 @@ export default () => {
           <Form.Item
             label={
               <Space>
-                <TitleComponent
-                  data={
-                    <>
-                      <span>执行动作</span>
-                      <span style={{ color: 'red', margin: '0 4px' }}>*</span>
-                    </>
-                  }
-                  style={{ margin: 0 }}
-                />
+                <TitleComponent data={<span>执行动作</span>} style={{ margin: 0 }} />
                 <Tooltip
                   title={
                     <div>
@@ -386,19 +367,7 @@ export default () => {
               </Space>
             }
           >
-            <Form.List
-              name="actions"
-              rules={[
-                {
-                  validator: async (_: any, value: any) => {
-                    if (!value) {
-                      return Promise.reject(new Error('请添加执行动作'));
-                    }
-                    return Promise.resolve();
-                  },
-                },
-              ]}
-            >
+            <Form.List name="actions">
               {(fields, { add, remove }, { errors }) => (
                 <>
                   <div className={'scene-actions'}>
@@ -412,6 +381,7 @@ export default () => {
                         triggerType={triggerType}
                         onRemove={() => remove(name)}
                         actionItemData={actionsData.length && actionsData[name]}
+                        parallel={parallel}
                       />
                     ))}
                     <Form.Item noStyle>

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

@@ -301,8 +301,7 @@ const TriggerTerm = (props: Props, ref: any) => {
                     type: 'void',
                     'x-component': 'FormGrid',
                     'x-decorator-props': {
-                      maxColumns: 24,
-                      minColumns: 24,
+                      columns: 12,
                     },
                     properties: {
                       // columns

+ 0 - 7
src/pages/system/Department/Assets/deivce/bind.tsx

@@ -73,13 +73,6 @@ const Bind = observer((props: Props) => {
       dataIndex: 'state',
       valueType: 'select',
       valueEnum: {
-        all: {
-          text: intl.formatMessage({
-            id: 'pages.searchTable.titleStatus.all',
-            defaultMessage: '全部',
-          }),
-          status: 'Default',
-        },
         onLine: {
           text: intl.formatMessage({
             id: 'pages.device.instance.status.onLine',

+ 9 - 8
src/pages/system/Department/Assets/deivce/index.tsx

@@ -82,6 +82,7 @@ export default observer((props: { parentId: string }) => {
       dataIndex: 'id',
       title: 'ID',
       width: 220,
+      fixed: 'left',
     },
     {
       dataIndex: 'name',
@@ -89,6 +90,7 @@ export default observer((props: { parentId: string }) => {
         id: 'pages.table.name',
         defaultMessage: '名称',
       }),
+      width: 200,
     },
     {
       title: intl.formatMessage({
@@ -99,6 +101,7 @@ export default observer((props: { parentId: string }) => {
       render: (_, row) => {
         return row.productName;
       },
+      width: 200,
     },
     {
       title: '资产权限',
@@ -107,6 +110,7 @@ export default observer((props: { parentId: string }) => {
       render: (_, row) => {
         return handlePermissionsMap(row.grantedPermissions);
       },
+      width: 80,
     },
     {
       title: intl.formatMessage({
@@ -115,6 +119,7 @@ export default observer((props: { parentId: string }) => {
       }),
       dataIndex: 'registryTime',
       valueType: 'dateTime',
+      width: 160,
     },
     {
       title: intl.formatMessage({
@@ -126,13 +131,6 @@ export default observer((props: { parentId: string }) => {
       // onFilter: true,
       valueType: 'select',
       valueEnum: {
-        all: {
-          text: intl.formatMessage({
-            id: 'pages.searchTable.titleStatus.all',
-            defaultMessage: '全部',
-          }),
-          status: 'Default',
-        },
         onLine: {
           text: intl.formatMessage({
             id: 'pages.device.instance.status.onLine',
@@ -150,13 +148,14 @@ export default observer((props: { parentId: string }) => {
         notActive: {
           text: intl.formatMessage({
             id: 'pages.device.instance.status.notActive',
-            defaultMessage: '未启用',
+            defaultMessage: '用',
           }),
           status: 'notActive',
         },
       },
       render: (_, row) => <DeviceBadge type={row.state.value} text={row.state.text} />,
       search: false,
+      width: 80,
     },
     {
       title: intl.formatMessage({
@@ -166,6 +165,7 @@ export default observer((props: { parentId: string }) => {
       valueType: 'option',
       align: 'center',
       width: 200,
+      fixed: 'right',
       render: (text, record) => [
         <Popconfirm
           title={intl.formatMessage({
@@ -277,6 +277,7 @@ export default observer((props: { parentId: string }) => {
         search={false}
         params={searchParam}
         gridColumn={2}
+        scroll={{ x: 1366 }}
         request={async (params) => {
           if (!props.parentId) {
             return {

+ 6 - 0
src/pages/system/Department/Assets/product/index.tsx

@@ -69,6 +69,7 @@ export default observer((props: { parentId: string }) => {
       dataIndex: 'id',
       title: 'ID',
       width: 220,
+      fixed: 'left',
     },
     {
       dataIndex: 'name',
@@ -79,6 +80,7 @@ export default observer((props: { parentId: string }) => {
       search: {
         transform: (value) => ({ name$LIKE: value }),
       },
+      width: 200,
     },
     {
       title: '资产权限',
@@ -87,6 +89,7 @@ export default observer((props: { parentId: string }) => {
       render: (_, row) => {
         return handlePermissionsMap(row.grantedPermissions);
       },
+      width: 80,
     },
     {
       title: intl.formatMessage({
@@ -95,6 +98,7 @@ export default observer((props: { parentId: string }) => {
       }),
       dataIndex: 'describe',
       hideInSearch: true,
+      width: 200,
     },
     {
       title: intl.formatMessage({
@@ -104,6 +108,7 @@ export default observer((props: { parentId: string }) => {
       valueType: 'option',
       align: 'center',
       width: 200,
+      fixed: 'right',
       render: (text, record) => [
         <Popconfirm
           title={intl.formatMessage({
@@ -232,6 +237,7 @@ export default observer((props: { parentId: string }) => {
             status: resp.status,
           };
         }}
+        scroll={{ x: 1366 }}
         rowSelection={{
           selectedRowKeys: Models.unBindKeys,
           onChange: (selectedRowKeys, selectedRows) => {

+ 5 - 0
src/pages/system/Department/Member/index.tsx

@@ -52,6 +52,8 @@ const Member = observer((props: { parentId: string }) => {
       search: {
         transform: (value) => ({ name$LIKE: value }),
       },
+      width: 120,
+      fixed: 'left',
     },
     {
       dataIndex: 'username',
@@ -62,6 +64,7 @@ const Member = observer((props: { parentId: string }) => {
       search: {
         transform: (value) => ({ username$LIKE: value }),
       },
+      width: 120,
     },
     {
       title: intl.formatMessage({
@@ -111,6 +114,7 @@ const Member = observer((props: { parentId: string }) => {
           }
         />
       ),
+      width: 80,
     },
     {
       title: intl.formatMessage({
@@ -119,6 +123,7 @@ const Member = observer((props: { parentId: string }) => {
       }),
       valueType: 'option',
       width: 200,
+      fixed: 'right',
       render: (text, record) => [
         <Popconfirm
           title={intl.formatMessage({