Просмотр исходного кода

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

wzyyy 3 лет назад
Родитель
Сommit
e156c532e9
29 измененных файлов с 510 добавлено и 169 удалено
  1. 11 5
      src/components/BindParentDevice/index.tsx
  2. 2 2
      src/components/ProTableCard/CardItems/AccessConfig/index.less
  3. 13 10
      src/components/ProTableCard/index.less
  4. 1 1
      src/global.less
  5. 17 8
      src/pages/device/Instance/Detail/ChildDevice/BindChildDevice/index.tsx
  6. 24 13
      src/pages/device/Instance/Detail/ChildDevice/index.tsx
  7. 16 3
      src/pages/device/Instance/Detail/Diagnose/Message/index.tsx
  8. 193 39
      src/pages/device/Instance/Detail/Diagnose/Status/ManualInspection.tsx
  9. 154 32
      src/pages/device/Instance/Detail/Diagnose/Status/index.tsx
  10. 8 8
      src/pages/device/Instance/Detail/Diagnose/Status/model.ts
  11. 2 2
      src/pages/device/Instance/Detail/Info/index.tsx
  12. 2 1
      src/pages/device/Instance/Save/index.tsx
  13. 4 0
      src/pages/device/Instance/service.ts
  14. 1 1
      src/pages/device/Product/Detail/BaseInfo/index.tsx
  15. 1 1
      src/pages/device/components/Metadata/Cat/index.tsx
  16. 1 1
      src/pages/device/components/Metadata/Import/index.tsx
  17. 0 1
      src/pages/home/device/index.tsx
  18. 4 4
      src/pages/link/AccessConfig/Detail/Access/index.less
  19. 19 14
      src/pages/link/Type/Detail/index.tsx
  20. 2 2
      src/pages/notice/Config/BindUser/index.tsx
  21. 8 8
      src/pages/notice/Template/Detail/index.tsx
  22. 1 1
      src/pages/rule-engine/Alarm/Configuration/Save/index.tsx
  23. 1 1
      src/pages/rule-engine/Scene/Save/action/VariableItems/builtIn.tsx
  24. 2 3
      src/pages/rule-engine/Scene/Save/action/device/index.tsx
  25. 1 1
      src/pages/rule-engine/Scene/Save/index.tsx
  26. 3 3
      src/pages/system/Department/Assets/deivce/bind.tsx
  27. 1 0
      src/pages/system/Platforms/Api/leftTree.tsx
  28. 1 1
      src/pages/system/Platforms/Api/swagger-ui/base.tsx
  29. 17 3
      src/pages/system/Role/Detail/Permission/Allocate/MenuPermission.tsx

+ 11 - 5
src/components/BindParentDevice/index.tsx

@@ -4,7 +4,7 @@ import SearchComponent from '@/components/SearchComponent';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import { useRef, useState } from 'react';
-import { service, statusMap } from '@/pages/device/Instance';
+import { service } from '@/pages/device/Instance';
 import { useIntl } from 'umi';
 import moment from 'moment';
 
@@ -14,6 +14,11 @@ interface Props {
   onOk: (parentId: string) => void;
 }
 
+const statusMap = new Map();
+statusMap.set('online', 'success');
+statusMap.set('offline', 'error');
+statusMap.set('notActive', 'warning');
+
 const BindParentDevice = (props: Props) => {
   const intl = useIntl();
 
@@ -42,6 +47,7 @@ const BindParentDevice = (props: Props) => {
       dataIndex: 'registryTime',
       ellipsis: true,
       width: '200px',
+      valueType: 'dateTime',
       render: (text: any) => (!!text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/'),
       sorter: true,
     },
@@ -59,21 +65,21 @@ const BindParentDevice = (props: Props) => {
             id: 'pages.device.instance.status.notActive',
             defaultMessage: '未启用',
           }),
-          value: 'notActive',
+          status: 'notActive',
         },
         offline: {
           text: intl.formatMessage({
             id: 'pages.device.instance.status.offLine',
             defaultMessage: '离线',
           }),
-          value: 'offline',
+          status: 'offline',
         },
         online: {
           text: intl.formatMessage({
             id: 'pages.device.instance.status.onLine',
             defaultMessage: '在线',
           }),
-          value: 'online',
+          status: 'online',
         },
       },
     },
@@ -122,7 +128,7 @@ const BindParentDevice = (props: Props) => {
             submitBtn();
           }}
         >
-          确
+          确
         </Button>,
       ]}
     >

+ 2 - 2
src/components/ProTableCard/CardItems/AccessConfig/index.less

