Sfoglia il codice sorgente

fix: 修改设备诊断

sun-chaochao 3 anni fa
parent
commit
a85c5c78c7

+ 181 - 0
src/components/BindParentDevice/index.tsx

@@ -0,0 +1,181 @@
+import { Badge, Button, Modal } from 'antd';
+import type { DeviceInstance } from '@/pages/device/Instance/typings';
+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 { useIntl } from 'umi';
+import moment from 'moment';
+
+interface Props {
+  data: Partial<DeviceInstance>;
+  onCancel: () => void;
+  onOk: (parentId: string) => void;
+}
+
+const BindParentDevice = (props: Props) => {
+  const intl = useIntl();
+
+  const actionRef = useRef<ActionType>();
+  const [searchParams, setSearchParams] = useState<any>({});
+  const [bindKeys, setBindKeys] = useState<any[]>([]);
+
+  const columns: ProColumns<DeviceInstance>[] = [
+    {
+      title: 'ID',
+      dataIndex: 'id',
+      ellipsis: true,
+    },
+    {
+      title: '设备名称',
+      ellipsis: true,
+      dataIndex: 'name',
+    },
+    {
+      title: '所属产品',
+      ellipsis: true,
+      dataIndex: 'productName',
+    },
+    {
+      title: '注册时间',
+      dataIndex: 'registryTime',
+      ellipsis: true,
+      width: '200px',
+      render: (text: any) => (!!text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/'),
+      sorter: true,
+    },
+    {
+      title: '状态',
+      dataIndex: 'state',
+      ellipsis: true,
+      width: 100,
+      renderText: (record) =>
+        record ? <Badge status={statusMap.get(record.value)} text={record.text} /> : '',
+      valueType: 'select',
+      valueEnum: {
+        notActive: {
+          text: intl.formatMessage({
+            id: 'pages.device.instance.status.notActive',
+            defaultMessage: '未启用',
+          }),
+          value: 'notActive',
+        },
+        offline: {
+          text: intl.formatMessage({
+            id: 'pages.device.instance.status.offLine',
+            defaultMessage: '离线',
+          }),
+          value: 'offline',
+        },
+        online: {
+          text: intl.formatMessage({
+            id: 'pages.device.instance.status.onLine',
+            defaultMessage: '在线',
+          }),
+          value: 'online',
+        },
+      },
+    },
+  ];
+
+  const submitBtn = async () => {
+    // const resp = await service.bindDevice(InstanceModel.detail.id!, bindKeys);
+    // if (resp.status === 200) {
+    //   props.onCancel();
+    //   setBindKeys([]);
+    //   actionRef.current?.reset?.();
+    // }
+  };
+
+  return (
+    <Modal
+      maskClosable={false}
+      title="绑定父设备"
+      visible
+      width={1000}
+      onOk={() => {
+        submitBtn();
+      }}
+      onCancel={() => {
+        props.onCancel();
+        setBindKeys([]);
+      }}
+      footer={[
+        <Button
+          key="back"
+          onClick={() => {
+            props.onCancel();
+            setBindKeys([]);
+            actionRef.current?.reset?.();
+          }}
+        >
+          取消
+        </Button>,
+        <Button
+          disabled={!(bindKeys.length > 0)}
+          key="submit"
+          type="primary"
+          onClick={() => {
+            submitBtn();
+          }}
+        >
+          确认
+        </Button>,
+      ]}
+    >
+      <SearchComponent<DeviceInstance>
+        field={[...columns]}
+        target="parents-device-bind"
+        enableSave={false}
+        model={'simple'}
+        defaultParam={[
+          {
+            terms: [
+              {
+                column: 'productId$product-info',
+                value: [
+                  {
+                    column: 'deviceType',
+                    termType: 'eq',
+                    value: 'gateway',
+                  },
+                ],
+              },
+            ],
+          },
+          {
+            terms: [{ column: 'id$not', value: props.data.id!, type: 'and' }],
+          },
+        ]}
+        onSearch={(param) => {
+          actionRef.current?.reset?.();
+          setSearchParams(param);
+        }}
+      />
+      <ProTable<DeviceInstance>
+        search={false}
+        columns={columns}
+        size="small"
+        rowSelection={{
+          type: 'radio',
+          selectedRowKeys: bindKeys,
+          onChange: (selectedRowKeys, selectedRows) => {
+            setBindKeys(selectedRows.map((item) => item.id));
+          },
+        }}
+        tableAlertRender={false}
+        actionRef={actionRef}
+        params={searchParams}
+        rowKey="id"
+        toolBarRender={false}
+        pagination={{
+          pageSize: 10,
+        }}
+        request={(params) => service.query({ ...params })}
+      />
+    </Modal>
+  );
+};
+
+export default BindParentDevice;

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

@@ -133,7 +133,7 @@ const BindChildDevice = (props: Props) => {
         defaultParam={[
           {
             terms: [
-              { column: 'parentId$isnull', value: '' },
+              { column: 'parentId$isnull', value: '1' },
               { column: 'parentId$not', value: InstanceModel.detail.id!, type: 'or' },
             ],
           },

+ 1 - 1
src/pages/device/Instance/Detail/Diagnose/Status/DiagnosticAdvice.tsx

@@ -46,7 +46,7 @@ const DiagnosticAdvice = (props: Props) => {
           <Descriptions.Item span={1} label="设备ID">
             {data?.info?.id || ''}
           </Descriptions.Item>
-          {data?.info?.address.length > 0 && (
+          {data?.info?.address?.length > 0 && (
             <Descriptions.Item span={1} label="连接地址">
               <Tooltip
                 placement="topLeft"

+ 179 - 5
src/pages/device/Instance/Detail/Diagnose/Status/index.tsx

@@ -26,6 +26,7 @@ import { getMenuPathByCode, getMenuPathByParams, MENUS_CODE } from '@/utils/menu
 import ManualInspection from './ManualInspection';
 import useHistory from '@/hooks/route/useHistory';
 import DiagnosticAdvice from './DiagnosticAdvice';
+import BindParentDevice from '@/components/BindParentDevice';
 interface Props {
   providerType: 'network' | 'child-device' | 'media' | 'cloud' | 'channel' | undefined;
 }
@@ -46,6 +47,9 @@ const Status = observer((props: Props) => {
   const [diagnoseVisible, setDiagnoseVisible] = useState<boolean>(false);
   const [diagnoseData, setDiagnoseData] = useState<any>({});
 
+  // 绑定父设备
+  const [bindParentVisible, setBindParentVisible] = useState<boolean>(false);
+
   // 跳转到产品设备接入配置
   const jumpAccessConfig = () => {
     const purl = getMenuPathByCode(MENUS_CODE['device/Product/Detail']);
@@ -402,7 +406,15 @@ const Status = observer((props: Props) => {
                       status="default"
                       text={
                         <span>
-                          未绑定父设备,请先<a>绑定</a>父设备后重试
+                          未绑定父设备,请先
+                          <a
+                            onClick={() => {
+                              setBindParentVisible(true);
+                            }}
+                          >
+                            绑定
+                          </a>
+                          父设备后重试
                         </span>
                       }
                     />
@@ -1089,13 +1101,158 @@ const Status = observer((props: Props) => {
     });
 
   // // opc
-  // const diagnoseOpcua = () => new Promise(() => {
+  const diagnoseOpcua = () =>
+    new Promise(async (resolve) => {
+      if (device.accessProvider === 'opc-ua') {
+        let item: ListProps | undefined = undefined;
+        const response = await service.noPagingOpcua({
+          paging: false,
+          terms: [
+            {
+              column: 'id$bind-opc',
+              value: device.id,
+            },
+          ],
+        });
+        if (response.status === 200) {
+          if (response.result.length > 0) {
+            item = {
+              key: `opc-ua-config`,
+              name: `OPC UA通道配置`,
+              desc: '诊断设备是否已绑定通道,未绑定通道将导致设备连接失败',
+              status: 'success',
+              text: '正常',
+              info: null,
+            };
+          } else {
+            item = {
+              key: `opc-ua-config`,
+              name: `OPC UA通道配置`,
+              desc: '诊断设备是否已绑定通道,未绑定通道将导致设备连接失败',
+              status: 'error',
+              text: '异常',
+              info: (
+                <div>
+                  <div className={styles.infoItem}>
+                    <Badge
+                      status="default"
+                      text={
+                        <span>
+                          设备未绑定通道,请先<a>配置</a>
+                        </span>
+                      }
+                    />
+                  </div>
+                </div>
+              ),
+            };
+          }
+          setTimeout(() => {
+            if (item) {
+              DiagnoseStatusModel.list = modifyArrayList(
+                DiagnoseStatusModel.list,
+                item,
+                DiagnoseStatusModel.list.length,
+              );
+            }
+            DiagnoseStatusModel.count++;
+            resolve({});
+          }, time);
+        }
+      } else {
+        resolve({});
+      }
+    });
 
+  // opc ua 连接状态
+  // const diagnoseOpcuaState = () => new Promise(async (resolve) => {
+  //   if (device.accessProvider === 'opc-ua') {
+  //     let item: ListProps | undefined = undefined;
+  //     const response = await service.noPagingOpcua({
+  //       paging: false,
+  //       terms: [
+  //         {
+  //           column: 'id$bind-opc',
+  //           value: device.id,
+  //         },
+  //       ],
+  //     })
+  //     if (response.status === 200) {
+  //       if (response.result.length > 0) {
+  //         item = {
+  //           key: `opc-ua-state`,
+  //           name: `OPC UA通道连接状态`,
+  //           desc: '诊断通道连接状态是否已连接,未连接状态将导致设备连接失败',
+  //           status: 'success',
+  //           text: '正常',
+  //           info: null,
+  //         }
+  //       } else {
+  //         item = {
+  //           key: `opc-ua-state`,
+  //           name: `OPC UA通道连接状态`,
+  //           desc: '诊断通道连接状态是否已连接,未连接状态将导致设备连接失败',
+  //           status: 'error',
+  //           text: '异常',
+  //           info: (
+  //             <div>
+  //               <div className={styles.infoItem}>
+  //                 <Badge
+  //                   status="default"
+  //                   text={<span>通道未连接成功,请联系管理员处理</span>}
+  //                 />
+  //               </div>
+  //             </div>
+  //           ),
+  //         }
+  //       }
+  //       setTimeout(() => {
+  //         if (item) {
+  //           DiagnoseStatusModel.list = modifyArrayList(DiagnoseStatusModel.list, item, DiagnoseStatusModel.list.length);
+  //         }
+  //         DiagnoseStatusModel.count++;
+  //         resolve({});
+  //       }, time);
+  //     }
+  //   } else {
+  //     resolve({})
+  //   }
   // })
   // //modbus
-  // const diagnoseModbus = () => new Promise(() => {
+  const diagnoseModbus = () =>
+    new Promise((resolve) => {
+      if (device.accessProvider === 'modbus-tcp') {
+      } else {
+        resolve({});
+      }
+    });
 
-  // })
+  // 数据点绑定
+  const diagnoseDataPointBind = () =>
+    new Promise((resolve) => {
+      if (device.accessProvider === 'modbus-tcp' || device.accessProvider === 'opc-ua') {
+      } else {
+        resolve({});
+      }
+    });
+
+  // onenet
+  const diagnoseOnenet = () =>
+    new Promise((resolve) => {
+      if (device.accessProvider === 'OneNet') {
+      } else {
+        resolve({});
+      }
+    });
+
+  // ctwing
+  const diagnoseCTWing = () =>
+    new Promise((resolve) => {
+      if (device.accessProvider === 'Ctwing') {
+      } else {
+        resolve({});
+      }
+    });
 
   // 设备离线且全部诊断项都是正确的情况后
   const diagnoseNetworkOtherConfig = async () => {
@@ -1290,6 +1447,13 @@ const Status = observer((props: Props) => {
       await diagnoseParentDevice();
       await diagnoseProduct();
       await diagnoseDevice();
+      DiagnoseStatusModel.percent = 60;
+      await diagnoseProductAuthConfig();
+      await diagnoseDeviceAuthConfig();
+      DiagnoseStatusModel.percent = 80;
+      await diagnoseModbus();
+      await diagnoseOpcua();
+      await diagnoseDataPointBind();
     } else if (providerType === 'media') {
       DiagnoseStatusModel.list = [...mediaInitList];
       await diagnoseGateway();
@@ -1302,12 +1466,21 @@ const Status = observer((props: Props) => {
       DiagnoseStatusModel.percent = 40;
       await diagnoseProduct();
       await diagnoseDevice();
+      DiagnoseStatusModel.percent = 80;
+      await diagnoseCTWing();
+      await diagnoseOnenet();
     } else if (providerType === 'channel') {
       DiagnoseStatusModel.list = [...channelInitList];
       await diagnoseGateway();
-      DiagnoseStatusModel.percent = 40;
+      DiagnoseStatusModel.percent = 20;
       await diagnoseProduct();
       await diagnoseDevice();
+      DiagnoseStatusModel.percent = 40;
+      await diagnoseModbus();
+      await diagnoseOpcua();
+      // await diagnoseOpcuaState();
+      await diagnoseDataPointBind();
+      DiagnoseStatusModel.percent = 80;
     }
     DiagnoseStatusModel.percent = 100;
     DiagnoseStatusModel.status = 'finish';
@@ -1384,6 +1557,7 @@ const Status = observer((props: Props) => {
           }}
         />
       )}
+      {bindParentVisible && <BindParentDevice data={device} onCancel={() => {}} onOk={() => {}} />}
     </div>
   );
 });

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

@@ -44,7 +44,6 @@ const Diagnose = observer(() => {
       setProviderType('network');
     }
     DiagnoseStatusModel.state = 'loading';
-
     return () => {
       DiagnoseStatusModel.list = [];
       DiagnoseStatusModel.count = 0;

+ 5 - 4
src/pages/device/Instance/Detail/Running/Property/FileComponent/index.tsx

@@ -34,7 +34,7 @@ const FileComponent = (props: Props) => {
   const renderValue = () => {
     if (value?.formatValue !== 0 && !value?.formatValue) {
       return (
-        <div className={props.type === 'card' ? styles.cardValue : styles.otherValue}>{''}</div>
+        <div className={props.type === 'card' ? styles.cardValue : styles.otherValue}>{'--'}</div>
       );
     } else if (data?.valueType?.type === 'file') {
       if (
@@ -61,7 +61,7 @@ const FileComponent = (props: Props) => {
                 message.error('该图片无法访问');
               } else {
                 const flag =
-                  ['.jpg', '.png'].find((item) => value?.formatValue.includes(item)) || '';
+                  ['.jpg', '.png'].find((item) => value?.formatValue.includes(item)) || '--';
                 setType(flag);
                 setVisible(true);
               }
@@ -90,7 +90,8 @@ const FileComponent = (props: Props) => {
                 message.error('当前仅支持播放.mp4,.flv,.m3u8格式的视频');
               } else {
                 const flag =
-                  ['.m3u8', '.flv', '.mp4'].find((item) => value?.formatValue.includes(item)) || '';
+                  ['.m3u8', '.flv', '.mp4'].find((item) => value?.formatValue.includes(item)) ||
+                  '--';
                 setType(flag);
                 setVisible(true);
               }
@@ -107,7 +108,7 @@ const FileComponent = (props: Props) => {
         const flag =
           ['.txt', '.doc', '.xls', '.pdf', '.ppt', '.docx', '.xlsx', '.pptx'].find((item) =>
             value?.formatValue.includes(item),
-          ) || '';
+          ) || '--';
         return (
           <div className={props.type === 'card' ? styles.cardValue : styles.otherValue}>
             <img src={imgMap.get(flag.slice(1))} />

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

@@ -350,6 +350,17 @@ class Service extends BaseService<DeviceInstance> {
     request(`/${SystemConst.API_BASE}/device/transparent-codec/${productId}`, {
       method: 'DELETE',
     });
+  // 查询设备下点位
+  public noPagingOpcua = (data: any) =>
+    request(`/${SystemConst.API_BASE}/opc/client/_query/no-paging`, {
+      method: 'POST',
+      data,
+    });
+  public queryMetadatabyId = (data: any) =>
+    request(`/${SystemConst.API_BASE}/modbus/master/_query/no-paging`, {
+      method: 'POST',
+      data,
+    });
 }
 
 export default Service;