Bläddra i källkod

Merge branch 'next' of github.com:jetlinks/jetlinks-ui-antd into next-wzy

wzyyy 3 år sedan
förälder
incheckning
8934341122

+ 0 - 1
src/components/Ellipsis/index.tsx

@@ -51,7 +51,6 @@ export default (props: EllipsisProps) => {
         const _width = props.limitWidth
           ? props.limitWidth * (props.row || 1)
           : parentWidthNumber * (props.row || 1);
-        console.log(extraSize.width, _width, props.title);
         if (extraWidthNumber >= _width) {
           setIsEllipsis(true);
         } else {

+ 8 - 4
src/components/Metadata/JsonParam/index.tsx

@@ -7,19 +7,20 @@ import {
   NumberPicker,
   Select,
 } from '@formily/antd';
-import { createSchemaField } from '@formily/react';
+import { createSchemaField, observer } from '@formily/react';
 import type { ISchema } from '@formily/json-schema';
 import { DataTypeList, DateTypeList } from '@/pages/device/data';
 import { Store } from 'jetlinks-store';
 import { useAsyncDataSource } from '@/utils/util';
 import { service } from '@/pages/device/components/Metadata';
+import MetadataModel from '@/pages/device/components/Metadata/Base/model';
 
 // 不算是自定义组件。只是抽离了JSONSchema
 interface Props {
   keys?: string;
 }
 
-const JsonParam = (props: Props) => {
+const JsonParam = observer((props: Props) => {
   const SchemaField = createSchemaField({
     components: {
       FormItem,
@@ -107,7 +108,10 @@ const JsonParam = (props: Props) => {
                       required: true,
                       'x-decorator': 'FormItem',
                       'x-component': 'Select',
-                      enum: DataTypeList,
+                      enum:
+                        MetadataModel.type === 'functions'
+                          ? DataTypeList.filter((item) => item.value !== 'file')
+                          : DataTypeList,
                     },
                     unit: {
                       title: '单位',
@@ -220,5 +224,5 @@ const JsonParam = (props: Props) => {
     },
   };
   return <SchemaField schema={schema} scope={{ useAsyncDataSource, getUnit }} />;
-};
+});
 export default JsonParam;

+ 201 - 271
src/pages/device/Instance/Detail/Diagnose/Status/index.tsx

@@ -74,6 +74,10 @@ const Status = observer((props: Props) => {
     setArtificiaData({ ...params });
   };
 
+  const isExit = (arr1: any[], arr2: any[]) => {
+    return arr1.find((item) => arr2.includes(item));
+  };
+
   const modifyArrayList = (oldList: ListProps[], item: ListProps, index?: number) => {
     let newList: ListProps[] = [];
     if (index !== 0 && !index) {
@@ -95,6 +99,9 @@ const Status = observer((props: Props) => {
   // 网络信息
   const diagnoseNetwork = () =>
     new Promise((resolve) => {
+      if (!DiagnoseStatusModel.flag) {
+        resolve({});
+      }
       if (device.state?.value === 'online') {
         setTimeout(() => {
           DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
@@ -211,6 +218,9 @@ const Status = observer((props: Props) => {
   // 设备接入网关
   const diagnoseGateway = () =>
     new Promise((resolve) => {
+      if (!DiagnoseStatusModel.flag) {
+        resolve({});
+      }
       const desc =
         providerType && ['child-device', 'cloud'].includes(providerType)
           ? '诊断设备接入网关状态是否正常,网关配置是否正确'
@@ -504,6 +514,9 @@ const Status = observer((props: Props) => {
   // 网关父设备
   const diagnoseParentDevice = () =>
     new Promise(async (resolve) => {
+      if (!DiagnoseStatusModel.flag) {
+        resolve({});
+      }
       if (device.state?.value === 'online') {
         setTimeout(() => {
           DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
@@ -653,6 +666,9 @@ const Status = observer((props: Props) => {
   // 产品状态
   const diagnoseProduct = () =>
     new Promise((resolve) => {
+      if (!DiagnoseStatusModel.flag) {
+        resolve({});
+      }
       if (device.state?.value === 'online') {
         setTimeout(() => {
           DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
@@ -742,6 +758,9 @@ const Status = observer((props: Props) => {
   // 设备状态
   const diagnoseDevice = () =>
     new Promise((resolve) => {
+      if (!DiagnoseStatusModel.flag) {
+        resolve({});
+      }
       if (device.state?.value === 'online') {
         setTimeout(() => {
           DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
@@ -830,6 +849,9 @@ const Status = observer((props: Props) => {
   // 产品认证配置
   const diagnoseProductAuthConfig = () =>
     new Promise(async (resolve) => {
+      if (!DiagnoseStatusModel.flag) {
+        resolve({});
+      }
       if (device?.productId) {
         const response = await service.queryProductConfig(device.productId);
         if (response.status === 200 && response.result.length > 0) {
@@ -865,125 +887,12 @@ const Status = observer((props: Props) => {
                 DiagnoseStatusModel.count++;
                 resolve({});
               }, time);
-            } else if (properties.length > 0 && Object.keys(configuration).length > 0) {
-              if (
-                _.union(Object.keys(configuration), properties).length <
-                Object.keys(configuration).length + properties.length
-              ) {
-                setTimeout(() => {
-                  DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
-                    key: `product-auth${i}`,
-                    name: `产品-${item?.name}`,
-                    desc: '诊断产品MQTT认证配置是否正确,错误的配置将导致连接失败',
-                    status: 'error',
-                    text: '可能存在异常',
-                    info: (
-                      <div>
-                        <div className={styles.infoItem}>
-                          <Badge
-                            status="default"
-                            text={
-                              <span>
-                                请
-                                <a
-                                  onClick={() => {
-                                    manualInspection({
-                                      type: 'product',
-                                      key: `product-auth${i}`,
-                                      name: `产品-${item?.name}`,
-                                      desc: '诊断产品MQTT认证配置是否正确,错误的配置将导致连接失败',
-                                      data: { ...item },
-                                      configuration,
-                                      productId: device.productId,
-                                    });
-                                  }}
-                                >
-                                  人工检查
-                                </a>
-                                产品{item.name}
-                                配置是否已填写正确,若您确定该项无需诊断可
-                                <Popconfirm
-                                  title="确认忽略?"
-                                  onConfirm={() => {
-                                    DiagnoseStatusModel.list = modifyArrayList(
-                                      DiagnoseStatusModel.list,
-                                      {
-                                        key: `product-auth${i}`,
-                                        name: `产品-${item?.name}`,
-                                        desc: '诊断产品MQTT认证配置是否正确,错误的配置将导致连接失败',
-                                        status: 'success',
-                                        text: '正常',
-                                        info: null,
-                                      },
-                                    );
-                                  }}
-                                >
-                                  <a>忽略</a>
-                                </Popconfirm>
-                              </span>
-                            }
-                          />
-                        </div>
-                      </div>
-                    ),
-                  });
-                  DiagnoseStatusModel.count++;
-                  resolve({});
-                }, time);
-              } else {
-                setTimeout(() => {
-                  DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
-                    key: `product-auth${i}`,
-                    name: `产品-${item?.name}`,
-                    desc: '诊断产品MQTT认证配置是否正确,错误的配置将导致连接失败',
-                    status: 'error',
-                    text: '异常',
-                    info: (
-                      <div>
-                        <div className={styles.infoItem}>
-                          <Badge
-                            status="default"
-                            text={
-                              <span>
-                                请根据设备接入配置需要
-                                <a
-                                  onClick={() => {
-                                    jumpAccessConfig();
-                                  }}
-                                >
-                                  填写
-                                </a>
-                                ,若您确定该项无需诊断可
-                                <Popconfirm
-                                  title="确认忽略?"
-                                  onConfirm={() => {
-                                    DiagnoseStatusModel.list = modifyArrayList(
-                                      DiagnoseStatusModel.list,
-                                      {
-                                        key: `product-auth${i}`,
-                                        name: `产品-${item?.name}`,
-                                        desc: '诊断产品MQTT认证配置是否正确,错误的配置将导致连接失败',
-                                        status: 'success',
-                                        text: '正常',
-                                        info: null,
-                                      },
-                                    );
-                                  }}
-                                >
-                                  <a>忽略</a>
-                                </Popconfirm>
-                              </span>
-                            }
-                          />
-                        </div>
-                      </div>
-                    ),
-                  });
-                  DiagnoseStatusModel.count++;
-                  resolve({});
-                }, time);
-              }
-            } else if (properties.length > 0 && Object.keys(configuration).length === 0) {
+            } else if (
+              !isExit(
+                properties,
+                Object.keys(configuration).filter((k: string) => !!configuration[k]),
+              )
+            ) {
               setTimeout(() => {
                 DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
                   key: `product-auth${i}`,
@@ -1035,6 +944,67 @@ const Status = observer((props: Props) => {
                 DiagnoseStatusModel.count++;
                 resolve({});
               }, time);
+            } else {
+              setTimeout(() => {
+                DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
+                  key: `product-auth${i}`,
+                  name: `产品-${item?.name}`,
+                  desc: '诊断产品MQTT认证配置是否正确,错误的配置将导致连接失败',
+                  status: 'error',
+                  text: '可能存在异常',
+                  info: (
+                    <div>
+                      <div className={styles.infoItem}>
+                        <Badge
+                          status="default"
+                          text={
+                            <span>
+                              请
+                              <a
+                                onClick={() => {
+                                  manualInspection({
+                                    type: 'product',
+                                    key: `product-auth${i}`,
+                                    name: `产品-${item?.name}`,
+                                    desc: '诊断产品MQTT认证配置是否正确,错误的配置将导致连接失败',
+                                    data: { ...item },
+                                    configuration,
+                                    productId: device.productId,
+                                  });
+                                }}
+                              >
+                                人工检查
+                              </a>
+                              产品{item.name}
+                              配置是否已填写正确,若您确定该项无需诊断可
+                              <Popconfirm
+                                title="确认忽略?"
+                                onConfirm={() => {
+                                  DiagnoseStatusModel.list = modifyArrayList(
+                                    DiagnoseStatusModel.list,
+                                    {
+                                      key: `product-auth${i}`,
+                                      name: `产品-${item?.name}`,
+                                      desc: '诊断产品MQTT认证配置是否正确,错误的配置将导致连接失败',
+                                      status: 'success',
+                                      text: '正常',
+                                      info: null,
+                                    },
+                                  );
+                                }}
+                              >
+                                <a>忽略</a>
+                              </Popconfirm>
+                            </span>
+                          }
+                        />
+                      </div>
+                    </div>
+                  ),
+                });
+                DiagnoseStatusModel.count++;
+                resolve({});
+              }, time);
             }
           });
         } else {
@@ -1046,6 +1016,9 @@ const Status = observer((props: Props) => {
   // 设备认证配置
   const diagnoseDeviceAuthConfig = () =>
     new Promise(async (resolve) => {
+      if (!DiagnoseStatusModel.flag) {
+        resolve({});
+      }
       if (device?.id) {
         const response = await service.queryDeviceConfig(device.id);
         if (response.status === 200 && response.result.length > 0) {
@@ -1081,125 +1054,12 @@ const Status = observer((props: Props) => {
                 DiagnoseStatusModel.count++;
                 resolve({});
               }, time);
-            } else if (properties.length > 0 && Object.keys(configuration).length > 0) {
-              if (
-                _.union(Object.keys(configuration), properties).length <
-                Object.keys(configuration).length + properties.length
-              ) {
-                setTimeout(() => {
-                  DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
-                    key: `device-auth${i}`,
-                    name: `设备-${item?.name}`,
-                    desc: '诊断设备MQTT认证配置是否正确,错误的配置将导致连接失败',
-                    status: 'error',
-                    text: '可能存在异常',
-                    info: (
-                      <div>
-                        <div className={styles.infoItem}>
-                          <Badge
-                            status="default"
-                            text={
-                              <span>
-                                请
-                                <a
-                                  onClick={() => {
-                                    manualInspection({
-                                      type: 'device',
-                                      key: `device-auth${i}`,
-                                      name: `设备-${item?.name}`,
-                                      desc: '诊断设备MQTT认证配置是否正确,错误的配置将导致连接失败',
-                                      data: { ...item },
-                                      configuration,
-                                      productId: device.productId,
-                                    });
-                                  }}
-                                >
-                                  人工检查
-                                </a>
-                                设备{item.name}
-                                配置是否已填写正确,若您确定该项无需诊断可
-                                <Popconfirm
-                                  title="确认忽略?"
-                                  onConfirm={() => {
-                                    DiagnoseStatusModel.list = modifyArrayList(
-                                      DiagnoseStatusModel.list,
-                                      {
-                                        key: `device-auth${i}`,
-                                        name: `设备-${item?.name}`,
-                                        desc: '诊断设备MQTT认证配置是否正确,错误的配置将导致连接失败',
-                                        status: 'success',
-                                        text: '正常',
-                                        info: null,
-                                      },
-                                    );
-                                  }}
-                                >
-                                  <a>忽略</a>
-                                </Popconfirm>
-                              </span>
-                            }
-                          />
-                        </div>
-                      </div>
-                    ),
-                  });
-                  DiagnoseStatusModel.count++;
-                  resolve({});
-                }, time);
-              } else {
-                setTimeout(() => {
-                  DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
-                    key: `device-auth${i}`,
-                    name: `设备-${item?.name}`,
-                    desc: '诊断设备MQTT认证配置是否正确,错误的配置将导致连接失败',
-                    status: 'error',
-                    text: '异常',
-                    info: (
-                      <div>
-                        <div className={styles.infoItem}>
-                          <Badge
-                            status="default"
-                            text={
-                              <span>
-                                请根据设备接入配置需要
-                                <a
-                                  onClick={() => {
-                                    jumpDeviceConfig();
-                                  }}
-                                >
-                                  填写
-                                </a>
-                                ,若您确定该项无需诊断可
-                                <Popconfirm
-                                  title="确认忽略?"
-                                  onConfirm={() => {
-                                    DiagnoseStatusModel.list = modifyArrayList(
-                                      DiagnoseStatusModel.list,
-                                      {
-                                        key: `device-auth${i}`,
-                                        name: `设备-${item?.name}`,
-                                        desc: '诊断设备MQTT认证配置是否正确,错误的配置将导致连接失败',
-                                        status: 'success',
-                                        text: '正常',
-                                        info: null,
-                                      },
-                                    );
-                                  }}
-                                >
-                                  <a>忽略</a>
-                                </Popconfirm>
-                              </span>
-                            }
-                          />
-                        </div>
-                      </div>
-                    ),
-                  });
-                  DiagnoseStatusModel.count++;
-                  resolve({});
-                }, time);
-              }
-            } else if (properties.length > 0 && Object.keys(configuration).length === 0) {
+            } else if (
+              !isExit(
+                properties,
+                Object.keys(configuration).filter((k: string) => !!configuration[k]),
+              )
+            ) {
               setTimeout(() => {
                 DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
                   key: `device-auth${i}`,
@@ -1251,6 +1111,67 @@ const Status = observer((props: Props) => {
                 DiagnoseStatusModel.count++;
                 resolve({});
               }, time);
+            } else {
+              setTimeout(() => {
+                DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
+                  key: `device-auth${i}`,
+                  name: `设备-${item?.name}`,
+                  desc: '诊断设备MQTT认证配置是否正确,错误的配置将导致连接失败',
+                  status: 'error',
+                  text: '可能存在异常',
+                  info: (
+                    <div>
+                      <div className={styles.infoItem}>
+                        <Badge
+                          status="default"
+                          text={
+                            <span>
+                              请
+                              <a
+                                onClick={() => {
+                                  manualInspection({
+                                    type: 'device',
+                                    key: `device-auth${i}`,
+                                    name: `设备-${item?.name}`,
+                                    desc: '诊断设备MQTT认证配置是否正确,错误的配置将导致连接失败',
+                                    data: { ...item },
+                                    configuration,
+                                    productId: device.productId,
+                                  });
+                                }}
+                              >
+                                人工检查
+                              </a>
+                              设备{item.name}
+                              配置是否已填写正确,若您确定该项无需诊断可
+                              <Popconfirm
+                                title="确认忽略?"
+                                onConfirm={() => {
+                                  DiagnoseStatusModel.list = modifyArrayList(
+                                    DiagnoseStatusModel.list,
+                                    {
+                                      key: `device-auth${i}`,
+                                      name: `设备-${item?.name}`,
+                                      desc: '诊断设备MQTT认证配置是否正确,错误的配置将导致连接失败',
+                                      status: 'success',
+                                      text: '正常',
+                                      info: null,
+                                    },
+                                  );
+                                }}
+                              >
+                                <a>忽略</a>
+                              </Popconfirm>
+                            </span>
+                          }
+                        />
+                      </div>
+                    </div>
+                  ),
+                });
+                DiagnoseStatusModel.count++;
+                resolve({});
+              }, time);
             }
           });
         } else {
@@ -1462,6 +1383,9 @@ const Status = observer((props: Props) => {
   // onenet
   const diagnoseOnenet = () =>
     new Promise(async (resolve) => {
+      if (!DiagnoseStatusModel.flag) {
+        resolve({});
+      }
       if (device.accessProvider === 'OneNet') {
         const response = await service.queryDeviceConfig(device?.id || '');
         DiagnoseStatusModel.configuration.device = response.result;
@@ -1575,6 +1499,9 @@ const Status = observer((props: Props) => {
   // ctwing
   const diagnoseCTWing = () =>
     new Promise(async (resolve) => {
+      if (!DiagnoseStatusModel.flag) {
+        resolve({});
+      }
       if (device.accessProvider === 'Ctwing') {
         const response = await service.queryDeviceConfig(device?.id || '');
         DiagnoseStatusModel.configuration.device = response.result;
@@ -1862,6 +1789,12 @@ const Status = observer((props: Props) => {
     }
   }, [DiagnoseStatusModel.status, DiagnoseStatusModel.list]);
 
+  const percentChange = () => {
+    if (DiagnoseStatusModel.percent < 100) {
+      DiagnoseStatusModel.percent += 20;
+    }
+  };
+
   const handleSearch = async () => {
     DiagnoseStatusModel.gateway = {};
     DiagnoseStatusModel.product = {};
@@ -1872,46 +1805,36 @@ const Status = observer((props: Props) => {
     DiagnoseStatusModel.count = 0;
     DiagnoseStatusModel.status = 'loading';
     DiagnoseStatusModel.percent = 0;
+    let arr: any[] = [];
     if (providerType === 'network') {
       DiagnoseStatusModel.list = [...networkInitList];
-      await diagnoseNetwork();
-      DiagnoseStatusModel.percent = 20;
-      await diagnoseGateway();
-      DiagnoseStatusModel.percent = 40;
-      await diagnoseProduct();
-      await diagnoseDevice();
-      DiagnoseStatusModel.percent = 60;
-      await diagnoseProductAuthConfig();
-      await diagnoseDeviceAuthConfig();
+      arr = [
+        diagnoseNetwork,
+        diagnoseGateway,
+        diagnoseProduct,
+        diagnoseDevice,
+        diagnoseProductAuthConfig,
+        diagnoseDeviceAuthConfig,
+      ];
     } else if (providerType === 'child-device') {
       DiagnoseStatusModel.list = [...childInitList];
-      await diagnoseGateway();
-      DiagnoseStatusModel.percent = 20;
-      await diagnoseParentDevice();
-      await diagnoseProduct();
-      DiagnoseStatusModel.percent = 40;
-      await diagnoseDevice();
-      DiagnoseStatusModel.percent = 60;
-      await diagnoseProductAuthConfig();
-      await diagnoseDeviceAuthConfig();
-      DiagnoseStatusModel.percent = 80;
+      arr = [
+        diagnoseGateway,
+        diagnoseParentDevice,
+        diagnoseProduct,
+        diagnoseDevice,
+        diagnoseProductAuthConfig,
+        diagnoseDeviceAuthConfig,
+      ];
     } else if (providerType === 'media') {
       DiagnoseStatusModel.list = [...mediaInitList];
-      await diagnoseGateway();
-      DiagnoseStatusModel.percent = 40;
-      await diagnoseProduct();
-      await diagnoseDevice();
+      arr = [diagnoseGateway, diagnoseProduct, diagnoseDevice];
     } else if (providerType === 'cloud') {
       DiagnoseStatusModel.list = [...cloudInitList];
-      await diagnoseGateway();
-      DiagnoseStatusModel.percent = 40;
-      await diagnoseProduct();
-      await diagnoseDevice();
-      DiagnoseStatusModel.percent = 80;
-      await diagnoseCTWing();
-      await diagnoseOnenet();
+      arr = [diagnoseGateway, diagnoseProduct, diagnoseDevice, diagnoseCTWing, diagnoseOnenet];
     } else if (providerType === 'channel') {
       message.error('未开发');
+      return;
       // DiagnoseStatusModel.list = [...channelInitList];
       // await diagnoseGateway();
       // DiagnoseStatusModel.percent = 20;
@@ -1925,11 +1848,18 @@ const Status = observer((props: Props) => {
       // await diagnoseDataPointBind();
       // DiagnoseStatusModel.percent = 80;
     }
-    DiagnoseStatusModel.percent = 100;
-    DiagnoseStatusModel.status = 'finish';
+    if (arr.length > 0) {
+      for (let i = 0; i < arr.length; i++) {
+        await arr[i]();
+        percentChange();
+      }
+      DiagnoseStatusModel.percent = 100;
+      DiagnoseStatusModel.status = 'finish';
+    }
   };
 
   useEffect(() => {
+    DiagnoseStatusModel.flag = true;
     if (DiagnoseStatusModel.state === 'loading' && providerType) {
       handleSearch();
     }
@@ -1940,7 +1870,7 @@ const Status = observer((props: Props) => {
       <div className={styles.statusHeader}>
         <TitleComponent data={'连接详情'} />
         <Space>
-          {DiagnoseStatusModel.status === 'finish' && (
+          {DiagnoseStatusModel.status === 'finish' && device.state?.value !== 'online' && (
             <Button
               type="primary"
               onClick={async () => {

+ 3 - 1
src/pages/device/Instance/Detail/Diagnose/Status/model.ts

@@ -1,7 +1,7 @@
 import type { ProductItem } from '@/pages/device/Product/typings';
 import { model } from '@formily/reactive';
 import type { ReactNode } from 'react';
-import { DeviceInstance } from '../../../typings';
+import type { DeviceInstance } from '../../../typings';
 
 export const StatusMap = new Map();
 StatusMap.set('error', require('/public/images/diagnose/status/error.png'));
@@ -254,6 +254,7 @@ export const DiagnoseStatusModel = model<{
       status: 'loading' | 'success' | 'error';
     };
   };
+  flag: boolean; // 离开页面后让还未执行的方法停止
 }>({
   list: [],
   product: {},
@@ -280,6 +281,7 @@ export const DiagnoseStatusModel = model<{
       status: 'loading',
     },
   },
+  flag: true,
 });
 
 export const gatewayList = [

+ 1 - 0
src/pages/device/Instance/Detail/Diagnose/index.tsx

@@ -50,6 +50,7 @@ const Diagnose = observer(() => {
       DiagnoseStatusModel.percent = 0;
       DiagnoseStatusModel.status = 'loading';
       DiagnoseStatusModel.state = 'loading';
+      DiagnoseStatusModel.flag = false;
     };
   }, [InstanceModel.active]);
 

+ 14 - 2
src/pages/device/Product/Detail/Access/index.tsx

@@ -447,10 +447,20 @@ const Access = () => {
     });
   };
 
+  const flatObj = (obj: any, result: any) => {
+    Object.keys(obj).forEach((key: string) => {
+      if (typeof obj[key] === 'string') {
+        result[key] = obj[key];
+      } else {
+        flatObj(obj[key], result);
+      }
+    });
+  };
+
   const renderConfigCard = () => {
     const itemSchema: any = (metadata || []).map((item: any) => {
       return {
-        type: 'object',
+        type: 'void',
         properties: {
           grid: {
             type: 'void',
@@ -517,7 +527,9 @@ const Access = () => {
             type="primary"
             onClick={async () => {
               const values = (await form.submit()) as any;
-              const { storePolicy, ...extra } = values;
+              const result: any = {};
+              flatObj(values, result);
+              const { storePolicy, ...extra } = result;
               const resp = await productService.modify(id || '', {
                 id,
                 configuration: { ...extra },

+ 2 - 0
src/pages/device/components/Metadata/Base/Edit/index.tsx

@@ -216,6 +216,8 @@ const Edit = observer((props: Props) => {
                   label: 'object(结构体)',
                 },
               ]
+            : MetadataModel.type === 'functions'
+            ? DataTypeList.filter((item) => item.value !== 'file')
             : DataTypeList,
       },
       unit: {

+ 1 - 1
src/pages/link/Type/Detail/index.tsx

@@ -735,7 +735,7 @@ const Save = observer(() => {
             enum: [{ label: 'JavaScript', value: 'javascript' }],
           },
           script: {
-            title: '脚本解析',
+            title: '解析脚本',
             'x-component': 'FMonacoEditor',
             'x-decorator': 'FormItem',
             'x-decorator-props': {

+ 1 - 1
src/pages/notice/Template/index.tsx

@@ -104,7 +104,7 @@ const Template = observer(() => {
       dataIndex: 'provider',
       title: '通知方式',
       renderText: (text, record) => {
-        return typeList[record.type][record.provider];
+        return typeList[record?.type][record?.provider];
       },
       valueType: 'select',
       valueEnum: list[id],

+ 1 - 1
src/pages/rule-engine/Scene/Save/Explanation.less

@@ -4,7 +4,7 @@
   padding: 24px;
   color: rgba(#000, 0.8);
   font-size: 14px;
-  background-color: #fafafa;
+  border: 1px solid #e0e0e0;
 
   .url {
     padding: 8px 16px;

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

@@ -54,7 +54,7 @@ export default (props: BuiltInProps) => {
     queryBuiltInParams(data, params).then((res: any) => {
       if (res.status === 200) {
         const actionParams = res.result.filter((item: any) => item.id === `action_${props.name}`);
-        const _data = props.name === 0 ? res.result : BuiltInParamsHandleTreeData(actionParams);
+        const _data = BuiltInParamsHandleTreeData(props.name === 0 ? res.result : actionParams);
         setBuiltInList(_data);
       }
     });

+ 39 - 38
src/pages/rule-engine/Scene/Save/action/action.tsx

@@ -14,7 +14,7 @@ import WriteProperty from './device/WriteProperty';
 import ReadProperty from './device/readProperty';
 import FunctionCall from './device/functionCall';
 import { InputNumber } from '../components';
-import { ArrowUpOutlined, DeleteOutlined, ArrowDownOutlined } from '@ant-design/icons';
+import { ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons';
 import { observer } from '@formily/reactive-react';
 import ConditionalFiltering from './device/ConditionalFiltering';
 
@@ -253,43 +253,7 @@ export default observer((props: ActionProps) => {
 
   return (
     <div className={'actions-item'}>
-      <div className={'actions-item-title'}>
-        执行动作 {props.name + 1}
-        <Button
-          onClick={props.onRemove}
-          danger
-          style={{
-            padding: '0 8px',
-            margin: '0 0 12px 12px',
-          }}
-        >
-          <DeleteOutlined />
-        </Button>
-        <Button
-          onClick={() => {
-            props.onMove?.('up');
-          }}
-          disabled={name === 0}
-          style={{
-            padding: '0 8px',
-            margin: '0 0 12px 12px',
-          }}
-        >
-          <ArrowUpOutlined />
-        </Button>
-        <Button
-          onClick={() => {
-            props.onMove?.('down');
-          }}
-          disabled={props.isLast}
-          style={{
-            padding: '0 8px',
-            margin: '0 0 12px 12px',
-          }}
-        >
-          <ArrowDownOutlined />
-        </Button>
-      </div>
+      <div className={'actions-item-title'}>执行动作: {props.name + 1}</div>
       <Row gutter={24}>
         <Col span={4}>
           <Form.Item
@@ -450,6 +414,43 @@ export default observer((props: ActionProps) => {
           </Row>
         </>
       ) : null}
+      <div className={'actions-item-footer'}>
+        <Button
+          onClick={() => {
+            props.onMove?.('up');
+          }}
+          disabled={name === 0}
+          style={{
+            padding: '0 8px',
+            margin: '0 0 12px 12px',
+          }}
+        >
+          <ArrowUpOutlined />
+        </Button>
+        <Button
+          onClick={() => {
+            props.onMove?.('down');
+          }}
+          disabled={props.isLast}
+          style={{
+            padding: '0 8px',
+            margin: '0 0 12px 12px',
+          }}
+        >
+          <ArrowDownOutlined />
+        </Button>
+        <Button
+          onClick={props.onRemove}
+          danger
+          style={{
+            width: 80,
+            marginLeft: 24,
+          }}
+        >
+          {/*<DeleteOutlined />*/}
+          删除
+        </Button>
+      </div>
     </div>
   );
 });

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

@@ -260,7 +260,7 @@ export default (props: ConditionalFilteringProps) => {
           </ItemGroup>
         </Form.Item>
       </Col>
-      <Col>执行后续动作</Col>
+      <Col>执行后续动作</Col>
     </>
   );
 };

+ 42 - 17
src/pages/rule-engine/Scene/Save/action/device/WriteProperty/index.tsx

@@ -1,10 +1,11 @@
 import { Col, DatePicker, Input, InputNumber, Row, Select, TreeSelect } from 'antd';
 import type { FormInstance } from 'antd';
-import { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
 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';
+import { cloneDeep } from 'lodash';
 
 interface WritePropertyProps {
   properties: any[];
@@ -24,6 +25,7 @@ export default (props: WritePropertyProps) => {
   const [propertiesKey, setPropertiesKey] = useState<string | undefined>(undefined);
   const [propertiesValue, setPropertiesValue] = useState(undefined);
   const [propertiesType, setPropertiesType] = useState('');
+  const paramsListRef = useRef<any[]>();
 
   const handleName = (data: any) => {
     return (
@@ -60,30 +62,47 @@ export default (props: WritePropertyProps) => {
     }
   };
 
-  const sourceChangeEvent = () => {
+  const filterParamsData = (type?: string, data?: any[]): any[] => {
+    if (type && data) {
+      return data.filter((item) => {
+        if (item.children) {
+          const _children = filterParamsData(type, item.children);
+          item.children = _children;
+          return _children.length ? true : false;
+        } else if (item.type === type) {
+          return true;
+        }
+        return false;
+      });
+    }
+    return data || [];
+  };
+
+  const sourceChangeEvent = useCallback(() => {
     onChange(propertiesKey, undefined, source);
     const params = props.name - 1 >= 0 ? { action: props.name - 1 } : undefined;
     const data = props.form.getFieldsValue();
     queryBuiltInParams(data, params).then((res: any) => {
       if (res.status === 200) {
         const actionParams = res.result.filter((item: any) => item.id === `action_${props.name}`);
-        const _data = props.name === 0 ? res.result : handleTreeData(actionParams);
+        // 获取当前属性类型,过滤不同类型的数据
+        const propertiesItem = props.properties
+          .filter((item) => {
+            if (item.expands && item.expands.type) {
+              return item.expands.type.includes('write');
+            }
+            return false;
+          })
+          .find((item) => item.id === propertiesKey);
+        const type = propertiesItem?.valueType?.type;
+        const _params = props.name === 0 ? res.result : actionParams;
+        paramsListRef.current = cloneDeep(_params);
+        const _filterData = filterParamsData(type, _params);
+        const _data = handleTreeData(_filterData);
         setBuiltInList(_data);
       }
     });
-    // if (props.parallel === false) {
-    //   // 串行
-    // } else {
-    //   // 并行
-    //   queryBuiltInParams({
-    //     trigger: { type: props.type },
-    //   }).then((res: any) => {
-    //     if (res.status === 200) {
-    //       setBuiltInList(handleTreeData(res.result));
-    //     }
-    //   });
-    // }
-  };
+  }, [props.properties, propertiesKey, source]);
 
   useEffect(() => {
     if (source === 'upper') {
@@ -204,8 +223,14 @@ export default (props: WritePropertyProps) => {
           })}
           fieldNames={{ label: 'name', value: 'id' }}
           style={{ width: '100%' }}
-          onSelect={(key: any) => {
+          onSelect={(key: any, node: any) => {
             onChange(key, undefined, source);
+            if (source === 'upper') {
+              const newArr = cloneDeep(paramsListRef.current);
+              const _filterData = filterParamsData(node?.valueType?.type, newArr);
+              const _data = handleTreeData(_filterData);
+              setBuiltInList(_data);
+            }
           }}
           placeholder={'请选择属性'}
         ></Select>

+ 13 - 9
src/pages/rule-engine/Scene/Save/action/device/deviceModal.tsx

@@ -1,10 +1,11 @@
 import { Badge, Button, Input, message, Modal } from 'antd';
-import { useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
 import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
 import { DeviceItem } from '@/pages/system/Department/typings';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import SearchComponent from '@/components/SearchComponent';
 import { queryDevice } from '@/pages/rule-engine/Scene/Save/action/device/service';
+import { AIcon } from '@/components';
 
 interface DeviceModelProps {
   value?: ChangeValueType[];
@@ -107,6 +108,15 @@ export default (props: DeviceModelProps) => {
     },
   ];
 
+  const onClick = useCallback(() => {
+    if (!props.productId) {
+      message.warning('请选择产品');
+    } else {
+      setVisible(true);
+      setSelectKeys(value ? [...value] : []);
+    }
+  }, [props.productId, value]);
+
   return (
     <>
       {visible && (
@@ -189,14 +199,8 @@ export default (props: DeviceModelProps) => {
       )}
       <Input
         placeholder={'请选择设备'}
-        onClick={() => {
-          if (!props.productId) {
-            message.warning('请选择产品');
-          } else {
-            setVisible(true);
-            setSelectKeys(value ? [...value] : []);
-          }
-        }}
+        onClick={onClick}
+        addonAfter={<AIcon type={'icon-shebei'} onClick={onClick} />}
         style={{ width: '100%' }}
         value={value && value.map((item) => item.name).toString()}
         readOnly

+ 12 - 0
src/pages/rule-engine/Scene/Save/components/TriggerWay/index.less

@@ -11,6 +11,7 @@
     border: 1px solid #e0e4e8;
     border-radius: 2px;
     cursor: pointer;
+    opacity: 0.6;
     transition: all 0.3s;
 
     .way-item-title {
@@ -32,16 +33,27 @@
 
     &:hover {
       color: @primary-color-hover;
+      opacity: 0.8;
     }
 
     &.active {
       border-color: @primary-color-active;
+      opacity: 1;
     }
   }
 
   &.disabled {
     .trigger-way-item {
       cursor: not-allowed;
+
+      &:hover {
+        color: initial;
+        opacity: 0.6;
+      }
+
+      &.active {
+        opacity: 1;
+      }
     }
   }
 }

+ 25 - 2
src/pages/rule-engine/Scene/Save/index.less

@@ -3,8 +3,31 @@
 .scene-save {
   .trigger-type-content,
   & .scene-actions {
-    padding: 24px 24px 0 24px;
-    background-color: @bgColor;
+    .actions-item {
+      padding: 24px 24px 0 24px;
+      background-color: @bgColor;
+
+      &:not(:first-child) {
+        margin-top: 16px;
+      }
+
+      .actions-item-title {
+        margin-bottom: 16px;
+      }
+
+      .actions-item-footer {
+        display: flex;
+        justify-content: flex-end;
+        padding-top: 16px;
+        border-top: 1px solid #2f54eb;
+      }
+
+      .template-variable {
+        margin-bottom: 16px;
+        padding: 16px;
+        border: 1px solid #e6e6e6;
+      }
+    }
   }
 
   .ant-form-item-with-help .ant-form-item-explain {

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

@@ -160,6 +160,7 @@ export default () => {
           };
           setShakeLimit(newShake);
         }}
+        style={{ marginRight: 16 }}
       />
       {shakeLimit.enabled && (
         <>
@@ -175,7 +176,7 @@ export default () => {
               setShakeLimit(newShake);
             }}
           />
-          <span> 秒内发生 </span>
+          <span style={{ padding: '0 16px' }}> 秒内发生 </span>
           <InputNumber
             value={shakeLimit.threshold}
             min={1}
@@ -188,7 +189,7 @@ export default () => {
               setShakeLimit(newShake);
             }}
           />
-          <span>次及以上时,处理</span>
+          <span style={{ padding: '0 16px' }}>次及以上时,处理</span>
           <Radio.Group
             value={shakeLimit.alarmFirst}
             options={[
@@ -260,7 +261,6 @@ export default () => {
                     setActionParams({ trigger: allValues.trigger }); // 用于内置参数请求
                   }
                 }
-                console.log('scene save', allValues);
                 if (allValues.actions) {
                   setActionsData(allValues.actions);
                 }
@@ -378,12 +378,16 @@ export default () => {
                         ))}
                         <Form.Item noStyle>
                           <Button
-                            type="dashed"
+                            type="primary"
+                            ghost
+                            style={{
+                              width: '100%',
+                              marginTop: 16,
+                            }}
                             onClick={() => {
                               add();
                               setActionDataCount(actionDataCount + 1);
                             }}
-                            block
                             icon={<PlusOutlined />}
                           >
                             新增

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

@@ -177,7 +177,7 @@ export default observer((props: TriggerProps) => {
         {!!productId && (
           <Col span={12}>
             <Form.Item noStyle>
-              <ItemGroup>
+              <ItemGroup compact>
                 <Form.Item name={['trigger', 'device', 'selector']} initialValue={'fixed'}>
                   <Select
                     options={[

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

@@ -314,8 +314,8 @@ const TriggerTerm = (props: Props, ref: any) => {
                   layout: {
                     type: 'void',
                     'x-component': 'FormGrid',
-                    'x-decorator-props': {
-                      columns: 12,
+                    'x-component-props': {
+                      minColumns: 24,
                     },
                     properties: {
                       // columns
@@ -325,7 +325,7 @@ const TriggerTerm = (props: Props, ref: any) => {
                         'x-decorator': 'FormItem',
                         'x-component': 'TreeSelect',
                         'x-decorator-props': {
-                          gridSpan: 4,
+                          gridSpan: 10,
                         },
                         required: true,
                         'x-component-props': {
@@ -342,7 +342,7 @@ const TriggerTerm = (props: Props, ref: any) => {
                         'x-decorator': 'FormItem',
                         'x-component': 'Select',
                         'x-decorator-props': {
-                          gridSpan: 1,
+                          gridSpan: 4,
                         },
                         'x-component-props': {
                           placeholder: '操作符',
@@ -354,7 +354,7 @@ const TriggerTerm = (props: Props, ref: any) => {
                         'x-component': 'FInputGroup',
                         'x-decorator': 'FormItem',
                         'x-decorator-props': {
-                          gridSpan: 3,
+                          gridSpan: 9,
                           style: {
                             width: '100%',
                           },
@@ -473,6 +473,14 @@ const TriggerTerm = (props: Props, ref: any) => {
                         type: 'void',
                         'x-decorator': 'FormItem',
                         'x-component': 'ArrayItems.Remove',
+                        'x-component-props': {
+                          style: {
+                            padding: '6px 8px',
+                            color: '#ff4d4f',
+                            border: '1px solid #ff4d4f',
+                            borderRadius: '2px',
+                          },
+                        },
                         'x-decorator-props': {
                           gridSpan: 1,
                         },
@@ -486,12 +494,24 @@ const TriggerTerm = (props: Props, ref: any) => {
                   type: 'void',
                   title: '添加条件',
                   'x-component': 'ArrayItems.Addition',
+                  'x-component-props': {
+                    type: 'primary',
+                    ghost: true,
+                  },
                 },
               },
             },
             remove: {
               type: 'void',
               'x-component': 'FTermArrayCards.Remove',
+              'x-component-props': {
+                style: {
+                  padding: '6px 8px',
+                  color: '#ff4d4f',
+                  border: '1px solid #ff4d4f',
+                  borderRadius: '2px',
+                },
+              },
             },
           },
         },
@@ -500,6 +520,10 @@ const TriggerTerm = (props: Props, ref: any) => {
             type: 'void',
             title: '添加分组',
             'x-component': 'FTermArrayCards.Addition',
+            'x-component-props': {
+              type: 'primary',
+              ghost: true,
+            },
           },
         },
       },