@@ -3,8 +3,8 @@
 .access-config-card-item {
   &.active {
     position: relative;
-    color: @primary-color-active;
-    border: 1px solid @primary-color-active;
+    color: #2f54eb;
+    border: 1px solid #2f54eb;
 
     .checked-icon {
       display: block;

+ 13 - 10
src/components/ProTableCard/index.less

@@ -143,16 +143,6 @@
   width: 100%;
   background-color: #fff;
 
-  &.item-active {
-    position: relative;
-    color: #2f54eb;
-    border: 1px solid #2f54eb;
-
-    .checked-icon {
-      display: block;
-    }
-  }
-
   .checked-icon {
     position: absolute;
     right: -22px;
@@ -268,6 +258,19 @@
     }
   }
 
+  &.item-active {
+    position: relative;
+    color: #2f54eb;
+
+    .checked-icon {
+      display: block;
+    }
+
+    .card-warp {
+      border: 1px solid #2f54eb;
+    }
+  }
+
   .card-tools {
     display: flex;
     margin-top: 8px;

+ 1 - 1
src/global.less

@@ -141,6 +141,6 @@ input[type='tel'] {
 }
 
 //引导遮罩
-#driver-page-overlay{
+#driver-page-overlay {
   opacity: 0.35 !important;
 }

+ 17 - 8
src/pages/device/Instance/Detail/ChildDevice/BindChildDevice/index.tsx

@@ -4,18 +4,21 @@ import SearchComponent from '@/components/SearchComponent';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import { useRef, useState } from 'react';
-import { InstanceModel, service, statusMap } from '@/pages/device/Instance';
+import { InstanceModel, service } from '@/pages/device/Instance';
 import { useIntl } from 'umi';
 import moment from 'moment';
 
 interface Props {
-  visible: boolean;
   data: Partial<DeviceInstance>;
   onCancel: () => void;
 }
 
+const statusMap = new Map();
+statusMap.set('online', 'success');
+statusMap.set('offline', 'error');
+statusMap.set('notActive', 'warning');
+
 const BindChildDevice = (props: Props) => {
-  const { visible } = props;
   const intl = useIntl();
 
   const actionRef = useRef<ActionType>();
@@ -42,8 +45,13 @@ const BindChildDevice = (props: Props) => {
       title: '注册时间',
       dataIndex: 'registryTime',
       ellipsis: true,
+      valueType: 'dateTime',
       width: '200px',
-      render: (text: any) => (!!text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/'),
+      render: (text: any, record: any) => {
+        return !record?.registryTime
+          ? ''
+          : moment(record?.registryTime).format('YYYY-MM-DD HH:mm:ss');
+      },
       sorter: true,
     },
     {
@@ -60,21 +68,21 @@ const BindChildDevice = (props: Props) => {
             id: 'pages.device.instance.status.notActive',
             defaultMessage: '未启用',
           }),
-          value: 'notActive',
+          status: 'notActive',
         },
         offline: {
           text: intl.formatMessage({
             id: 'pages.device.instance.status.offLine',
             defaultMessage: '离线',
           }),
-          value: 'offline',
+          status: 'offline',
         },
         online: {
           text: intl.formatMessage({
             id: 'pages.device.instance.status.onLine',
             defaultMessage: '在线',
           }),
-          value: 'online',
+          status: 'online',
         },
       },
     },
@@ -93,7 +101,7 @@ const BindChildDevice = (props: Props) => {
     <Modal
       maskClosable={false}
       title="绑定子设备"
-      visible={visible}
+      visible
       width={1000}
       onOk={() => {
         submitBtn();
@@ -129,6 +137,7 @@ const BindChildDevice = (props: Props) => {
         field={[...columns]}
         target="child-device-bind"
         enableSave={false}
+        model="simple"
         // pattern={'simple'}
         defaultParam={[
           {

+ 24 - 13
src/pages/device/Instance/Detail/ChildDevice/index.tsx

@@ -4,7 +4,7 @@ import type { LogItem } from '@/pages/device/Instance/Detail/Log/typings';
 import { Badge, Button, Card, Popconfirm, Tooltip } from 'antd';
 import { DisconnectOutlined, SearchOutlined } from '@ant-design/icons';
 import { useIntl } from '@@/plugin-locale/localeExports';
-import { InstanceModel, service, statusMap } from '@/pages/device/Instance';
+import { InstanceModel, service } from '@/pages/device/Instance';
 import { useRef, useState } from 'react';
 import SearchComponent from '@/components/SearchComponent';
 import BindChildDevice from './BindChildDevice';
@@ -14,6 +14,11 @@ import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { useDomFullHeight } from '@/hooks';
 import { onlyMessage } from '@/utils/util';
 
+const statusMap = new Map();
+statusMap.set('online', 'success');
+statusMap.set('offline', 'error');
+statusMap.set('notActive', 'warning');
+
 const ChildDevice = () => {
   const intl = useIntl();
   const [visible, setVisible] = useState<boolean>(false);
@@ -53,7 +58,12 @@ const ChildDevice = () => {
       title: '注册时间',
       dataIndex: 'registryTime',
       width: '200px',
-      render: (text: any) => (!!text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/'),
+      valueType: 'dateTime',
+      render: (text: any, record: any) => {
+        return !record?.registryTime
+          ? ''
+          : moment(record?.registryTime).format('YYYY-MM-DD HH:mm:ss');
+      },
       sorter: true,
     },
     {
@@ -68,21 +78,21 @@ const ChildDevice = () => {
             id: 'pages.device.instance.status.notActive',
             defaultMessage: '未启用',
           }),
-          value: 'notActive',
+          status: 'notActive',
         },
         offline: {
           text: intl.formatMessage({
             id: 'pages.device.instance.status.offLine',
             defaultMessage: '离线',
           }),
-          value: 'offline',
+          status: 'offline',
         },
         online: {
           text: intl.formatMessage({
             id: 'pages.device.instance.status.onLine',
             defaultMessage: '在线',
           }),
-          value: 'online',
+          status: 'online',
         },
       },
     },
@@ -189,14 +199,15 @@ const ChildDevice = () => {
         }}
         request={(params) => service.query(params)}
       />
-      <BindChildDevice
-        visible={visible}
-        data={{}}
-        onCancel={() => {
-          setVisible(false);
-          actionRef.current?.reload?.();
-        }}
-      />
+      {visible && (
+        <BindChildDevice
+          data={{}}
+          onCancel={() => {
+            setVisible(false);
+            actionRef.current?.reload?.();
+          }}
+        />
+      )}
     </Card>
   );
 };

+ 16 - 3
src/pages/device/Instance/Detail/Diagnose/Message/index.tsx

@@ -23,6 +23,21 @@ import Log from './Log';
 import { DiagnoseStatusModel, messageStatusMap, messageStyleMap } from '../Status/model';
 import { observer } from '@formily/reactive-react';
 
+// const DataTypeComponent = (value: string) => {
+//   switch (value) {
+//     case 'array':
+//       return <div>{value}array</div>
+//     // case 'enum':
+//     //   return <div>{value}</div>
+//     case 'geo':
+//       return <div>{value}geo</div>
+//     case 'file':
+//       return <div>{value}file</div>
+//     default:
+//       return <div>{value}</div>
+//   }
+// }
+
 const DatePicker1: any = DatePicker;
 
 const Message = observer(() => {
@@ -287,6 +302,7 @@ const Message = observer(() => {
       FSelect,
       FDatePicker,
       NumberPicker,
+      DataTypeComponent,
     },
   });
 
@@ -328,9 +344,6 @@ const Message = observer(() => {
                   type: 'string',
                   'x-decorator': 'FormItem',
                   'x-component': 'PreviewText.Input',
-                  // 'x-decorator-props': {
-                  //   tooltip: '使用固定的通知配置来发送此通知模版',
-                  // },
                 },
               },
             },

+ 193 - 39
src/pages/device/Instance/Detail/Diagnose/Status/ManualInspection.tsx

@@ -2,8 +2,9 @@ import { Button, Descriptions, Modal } from 'antd';
 import styles from './index.less';
 import { InfoCircleOutlined } from '@ant-design/icons';
 import { useHistory } from 'umi';
-import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
+import { getMenuPathByCode, getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { InstanceModel } from '@/pages/device/Instance';
+import { randomString } from '@/utils/util';
 interface Props {
   close: () => void;
   data: any;
@@ -19,6 +20,189 @@ const ManualInspection = (props: Props) => {
     props.save(data);
   };
 
+  const dataRender = () => {
+    if (data.type === 'device' || data.type === 'product') {
+      return (
+        <>
+          <div style={{ flex: 1 }}>
+            <div className={styles.alert}>
+              <InfoCircleOutlined style={{ marginRight: 10 }} />
+              请检查配置项是否填写正确,若您确定该项无需诊断可
+              <a
+                onClick={() => {
+                  okBtn();
+                }}
+              >
+                忽略
+              </a>
+            </div>
+            <div style={{ marginTop: 10 }}>
+              <Descriptions title={data?.data?.name} layout="vertical" bordered>
+                {(data?.data?.properties || []).map((item: any) => (
+                  <Descriptions.Item
+                    key={item.property}
+                    label={`${item.name}${item?.description ? `(${item.description})` : ''}`}
+                  >
+                    {data?.configuration[item.property] || ''}
+                  </Descriptions.Item>
+                ))}
+              </Descriptions>
+            </div>
+          </div>
+          {data?.data?.description ? (
+            <div
+              style={{ width: '50%', border: '1px solid #f0f0f0', padding: 10, borderLeft: 'none' }}
+            >
+              <h4>诊断项说明</h4>
+              <p>{data?.data?.description}</p>
+            </div>
+          ) : (
+            ''
+          )}
+        </>
+      );
+    } else if (data.type === 'cloud') {
+      return (
+        <>
+          <div style={{ flex: 1 }}>
+            <div className={styles.alert}>
+              <InfoCircleOutlined style={{ marginRight: 10 }} />
+              请检查配置项是否填写正确,若您确定该项无需诊断可
+              <a
+                onClick={() => {
+                  okBtn();
+                }}
+              >
+                忽略
+              </a>
+            </div>
+            <div style={{ marginTop: 10 }}>
+              <Descriptions title={data?.data?.name} layout="vertical" bordered>
+                {data.configuration?.provider === 'OneNet' ? (
+                  <>
+                    <Descriptions.Item label={'接口地址'}>
+                      {data?.configuration?.configuration?.apiAddress || ''}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'apiKey'}>
+                      {data?.configuration?.configuration?.apiKey || ''}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'通知Token'}>
+                      {data?.configuration?.configuration?.validateToken || ''}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'aesKey'}>
+                      {data?.configuration?.configuration?.aesKey || ''}
+                    </Descriptions.Item>
+                  </>
+                ) : (
+                  <>
+                    <Descriptions.Item label={'接口地址'}>
+                      {data?.configuration?.configuration?.apiAddress || ''}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'appKey'}>
+                      {data?.configuration?.configuration?.appKey || ''}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'appSecret'}>
+                      {data?.configuration?.configuration?.appSecret || ''}
+                    </Descriptions.Item>
+                  </>
+                )}
+              </Descriptions>
+            </div>
+          </div>
+          {data?.configuration?.configuration?.description ? (
+            <div
+              style={{ width: '50%', border: '1px solid #f0f0f0', padding: 10, borderLeft: 'none' }}
+            >
+              <h4>诊断项说明</h4>
+              <p>{data?.configuration?.configuration?.description}</p>
+            </div>
+          ) : (
+            ''
+          )}
+        </>
+      );
+    } else if (data.type === 'media') {
+      return (
+        <>
+          <div style={{ flex: 1 }}>
+            <div className={styles.alert}>
+              <InfoCircleOutlined style={{ marginRight: 10 }} />
+              请检查配置项是否填写正确,若您确定该项无需诊断可
+              <a
+                onClick={() => {
+                  okBtn();
+                }}
+              >
+                忽略
+              </a>
+            </div>
+            <div style={{ marginTop: 10 }}>
+              <Descriptions title={data?.data?.name} layout="vertical" bordered>
+                {data?.configuration?.configuration?.shareCluster ? (
+                  <>
+                    <Descriptions.Item label={'SIP 域'}>
+                      {data?.configuration?.configuration?.domain || ''}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'SIP ID'}>
+                      {data?.configuration?.configuration?.sipId || ''}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'集群'}>
+                      {data?.configuration?.configuration?.shareCluster ? '共享配置' : '独立配置'}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'SIP 地址'}>
+                      {`${data?.configuration?.configuration?.hostPort?.host}:${data?.configuration?.configuration?.hostPort?.port}`}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'公网 Host'}>
+                      {`${data?.configuration?.configuration?.hostPort?.publicHost}:${data?.configuration?.configuration?.hostPort?.publicPort}`}
+                    </Descriptions.Item>
+                  </>
+                ) : (
+                  <>
+                    <Descriptions.Item label={'SIP 域'}>
+                      {data?.configuration?.configuration?.domain || ''}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'SIP ID'}>
+                      {data?.configuration?.configuration?.sipId || ''}
+                    </Descriptions.Item>
+                    <Descriptions.Item label={'集群'}>
+                      {data?.configuration?.configuration?.shareCluster ? '共享配置' : '独立配置'}
+                    </Descriptions.Item>
+                    {data?.configuration?.configuration?.cluster.map((i: any, it: number) => (
+                      <div key={randomString()}>
+                        <div>节点{it + 1}</div>
+                        <Descriptions.Item label={'节点名称'}>
+                          {i?.clusterNodeId || ''}
+                        </Descriptions.Item>
+                        <Descriptions.Item label={'SIP 地址'}>
+                          {`${i.host}:${i?.port}`}
+                        </Descriptions.Item>
+                        <Descriptions.Item label={'公网 Host'}>
+                          {`${i?.publicHost}:${i?.publicPort}`}
+                        </Descriptions.Item>
+                      </div>
+                    ))}
+                  </>
+                )}
+              </Descriptions>
+            </div>
+          </div>
+          {data?.configuration?.configuration.description ? (
+            <div
+              style={{ width: '50%', border: '1px solid #f0f0f0', padding: 10, borderLeft: 'none' }}
+            >
+              <h4>诊断项说明</h4>
+              <p>{data?.configuration?.description}</p>
+            </div>
+          ) : (
+            ''
+          )}
+        </>
+      );
+    } else {
+      return null;
+    }
+  };
+
   return (
     <Modal
       title="人工检查"
@@ -32,13 +216,19 @@ const ManualInspection = (props: Props) => {
           onClick={() => {
             if (data.type === 'device') {
               InstanceModel.active = 'detail';
-            } else {
+            } else if (data.type === 'product') {
               history.push(
                 `${getMenuPathByParams(MENUS_CODE['device/Product/Detail'], data.productId)}`,
                 {
                   tab: 'access',
                 },
               );
+            } else {
+              history.push(
+                `${getMenuPathByCode(MENUS_CODE['link/AccessConfig/Detail'])}?id=${
+                  data.configuration?.id
+                }`,
+              );
             }
             props.close();
           }}
@@ -56,43 +246,7 @@ const ManualInspection = (props: Props) => {
       ]}
       visible
     >
-      <div style={{ display: 'flex' }}>
-        <div style={{ flex: 1 }}>
-          <div className={styles.alert}>
-            <InfoCircleOutlined style={{ marginRight: 10 }} />
-            请检查配置项是否填写正确,若您确定该项无需诊断可
-            <a
-              onClick={() => {
-                okBtn();
-              }}
-            >
-              忽略
-            </a>
-          </div>
-          <div style={{ marginTop: 10 }}>
-            <Descriptions title={data?.data?.name} layout="vertical" bordered>
-              {(data?.data?.properties || []).map((item: any) => (
-                <Descriptions.Item
-                  key={item.property}
-                  label={`${item.name}${item?.description ? `(${item.description})` : ''}`}
-                >
-                  {data?.configuration[item.property] || ''}
-                </Descriptions.Item>
-              ))}
-            </Descriptions>
-          </div>
-        </div>
-        {data?.data?.description ? (
-          <div
-            style={{ width: '50%', border: '1px solid #f0f0f0', padding: 10, borderLeft: 'none' }}
-          >
-            <h4>诊断项说明</h4>
-            <p>{data?.data?.description}</p>
-          </div>
-        ) : (
-          ''
-        )}
-      </div>
+      <div style={{ display: 'flex' }}>{dataRender()}</div>
     </Modal>
   );
 };

