wzyyy 3 лет назад
Родитель
Сommit
47f8de8bd0
38 измененных файлов с 488 добавлено и 192 удалено
  1. BIN
      public/images/cloud/dueros-doc.jpg
  2. 1 0
      src/components/AMapComponent/PathSimplifier/PathNavigator.tsx
  3. 30 5
      src/components/AMapComponent/PathSimplifier/index.tsx
  4. 20 0
      src/components/AMapComponent/hooks/Distance.tsx
  5. 1 1
      src/components/ProTableCard/CardItems/duerOs.tsx
  6. 52 20
      src/pages/Northbound/AliCloud/Detail/index.tsx
  7. 7 0
      src/pages/Northbound/DuerOS/Detail/Doc.tsx
  8. 75 13
      src/pages/Northbound/DuerOS/Detail/index.tsx
  9. 69 15
      src/pages/Northbound/DuerOS/index.tsx
  10. 3 0
      src/pages/Northbound/DuerOS/service.ts
  11. 2 0
      src/pages/account/Center/index.less
  12. 1 0
      src/pages/cloud/DuerOS/typings.d.ts
  13. 61 32
      src/pages/demo/AMap/index.tsx
  14. 25 17
      src/pages/device/Instance/Detail/MetadataLog/Property/AMap.tsx
  15. 4 2
      src/pages/device/Instance/Detail/MetadataLog/Property/index.tsx
  16. 1 1
      src/pages/device/Instance/Detail/Running/Property/FileComponent/Detail.tsx
  17. 2 6
      src/pages/device/Instance/Detail/Running/Property/FileComponent/index.tsx
  18. 2 2
      src/pages/link/AccessConfig/Detail/Cloud/Protocol/index.tsx
  19. 1 1
      src/pages/link/Channel/Modbus/Access/addPoint/index.tsx
  20. 1 1
      src/pages/link/Channel/Modbus/Access/bindDevice/index.tsx
  21. 1 1
      src/pages/link/Channel/Modbus/Access/index.tsx
  22. 1 1
      src/pages/link/Channel/Modbus/Save/index.tsx
  23. 1 0
      src/pages/link/Channel/Modbus/index.less
  24. 1 1
      src/pages/link/Channel/Opcua/Access/addPoint/index.tsx
  25. 1 1
      src/pages/link/Channel/Opcua/Access/bindDevice/index.tsx
  26. 1 1
      src/pages/link/Channel/Opcua/Access/index.tsx
  27. 2 27
      src/pages/rule-engine/Scene/Save/action/device/AllDevice.tsx
  28. 20 6
      src/pages/rule-engine/Scene/Save/action/device/index.tsx
  29. 49 0
      src/pages/rule-engine/Scene/Save/action/device/relationSelect.tsx
  30. 10 0
      src/pages/rule-engine/Scene/Save/action/service.ts
  31. 3 1
      src/pages/rule-engine/Scene/Save/components/InputUpload/index.tsx
  32. 5 5
      src/pages/rule-engine/Scene/Save/index.tsx
  33. 23 4
      src/pages/rule-engine/Scene/Save/trigger/OrgTreeSelect.tsx
  34. 5 23
      src/pages/rule-engine/Scene/Save/trigger/index.tsx
  35. 0 1
      src/pages/rule-engine/Scene/TriggerTerm/index.tsx
  36. 1 1
      src/pages/system/Platforms/Api/basePage.tsx
  37. 5 2
      src/pages/system/Platforms/save.tsx
  38. 1 1
      src/pages/system/Platforms/service.ts

BIN
public/images/cloud/dueros-doc.jpg


+ 1 - 0
src/components/AMapComponent/PathSimplifier/PathNavigator.tsx

@@ -86,6 +86,7 @@ export default (props: PathNavigatorProps) => {
     return () => {
       if (PathNavigatorRef.current) {
         removeEvent();
+        PathNavigatorRef.current.destroy();
       }
     };
   }, []);

+ 30 - 5
src/components/AMapComponent/PathSimplifier/index.tsx

@@ -71,12 +71,29 @@ const PathSimplifier = (props: PathSimplifierProps) => {
     });
   };
 
+  const clear = () => {
+    if (pathSimplifierRef.current) {
+      setLoading(false);
+      pathSimplifierRef.current!.clearPathNavigators();
+      pathSimplifierRef.current?.setData([]);
+      props.__map__.remove(pathSimplifierRef.current);
+    }
+  };
+
   useEffect(() => {
-    if (pathSimplifierRef.current && props.pathData) {
-      pathSimplifierRef.current?.setData(
-        props.pathData.map((item) => ({ name: item.name || '路线', path: item.path })),
-      );
-      setLoading(true);
+    if (pathSimplifierRef.current) {
+      if (props.pathData && props.pathData.length) {
+        setLoading(false);
+        setTimeout(() => {
+          pathSimplifierRef.current?.setData(
+            props.pathData!.map((item) => ({ name: item.name || '路线', path: item.path })),
+          );
+          setLoading(true);
+        }, 10);
+      } else {
+        setLoading(false);
+        pathSimplifierRef.current.setData([]);
+      }
     }
   }, [props.pathData]);
 
@@ -86,6 +103,14 @@ const PathSimplifier = (props: PathSimplifierProps) => {
     }
   }, [__map__]);
 
+  useEffect(() => {
+    return () => {
+      if (props.__map__) {
+        clear();
+      }
+    };
+  }, []);
+
   return <>{loading && renderChildren()}</>;
 };
 

+ 20 - 0
src/components/AMapComponent/hooks/Distance.tsx

@@ -0,0 +1,20 @@
+import { useState } from 'react';
+
+const useDistance = () => {
+  const [distance, setDistance] = useState(0);
+
+  const onDistance = (data: number[][]) => {
+    if (window.AMap && data && data.length > 2) {
+      const pointArr = data.map((point) => new window.AMap.LngLat(point[0], point[1]));
+      const distanceOfLine = AMap.GeometryUtil.distanceOfLine(pointArr);
+      setDistance(Math.round(distanceOfLine));
+    }
+  };
+
+  return {
+    distance,
+    onDistance,
+  };
+};
+
+export default useDistance;

+ 1 - 1
src/components/ProTableCard/CardItems/duerOs.tsx

