Przeglądaj źródła

feat: 数据解析及api首页

wzyyy 3 lat temu
rodzic
commit
65818dbe07

BIN
public/images/apiHome.png


Plik diff jest za duży
+ 317 - 2
src/pages/device/Instance/Detail/Parsing/index.tsx


+ 10 - 8
src/pages/device/Instance/Detail/index.tsx

@@ -136,14 +136,6 @@ const InstanceDetail = observer(() => {
       component: <Functions />,
     },
     {
-      key: 'parsing',
-      tab: intl.formatMessage({
-        id: 'pages.device.instanceDetail.parsing',
-        defaultMessage: '数据解析',
-      }),
-      component: <Parsing />,
-    },
-    {
       key: 'log',
       tab: intl.formatMessage({
         id: 'pages.device.instanceDetail.log',
@@ -185,6 +177,16 @@ const InstanceDetail = observer(() => {
           component: <MetadataMap type="device" />,
         });
       }
+      if (response.result.transport === 'MQTT' || response.result.transport === 'HTTP') {
+        datalist.push({
+          key: 'parsing',
+          tab: intl.formatMessage({
+            id: 'pages.device.instanceDetail.parsing',
+            defaultMessage: '数据解析',
+          }),
+          component: <Parsing tag="device" data={InstanceModel.detail} />,
+        });
+      }
       if (response.result.protocol === 'modbus-tcp') {
         datalist.push({
           key: 'modbus',

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

@@ -303,6 +303,39 @@ class Service extends BaseService<DeviceInstance> {
       method: 'POST',
       data,
     });
+  //获取产品解析规则
+  public productCode = (productId: string) =>
+    request(`/${SystemConst.API_BASE}/device/transparent-codec/${productId}`, {
+      method: 'GET',
+    });
+  //保存产品解析规则
+  public saveProductCode = (productId: string, data: any) =>
+    request(`/${SystemConst.API_BASE}/device/transparent-codec/${productId}`, {
+      method: 'POST',
+      data,
+    });
+  //获取设备解析规则
+  public deviceCode = (productId: string, deviceId: string) =>
+    request(`/${SystemConst.API_BASE}/device/transparent-codec/${productId}/${deviceId}`, {
+      method: 'GET',
+    });
+  //保存设备解析规则
+  public saveDeviceCode = (productId: string, deviceId: string, data: any) =>
+    request(`/${SystemConst.API_BASE}/device/transparent-codec/${productId}/${deviceId}`, {
+      method: 'POST',
+      data,
+    });
+  //编码测试
+  public testCode = (data: any) =>
+    request(`/${SystemConst.API_BASE}/device/transparent-codec/decode-test`, {
+      method: 'POST',
+      data,
+    });
+  //获取指定协议
+  public getProtocal = (id: string, transport: string) =>
+    request(`/${SystemConst.API_BASE}/protocol/${id}/transport/${transport}`, {
+      method: 'GET',
+    });
 }
 
 export default Service;

+ 18 - 0
src/pages/device/Product/Detail/index.tsx

@@ -18,6 +18,7 @@ import SystemConst from '@/utils/const';
 import { PermissionButton } from '@/components';
 import { QuestionCircleOutlined } from '@ant-design/icons';
 import { onlyMessage } from '@/utils/util';
+import Parsing from '../../Instance/Detail/Parsing';
 
 export const ModelEnum = {
   base: 'base',
@@ -153,6 +154,7 @@ const ProductDetail = observer(() => {
   };
 
   useEffect(() => {
+    console.log(productModel.current);
     if (
       productModel.current?.accessProvider &&
       pList.includes(productModel.current?.accessProvider)
@@ -168,6 +170,22 @@ const ProductDetail = observer(() => {
     } else {
       setList([...initList]);
     }
+    if (
+      productModel.current?.transportProtocol === 'MQTT' ||
+      productModel.current?.transportProtocol === 'HTTP'
+    ) {
+      setList([
+        ...initList,
+        {
+          key: 'parsing',
+          tab: intl.formatMessage({
+            id: 'pages.device.instanceDetail.parsing',
+            defaultMessage: '数据解析',
+          }),
+          component: <Parsing tag="product" data={productModel.current} />,
+        },
+      ]);
+    }
   }, [productModel.current]);
 
   useEffect(() => {

+ 65 - 47
src/pages/media/Device/Save/index.tsx

@@ -136,6 +136,7 @@ const Save = () => {
                         model={'singular'}
                         itemStyle={{ width: '50%' }}
                         onSelect={(key) => {
+                          console.log(key);
                           setAccessType(key);
                           queryProduct(key);
                         }}
@@ -341,55 +342,72 @@ const Save = () => {
               </Form>
             </Col>
             <Col span={12}>
-              <div className={styles.doc} style={{ height: 800 }}>
-                <h1>1、概述</h1>
-                <div>
-                  视频设备通过GB/T28181接入平台整体分为2部分,包括平台端配置和设备端配置,不同的设备端配置的路径或页面存在差异,但配置项基本大同小异。
+              {accessType === 'gb28181-2016' ? (
+                <div className={styles.doc} style={{ height: 800 }}>
+                  <h1>1、概述</h1>
+                  <div>
+                    视频设备通过GB/T28181接入平台整体分为2部分,包括平台端配置和设备端配置,不同的设备端配置的路径或页面存在差异,但配置项基本大同小异。
+                  </div>
+                  <h1>2、配置说明</h1>
+                  <h1>平台端配置</h1>
+                  <h2>1、ID</h2>
+                  <div>设备唯一标识,若不填写,系统将自动生成唯一标识</div>
+                  <h2>2、所属产品</h2>
+                  <div>
+                    只能选择接入方式为GB/T28281的产品,若当前无对应产品,可点击右侧快速添加按钮,填写产品名称和选择GB/T28181类型的网关完成产品创建
+                  </div>
+                  <h2>3、接入密码</h2>
+                  <div>
+                    配置接入密码,设备端配置的密码需与该密码一致。该字段可在产品-设备接入页面进行统一配置,配置后所有设备将继承产品配置。设备单独修改后将脱离继承关系。
+                  </div>
+                  <h1>设备端配置</h1>
+                  <div>
+                    各个厂家、不同设备型号的设备端配置页面布局存在差异,但配置项基本大同小异,此处以大华摄像头为例作为接入配置示例
+                  </div>
+                  <div className={styles.image}>
+                    <Image width="100%" src={img1} />
+                  </div>
+                  <h2>1、SIP服务器编号/SIP域</h2>
+                  <div>
+                    SIP服务器编号填入该设备所属产品-接入方式页面“连接信息”的SIP。
+                    SIP域通常为SIP服务器编号的前10位。
+                  </div>
+                  <div className={styles.image}>
+                    <Image width="100%" src={img2} />
+                  </div>
+                  <h2>2、SIP服务器IP/端口</h2>
+                  <div>SIP服务器IP/端口填入该设备所属产品-接入方式页面中“连接信息”的IP/端口。</div>
+                  <div className={styles.image}>
+                    <Image width="100%" src={img3} />
+                  </div>
+                  <h2>3、设备编号</h2>
+                  <div>
+                    设备编号为设备唯一性标识,物联网平台的设备接入没有校验该字段,输入任意数字均不影响设备接入平台。
+                  </div>
+                  <h2>4、注册密码</h2>
+                  <div>填入该设备所属产品-接入方式页面中“GB28281配置”处的接入密码</div>
+                  <div className={styles.image}>
+                    <Image width="100%" src={img4} />
+                  </div>
+                  <h2>5、其他字段</h2>
+                  <div>不影响设备接入平台,可保持设备初始化值。</div>
                 </div>
-                <h1>2、配置说明</h1>
-                <h1>平台端配置</h1>
-                <h2>1、ID</h2>
-                <div>设备唯一标识,若不填写,系统将自动生成唯一标识</div>
-                <h2>2、所属产品</h2>
-                <div>
-                  只能选择接入方式为GB/T28281的产品,若当前无对应产品,可点击右侧快速添加按钮,填写产品名称和选择GB/T28181类型的网关完成产品创建
+              ) : (
+                <div className={styles.doc}>
+                  <h1>1、概述</h1>
+                  <div>视频设备通过RTSP、RTMP固定地址接入平台分为2步。</div>
+                  <div>1.添加视频设备</div>
+                  <div>2.添加视频下的通道地址。</div>
+                  <div>注:当前页面为新增视频设备,新增完成后点击设备的“通道”按钮,添加通道。</div>
+                  <h1>2.配置说明</h1>
+                  <h2>1. ID</h2>
+                  <div>设备唯一标识,若不填写,系统将自动生成唯一标识。</div>
+                  <h2>2. 所属产品</h2>
+                  <div>
+                    只能选择接入方式为固定地址的产品,若当前无对应产品,可点击右侧快速添加按钮,填写产品名称和选择固定地址类型的网关完成产品创建。
+                  </div>
                 </div>
-                <h2>3、接入密码</h2>
-                <div>
-                  配置接入密码,设备端配置的密码需与该密码一致。该字段可在产品-设备接入页面进行统一配置,配置后所有设备将继承产品配置。设备单独修改后将脱离继承关系。
-                </div>
-                <h1>设备端配置</h1>
-                <div>
-                  各个厂家、不同设备型号的设备端配置页面布局存在差异,但配置项基本大同小异,此处以大华摄像头为例作为接入配置示例
-                </div>
-                <div className={styles.image}>
-                  <Image width="100%" src={img1} />
-                </div>
-                <h2>1、SIP服务器编号/SIP域</h2>
-                <div>
-                  SIP服务器编号填入该设备所属产品-接入方式页面“连接信息”的SIP。
-                  SIP域通常为SIP服务器编号的前10位。
-                </div>
-                <div className={styles.image}>
-                  <Image width="100%" src={img2} />
-                </div>
-                <h2>2、SIP服务器IP/端口</h2>
-                <div>SIP服务器IP/端口填入该设备所属产品-接入方式页面中“连接信息”的IP/端口。</div>
-                <div className={styles.image}>
-                  <Image width="100%" src={img3} />
-                </div>
-                <h2>3、设备编号</h2>
-                <div>
-                  设备编号为设备唯一性标识,物联网平台的设备接入没有校验该字段,输入任意数字均不影响设备接入平台。
-                </div>
-                <h2>4、注册密码</h2>
-                <div>填入该设备所属产品-接入方式页面中“GB28281配置”处的接入密码</div>
-                <div className={styles.image}>
-                  <Image width="100%" src={img4} />
-                </div>
-                <h2>5、其他字段</h2>
-                <div>不影响设备接入平台,可保持设备初始化值。</div>
-              </div>
+              )}
             </Col>
           </Row>
         </Card>

+ 18 - 8
src/pages/system/Platforms/Api/base.tsx

@@ -8,9 +8,10 @@ import { observer } from '@formily/react';
 import './index.less';
 import { useLocation } from 'umi';
 import { useDomFullHeight } from '@/hooks';
+import Home from '../Home';
 
 export const ApiModel = model<{
-  data: any[];
+  data: any[] | undefined;
   baseUrl: string;
   showTable: boolean;
   components: any;
@@ -36,6 +37,7 @@ interface ApiPageProps {
    */
   isOpenGranted?: boolean;
   type?: 'all' | 'empowerment' | 'authorize';
+  showHome?: boolean;
 }
 
 export default observer((props: ApiPageProps) => {
@@ -98,21 +100,29 @@ export default observer((props: ApiPageProps) => {
           isShowGranted={props.isShowGranted}
           grantKeys={GrantKeys}
           operations={operations}
+          showHome={props.showHome}
           type={props.type}
           onSelect={(data) => {
+            console.log(data);
             ApiModel.data = data;
             ApiModel.showTable = true;
           }}
         />
       </div>
       {ApiModel.showTable ? (
-        <Table
-          data={ApiModel.data}
-          operations={operations}
-          isOpenGranted={props.isOpenGranted}
-          isShowGranted={props.isShowGranted}
-          grantKeys={GrantKeys}
-        />
+        <>
+          {ApiModel.data ? (
+            <Table
+              data={ApiModel.data}
+              operations={operations}
+              isOpenGranted={props.isOpenGranted}
+              isShowGranted={props.isShowGranted}
+              grantKeys={GrantKeys}
+            />
+          ) : (
+            <Home />
+          )}
+        </>
       ) : (
         <SwaggerUI showDebugger={props.showDebugger} />
       )}

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

@@ -4,7 +4,7 @@ import BasePage from './base';
 export default () => {
   return (
     <PageContainer>
-      <BasePage type={'empowerment'} />
+      <BasePage type={'empowerment'} showHome={true} />
     </PageContainer>
   );
 };

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

@@ -12,6 +12,7 @@ type LeftTreeType = {
   grantKeys?: string[]; // 已授权的接口
   type?: 'all' | 'empowerment' | 'authorize'; // 全部、赋权、授权
   operations?: string[]; // 能赋权的key
+  showHome?: boolean;
 };
 
 interface DataNode {
@@ -28,7 +29,19 @@ export default (props: LeftTreeType) => {
   const getLevelOne = async () => {
     const resp = await service.getApiFirstLevel();
     if (resp.urls && resp.urls.length) {
-      setTreeData(resp.urls.map((item: any) => ({ ...item, id: item.url })));
+      if (props.showHome) {
+        const home = [
+          {
+            id: 'home',
+            name: '首页',
+            isLeaf: true,
+          },
+        ];
+        ApiModel.data = undefined;
+        setTreeData(home.concat(resp.urls.map((item: any) => ({ ...item, id: item.url }))));
+      } else {
+        setTreeData(resp.urls.map((item: any) => ({ ...item, id: item.url })));
+      }
     }
   };
 
@@ -152,6 +165,12 @@ export default (props: LeftTreeType) => {
           props.onSelect(node.extraData);
         }
       }}
+      // onExpand={(_,{node}:any)=>{
+      //   if (node.isLeaf && props.onSelect) {
+      //     props.onSelect(node.extraData);
+      //   }
+      // }}
+      defaultSelectedKeys={['home']}
       loadData={onLoadData}
       treeData={treeData}
     />

+ 38 - 0
src/pages/system/Platforms/Home/index.less

@@ -0,0 +1,38 @@
+.home {
+  padding: 20px;
+
+  h1 {
+    font-weight: 600;
+    font-size: 20px;
+  }
+
+  h2 {
+    font-weight: 600;
+    font-size: 18px;
+  }
+
+  .h2-text {
+    color: #999;
+  }
+
+  h3 {
+    margin-top: 10px;
+    font-weight: 600;
+    font-size: 16px;
+  }
+
+  .h3-text {
+    max-width: 530px;
+    margin-top: 3px;
+    color: #999;
+  }
+
+  p {
+    color: #666;
+  }
+
+  .div-border {
+    padding: 10px;
+    border-left: 10px solid #eee;
+  }
+}

Plik diff jest za duży
+ 175 - 0
src/pages/system/Platforms/Home/index.tsx


+ 1 - 1
src/pages/system/Platforms/Setting/index.tsx

@@ -9,7 +9,7 @@ export default () => {
         <ExclamationCircleOutlined style={{ marginRight: 12, fontSize: 16 }} />
         配置系统支持API赋权的范围
       </div>
-      <ApiPage type={'all'} showDebugger={true} isOpenGranted={false} />
+      <ApiPage type={'all'} showDebugger={true} isOpenGranted={false} showHome={false} />
     </PageContainer>
   );
 };

+ 1 - 1
src/pages/system/Platforms/View/index.tsx

@@ -111,7 +111,7 @@ export default () => {
         </Col>
         <Col span={24}>
           <Card title={'API文档'}>
-            <ApiPage type={'authorize'} showDebugger={true} isShowGranted={true} />
+            <ApiPage type={'authorize'} showDebugger={true} isShowGranted={true} showHome={true} />
           </Card>
         </Col>
       </Row>