+ 154 - 32
src/pages/device/Instance/Detail/Diagnose/Status/index.tsx

@@ -208,16 +208,19 @@ const Status = observer((props: Props) => {
         }
       }
     });
-
   // 设备接入网关
   const diagnoseGateway = () =>
     new Promise((resolve) => {
+      const desc =
+        providerType && ['child-device', 'cloud'].includes(providerType)
+          ? '诊断设备接入网关状态是否正常,网关配置是否正确'
+          : '诊断设备接入网关状态是否正常,禁用状态将导致连接失败';
       if (device.state?.value === 'online') {
         setTimeout(() => {
           DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, {
             key: 'gateway',
             name: '设备接入网关',
-            desc: '诊断设备接入网关状态是否正常,禁用状态将导致连接失败',
+            desc: desc,
             status: 'success',
             text: '正常',
             info: null,
@@ -233,19 +236,81 @@ const Status = observer((props: Props) => {
               if (response.status === 200) {
                 DiagnoseStatusModel.gateway = response.result;
                 if (response.result?.state?.value === 'enabled') {
-                  item = {
-                    key: 'gateway',
-                    name: '设备接入网关',
-                    desc: '诊断设备接入网关状态是否正常,禁用状态将导致连接失败',
-                    status: 'success',
-                    text: '正常',
-                    info: null,
-                  };
+                  if (providerType === 'cloud' || device?.accessProvider === 'gb28181-2016') {
+                    item = {
+                      key: 'gateway',
+                      name: '设备接入网关',
+                      desc: desc,
+                      status: 'error',
+                      text: '可能存在异常',
+                      info: (
+                        <div>
+                          <div className={styles.infoItem}>
+                            <Badge
+                              status="default"
+                              text={
+                                <span>
+                                  请
+                                  <a
+                                    onClick={async () => {
+                                      const config = await service.getGatewayDetail(
+                                        response.result?.id || '',
+                                      );
+                                      if (config.status === 200) {
+                                        manualInspection({
+                                          type: providerType,
+                                          key: `gateway`,
+                                          name: `设备接入网关`,
+                                          desc: desc,
+                                          data: { name: `${device?.accessProvider}配置` },
+                                          configuration: { ...config.result },
+                                        });
+                                      }
+                                    }}
+                                  >
+                                    人工检查
+                                  </a>
+                                  网关配置是否已填写正确,若您确定该项无需诊断可
+                                  <Popconfirm
+                                    title="确认忽略?"
+                                    onConfirm={() => {
+                                      DiagnoseStatusModel.list = modifyArrayList(
+                                        DiagnoseStatusModel.list,
+                                        {
+                                          key: 'gateway',
+                                          name: '设备接入网关',
+                                          desc: desc,
+                                          status: 'success',
+                                          text: '正常',
+                                          info: null,
+                                        },
+                                      );
+                                    }}
+                                  >
+                                    <a>忽略</a>
+                                  </Popconfirm>
+                                </span>
+                              }
+                            />
+                          </div>
+                        </div>
+                      ),
+                    };
+                  } else {
+                    item = {
+                      key: 'gateway',
+                      name: '设备接入网关',
+                      desc: desc,
+                      status: 'success',
+                      text: '正常',
+                      info: null,
+                    };
+                  }
                 } else {
                   item = {
                     key: 'gateway',
                     name: '设备接入网关',
-                    desc: '诊断设备接入网关状态是否正常,禁用状态将导致连接失败',
+                    desc: desc,
                     status: 'error',
                     text: '异常',
                     info: (
@@ -270,7 +335,7 @@ const Status = observer((props: Props) => {
                                           {
                                             key: 'gateway',
                                             name: '设备接入网关',
-                                            desc: '诊断设备接入网关状态是否正常,禁用状态将导致连接失败',
+                                            desc: desc,
                                             status: 'success',
                                             text: '正常',
                                             info: null,
@@ -306,19 +371,81 @@ const Status = observer((props: Props) => {
           }
         } else {
           if (DiagnoseStatusModel.gateway?.state?.value === 'enabled') {
-            item = {
-              key: 'gateway',
-              name: '设备接入网关',
-              desc: '诊断设备接入网关状态是否正常,禁用状态将导致连接失败',
-              status: 'success',
-              text: '正常',
-              info: null,
-            };
+            if (providerType === 'cloud' || device?.accessProvider === 'gb28181-2016') {
+              item = {
+                key: 'gateway',
+                name: '设备接入网关',
+                desc: desc,
+                status: 'error',
+                text: '可能存在异常',
+                info: (
+                  <div>
+                    <div className={styles.infoItem}>
+                      <Badge
+                        status="default"
+                        text={
+                          <span>
+                            请
+                            <a
+                              onClick={async () => {
+                                const config = await service.getGatewayDetail(
+                                  DiagnoseStatusModel.gateway?.id || '',
+                                );
+                                if (config.status === 200) {
+                                  manualInspection({
+                                    type: providerType,
+                                    key: `gateway`,
+                                    name: `设备接入网关`,
+                                    desc: desc,
+                                    data: { name: `${device?.accessProvider}配置` },
+                                    configuration: { ...config.result },
+                                  });
+                                }
+                              }}
+                            >
+                              人工检查
+                            </a>
+                            网关配置是否已填写正确,若您确定该项无需诊断可
+                            <Popconfirm
+                              title="确认忽略?"
+                              onConfirm={() => {
+                                DiagnoseStatusModel.list = modifyArrayList(
+                                  DiagnoseStatusModel.list,
+                                  {
+                                    key: 'gateway',
+                                    name: '设备接入网关',
+                                    desc: desc,
+                                    status: 'success',
+                                    text: '正常',
+                                    info: null,
+                                  },
+                                );
+                              }}
+                            >
+                              <a>忽略</a>
+                            </Popconfirm>
+                          </span>
+                        }
+                      />
+                    </div>
+                  </div>
+                ),
+              };
+            } else {
+              item = {
+                key: 'gateway',
+                name: '设备接入网关',
+                desc: desc,
+                status: 'success',
+                text: '正常',
+                info: null,
+              };
+            }
           } else {
             item = {
               key: 'gateway',
               name: '设备接入网关',
-              desc: '诊断设备接入网关状态是否正常,禁用状态将导致连接失败',
+              desc: desc,
               status: 'error',
               text: '异常',
               info: (
@@ -341,7 +468,7 @@ const Status = observer((props: Props) => {
                                     {
                                       key: 'gateway',
                                       name: '设备接入网关',
-                                      desc: '诊断设备接入网关状态是否正常,禁用状态将导致连接失败',
+                                      desc: desc,
                                       status: 'success',
                                       text: '正常',
                                       info: null,
@@ -428,7 +555,7 @@ const Status = observer((props: Props) => {
         } else {
           let item: ListProps | undefined = undefined;
           const response = await service.detail(device?.parentId);
-          DiagnoseStatusModel.parent = resp.result;
+          DiagnoseStatusModel.parent = response.result;
           if (response.status === 200) {
             if (response?.result?.state?.value === 'notActive') {
               item = {
@@ -704,7 +831,7 @@ const Status = observer((props: Props) => {
   const diagnoseProductAuthConfig = () =>
     new Promise(async (resolve) => {
       if (device?.productId) {
-        const response = await service.queryDeviceConfig(device.productId);
+        const response = await service.queryProductConfig(device.productId);
         if (response.status === 200 && response.result.length > 0) {
           DiagnoseStatusModel.configuration.product = response.result;
           const list = [...DiagnoseStatusModel.list];
@@ -1758,21 +1885,15 @@ const Status = observer((props: Props) => {
       await diagnoseDeviceAuthConfig();
     } else if (providerType === 'child-device') {
       DiagnoseStatusModel.list = [...childInitList];
-      await diagnoseNetwork();
       await diagnoseGateway();
       DiagnoseStatusModel.percent = 20;
       await diagnoseParentDevice();
       await diagnoseProduct();
-      await diagnoseDevice();
       DiagnoseStatusModel.percent = 40;
+      await diagnoseDevice();
+      DiagnoseStatusModel.percent = 60;
       await diagnoseProductAuthConfig();
       await diagnoseDeviceAuthConfig();
-      DiagnoseStatusModel.percent = 60;
-      // await diagnoseModbus();
-      // await diagnoseOpcua();
-      // await diagnoseModbusState();
-      // await diagnoseOpcuaState();
-      // await diagnoseDataPointBind();
       DiagnoseStatusModel.percent = 80;
     } else if (providerType === 'media') {
       DiagnoseStatusModel.list = [...mediaInitList];
@@ -1981,6 +2102,7 @@ const Status = observer((props: Props) => {
               info: null,
             });
             InstanceModel.detail.parentId = parentId;
+            setBindParentVisible(false);
           }}
         />
       )}

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

@@ -81,14 +81,14 @@ export const childInitList: ListProps[] = [
   //   text: '正在诊断中...',
   //   info: null,
   // },
-  {
-    key: 'network',
-    name: '网络组件',
-    desc: '诊断网络组件配置是否正确,配置错误将导致设备连接失败',
-    status: 'loading',
-    text: '正在诊断中...',
-    info: null,
-  },
+  // {
+  //   key: 'network',
+  //   name: '网络组件',
+  //   desc: '诊断网络组件配置是否正确,配置错误将导致设备连接失败',
+  //   status: 'loading',
+  //   text: '正在诊断中...',
+  //   info: null,
+  // },
   {
     key: 'gateway',
     name: '设备接入网关',

+ 2 - 2
src/pages/device/Instance/Detail/Info/index.tsx

@@ -66,9 +66,9 @@ const Info = observer(() => {
             </Tooltip>
           </Descriptions.Item>
           <Descriptions.Item label={'产品分类'}>
-          <Tooltip placement="topLeft" title= {InstanceModel.detail?.classifiedName}>
+            <Tooltip placement="topLeft" title={InstanceModel.detail?.classifiedName}>
               <div className="ellipsis" style={{ maxWidth: 250 }}>
-              {InstanceModel.detail?.classifiedName}
+                {InstanceModel.detail?.classifiedName}
               </div>
             </Tooltip>
           </Descriptions.Item>

+ 2 - 1
src/pages/device/Instance/Save/index.tsx

@@ -220,6 +220,7 @@ const Save = (props: Props) => {
                   ),
                 },
               ]}
+              tooltip={'只能选择“正常”状态的产品'}
               required
             >
               <Select
@@ -231,7 +232,7 @@ const Save = (props: Props) => {
                     productName: node.label,
                   });
                 }}
-                placeholder={'请选择状态为正常的产品'}
+                placeholder={'请选择状态为正常的产品'}
                 filterOption={(input, option) => option.label.includes(input)}
               />
             </Form.Item>

+ 4 - 0
src/pages/device/Instance/service.ts

@@ -361,6 +361,10 @@ class Service extends BaseService<DeviceInstance> {
       method: 'POST',
       data,
     });
+  public getGatewayDetail = (id: string) =>
+    request(`/${SystemConst.API_BASE}/gateway/device/${id}`, {
+      method: 'GET',
+    });
 }
 
 export default Service;

+ 1 - 1
src/pages/device/Product/Detail/BaseInfo/index.tsx

@@ -186,7 +186,7 @@ const BaseInfo = (props: BaseInfoProps) => {
         >
           <Tooltip placement="topLeft" title={productModel.current?.classifiedName}>
             <div className="ellipsis-70" style={{ width: 300 }}>
-            {productModel.current?.classifiedName}
+              {productModel.current?.classifiedName}
             </div>
           </Tooltip>
         </Descriptions.Item>

+ 1 - 1
src/pages/device/components/Metadata/Cat/index.tsx

@@ -83,7 +83,7 @@ const Cat = observer((props: Props) => {
       }
     >
       <div style={{ background: '#F6F6F6' }}>
-        <p style={{ padding: 10 ,color:'rgba(0, 0, 0, 0.55)'}}>
+        <p style={{ padding: 10, color: 'rgba(0, 0, 0, 0.55)' }}>
           物模型是对设备在云端的功能描述,包括设备的属性、服务和事件。物联网平台通过定义一种物的描述语言来描述物模型,称之为
           TSL(即 Thing Specification Language),采用 JSON 格式,您可以根据 TSL
           组装上报设备的数据。您可以导出完整物模型,用于云端应用开发。

+ 1 - 1
src/pages/device/components/Metadata/Import/index.tsx

@@ -192,7 +192,7 @@ const Import = (props: Props) => {
       obj.events = old?.event || [];
     }
     if (fid.includes('propertyNotModifiable')) {
-      obj.properties = old?.properties || {};
+      obj.properties = old?.properties || [];
     }
     return obj;
   };

+ 0 - 1
src/pages/home/device/index.tsx

@@ -207,7 +207,6 @@ const Device = () => {
         />
       </Col>
 
-
       <ProductChoose
         visible={productVisible}
         close={() => {

+ 4 - 4
src/pages/link/AccessConfig/Detail/Access/index.less

@@ -20,7 +20,7 @@
 }
 
 .title {
-  width: '100%';
+  width: 100%;
   overflow: hidden;
   font-weight: 800;
   white-space: nowrap;
@@ -118,7 +118,7 @@
     height: 44px;
     color: #fff;
     background-color: red;
-    background-color: @primary-color-active;
+    background-color: #2f54eb;
     transform: rotate(-45deg);
 
     > div {
@@ -136,8 +136,8 @@
   }
   &.checked {
     position: relative;
-    color: @primary-color-active;
-    border-color: @primary-color-active;
+    color: #2f54eb;
+    border-color: #2f54eb;
 
     .checkedIcon {
       display: block;

+ 19 - 14
src/pages/link/Type/Detail/index.tsx

@@ -135,6 +135,9 @@ const Save = observer(() => {
               f.setFieldState('grid.configuration.panel1.layout2.secure', (state) => {
                 state.value = false;
               });
+              f.setFieldState('shareCluster', (state) => {
+                state.value = true;
+              });
             }
             const _host = filterConfigByType(_.cloneDeep(configRef.current), value);
             f.setFieldState('grid.configuration.panel1.layout2.host', (state) => {
@@ -157,17 +160,19 @@ const Save = observer(() => {
           });
           onFieldValueChange('shareCluster', (field, f5) => {
             const value = (field as Field).value;
-            if (value) {
-              // 共享配置
-              f5.setFieldState('grid.configuration.panel1.layout2.host', (state) => {
-                state.value = '0.0.0.0';
-                state.disabled = true;
-              });
-            } else {
-              // 独立配置
-              f5.setFieldState('grid.cluster.cluster', (state) => {
-                state.value = [{}];
-              });
+            if (f5.modified) {
+              if (value) {
+                // 共享配置
+                f5.setFieldState('grid.configuration.panel1.layout2.host', (state) => {
+                  state.value = '0.0.0.0';
+                  state.disabled = true;
+                });
+              } else {
+                // 独立配置
+                f5.setFieldState('grid.cluster.cluster', (state) => {
+                  state.value = [{}];
+                });
+              }
             }
           });
           onFieldValueChange('grid.cluster.cluster.*.layout2.serverId', async (field, f3) => {
@@ -180,8 +185,8 @@ const Save = observer(() => {
           });
           onFieldValueChange('grid.cluster.cluster.*.layout2.host', async (field, f4) => {
             const host = (field as Field).value;
-            const value = (field.query('.serverId').take() as Field).value;
-            const type = (field.query('type').take() as Field).value;
+            const value = (field.query('.serverId').take() as Field)?.value;
+            const type = (field.query('type').take() as Field)?.value;
             const response = await getResourceById(value, type);
             const _ports = response.find((item) => item.host === host);
             f4.setFieldState(field.query('.port').take(), async (state) => {
@@ -212,7 +217,7 @@ const Save = observer(() => {
       if (!_data.shareCluster) {
         _data.cluster = _data.cluster?.map((item: any) => ({ ...item.configuration }));
       }
-      form.setValues(_data);
+      form.setValues({ ..._data });
     });
     return () => {
       subscription.unsubscribe();

+ 2 - 2
src/pages/notice/Config/BindUser/index.tsx

@@ -22,10 +22,10 @@ const BindUser = (props: Props) => {
 
   const getUsers = async (id: string) => {
     const resp = await service.syncUser.noBindUser({
-      pagign: false,
+      paging: false,
       terms: [
         {
-          column: `id$user-third${state.current?.type}_${state.current?.provider}$not`,
+          column: `id$user-third$${state.current?.type}_${state.current?.provider}$not`,
           value: id,
         },
       ],

+ 8 - 8
src/pages/notice/Template/Detail/index.tsx

@@ -581,10 +581,10 @@ const Detail = observer(() => {
                         title: '收信部门',
                         'x-component': 'Select',
                         'x-decorator': 'FormItem',
-                        'x-decorator-props': {
-                          tooltip: '如果不填写该字段,将在使用此模版发送通知时进行指定。',
-                          gridSpan: 1,
-                        },
+                        // 'x-decorator-props': {
+                        //   tooltip: '如果不填写该字段,将在使用此模版发送通知时进行指定。',
+                        //   gridSpan: 1,
+                        // },
                         'x-component-props': {
                           placeholder: '请选择收信部门',
                         },
@@ -788,10 +788,10 @@ const Detail = observer(() => {
                         required: true,
                         'x-component': 'Select',
                         'x-decorator': 'FormItem',
-                        'x-decorator-props': {
-                          tooltip: '如果不填写该字段,将在使用此模板发送通知时进行指定',
-                          gridSpan: 1,
-                        },
+                        // 'x-decorator-props': {
+                        //   tooltip: '如果不填写该字段,将在使用此模板发送通知时进行指定',
+                        //   gridSpan: 1,
+                        // },
                         'x-component-props': {
                           placeholder: '请选择收信部门',
                         },

+ 1 - 1
src/pages/rule-engine/Alarm/Configuration/Save/index.tsx

@@ -129,7 +129,7 @@ const Save = (props: Props) => {
 
     const resp: any = await service.update({
       ...data,
-      state: 'disabled',
+      // state: 'disabled',
       sceneTriggerType: scene.triggerType,
       sceneName: scene.name,
     });

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

@@ -64,7 +64,7 @@ export default (props: BuiltInProps) => {
     if (source === 'upper') {
       sourceChangeEvent();
     }
-  }, [source, props.trigger, props.parallel]);
+  }, [source, props.trigger, props.parallel, props.type]);
 
   useEffect(() => {
     if (props.trigger?.trigger?.device?.productId && source === 'upper') {

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

@@ -111,8 +111,6 @@ export default (props: DeviceProps) => {
         handleMetadata(productItem.metadata);
       }
     }
-
-    props.onProductIdChange(productId);
   }, [productId]);
 
   useEffect(() => {
@@ -179,13 +177,14 @@ export default (props: DeviceProps) => {
             placeholder={'请选择产品'}
             style={{ width: '100%' }}
             listHeight={220}
-            onChange={() => {
+            onChange={(value) => {
               // setMessageType(MessageTypeEnum.WRITE_PROPERTY)
               props.form?.setFields([
                 { name: ['actions', name, 'device', 'selector'], value: SourceEnum.fixed },
                 { name: ['actions', name, 'device', 'selectorValues'], value: undefined },
                 { name: ['actions', name, 'device', 'message', 'functionId'], value: undefined },
               ]);
+              props.onProductIdChange(value);
             }}
             fieldNames={{ label: 'name', value: 'id' }}
             filterOption={(input: string, option: any) =>

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

@@ -367,7 +367,7 @@ export default () => {
                                 move(name, name + 1);
                               }
                             }}
-                            actionItemData={actionDataCount && actionsData[name]}
+                            actionItemData={actionsData[name]}
                             isLast={!actionDataCount || actionDataCount - 1 === name}
                             parallel={parallel}
                           />

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

@@ -138,9 +138,9 @@ const Bind = observer((props: Props) => {
     ];
     if (Object.keys(params).length) {
       _params.push({
-        column: 'parentId$product-info',
-        termType: 'eq',
-        value: 'accessId is ' + params.productId[0],
+        type: 'and',
+        column: 'productId$product-info',
+        value: 'id is ' + params.productId[0],
       });
     }
     return _params;

+ 1 - 0
src/pages/system/Platforms/Api/leftTree.tsx

@@ -90,6 +90,7 @@ export default (props: LeftTreeType) => {
           from(service.getApiNextLevel(item.name)).pipe(
             map((resp: any) => {
               if (resp && resp.components) {
+                ApiModel.components = { ...ApiModel.components, ...resp.components.schemas };
                 return handleTreeData(resp);
               }
               return undefined;

+ 1 - 1
src/pages/system/Platforms/Api/swagger-ui/base.tsx

@@ -77,7 +77,7 @@ export default observer(() => {
         const entityName = refUrl.split('/').pop();
         const entityType = ObjectFindValue('type', ApiModel.swagger.requestBody.content);
         const entityRequired = ApiModel.swagger.requestBody.required;
-        console.log(entityName);
+        console.log(entityName, ApiModel.components);
         const entity: any = ApiModel.components[entityName];
         const file = ObjectFindValue('file', ApiModel.swagger.requestBody.content);
         // 是否为文件上传

+ 17 - 3
src/pages/system/Role/Detail/Permission/Allocate/MenuPermission.tsx

@@ -27,10 +27,14 @@ const MenuPermission = (props: Props) => {
     setIndeterminate(props.value?.check === 2);
     const val =
       (props.value?.assetAccesses || []).filter((i: any) => i?.granted)[0]?.supportId || '';
+    // if (!val && props.value?.check === 1) {
+    //   setCheckValue('creator');
+    // } else {
     setCheckValue(val);
+    // }
   }, [props.value]);
 
-  const checkAllData: any = (data: any[], check: boolean) => {
+  const checkAllData: any = (data: any[], check: boolean, cvalue?: any) => {
     if (Array.isArray(data) && data.length > 0) {
       return data.map((item) => {
         const buttons = (item?.buttons || []).map((i: any) => {
@@ -41,9 +45,15 @@ const MenuPermission = (props: Props) => {
         });
         return {
           ...item,
+          assetAccesses: (item?.assetAccesses || []).map((i: any) => {
+            return {
+              ...i,
+              granted: !cvalue ? false : !i.granted ? i.supportId === cvalue : i.granted,
+            };
+          }),
           check: check ? 1 : 3, // 1: 全选 2: 只选了部分 3: 一个都没选
           buttons: [...buttons],
-          children: item?.children ? checkAllData(item?.children || [], check) : [],
+          children: item?.children ? checkAllData(item?.children || [], check, cvalue) : [],
         };
       });
     }
@@ -100,8 +110,10 @@ const MenuPermission = (props: Props) => {
               }}
               onChange={(e) => {
                 let access: any[] = [];
+                let cvalue: any = checkValue;
                 if (e.target.checked && !checkValue) {
                   setCheckValue('creator');
+                  cvalue = 'creator';
                   access = (value?.assetAccesses || []).map((i: any) => {
                     return {
                       ...i,
@@ -110,6 +122,7 @@ const MenuPermission = (props: Props) => {
                   });
                 } else if (!e.target.checked) {
                   setCheckValue('');
+                  cvalue = '';
                   access = (value?.assetAccesses || []).map((i: any) => {
                     return {
                       ...i,
@@ -117,6 +130,7 @@ const MenuPermission = (props: Props) => {
                     };
                   });
                 } else {
+                  cvalue = checkValue;
                   access = value?.assetAccesses || [];
                 }
                 setCheckAll(e.target.checked);
@@ -132,7 +146,7 @@ const MenuPermission = (props: Props) => {
                   assetAccesses: [...access],
                   check: e.target.checked ? 1 : 3, // 1: 全选 2: 只选了部分 3: 一个都没选
                   buttons: [...buttons],
-                  children: checkAllData(value.children || [], e.target.checked),
+                  children: checkAllData(value.children || [], e.target.checked, cvalue),
                 });
               }}
             >