@@ -39,7 +39,7 @@ export default (props: DuerOSProps) => {
             <div>
               <label>产品</label>
               <div className={'ellipsis'}>
-                <Tooltip title={props?.name || ''}>{props?.name || ''}</Tooltip>
+                <Tooltip title={props?.productName || ''}>{props?.productName || ''}</Tooltip>
               </div>
             </div>
             <div>

+ 52 - 20
src/pages/Northbound/AliCloud/Detail/index.tsx

@@ -11,20 +11,19 @@ import {
   Select,
 } from '@formily/antd';
 import type { Field } from '@formily/core';
-import { createForm, onFieldValueChange } from '@formily/core';
+import { createForm, FormPath, onFieldChange, onFieldValueChange } from '@formily/core';
 import { createSchemaField, observer } from '@formily/react';
 import { Card, Col, Image, message, Row } from 'antd';
-import { useEffect, useMemo, useState } from 'react';
+import { useEffect, useMemo } from 'react';
 import { useParams } from 'umi';
 import { useAsyncDataSource } from '@/utils/util';
 import './index.less';
 import { service } from '@/pages/Northbound/AliCloud';
 import usePermissions from '@/hooks/permission';
+import { Store } from 'jetlinks-store';
 
 const Detail = observer(() => {
   const params = useParams<{ id: string }>();
-  const [dataList, setDataList] = useState<any[]>([]);
-  const [productList, setProductList] = useState<any[]>([]);
 
   const form = useMemo(
     () =>
@@ -35,20 +34,47 @@ const Detail = observer(() => {
             const regionId = field.query('accessConfig.regionId').value();
             const accessKeyId = field.query('accessConfig.accessKeyId').value();
             const accessSecret = field.query('accessConfig.accessSecret').value();
+            let response: any[] = [];
             if (regionId && accessKeyId && accessSecret) {
-              const response = await service.getAliyunProductsList({
+              response = await service.getAliyunProductsList({
                 regionId,
                 accessKeyId,
                 accessSecret,
               });
-              f.setFieldState(field.query('bridgeProductKey'), (state) => {
-                state.dataSource = response;
-                setDataList(response);
+            }
+            f.setFieldState(field.query('bridgeProductKey'), (state) => {
+              state.dataSource = response;
+              Store.set('datalist', response);
+            });
+          });
+
+          onFieldChange('mappings.*.productKey', async (field, f) => {
+            const propertyPath = FormPath.transform(
+              field.path,
+              /\d+/,
+              (index) => `mappings.${index}`,
+            );
+            const value = field.query('.productKey').value();
+            if ((Store.get('datalist') || [])?.length > 0) {
+              f.setFieldState(propertyPath, (state) => {
+                state.componentProps = {
+                  header:
+                    (Store.get('datalist') || []).find((item: any) => item.value === value || '')
+                      ?.label || `产品映射`,
+                };
               });
             } else {
-              f.setFieldState(field.query('bridgeProductKey'), (state) => {
-                state.dataSource = [];
-                setDataList([]);
+              const accessConfig = field.query('accessConfig').value();
+              let response: any[] = [];
+              if (Object.keys(accessConfig).length >= 3) {
+                response = await service.getAliyunProductsList(accessConfig);
+              }
+              f.setFieldState(propertyPath, (state) => {
+                Store.set('datalist', response);
+                state.componentProps = {
+                  header:
+                    response.find((item: any) => item.value === value || '')?.label || `产品映射`,
+                };
               });
             }
           });
@@ -85,35 +111,39 @@ const Detail = observer(() => {
     const checked = [...items];
     const index = checked.findIndex((i) => i === f.value);
     checked.splice(index, 1);
-    if (productList?.length > 0) {
+    if (Store.get('productList')?.length > 0) {
       return new Promise((resolve) => {
-        const list = productList.filter((j: any) => !checked.includes(j.value));
+        const list = Store.get('productList').filter((j: any) => !checked.includes(j.value));
         resolve(list);
       });
     } else {
       return service.getProductsList({ paging: false }).then((resp) => {
-        setProductList(resp);
+        Store.set('productList', resp);
         return resp.filter((j: any) => !checked.includes(j.value));
       });
     }
   };
 
   const queryAliyunProductList = (f: Field) => {
+    const accessConfig = form.getValuesIn('accessConfig') || {};
     const items = form.getValuesIn('mappings')?.map((i: any) => i?.productKey) || [];
     const checked = [...items];
     const index = checked.findIndex((i) => i === f.value);
     checked.splice(index, 1);
-    if (dataList?.length > 0) {
+    if ((Store.get('datalist') || [])?.length > 0) {
       return new Promise((resolve) => {
-        const list = dataList.filter((j: any) => !checked.includes(j.value));
+        const list = (Store.get('datalist') || []).filter((j: any) => !checked.includes(j.value));
         resolve(list);
       });
-    } else {
-      const accessConfig = form.getValuesIn('accessConfig') || {};
+    } else if (Object.keys(accessConfig).length >= 3) {
       return service.getAliyunProductsList(accessConfig).then((resp) => {
-        setDataList(resp);
+        Store.set('datalist', resp);
         return resp.filter((j: any) => !checked.includes(j.value));
       });
+    } else {
+      return new Promise((resolve) => {
+        resolve([]);
+      });
     }
   };
 
@@ -343,7 +373,9 @@ const Detail = observer(() => {
 
   const handleSave = async () => {
     const data: any = await form.submit();
-    const product = dataList.find((item) => item?.value === data?.bridgeProductKey);
+    const product = (Store.get('datalist') || []).find(
+      (item: any) => item?.value === data?.bridgeProductKey,
+    );
     data.bridgeProductName = product?.label || '';
     const response: any = data.id ? await service.update(data) : await service.save(data);
     if (response.status === 200) {

+ 7 - 0
src/pages/Northbound/DuerOS/Detail/Doc.tsx

@@ -1,3 +1,7 @@
+import { Image } from 'antd';
+
+const image = require('/public/images/cloud/dueros-doc.jpg');
+
 const Doc = () => {
   return (
     <div className="doc">
@@ -14,6 +18,9 @@ const Doc = () => {
       <h1>2. 操作步骤</h1>
       <div>
         <h2>1、在百度小度技能平台创建技能,并授权。完成物联网平台与dueros的关联。</h2>
+        <div className={'image'}>
+          <Image width="100%" src={image} />
+        </div>
         <h2>2、登录物联网平台,进行平台内产品与dueros产品的数据映射。</h2>
         <h2>
           3、智能家居用户通过物联网平台中的用户,登录小度APP,获取平台内当前用户的所属设备。获取后即可进行语音控制。

+ 75 - 13
src/pages/Northbound/DuerOS/Detail/index.tsx

@@ -15,7 +15,14 @@ import {
 } from '@formily/antd';
 import { PermissionButton } from '@/components';
 import { useMemo } from 'react';
-import { createForm, Field, onFieldReact, onFieldValueChange, onFormInit } from '@formily/core';
+import {
+  createForm,
+  Field,
+  FormPath,
+  onFieldReact,
+  onFieldValueChange,
+  onFormInit,
+} from '@formily/core';
 import { useAsyncDataSource } from '@/utils/util';
 import { service } from '..';
 import { Store } from 'jetlinks-store';
@@ -48,7 +55,6 @@ const Save = () => {
   const findApplianceType = (_id: string) => {
     if (!_id) return;
     const _productTypes = Store.get('product-types');
-    console.log(_productTypes, 'tt');
     return _productTypes?.find((item: any) => item.id === _id);
   };
 
@@ -81,9 +87,24 @@ const Save = () => {
             }
             form1.setInitialValues(_data);
           });
-          onFieldReact('actionMappings.*.layout.action', (field) => {
+          onFieldReact('actionMappings.*.layout.action', (field, f) => {
             const productType = field.query('applianceType').value();
-            (field as Field).setDataSource(findApplianceType(productType)?.actions);
+            const actions = findApplianceType(productType)?.actions;
+            (field as Field).setDataSource(actions);
+
+            const actionPath = FormPath.transform(
+              field.path,
+              /\d+/,
+              (index) => `actionMappings.${index}`,
+            );
+            const value = (field as Field).value;
+
+            const title = actions.find((item: any) => item.id === value)?.name;
+            f.setFieldState(actionPath, (state) => {
+              state.componentProps = {
+                header: title || '动作映射',
+              };
+            });
           });
           onFieldReact('actionMappings.*.layout.command.message.properties', (field) => {
             const product = field.query('id').value();
@@ -102,7 +123,7 @@ const Save = () => {
               const _functionList = findProductMetadata(product)?.functions;
               const _function =
                 _functionList && _functionList.find((item: any) => item.id === functionId);
-              form1.setFieldState(field.query('.function'), (state) => {
+              form1.setFieldState(field.query('.inputs'), (state) => {
                 state.value = _function?.inputs.map((item: any) => ({
                   ...item,
                   valueType: item?.valueType?.type,
@@ -110,9 +131,22 @@ const Save = () => {
               });
             },
           );
-          onFieldReact('propertyMappings.*.layout.source', (field) => {
+          onFieldReact('propertyMappings.*.layout.source', (field, f) => {
             const productType = field.query('applianceType').value();
-            (field as Field).setDataSource(findApplianceType(productType)?.properties);
+            const propertiesList = findApplianceType(productType)?.properties;
+            (field as Field).setDataSource();
+            const propertyMappingPath = FormPath.transform(
+              field.path,
+              /\d+/,
+              (index) => `propertyMappings.${index}`,
+            );
+            const value = (field as Field).value;
+            const title = propertiesList.find((item: any) => item.id === value)?.name;
+            f.setFieldState(propertyMappingPath, (state) => {
+              state.componentProps = {
+                header: title || '属性映射',
+              };
+            });
           });
           onFieldReact('propertyMappings.*.layout.target', (field) => {
             const product = field.query('id').value();
@@ -144,8 +178,7 @@ const Save = () => {
     const index = checked.findIndex((i) => i === f.value);
     checked.splice(index, 1);
     const _productType = form.getValuesIn('applianceType');
-    const targetList = findApplianceType(_productType?.value)?.properties;
-    console.log(targetList, 'list', _productType);
+    const targetList = findApplianceType(_productType)?.properties;
     const list = targetList?.filter((i: { id: string }) => !checked.includes(i.id));
     return new Promise((resolve) => resolve(list));
   };
@@ -202,12 +235,13 @@ const Save = () => {
             title: '设备类型',
             'x-decorator-props': {
               gridSpan: 1,
+              tooltip: 'DuerOS平台拟定的规范',
             },
             type: 'string',
             'x-decorator': 'FormItem',
             'x-component': 'Select',
             'x-component-props': {
-              placeholder: '请选择产品',
+              placeholder: '请选择设备类型',
               fieldNames: {
                 label: 'name',
                 value: 'id',
@@ -250,6 +284,7 @@ const Save = () => {
                   'x-decorator-props': {
                     layout: 'vertical',
                     labelAlign: 'left',
+                    tooltip: 'DuerOS平台拟定的设备类型具有的相关动作',
                   },
                   required: true,
                   'x-component-props': {
@@ -266,7 +301,9 @@ const Save = () => {
                   'x-decorator-props': {
                     layout: 'vertical',
                     labelAlign: 'left',
+                    tooltip: '映射物联网平台中所选产品具备的动作',
                   },
+                  required: true,
                   enum: [
                     { label: '下发指令', value: 'command' },
                     { label: '获取历史数据', value: 'latestData' },
@@ -283,6 +320,7 @@ const Save = () => {
                         labelAlign: 'left',
                         gridSpan: 2,
                       },
+                      required: true,
                       'x-component': 'Select',
                       'x-decorator': 'FormItem',
                       enum: [
@@ -304,6 +342,7 @@ const Save = () => {
                       properties: {
                         properties: {
                           title: '属性',
+                          required: true,
                           'x-component': 'Select',
                           'x-decorator': 'FormItem',
                           'x-decorator-props': {
@@ -341,6 +380,7 @@ const Save = () => {
                         },
                         value: {
                           title: '值',
+                          required: true,
                           'x-component': 'Input',
                           'x-decorator': 'FormItem',
                           'x-decorator-props': {
@@ -358,6 +398,7 @@ const Save = () => {
                         },
                         functionId: {
                           title: '功能',
+                          required: true,
                           'x-component': 'Select',
                           'x-decorator': 'FormItem',
                           'x-decorator-props': {
@@ -383,6 +424,7 @@ const Save = () => {
                         inputs: {
                           title: '参数列表',
                           type: 'array',
+                          required: true,
                           'x-component': 'ArrayTable',
                           'x-decorator': 'FormItem',
                           'x-decorator-props': {
@@ -403,6 +445,7 @@ const Save = () => {
                                 properties: {
                                   name: {
                                     type: 'string',
+                                    required: true,
                                     'x-component': 'PreviewText.Input',
                                   },
                                 },
@@ -414,6 +457,7 @@ const Save = () => {
                                 properties: {
                                   valueType: {
                                     type: 'string',
+                                    required: true,
                                     'x-component': 'PreviewText.Input',
                                   },
                                 },
@@ -425,6 +469,7 @@ const Save = () => {
                                 properties: {
                                   value: {
                                     type: 'string',
+                                    required: true,
                                     'x-component': 'Input',
                                   },
                                 },
@@ -469,7 +514,7 @@ const Save = () => {
           type: 'object',
           'x-component': 'ArrayCollapse.CollapsePanel',
           'x-component-props': {
-            header: '动作',
+            header: '属性映射',
           },
           properties: {
             index: {
@@ -493,6 +538,7 @@ const Save = () => {
                     layout: 'vertical',
                     labelAlign: 'left',
                   },
+                  required: true,
                   'x-component-props': {
                     fieldNames: {
                       label: 'name',
@@ -509,6 +555,7 @@ const Save = () => {
                     layout: 'vertical',
                     labelAlign: 'left',
                   },
+                  required: true,
                   'x-component-props': {
                     fieldNames: {
                       label: 'name',
@@ -534,14 +581,29 @@ const Save = () => {
           },
         },
       },
+      description: {
+        title: '说明',
+        'x-component': 'Input.TextArea',
+        'x-decorator': 'FormItem',
+        'x-component-props': {
+          rows: 3,
+          showCount: true,
+          maxLength: 200,
+          placeholder: '请输入说明',
+        },
+      },
     },
   };
 
   const handleSave = async () => {
     const data: any = await form.submit();
     const productName = Store.get('product-list')?.find((item: any) => item.id === data.id)?.name;
-    await service.savePatch({ ...data, productName });
-    message.success('保存成功!');
+    const resp: any = await service.savePatch({ ...data, productName });
+    if (resp.status === 200) {
+      message.success('保存成功!');
+    } else {
+      message.error('保存失败!');
+    }
     history.back();
   };
   return (

+ 69 - 15
src/pages/Northbound/DuerOS/index.tsx

@@ -4,13 +4,15 @@ import { useRef, useState } from 'react';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import { PermissionButton, ProTableCard } from '@/components';
 import {
+  CloseCircleOutlined,
   DeleteOutlined,
   EditOutlined,
   ExclamationCircleFilled,
+  PlayCircleOutlined,
   PlusOutlined,
 } from '@ant-design/icons';
 import { useIntl } from '@@/plugin-locale/localeExports';
-import { message, Space } from 'antd';
+import { Badge, message, Space } from 'antd';
 import { DuerOSItem } from '@/pages/Northbound/DuerOS/types';
 import DuerOSCard from '@/components/ProTableCard/CardItems/duerOs';
 import { history } from '@@/core/history';
@@ -53,10 +55,64 @@ export default () => {
           })}
       </PermissionButton>,
       <PermissionButton
+        style={{ padding: 0 }}
+        isPermission={permission.action}
+        type="link"
+        key="changeState"
+        popConfirm={{
+          title: intl.formatMessage({
+            id: `pages.data.option.${
+              record.state?.value === 'enabled' ? 'disabled' : 'enabled'
+            }.tips`,
+            defaultMessage: `确认${record.state?.value === 'enabled' ? '禁用' : '启用'}?`,
+          }),
+          onConfirm: async () => {
+            const map = {
+              disabled: 'enable',
+              enabled: 'disable',
+            };
+            const resp = await service.changeState(record.id, map[record.state?.value]);
+            if (resp.status === 200) {
+              message.success(
+                intl.formatMessage({
+                  id: 'pages.data.option.success',
+                  defaultMessage: '操作成功!',
+                }),
+              );
+            } else {
+              message.error('操作失败!');
+            }
+
+            actionRef.current?.reload();
+          },
+        }}
+        tooltip={{
+          title: intl.formatMessage({
+            id: `pages.data.option.${record.state?.value === 'enabled' ? 'disabled' : 'enabled'}`,
+            defaultMessage: record.state?.value === 'enabled' ? '禁用' : '启用',
+          }),
+        }}
+      >
+        {record.state?.value === 'enabled' ? (
+          <>
+            {' '}
+            <CloseCircleOutlined /> {type === 'card' && '禁用'}
+          </>
+        ) : (
+          <>
+            <PlayCircleOutlined /> {type === 'card' && '启用'}
+          </>
+        )}
+      </PermissionButton>,
+      <PermissionButton
         key={'delete'}
         type={'link'}
         style={{ padding: 0 }}
         isPermission={permission.delete}
+        disabled={record.state?.value === 'enabled'}
+        tooltip={{
+          title: record.state?.value === 'disabled' ? '删除' : '请先禁用该数据,再删除。',
+        }}
         popConfirm={{
           title: '确认删除?',
           onConfirm: async () => {
@@ -65,9 +121,6 @@ export default () => {
             actionRef.current?.reload();
           },
         }}
-        tooltip={{
-          title: '删除',
-        }}
       >
         <DeleteOutlined />
       </PermissionButton>,
@@ -98,18 +151,19 @@ export default () => {
       renderText: (data) => data.text,
     },
     {
-      title: intl.formatMessage({
-        id: 'pages.cloud.duerOS.manufacturerName',
-        defaultMessage: '厂家名称',
-      }),
-      dataIndex: 'manufacturerName',
+      title: '说明',
+      dataIndex: 'description',
     },
     {
-      title: intl.formatMessage({
-        id: 'pages.cloud.duerOS.version',
-        defaultMessage: '动作数量',
-      }),
-      dataIndex: 'version',
+      title: '状态',
+      dataIndex: 'state',
+      renderText: (data) => {
+        const map = {
+          disabled: <Badge status="error" text="禁用" />,
+          enabled: <Badge status="success" text="正常" />,
+        };
+        return map[data.value];
+      },
     },
     {
       title: intl.formatMessage({
@@ -160,7 +214,7 @@ export default () => {
         headerTitle={
           <Space>
             <PermissionButton
-              isPermission={true}
+              isPermission={permission.add}
               onClick={() => {
                 history.push(getMenuPathByCode(MENUS_CODE['Northbound/DuerOS/Detail']));
               }}

+ 3 - 0
src/pages/Northbound/DuerOS/service.ts

@@ -16,6 +16,9 @@ class Service extends BaseService<DuerOSItem> {
         paging: false,
       },
     });
+
+  public changeState = (id: string, state: 'enable' | 'disable') =>
+    request(`/${SystemConst.API_BASE}/dueros/product/${id}/_${state}`, { method: 'POST' });
 }
 
 export default Service;

+ 2 - 0
src/pages/account/Center/index.less

@@ -18,10 +18,12 @@
   .content {
     width: 80%;
     padding-top: 15px;
+
     :global {
       .ant-descriptions-item-label::after {
         content: none;
       }
+
       .ant-descriptions-item-content {
         color: #666363d9;
       }

+ 1 - 0
src/pages/cloud/DuerOS/typings.d.ts

@@ -28,6 +28,7 @@ type ActionMapping = {
   };
 };
 type DuerOSItem = {
+  productName?: string;
   version: number;
   manufacturerName: string;
   autoReportProperty: boolean;

+ 61 - 32
src/pages/demo/AMap/index.tsx

@@ -1,39 +1,47 @@
 import { AMap, PathSimplifier } from '@/components';
 import { usePlaceSearch } from '@/components/AMapComponent/hooks';
 import { Marker } from 'react-amap';
-import { useState } from 'react';
-import { Select } from 'antd';
+import { useEffect, useState } from 'react';
+import { Button, Select } from 'antd';
 import { debounce } from 'lodash';
+import useDistance from '@/components/AMapComponent/hooks/Distance';
 
 export default () => {
-  const [speed] = useState(100000);
+  const { distance, onDistance } = useDistance();
+  const [speed, setSpeed] = useState(100000);
   const [markerCenter, setMarkerCenter] = useState<any>({ longitude: 0, latitude: 0 });
   const [map, setMap] = useState(null);
+  const [show, setShow] = useState(false);
 
   const { data, search } = usePlaceSearch(map);
 
+  const paths = [
+    [116.405289, 39.904987],
+    [113.964458, 40.54664],
+    [111.47836, 41.135964],
+    [108.949297, 41.670904],
+    [106.380111, 42.149509],
+    [103.774185, 42.56996],
+    [101.135432, 42.930601],
+    [98.46826, 43.229964],
+    [95.777529, 43.466798],
+    [93.068486, 43.64009],
+    [90.34669, 43.749086],
+    [87.61792, 43.793308],
+  ];
+
   const onSearch = (value: string) => {
     search(value);
   };
-  console.log(data);
+
+  useEffect(() => {
+    setSpeed((distance / 5) * 3.6);
+  }, [distance]);
 
   const [pathData] = useState([
     {
       name: '线路1',
-      path: [
-        [116.405289, 39.904987],
-        [113.964458, 40.54664],
-        [111.47836, 41.135964],
-        [108.949297, 41.670904],
-        [106.380111, 42.149509],
-        [103.774185, 42.56996],
-        [101.135432, 42.930601],
-        [98.46826, 43.229964],
-        [95.777529, 43.466798],
-        [93.068486, 43.64009],
-        [90.34669, 43.749086],
-        [87.61792, 43.793308],
-      ],
+      path: paths,
     },
   ]);
 
@@ -45,7 +53,9 @@ export default () => {
           height: 500,
           width: '100%',
         }}
-        onInstanceCreated={setMap}
+        onInstanceCreated={(_map) => {
+          setMap(_map);
+        }}
         events={{
           click: (e: any) => {
             setMarkerCenter({
@@ -59,19 +69,24 @@ export default () => {
           // @ts-ignore
           <Marker position={markerCenter} />
         ) : null}
-        <PathSimplifier pathData={pathData}>
-          <PathSimplifier.PathNavigator
-            speed={speed}
-            onCreate={(nav) => {
-              setTimeout(() => {
-                nav.pause();
-              }, 5000);
-              setTimeout(() => {
-                nav.resume(); // 恢复
-              }, 7000);
-            }}
-          />
-        </PathSimplifier>
+        {show && (
+          <PathSimplifier pathData={pathData}>
+            <PathSimplifier.PathNavigator
+              isAuto={false}
+              speed={speed}
+              onCreate={(nav) => {
+                onDistance(paths);
+
+                setTimeout(() => {
+                  nav.start();
+                }, 300);
+                // setTimeout(() => {
+                //   nav.resume(); // 恢复
+                // }, 7000);
+              }}
+            />
+          </PathSimplifier>
+        )}
       </AMap>
       <div style={{ position: 'absolute', top: 0 }}>
         <Select
@@ -84,6 +99,20 @@ export default () => {
             console.log(key, node);
           }}
         />
+        <Button
+          onClick={() => {
+            setShow(false);
+          }}
+        >
+          清除
+        </Button>
+        <Button
+          onClick={() => {
+            setShow(true);
+          }}
+        >
+          显示
+        </Button>
       </div>
     </div>
   );

+ 25 - 17
src/pages/device/Instance/Detail/MetadataLog/Property/AMap.tsx

@@ -1,4 +1,5 @@
 import { AMap, PathSimplifier } from '@/components';
+import useDistance from '@/components/AMapComponent/hooks/Distance';
 import { Button, Space } from 'antd';
 import { useEffect, useRef, useState } from 'react';
 
@@ -8,20 +9,28 @@ interface Props {
 }
 
 export default (props: Props) => {
-  const [speed] = useState(1000000);
+  const { distance, onDistance } = useDistance();
+  const [speed, setSpeed] = useState<number>(1000000);
   const PathNavigatorRef = useRef<PathNavigator | null>(null);
-  const [dataSource, setDataSource] = useState<any>({});
+  const [dataSource, setDataSource] = useState<any[]>([]);
 
   useEffect(() => {
     const list: any[] = [];
     (props?.value?.data || []).forEach((item: any) => {
       list.push([item.value.lon, item.value.lat]);
     });
-    setDataSource({
-      name: props?.name || '',
-      path: [...list],
-    });
+    setDataSource([
+      {
+        name: props?.name || '',
+        path: [...list],
+      },
+    ]);
   }, [props.value]);
+
+  useEffect(() => {
+    setSpeed((distance / 5) * 3.6);
+  }, [distance]);
+
   return (
     <div style={{ position: 'relative' }}>
       <div style={{ position: 'absolute', right: 0, top: 5, zIndex: 999 }}>
@@ -55,17 +64,16 @@ export default (props: Props) => {
           width: '100%',
         }}
       >
-        {(dataSource?.path || []).length > 0 ? (
-          <PathSimplifier pathData={[dataSource]}>
-            <PathSimplifier.PathNavigator
-              speed={speed}
-              isAuto={false}
-              onCreate={(nav) => {
-                PathNavigatorRef.current = nav;
-              }}
-            />
-          </PathSimplifier>
-        ) : null}
+        <PathSimplifier pathData={dataSource}>
+          <PathSimplifier.PathNavigator
+            speed={speed}
+            isAuto={false}
+            onCreate={(nav) => {
+              onDistance(dataSource[0]?.path);
+              PathNavigatorRef.current = nav;
+            }}
+          />
+        </PathSimplifier>
       </AMap>
     </div>
   );

+ 4 - 2
src/pages/device/Instance/Detail/MetadataLog/Property/index.tsx

@@ -149,6 +149,7 @@ const PropertyLog = (props: Props) => {
           type: 'and',
         },
       ],
+      sorts: [{ name: 'timestamp', order: 'asc' }],
     });
     if (resp.status === 200) {
       const dataList: any[] = [];
@@ -174,7 +175,7 @@ const PropertyLog = (props: Props) => {
           type: data?.name || '',
         });
       });
-      setChartsList(dataList);
+      setChartsList(dataList.reverse());
     }
   };
 
@@ -214,6 +215,7 @@ const PropertyLog = (props: Props) => {
             dataSource={dataSource?.data || []}
             columns={data?.valueType?.type === 'geoPoint' ? geoColumns : columns}
             pagination={{
+              current: dataSource?.pageIndex + 1,
               pageSize: dataSource?.pageSize || 10,
               showSizeChanger: true,
               total: dataSource?.total || 0,
@@ -231,7 +233,7 @@ const PropertyLog = (props: Props) => {
                   style={{ width: 120 }}
                   onChange={(value: string) => {
                     setCycle(value);
-                    if (cycle === '*') {
+                    if (value === '*') {
                       queryChartsList(start, end);
                     } else {
                       queryChartsAggList({

+ 1 - 1
src/pages/device/Instance/Detail/Running/Property/FileComponent/Detail.tsx

@@ -1,5 +1,5 @@
 import LivePlayer from '@/components/Player';
-import { Modal, Image } from 'antd';
+import { Image, Modal } from 'antd';
 
 interface Props {
   close: () => void;

+ 2 - 6
src/pages/device/Instance/Detail/Running/Property/FileComponent/index.tsx

@@ -1,7 +1,7 @@
 import type { PropertyMetadata } from '@/pages/device/Product/typings';
 import styles from './index.less';
 import Detail from './Detail';
-import { useEffect, useState } from 'react';
+import { useState } from 'react';
 import { message, Tooltip } from 'antd';
 
 interface Props {
@@ -31,12 +31,8 @@ const FileComponent = (props: Props) => {
   const isHttps = document.location.protocol === 'https:';
   const [temp, setTemp] = useState<boolean>(false);
 
-  useEffect(() => {
-    setTemp(false);
-  }, [props.value]);
-
   const renderValue = () => {
-    if (!value?.formatValue) {
+    if (value?.formatValue !== 0 && !value?.formatValue) {
       return <div className={props.type === 'card' ? styles.other : {}}>--</div>;
     } else if (data?.valueType?.type === 'file') {
       if (

+ 2 - 2
src/pages/link/AccessConfig/Detail/Cloud/Protocol/index.tsx

@@ -15,8 +15,8 @@ ProcotoleMapping.set('mqtt-client-gateway', 'MQTT');
 ProcotoleMapping.set('mqtt-server-gateway', 'MQTT');
 ProcotoleMapping.set('tcp-server-gateway', 'TCP');
 ProcotoleMapping.set('child-device', '');
-ProcotoleMapping.set('OneNet', 'OneNet');
-ProcotoleMapping.set('Ctwing', 'Ctwing');
+ProcotoleMapping.set('OneNet', 'HTTP');
+ProcotoleMapping.set('Ctwing', 'HTTP');
 ProcotoleMapping.set('modbus-tcp', 'MODBUS_TCP');
 ProcotoleMapping.set('opc-ua', 'OPC_UA');
 

+ 1 - 1
src/pages/link/Channel/Modbus/Access/addPoint/index.tsx

@@ -1,4 +1,4 @@
-import { Col, Form, Input, Modal, Row, Select, InputNumber, message } from 'antd';
+import { Col, Form, Input, InputNumber, message, Modal, Row, Select } from 'antd';
 import { useEffect, useState } from 'react';
 import { service } from '@/pages/link/Channel/Modbus';
 

+ 1 - 1
src/pages/link/Channel/Modbus/Access/bindDevice/index.tsx

@@ -2,7 +2,7 @@ import { Modal } from '@/components';
 import SearchComponent from '@/components/SearchComponent';
 import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
 import { Badge, message } from 'antd';
-import { useState, useRef } from 'react';
+import { useRef, useState } from 'react';
 import { service } from '@/pages/link/Channel/Modbus';
 import moment from 'moment';
 

+ 1 - 1
src/pages/link/Channel/Modbus/Access/index.tsx

@@ -1,7 +1,7 @@
 import PermissionButton from '@/components/PermissionButton';
 import { PageContainer } from '@ant-design/pro-layout';
 import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Badge, Card, Popconfirm, message, Tabs, Empty, Input } from 'antd';
+import { Badge, Card, Empty, Input, message, Popconfirm, Tabs } from 'antd';
 import { useIntl, useLocation } from 'umi';
 import { useEffect, useRef, useState } from 'react';
 import {

+ 1 - 1
src/pages/link/Channel/Modbus/Save/index.tsx

@@ -1,7 +1,7 @@
 import { useIntl } from 'umi';
 import { createForm } from '@formily/core';
 import { createSchemaField } from '@formily/react';
-import { Form, FormGrid, FormItem, Input, Select, NumberPicker } from '@formily/antd';
+import { Form, FormGrid, FormItem, Input, NumberPicker, Select } from '@formily/antd';
 import type { ISchema } from '@formily/json-schema';
 import { service } from '@/pages/link/Channel/Modbus';
 import { Modal } from '@/components';

+ 1 - 0
src/pages/link/Channel/Modbus/index.less

@@ -1,6 +1,7 @@
 .topCard {
   display: flex;
   align-items: center;
+
   .img {
     position: relative;
     top: 10px;

+ 1 - 1
src/pages/link/Channel/Opcua/Access/addPoint/index.tsx

@@ -1,4 +1,4 @@
-import { Col, Form, Input, Modal, Row, Select, InputNumber, Radio, message } from 'antd';
+import { Col, Form, Input, InputNumber, message, Modal, Radio, Row, Select } from 'antd';
 import { useEffect, useState } from 'react';
 import { service } from '@/pages/link/Channel/Opcua';
 import { DataTypeList } from '@/pages/device/data';

+ 1 - 1
src/pages/link/Channel/Opcua/Access/bindDevice/index.tsx

@@ -2,7 +2,7 @@ import { Modal } from '@/components';
 import SearchComponent from '@/components/SearchComponent';
 import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
 import { Badge, message } from 'antd';
-import { useEffect, useState, useRef } from 'react';
+import { useEffect, useRef, useState } from 'react';
 import { service } from '@/pages/link/Channel/Opcua';
 import moment from 'moment';
 

+ 1 - 1
src/pages/link/Channel/Opcua/Access/index.tsx

@@ -1,7 +1,7 @@
 import PermissionButton from '@/components/PermissionButton';
 import { PageContainer } from '@ant-design/pro-layout';
 import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Badge, Card, Popconfirm, message, Tabs, Empty, Input } from 'antd';
+import { Badge, Card, Empty, Input, message, Popconfirm, Tabs } from 'antd';
 import { useIntl, useLocation } from 'umi';
 import { useEffect, useRef, useState } from 'react';
 import {

+ 2 - 27
src/pages/rule-engine/Scene/Save/action/device/AllDevice.tsx

@@ -1,30 +1,5 @@
 import { Input } from 'antd';
-import { useEffect } from 'react';
-import { queryAllDevice } from '@/pages/rule-engine/Scene/Save/action/device/service';
 
-interface AllDeviceProps {
-  productId?: string;
-  value?: any;
-  onChange?: (value: any) => void;
-}
-
-export default (props: AllDeviceProps) => {
-  useEffect(() => {
-    queryAllDevice({
-      terms: [{ column: 'productId', value: props.productId }],
-      paging: false,
-    }).then((resp) => {
-      if (resp.status === 200 && props.onChange) {
-        props.onChange(resp.result.map((item: any) => ({ id: item.id, name: item.name })));
-      }
-    });
-  }, [props.productId]);
-
-  return (
-    <Input
-      style={{ width: '100%' }}
-      value={props.value ? props.value.map((item: any) => item.name).toString() : undefined}
-      readOnly
-    />
-  );
+export default () => {
+  return <Input style={{ width: '100%' }} value={'全部设备'} readOnly />;
 };

+ 20 - 6
src/pages/rule-engine/Scene/Save/action/device/index.tsx

@@ -5,6 +5,7 @@ import { getProductList } from '@/pages/rule-engine/Scene/Save/action/device/ser
 import Device from './deviceModal';
 import TagModal from './tagModal';
 import { ItemGroup } from '@/pages/rule-engine/Scene/Save/components';
+import RelationSelect from './relationSelect';
 
 interface DeviceProps {
   name: number;
@@ -21,7 +22,7 @@ enum SourceEnum {
   'all' = 'all',
   'fixed' = 'fixed',
   'tag' = 'tag',
-  'relation' = '',
+  'relation' = 'relation',
 }
 
 const DefaultSourceOptions = [
@@ -188,7 +189,9 @@ export default (props: DeviceProps) => {
             <Select
               options={sourceList}
               style={{ width: 120 }}
-              onSelect={(key: string) => setSelector(key)}
+              onSelect={(key: string) => {
+                setSelector(key);
+              }}
             />
           </Form.Item>
           {selector === SourceEnum.fixed && (
@@ -215,7 +218,7 @@ export default (props: DeviceProps) => {
               {...props.restField}
               rules={[{ required: true, message: '请选择关系人' }]}
             >
-              <Select style={{ width: '100%' }} placeholder={'请选择关系'} />
+              <RelationSelect />
             </Form.Item>
           )}
         </ItemGroup>
@@ -260,9 +263,20 @@ export default (props: DeviceProps) => {
           </Form.Item>
         ) : null}
       </Col>
-      <Form.Item name={[name, 'device', 'source']} hidden>
-        <Input />
-      </Form.Item>
+      {selector === SourceEnum.fixed || selector === SourceEnum.tag ? (
+        <Form.Item name={[name, 'device', 'source']} initialValue={'fixed'} hidden>
+          <Input />
+        </Form.Item>
+      ) : (
+        <>
+          <Form.Item name={[name, 'device', 'source']} initialValue={'upper'} hidden>
+            <Input />
+          </Form.Item>
+          <Form.Item name={[name, 'device', 'upperKey']} initialValue={'deviceId'} hidden>
+            <Input />
+          </Form.Item>
+        </>
+      )}
     </>
   );
 };

+ 49 - 0
src/pages/rule-engine/Scene/Save/action/device/relationSelect.tsx

@@ -0,0 +1,49 @@
+import { Select } from 'antd';
+import { useEffect, useState } from 'react';
+import { getRelations } from '@/pages/rule-engine/Scene/Save/action/service';
+
+interface RelationProps {
+  value?: any;
+  onChange?: (value?: any) => void;
+}
+
+export default (props: RelationProps) => {
+  const [options, setOptions] = useState([]);
+
+  const getRelation = async () => {
+    const resp = await getRelations();
+    if (resp.status === 200) {
+      setOptions(
+        resp.result.map((item: any) => ({
+          label: item.name,
+          value: item.id,
+        })),
+      );
+    }
+  };
+
+  useEffect(() => {
+    getRelation();
+  }, []);
+
+  return (
+    <Select
+      options={options}
+      style={{ width: '100%' }}
+      value={props.value ? props.value[0]?.value?.relation : undefined}
+      onSelect={(key: string) => {
+        if (props.onChange) {
+          props.onChange([
+            {
+              value: {
+                objectType: 'user',
+                relation: key,
+              },
+            },
+          ]);
+        }
+      }}
+      placeholder={'请选择关系'}
+    />
+  );
+};

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

@@ -75,3 +75,13 @@ export const queryWechatDepartments = (id: string) =>
 // 根据配置ID获取标签推送
 export const queryTag = (id: string) =>
   request(`${SystemConst.API_BASE}/notifier/wechat/corp/${id}/tags`, { method: 'GET' });
+
+export const getRelations = () =>
+  request(`${SystemConst.API_BASE}/relation/_query/no-paging`, {
+    method: 'POST',
+    data: {
+      paging: false,
+      sorts: [{ name: 'createTime', order: 'desc' }],
+      terms: [{ termType: 'eq', column: 'objectTypeName', value: '设备' }],
+    },
+  });

+ 3 - 1
src/pages/rule-engine/Scene/Save/components/InputUpload/index.tsx

@@ -27,7 +27,9 @@ export default (props: InputUploadProps) => {
     if (info.file.status === 'done') {
       info.file.url = info.file.response?.result;
       setLoading(false);
-      setUrl(info.file.response?.result);
+      if (onChange) {
+        onChange(info.file.response?.result);
+      }
     }
   };
 

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

@@ -77,13 +77,14 @@ export default () => {
         setParallel(_data.parallel);
 
         setTriggerValue({ trigger: _data.terms || [] });
-        setTriggerDatas(_data.terms);
+        setTriggerDatas(_data.trigger);
         if (_data.trigger?.shakeLimit) {
           setShakeLimit(_data.trigger?.shakeLimit || DefaultShakeLimit);
         }
         if (_data.trigger?.device) {
           setRequestParams({ trigger: _data.trigger });
         }
+
         if (_data.actions) {
           setActionsData(_data.actions);
         }
@@ -213,14 +214,13 @@ export default () => {
           onValuesChange={(changeValue, allValues) => {
             if (changeValue.trigger) {
               if (changeValue.trigger.device) {
-                if (changeValue.trigger.device.productId) {
-                  setTriggerValue([]);
-                  setRequestParams({ trigger: allValues.trigger });
-                } else if (
+                if (
                   changeValue.trigger.device.selectorValues ||
                   (changeValue.trigger.device.operation &&
                     changeValue.trigger.device.operation.operator)
                 ) {
+                  setTriggerValue([]);
+                  setRequestParams({ trigger: allValues.trigger });
                   setTriggerDatas(allValues.trigger);
                 }
               } else if (['timer', 'manual'].includes(changeValue.trigger.type)) {

+ 23 - 4
src/pages/rule-engine/Scene/Save/trigger/OrgTreeSelect.tsx

@@ -1,29 +1,48 @@
 import type { TreeSelectProps } from 'antd';
 import { TreeSelect } from 'antd';
-import React, { useEffect, useState } from 'react';
+import React, { useCallback, useEffect, useState } from 'react';
+import { queryOrgTree } from '@/pages/rule-engine/Scene/Save/trigger/service';
 
 interface OrgTreeSelect extends Omit<TreeSelectProps, 'onChange' | 'value'> {
   onChange?: (value: any[]) => void;
   value?: any;
+  productId?: string;
 }
 
 export default (props: OrgTreeSelect) => {
   const [myValue, setMyValue] = useState(props.value ? props.value[0].id : undefined);
   const { value, onChange, ...extraProps } = props;
+  const [orgTree, setOrgTree] = useState<any>([]);
+
+  const getOrg = useCallback(async () => {
+    if (props.productId) {
+      queryOrgTree(props.productId).then((resp) => {
+        if (resp && resp.status === 200) {
+          setOrgTree(resp.result);
+        }
+      });
+    }
+  }, [props.productId]);
+
+  useEffect(() => {
+    getOrg();
+  }, []);
 
   const onchange = (key: string, label: React.ReactNode[]) => {
     if (props.onChange) {
-      props.onChange([{ id: key, name: label[0] }]);
+      props.onChange([{ value: key, name: label[0] }]);
     }
   };
 
   useEffect(() => {
     if (props.value) {
-      setMyValue(props.value[0].id);
+      setMyValue(props.value[0].value);
     } else {
       setMyValue(undefined);
     }
   }, [props.value]);
 
-  return <TreeSelect<string> value={myValue} onChange={onchange} {...extraProps} />;
+  return (
+    <TreeSelect<string> value={myValue} treeData={orgTree} onChange={onchange} {...extraProps} />
+  );
 };

+ 5 - 23
src/pages/rule-engine/Scene/Save/trigger/index.tsx

@@ -3,7 +3,6 @@ import type { FormInstance } from 'antd';
 import { Col, Form, Row, Select } from 'antd';
 import { ItemGroup, TimingTrigger } from '@/pages/rule-engine/Scene/Save/components';
 import { getProductList } from '@/pages/rule-engine/Scene/Save/action/device/service';
-import { queryOrgTree } from '@/pages/rule-engine/Scene/Save/trigger/service';
 import Device from '@/pages/rule-engine/Scene/Save/action/device/deviceModal';
 import FunctionCall from '@/pages/rule-engine/Scene/Save/action/device/functionCall';
 import Operation from './operation';
@@ -48,15 +47,6 @@ export default observer((props: TriggerProps) => {
   const [functions, setFunctions] = useState([]); // 功能列表
 
   const [functionItem, setFunctionItem] = useState<any[]>([]); // 单个功能-属性列表
-  const [orgTree, setOrgTree] = useState<any>([]);
-
-  const getOrgTree = useCallback(() => {
-    queryOrgTree(productId).then((resp) => {
-      if (resp && resp.status === 200) {
-        setOrgTree(resp.result);
-      }
-    });
-  }, [queryOrgTree, productId]);
 
   const handleMetadata = (metadata?: string) => {
     try {
@@ -92,9 +82,6 @@ export default observer((props: TriggerProps) => {
     (id: string, metadata: any) => {
       setProductId(id);
       handleMetadata(metadata);
-      if (selector === 'org') {
-        getOrgTree();
-      }
     },
     [selector],
   );
@@ -142,7 +129,7 @@ export default observer((props: TriggerProps) => {
     getProducts();
   }, []);
 
-  console.log('triggerModel', FormModel);
+  console.log('triggerModel', selector);
 
   useEffect(() => {
     const triggerData = props.value;
@@ -151,9 +138,6 @@ export default observer((props: TriggerProps) => {
       const _device = triggerData.device;
 
       if (_device.selector) {
-        if (_device.selector === 'org') {
-          getOrgTree();
-        }
         setSelector(_device.selector);
       }
     }
@@ -178,6 +162,7 @@ export default observer((props: TriggerProps) => {
                 props.form?.resetFields([['trigger', 'device', 'selectorValues']]);
                 props.form?.resetFields([['trigger', 'device', 'operation']]);
                 productIdChange(key, node.metadata);
+                setSelector('fixed');
                 props.form?.setFieldsValue({
                   trigger: {
                     device: {
@@ -216,11 +201,8 @@ export default observer((props: TriggerProps) => {
                   />
                 </Form.Item>
                 {selector === 'all' && (
-                  <Form.Item
-                    name={['trigger', 'device', 'selectorValues']}
-                    rules={[{ required: true, message: '请选择设备' }]}
-                  >
-                    <AllDevice productId={productId} />
+                  <Form.Item>
+                    <AllDevice />
                   </Form.Item>
                 )}
                 {selector === 'fixed' && (
@@ -237,7 +219,7 @@ export default observer((props: TriggerProps) => {
                     rules={[{ required: true, message: '请选择部门' }]}
                   >
                     <OrgTreeSelect
-                      treeData={orgTree}
+                      productId={productId}
                       fieldNames={{ label: 'name', value: 'id' }}
                       placeholder={'请选择部门'}
                       style={{ width: '100%' }}

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

@@ -392,7 +392,6 @@ const TriggerTerm = (props: Props, ref: any) => {
                               },
                             },
                           },
-
                           metric: {
                             type: 'string',
                             'x-component': 'Select',

+ 1 - 1
src/pages/system/Platforms/Api/basePage.tsx

@@ -1,5 +1,5 @@
 import { Button, message, Table } from 'antd';
-import { useCallback, useEffect, useState, useRef } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
 import { useLocation } from 'umi';
 import { service } from '../index';
 import { ApiModel } from '@/pages/system/Platforms/Api/base';

+ 5 - 2
src/pages/system/Platforms/save.tsx

@@ -78,7 +78,7 @@ export default (props: SaveProps) => {
   const form = useMemo(
     () =>
       createForm({
-        validateFirst: true,
+        validateFirst: false,
       }),
     [props.data],
   );
@@ -103,6 +103,10 @@ export default (props: SaveProps) => {
           id: randomString(),
         });
       }
+    } else {
+      if (form) {
+        form.reset();
+      }
     }
   }, [props.type, props.visible]);
 
@@ -428,7 +432,6 @@ export default (props: SaveProps) => {
   const saveData = useCallback(async () => {
     // setLoading(true)
     const data: any = await form.submit();
-    console.log(data);
     if (data) {
       setLoading(true);
       const resp: any = props.type === 'edit' ? await service.edit(data) : await service.save(data);

+ 1 - 1
src/pages/system/Platforms/service.ts

@@ -65,7 +65,7 @@ class Service extends BaseService<platformsType> {
    * 获取可授权的接口ID
    */
   apiOperations = () =>
-    request(`/${SystemConst.API_BASE}//api-client/operations`, { method: 'GET' });
+    request(`/${SystemConst.API_BASE}/api-client/operations`, { method: 'GET' });
 }
 
 export default Service;