100011797 3 лет назад
Родитель
Сommit
97a90404bf

+ 2 - 2
src/components/SearchComponent/index.tsx

@@ -663,8 +663,8 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
         handleSearch(false);
         return;
       }
-      form.setInitialValues(JSON.parse(q));
-      handleSearch(false);
+      // form.setInitialValues(JSON.parse(q));
+      // handleSearch(false);
     }
   };
 

+ 1 - 0
src/global.less

@@ -153,4 +153,5 @@ input[type='tel'] {
 
 .ant-popover-buttons {
   display: flex;
+  justify-content: flex-end;
 }

+ 2 - 0
src/hooks/document/useDomFullHeight.tsx

@@ -32,12 +32,14 @@ const useDomFullHeight = (target: BasicTarget | string, extraHeight: number = 0)
 
   useEffect(() => {
     const el = getTargetElement(target);
+    console.log(target, 'target', el);
     let resizeObserver: ResizeObserver | undefined;
     if (el) {
       resizeObserver = new ResizeObserver((entries) => {
         entries.forEach((entry) => {
           const bodyClient = document.body.getBoundingClientRect();
           const domClient = entry.target.getBoundingClientRect();
+          console.log(domClient, 'domClient', bodyClient);
           if (domClient.y < 50) {
             setState(100);
           } else {

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

@@ -1,5 +1,6 @@
 import LivePlayer from '@/components/Player';
-import { Image, Input, Modal } from 'antd';
+import { Image, Modal } from 'antd';
+import ReactJson from 'react-json-view';
 
 interface Props {
   close: () => void;
@@ -16,7 +17,15 @@ const Detail = (props: Props) => {
     } else if (['.flv', '.m3u8', '.mp4'].includes(type)) {
       return <LivePlayer live={false} url={value?.formatValue} />;
     } else if (type === 'obj') {
-      return <Input.TextArea rows={15} bordered={false} value={value?.formatValue} />;
+      // @ts-ignore
+      return (
+        <ReactJson
+          displayObjectSize={false}
+          displayDataTypes={false}
+          name={false}
+          src={value?.formatValue}
+        />
+      );
     }
     return null;
   };

+ 1 - 1
src/pages/device/Instance/Detail/Running/Property/PropertyCard.less

@@ -22,7 +22,7 @@
   }
 }
 
-.value {
+.time-value {
   width: 100%;
   overflow: hidden;
   white-space: nowrap;

+ 15 - 7
src/pages/device/Instance/Detail/Running/Property/PropertyCard.tsx

@@ -106,14 +106,22 @@ const Property = (props: Props) => {
           <FileComponent type="card" value={dataValue} data={data} />
           <div style={{ marginTop: 10 }}>
             <div style={{ color: 'rgba(0, 0, 0, .65)', fontSize: 12 }}>更新时间</div>
-            <div
-              style={{ marginTop: 5, fontSize: 16, color: 'black', minHeight: 25 }}
-              className="value"
+            <Tooltip
+              title={
+                dataValue?.timestamp
+                  ? moment(dataValue?.timestamp).format('YYYY-MM-DD HH:mm:ss')
+                  : ''
+              }
             >
-              {dataValue?.timestamp
-                ? moment(dataValue?.timestamp).format('YYYY-MM-DD HH:mm:ss')
-                : ''}
-            </div>
+              <div
+                style={{ marginTop: 5, fontSize: 16, color: 'black', minHeight: 25 }}
+                className="time-value"
+              >
+                {dataValue?.timestamp
+                  ? moment(dataValue?.timestamp).format('YYYY-MM-DD HH:mm:ss')
+                  : ''}
+              </div>
+            </Tooltip>
           </div>
         </div>
       </Spin>

+ 1 - 1
src/pages/link/AccessConfig/index.tsx

@@ -26,7 +26,7 @@ const AccessConfig = () => {
   const [param, setParam] = useState<any>({ pageSize: 10, terms: [] });
   const { permission } = PermissionButton.usePermission('link/AccessConfig');
 
-  const { minHeight } = useDomFullHeight(`.link-accessConfig`, 36);
+  const { minHeight } = useDomFullHeight(`.link-accessConfig`, 24);
 
   const columns: ProColumns<any>[] = [
     {

+ 103 - 99
src/pages/link/DataCollect/components/Channel/index.tsx

@@ -27,7 +27,7 @@ const ChannelModel = model<{
 
 export default observer((props: Props) => {
   const intl = useIntl();
-  const { minHeight } = useDomFullHeight(`.data-collect-channel`, 24);
+  const { minHeight } = useDomFullHeight(`.data-collect-channel-card`, 24);
   const [param, setParam] = useState({ pageSize: 12, terms: [] });
   const { permission } = PermissionButton.usePermission('link/DataCollect/DataGathering');
   const [loading, setLoading] = useState<boolean>(true);
@@ -148,106 +148,110 @@ export default observer((props: Props) => {
           handleSearch(dt);
         }}
       />
-      <Card loading={loading} bordered={false}>
-        <div style={{ position: 'relative', minHeight }}>
-          <div style={{ height: '100%', paddingBottom: 48 }}>
-            {dataSource?.data.length ? (
-              <>
-                <Row gutter={[24, 24]} style={{ marginTop: 10 }}>
-                  {(dataSource?.data || []).map((record: any) => (
-                    <Col key={record.id} span={props.type ? 8 : 12}>
-                      <ChannelCard
-                        {...record}
-                        state={getState(record)}
-                        actions={[
-                          <PermissionButton
-                            type={'link'}
-                            onClick={() => {
-                              ChannelModel.current = record;
-                              ChannelModel.visible = true;
-                            }}
-                            key={'edit'}
-                            isPermission={permission.update}
-                          >
-                            <EditOutlined />
-                            {intl.formatMessage({
-                              id: 'pages.data.option.edit',
-                              defaultMessage: '编辑',
-                            })}
-                          </PermissionButton>,
-                          <PermissionButton
-                            key="delete"
-                            isPermission={permission.delete}
-                            type={'link'}
-                            style={{ padding: 0 }}
-                            // disabled={record?.state?.value !== 'disabled'}
-                            // tooltip={
-                            //   record?.state?.value !== 'disabled'
-                            //     ? {
-                            //         title: '正常的通道不能删除',
-                            //       }
-                            //     : undefined
-                            // }
-                            popConfirm={{
-                              title: '该操作将会删除下属采集器与点位,确定删除?',
-                              onConfirm: async () => {
-                                await service.removeChannel(record.id);
-                                handleSearch(param);
-                                onlyMessage(
-                                  intl.formatMessage({
-                                    id: 'pages.data.option.success',
-                                    defaultMessage: '操作成功!',
-                                  }),
-                                );
-                              },
-                            }}
-                          >
-                            <DeleteOutlined />
-                          </PermissionButton>,
-                        ]}
-                      />
-                    </Col>
-                  ))}
-                </Row>
-                <div
-                  style={{
-                    display: 'flex',
-                    justifyContent: 'flex-end',
-                    position: 'absolute',
-                    width: '100%',
-                    bottom: 0,
-                  }}
-                >
-                  <Pagination
-                    showSizeChanger
-                    size="small"
-                    className={'pro-table-card-pagination'}
-                    total={dataSource?.total || 0}
-                    current={dataSource?.pageIndex + 1}
-                    onChange={(page, size) => {
-                      handleSearch({
-                        ...param,
-                        pageIndex: page - 1,
-                        pageSize: size,
-                      });
-                    }}
-                    pageSizeOptions={[12, 24, 48, 96]}
-                    pageSize={dataSource?.pageSize}
-                    showTotal={(num) => {
-                      const minSize = dataSource?.pageIndex * dataSource?.pageSize + 1;
-                      const MaxSize = (dataSource?.pageIndex + 1) * dataSource?.pageSize;
-                      return `第 ${minSize} - ${MaxSize > num ? num : MaxSize} 条/总共 ${num} 条`;
-                    }}
+      <Card
+        loading={loading}
+        bordered={false}
+        style={{ position: 'relative', minHeight }}
+        className={'data-collect-channel-card'}
+      >
+        <div style={{ height: '100%', paddingBottom: 48 }}>
+          {dataSource?.data.length > 0 ? (
+            <Row gutter={[24, 24]} style={{ marginTop: 10 }}>
+              {(dataSource?.data || []).map((record: any) => (
+                <Col key={record.id} span={props.type ? 8 : 12}>
+                  <ChannelCard
+                    {...record}
+                    state={getState(record)}
+                    actions={[
+                      <PermissionButton
+                        type={'link'}
+                        onClick={() => {
+                          ChannelModel.current = record;
+                          ChannelModel.visible = true;
+                        }}
+                        key={'edit'}
+                        isPermission={permission.update}
+                      >
+                        <EditOutlined />
+                        {intl.formatMessage({
+                          id: 'pages.data.option.edit',
+                          defaultMessage: '编辑',
+                        })}
+                      </PermissionButton>,
+                      <PermissionButton
+                        key="delete"
+                        isPermission={permission.delete}
+                        type={'link'}
+                        style={{ padding: 0 }}
+                        // disabled={record?.state?.value !== 'disabled'}
+                        // tooltip={
+                        //   record?.state?.value !== 'disabled'
+                        //     ? {
+                        //         title: '正常的通道不能删除',
+                        //       }
+                        //     : undefined
+                        // }
+                        popConfirm={{
+                          title: '该操作将会删除下属采集器与点位,确定删除?',
+                          placement: 'topRight',
+                          onConfirm: async () => {
+                            await service.removeChannel(record.id);
+                            handleSearch(param);
+                            onlyMessage(
+                              intl.formatMessage({
+                                id: 'pages.data.option.success',
+                                defaultMessage: '操作成功!',
+                              }),
+                            );
+                          },
+                        }}
+                      >
+                        <DeleteOutlined />
+                      </PermissionButton>,
+                    ]}
                   />
-                </div>
-              </>
-            ) : (
-              <div style={{ height: minHeight - 150 }}>
-                <Empty />
-              </div>
-            )}
-          </div>
+                </Col>
+              ))}
+            </Row>
+          ) : (
+            <div style={{ height: minHeight - 150 }}>
+              <Empty />
+            </div>
+          )}
         </div>
+        {dataSource?.data?.length > 0 && (
+          <div
+            style={{
+              display: 'flex',
+              justifyContent: 'flex-end',
+              position: 'absolute',
+              width: '100%',
+              bottom: 0,
+            }}
+          >
+            <Pagination
+              showSizeChanger
+              size="small"
+              className={'pro-table-card-pagination'}
+              total={dataSource?.total || 0}
+              current={dataSource?.pageIndex + 1}
+              onChange={(page, size) => {
+                handleSearch({
+                  ...param,
+                  pageIndex: page - 1,
+                  pageSize: size,
+                });
+              }}
+              pageSizeOptions={[12, 24, 48, 96]}
+              pageSize={dataSource?.pageSize}
+              showTotal={(num) => {
+                const minSize = dataSource?.pageIndex * dataSource?.pageSize + 1;
+                const MaxSize = (dataSource?.pageIndex + 1) * dataSource?.pageSize;
+                return `第 ${minSize} - ${MaxSize > num ? num : MaxSize} 条/总共 ${num} 条`;
+              }}
+            />
+          </div>
+        )}
       </Card>
       {ChannelModel.visible && (
         <Save

+ 8 - 2
src/pages/link/DataCollect/components/Device/index.tsx

@@ -208,8 +208,13 @@ export default observer((props: Props) => {
           handleSearch(dt);
         }}
       />
-      <Card bordered={false} loading={loading}>
-        <div style={{ minHeight, position: 'relative' }}>
+      <Card
+        bordered={false}
+        loading={loading}
+        style={{ minHeight, position: 'relative' }}
+        className={'data-collect-collector'}
+      >
+        <div>
           <div style={{ paddingBottom: 48, height: '100%' }}>
             {!props.type && (
               <div style={{ width: '100%', display: 'flex', justifyContent: 'flex-start' }}>
@@ -311,6 +316,7 @@ export default observer((props: Props) => {
                             popConfirm={{
                               title: '该操作将会删除下属点位,确定删除?',
                               disabled: record?.state?.value !== 'disabled',
+                              placement: 'topRight',
                               onConfirm: async () => {
                                 if (record?.state?.value === 'disabled') {
                                   await service.removeCollector(record.id);

+ 3 - 0
src/pages/link/DataCollect/components/Point/Save/opc-ua.tsx

@@ -34,6 +34,9 @@ export default (props: Props) => {
       accessModes: props.data?.accessModes
         ? (props.data?.accessModes || []).map((item) => item.value)
         : [],
+      features: props.data?.features
+        ? (props.data?.features || []).map((item: any) => item?.value)
+        : [],
     });
   }, [props.data]);
 

+ 8 - 3
src/pages/link/DataCollect/components/Point/index.tsx

@@ -59,7 +59,7 @@ const PointModel = model<{
 
 const PointCard = observer((props: PointCardProps) => {
   const [subscribeTopic] = useSendWebsocketMessage();
-  const { minHeight } = useDomFullHeight(`.data-collect-point`, 24);
+  const { minHeight } = useDomFullHeight(`.data-collect-point`);
   const [param, setParam] = useState({ pageSize: 12, terms: [] });
   const [loading, setLoading] = useState<boolean>(true);
   const { permission } = PermissionButton.usePermission('link/DataCollect/DataGathering');
@@ -207,8 +207,13 @@ const PointCard = observer((props: PointCardProps) => {
           handleSearch(dt);
         }}
       />
-      <Card loading={loading} bordered={false}>
-        <div style={{ position: 'relative', minHeight }}>
+      <Card
+        loading={loading}
+        bordered={false}
+        className={'data-collect-point'}
+        style={{ position: 'relative', minHeight }}
+      >
+        <div>
           <div style={{ height: '100%', paddingBottom: 48 }}>
             {!props.type && (
               <div style={{ width: '100%', display: 'flex', justifyContent: 'flex-start' }}>

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

@@ -30,6 +30,7 @@ export default (props: Props) => {
       onCancel={() => {
         props.close();
       }}
+      width={750}
       onOk={async () => {
         const values = await form.validateFields();
         const obj = {
@@ -53,7 +54,6 @@ export default (props: Props) => {
           }
         }
       }}
-      width={700}
     >
       <Form name="scene-save" layout={'vertical'} form={form} autoComplete="off">
         <Form.Item

+ 288 - 288
src/pages/system/Menu/Setting/baseMenu.ts

@@ -1362,298 +1362,298 @@ export default [
               },
             ],
           },
+        ],
+      },
+      {
+        code: 'link/DataCollect',
+        name: '数据采集',
+        owner: 'iot',
+        sortIndex: 10,
+        url: '/iot/link/DataCollect',
+        icon: 'icon-shuxingpeizhi',
+        showPage: [],
+        permissions: [],
+        children: [
           {
-            code: 'link/DataCollect',
+            code: 'DataCollect/Dashboard',
+            name: '仪表盘',
+            owner: 'iot',
+            sortIndex: 1,
+            url: '/iot/DataCollect/Dashboard',
+            icon: 'icon-shujumoni',
+            showPage: [
+              'dashboard',
+              'data-collect-channel',
+              'data-collect-opc',
+              'data-collector',
+              'things-collector',
+            ],
+            permissions: [
+              { permission: 'dashboard', actions: ['query'] },
+              { permission: 'data-collect-channel', actions: ['query'] },
+              { permission: 'data-collect-opc', actions: ['query'] },
+              { permission: 'data-collector', actions: ['query'] },
+              { permission: 'things-collector', actions: ['query'] },
+            ],
+            buttons: [],
+          },
+          {
+            code: 'DataCollect/DataGathering',
             name: '数据采集',
             owner: 'iot',
-            sortIndex: 10,
-            url: '/iot/link/DataCollect',
-            icon: 'icon-shuxingpeizhi',
-            showPage: [],
+            sortIndex: 2,
+            url: '/iot/DataCollect/DataGathering',
+            icon: 'icon-rizhifuwu',
+            showPage: [
+              'data-collect-channel',
+              'data-collect-opc',
+              'data-collector',
+              'things-collector',
+            ],
+            permissions: [],
+            buttons: [
+              {
+                id: 'view',
+                name: '查看',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['query'],
+                  },
+                ],
+              },
+              {
+                id: 'add',
+                name: '新增',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['save', 'query'],
+                  },
+                ],
+              },
+              {
+                id: 'update',
+                name: '编辑',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'certificate',
+                    actions: ['query'],
+                  },
+                ],
+              },
+              {
+                id: 'action',
+                name: '禁用/启用',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['save', 'query'],
+                  },
+                ],
+              },
+              {
+                id: 'delete',
+                name: '删除',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['delete', 'query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['delete', 'query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['delete', 'query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['delete', 'query'],
+                  },
+                ],
+              },
+            ],
+          },
+          {
+            code: 'DataCollect/IntegratedQuery',
+            name: '综合查询',
+            owner: 'iot',
+            sortIndex: 3,
+            url: '/iot/DataCollect/IntegratedQuery',
+            icon: 'icon-zhilianshebei',
+            showPage: [
+              'data-collect-channel',
+              'data-collect-opc',
+              'data-collector',
+              'things-collector',
+            ],
             permissions: [],
-            children: [
-              {
-                code: 'link/DataCollect/Dashboard',
-                name: '仪表盘',
-                owner: 'iot',
-                sortIndex: 1,
-                url: '/iot/link/DataCollect/Dashboard',
-                icon: 'icon-shujumoni',
-                showPage: [
-                  'dashboard',
-                  'data-collect-channel',
-                  'data-collect-opc',
-                  'data-collector',
-                  'things-collector',
-                ],
-                permissions: [
-                  { permission: 'dashboard', actions: ['query'] },
-                  { permission: 'data-collect-channel', actions: ['query'] },
-                  { permission: 'data-collect-opc', actions: ['query'] },
-                  { permission: 'data-collector', actions: ['query'] },
-                  { permission: 'things-collector', actions: ['query'] },
-                ],
-                buttons: [],
-              },
-              {
-                code: 'link/DataCollect/DataGathering',
-                name: '数据采集',
-                owner: 'iot',
-                sortIndex: 2,
-                url: '/iot/link/DataCollect/DataGathering',
-                icon: 'icon-rizhifuwu',
-                showPage: [
-                  'data-collect-channel',
-                  'data-collect-opc',
-                  'data-collector',
-                  'things-collector',
-                ],
-                permissions: [],
-                buttons: [
-                  {
-                    id: 'view',
-                    name: '查看',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['query'],
-                      },
-                    ],
-                  },
-                  {
-                    id: 'add',
-                    name: '新增',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['save', 'query'],
-                      },
-                    ],
-                  },
-                  {
-                    id: 'update',
-                    name: '编辑',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'certificate',
-                        actions: ['query'],
-                      },
-                    ],
-                  },
-                  {
-                    id: 'action',
-                    name: '禁用/启用',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['save', 'query'],
-                      },
-                    ],
-                  },
-                  {
-                    id: 'delete',
-                    name: '删除',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['delete', 'query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['delete', 'query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['delete', 'query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['delete', 'query'],
-                      },
-                    ],
-                  },
-                ],
-              },
-              {
-                code: 'link/DataCollect/IntegratedQuery',
-                name: '综合查询',
-                owner: 'iot',
-                sortIndex: 3,
-                url: '/iot/link/DataCollect/IntegratedQuery',
-                icon: 'icon-zhilianshebei',
-                showPage: [
-                  'data-collect-channel',
-                  'data-collect-opc',
-                  'data-collector',
-                  'things-collector',
-                ],
-                permissions: [],
-                buttons: [
-                  {
-                    id: 'view',
-                    name: '查看',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['query'],
-                      },
-                    ],
-                  },
-                  {
-                    id: 'add',
-                    name: '新增',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['save', 'query'],
-                      },
-                    ],
-                  },
-                  {
-                    id: 'update',
-                    name: '编辑',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'certificate',
-                        actions: ['query'],
-                      },
-                    ],
-                  },
-                  {
-                    id: 'action',
-                    name: '禁用/启用',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['save', 'query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['save', 'query'],
-                      },
-                    ],
-                  },
-                  {
-                    id: 'delete',
-                    name: '删除',
-                    permissions: [
-                      {
-                        permission: 'data-collect-channel',
-                        actions: ['delete', 'query'],
-                      },
-                      {
-                        permission: 'data-collector',
-                        actions: ['delete', 'query'],
-                      },
-                      {
-                        permission: 'data-collect-opc',
-                        actions: ['delete', 'query'],
-                      },
-                      {
-                        permission: 'things-collector',
-                        actions: ['delete', 'query'],
-                      },
-                    ],
+            buttons: [
+              {
+                id: 'view',
+                name: '查看',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['query'],
+                  },
+                ],
+              },
+              {
+                id: 'add',
+                name: '新增',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['save', 'query'],
+                  },
+                ],
+              },
+              {
+                id: 'update',
+                name: '编辑',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'certificate',
+                    actions: ['query'],
+                  },
+                ],
+              },
+              {
+                id: 'action',
+                name: '禁用/启用',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['save', 'query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['save', 'query'],
+                  },
+                ],
+              },
+              {
+                id: 'delete',
+                name: '删除',
+                permissions: [
+                  {
+                    permission: 'data-collect-channel',
+                    actions: ['delete', 'query'],
+                  },
+                  {
+                    permission: 'data-collector',
+                    actions: ['delete', 'query'],
+                  },
+                  {
+                    permission: 'data-collect-opc',
+                    actions: ['delete', 'query'],
+                  },
+                  {
+                    permission: 'things-collector',
+                    actions: ['delete', 'query'],
                   },
                 ],
               },