You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@inlong.apache.org by do...@apache.org on 2022/08/02 12:27:41 UTC

[inlong] branch master updated: [INLONG-5330][Dashboard] Stream page optimization adjustment, remove collapse mode (#5331)

This is an automated email from the ASF dual-hosted git repository.

dockerzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git


The following commit(s) were added to refs/heads/master by this push:
     new 97500045d [INLONG-5330][Dashboard] Stream page optimization adjustment, remove collapse mode (#5331)
97500045d is described below

commit 97500045d52d8aa4ba14037d5c79714c26d879d0
Author: Daniel <le...@outlook.com>
AuthorDate: Tue Aug 2 20:27:36 2022 +0800

    [INLONG-5330][Dashboard] Stream page optimization adjustment, remove collapse mode (#5331)
---
 .../AccessHelper/FieldsConfig/dataFields.tsx       |  19 +-
 inlong-dashboard/src/locales/cn.json               |   6 +-
 inlong-dashboard/src/locales/en.json               |   6 +-
 .../AccessDetail/DataStream/StreamItemModal.tsx    |  88 +++---
 .../src/pages/AccessDetail/DataStream/config.tsx   | 149 ----------
 .../AccessDetail/DataStream/index.module.less      |  31 --
 .../src/pages/AccessDetail/DataStream/index.tsx    | 324 ++++++---------------
 7 files changed, 141 insertions(+), 482 deletions(-)

diff --git a/inlong-dashboard/src/components/AccessHelper/FieldsConfig/dataFields.tsx b/inlong-dashboard/src/components/AccessHelper/FieldsConfig/dataFields.tsx
index 809872cfd..77f375b06 100644
--- a/inlong-dashboard/src/components/AccessHelper/FieldsConfig/dataFields.tsx
+++ b/inlong-dashboard/src/components/AccessHelper/FieldsConfig/dataFields.tsx
@@ -25,32 +25,15 @@ import i18n from '@/i18n';
 import { fieldTypes as sourceFieldsTypes } from '@/components/MetaData/SourceDataFields';
 
 type RestParams = {
-  inlongGroupId?: string;
-  // Whether to use true operation for data source management
-  useDataSourcesActionRequest?: boolean;
-  // Whether to use real operation for data storage management
-  useDataStorageActionRequest?: boolean;
   // Whether the fieldList is in edit mode
   fieldListEditing?: boolean;
-  readonly?: boolean;
 };
 
 export default (
   names: (string | FormItemProps)[],
   currentValues: Record<string, any> = {},
-  {
-    inlongGroupId,
-    useDataSourcesActionRequest = false,
-    useDataStorageActionRequest = false,
-    fieldListEditing = true,
-    readonly = false,
-  }: RestParams = {},
+  { fieldListEditing = true }: RestParams = {},
 ): FormItemProps[] => {
-  // const basicProps = {
-  //   inlongGroupId: inlongGroupId,
-  //   inlongStreamId: currentValues.inlongStreamId,
-  // };
-
   const fields: FormItemProps[] = [
     {
       type: 'input',
diff --git a/inlong-dashboard/src/locales/cn.json b/inlong-dashboard/src/locales/cn.json
index c0289525a..c8c292456 100644
--- a/inlong-dashboard/src/locales/cn.json
+++ b/inlong-dashboard/src/locales/cn.json
@@ -10,6 +10,7 @@
   "basic.DeleteConfirm": "确认删除吗?",
   "basic.DeleteSuccess": "删除成功",
   "basic.Status": "状态",
+  "basic.Creator": "创建人",
   "basic.CreateTime": "创建时间",
   "basic.Yes": "是",
   "basic.No": "否",
@@ -311,6 +312,7 @@
   "pages.AccessDashboard.NewAccess": "新建接入",
   "pages.AccessDashboard.SuccessfullyDeleted": "删除成功",
   "pages.AccessDetail.DataSources.Type": "类型",
+  "pages.AccessDetail.DataSources.File": "文件",
   "pages.AccessDetail.DataSources.SaveSuccessfully": "保存成功",
   "pages.AccessDetail.DataSources.DeleteConfirm": "确认删除吗",
   "pages.AccessDetail.DataSources.DeleteSuccessfully": "删除成功",
@@ -341,10 +343,8 @@
   "pages.AccessDetail.DataStorage.Status.Error": "配置失败",
   "pages.AccessDetail.DataStorage.Status.Success": "配置成功",
   "pages.AccessDetail.DataStream.StreamItemModal.DataFlowConfiguration": "数据流配置",
-  "pages.AccessDetail.DataStream.NewDataStream": "新数据流",
+  "pages.AccessDetail.DataStream.Name": "数据流",
   "pages.AccessDetail.DataStream.CreateDataStream": "新建数据流",
-  "pages.AccessDetail.DataStream.Config.Save": "保存",
-  "pages.AccessDetail.DataStream.Config.Cancel": "取消",
   "pages.AccessDetail.DataStream.Status.New": "新建",
   "pages.AccessDetail.DataStream.Status.Pending": "配置中",
   "pages.AccessDetail.DataStream.Status.Error": "配置失败",
diff --git a/inlong-dashboard/src/locales/en.json b/inlong-dashboard/src/locales/en.json
index 01d753de4..be92cab2e 100644
--- a/inlong-dashboard/src/locales/en.json
+++ b/inlong-dashboard/src/locales/en.json
@@ -10,6 +10,7 @@
   "basic.DeleteConfirm": "Are you sure to delete?",
   "basic.DeleteSuccess": "Delete Success",
   "basic.Status": "Status",
+  "basic.Creator": "Creator",
   "basic.CreateTime": "CreateTime",
   "basic.Yes": "Yes",
   "basic.No": "No",
@@ -311,6 +312,7 @@
   "pages.AccessDashboard.NewAccess": "Create",
   "pages.AccessDashboard.SuccessfullyDeleted": "Successfully deleted",
   "pages.AccessDetail.DataSources.Type": "Type",
+  "pages.AccessDetail.DataSources.File": "File",
   "pages.AccessDetail.DataSources.SaveSuccessfully": "Save successfully",
   "pages.AccessDetail.DataSources.DeleteConfirm": "Delete confirm",
   "pages.AccessDetail.DataSources.DeleteSuccessfully": "Delete successfully",
@@ -341,10 +343,8 @@
   "pages.AccessDetail.DataStorage.Status.Error": "Error",
   "pages.AccessDetail.DataStorage.Status.Success": "Success",
   "pages.AccessDetail.DataStream.StreamItemModal.DataFlowConfiguration": "Data stream configuration",
-  "pages.AccessDetail.DataStream.NewDataStream": "New dataStream",
+  "pages.AccessDetail.DataStream.Name": "Name",
   "pages.AccessDetail.DataStream.CreateDataStream": "Create",
-  "pages.AccessDetail.DataStream.Config.Save": "Save",
-  "pages.AccessDetail.DataStream.Config.Cancel": "Cancel",
   "pages.AccessDetail.DataStream.Status.New": "New",
   "pages.AccessDetail.DataStream.Status.Pending": "Pending",
   "pages.AccessDetail.DataStream.Status.Error": "Error",
diff --git a/inlong-dashboard/src/pages/AccessDetail/DataStream/StreamItemModal.tsx b/inlong-dashboard/src/pages/AccessDetail/DataStream/StreamItemModal.tsx
index 6e8b63779..e15fda32f 100644
--- a/inlong-dashboard/src/pages/AccessDetail/DataStream/StreamItemModal.tsx
+++ b/inlong-dashboard/src/pages/AccessDetail/DataStream/StreamItemModal.tsx
@@ -26,55 +26,47 @@ import i18n from '@/i18n';
 import { genBusinessFields, genDataFields } from '@/components/AccessHelper';
 import request from '@/utils/request';
 import { dataToValues, valuesToData } from './helper';
-import { pickObject } from '@/utils';
 
 export interface Props extends ModalProps {
   inlongGroupId: string;
+  inlongStreamId?: string;
   record?: Record<string, any>;
   mqType: string;
 }
 
-export const genFormContent = (currentValues, inlongGroupId, mqType) => {
-  const extraParams = {
-    inlongGroupId,
-  };
-
+export const genFormContent = (isCreate, mqType) => {
   return [
-    ...genDataFields(
-      [
-        {
-          type: (
-            <Divider orientation="left">
-              {i18n.t('pages.AccessCreate.DataStream.config.Basic')}
-            </Divider>
-          ),
-        },
-        'inlongStreamId',
-        'name',
-        'description',
-        {
-          type: (
-            <Divider orientation="left">
-              {i18n.t('pages.AccessCreate.DataStream.config.DataInfo')}
-            </Divider>
-          ),
-        },
-        'dataType',
-        'dataEncoding',
-        'dataSeparator',
-        'rowTypeFields',
-        {
-          type: (
-            <Divider orientation="left">
-              {i18n.t('pages.AccessCreate.Business.config.AccessScale')}
-            </Divider>
-          ),
-          visible: mqType === 'PULSAR',
-        },
-      ],
-      currentValues,
-      extraParams,
-    ),
+    ...genDataFields([
+      {
+        type: (
+          <Divider orientation="left">
+            {i18n.t('pages.AccessCreate.DataStream.config.Basic')}
+          </Divider>
+        ),
+      },
+      'inlongStreamId',
+      'name',
+      'description',
+      {
+        type: (
+          <Divider orientation="left">
+            {i18n.t('pages.AccessCreate.DataStream.config.DataInfo')}
+          </Divider>
+        ),
+      },
+      'dataType',
+      'dataEncoding',
+      'dataSeparator',
+      'rowTypeFields',
+      {
+        type: (
+          <Divider orientation="left">
+            {i18n.t('pages.AccessCreate.Business.config.AccessScale')}
+          </Divider>
+        ),
+        visible: mqType === 'PULSAR',
+      },
+    ]),
     ...genBusinessFields(['dailyRecords', 'dailyStorage', 'peakRecords', 'maxLength']).map(
       item => ({
         ...item,
@@ -84,7 +76,7 @@ export const genFormContent = (currentValues, inlongGroupId, mqType) => {
   ].map(item => {
     const obj = { ...item };
 
-    if (obj.name === 'inlongStreamId' || obj.name === 'dataType') {
+    if (!isCreate && (obj.name === 'inlongStreamId' || obj.name === 'dataType')) {
       obj.type = 'text';
     }
 
@@ -92,15 +84,15 @@ export const genFormContent = (currentValues, inlongGroupId, mqType) => {
   });
 };
 
-const Comp: React.FC<Props> = ({ inlongGroupId, record, mqType, ...modalProps }) => {
+const Comp: React.FC<Props> = ({ inlongGroupId, inlongStreamId, mqType, ...modalProps }) => {
   const [form] = useForm();
 
-  const { run: getStreamData } = useRequest(
+  const { data: savedData, run: getStreamData } = useRequest(
     {
       url: '/stream/get',
       params: {
         groupId: inlongGroupId,
-        streamId: record.inlongStreamId,
+        streamId: inlongStreamId,
       },
     },
     {
@@ -111,7 +103,7 @@ const Comp: React.FC<Props> = ({ inlongGroupId, record, mqType, ...modalProps })
 
   const onOk = async () => {
     const values = {
-      ...pickObject(['id', 'inlongGroupId', 'inlongStreamId', 'version'], record),
+      ...savedData,
       ...(await form.validateFields()),
     };
 
@@ -129,7 +121,7 @@ const Comp: React.FC<Props> = ({ inlongGroupId, record, mqType, ...modalProps })
     if (modalProps.visible) {
       // open
       form.resetFields(); // Note that it will cause the form to remount to initiate a select request
-      if (Object.keys(record || {})?.length) {
+      if (inlongStreamId) {
         getStreamData();
       }
     }
@@ -145,7 +137,7 @@ const Comp: React.FC<Props> = ({ inlongGroupId, record, mqType, ...modalProps })
       <FormGenerator
         labelCol={{ span: 4 }}
         wrapperCol={{ span: 20 }}
-        content={genFormContent(record, inlongGroupId, mqType)}
+        content={genFormContent(!inlongStreamId, mqType)}
         form={form}
         useMaxWidth
       />
diff --git a/inlong-dashboard/src/pages/AccessDetail/DataStream/config.tsx b/inlong-dashboard/src/pages/AccessDetail/DataStream/config.tsx
index ba1c72708..b1f4fa19a 100644
--- a/inlong-dashboard/src/pages/AccessDetail/DataStream/config.tsx
+++ b/inlong-dashboard/src/pages/AccessDetail/DataStream/config.tsx
@@ -17,10 +17,7 @@
  * under the License.
  */
 
-import React from 'react';
-import { Divider } from 'antd';
 import i18n from '@/i18n';
-import { genBusinessFields, genDataFields } from '@/components/AccessHelper';
 import { statusList } from './status';
 
 export const getFilterFormContent = (defaultValues = {} as any) => [
@@ -39,149 +36,3 @@ export const getFilterFormContent = (defaultValues = {} as any) => [
     },
   },
 ];
-
-export const genExtraContent = ({
-  editingId,
-  record,
-  mqType,
-  onSave,
-  onCancel,
-  onEdit,
-  onDelete,
-}) => {
-  return editingId === record.id || (editingId === true && !record.id)
-    ? [
-        {
-          label: i18n.t('pages.AccessDetail.DataStream.Config.Save'),
-          onRun: onSave,
-          disabled: false,
-        },
-        {
-          label: i18n.t('pages.AccessDetail.DataStream.Config.Cancel'),
-          onRun: onCancel,
-          disabled: false,
-        },
-      ]
-    : [
-        {
-          label: i18n.t('basic.Edit'),
-          onRun: onEdit,
-          disabled: editingId,
-        },
-        {
-          label: i18n.t('basic.Delete'),
-          onRun: onDelete,
-          disabled: editingId,
-        },
-      ];
-};
-
-export const genFormContent = (editingId, currentValues, inlongGroupId, readonly, mqType) => {
-  const extraParams = {
-    inlongGroupId,
-    useDataSourcesActionRequest: !!currentValues?.id,
-    useDataStorageActionRequest: !!currentValues?.id,
-    fieldListEditing: editingId && !currentValues?.id,
-    readonly,
-  };
-
-  const isCreate = editingId === true;
-
-  return [
-    ...genDataFields(
-      [
-        isCreate && {
-          type: (
-            <Divider orientation="left">
-              {i18n.t('pages.AccessCreate.DataStream.config.Basic')}
-            </Divider>
-          ),
-        },
-        'inlongStreamId',
-        {
-          label: 'Topic Name',
-          type: 'text',
-          name: 'mqResource',
-          visible: mqType === 'PULSAR' && editingId !== true,
-        },
-        'name',
-        'description',
-        isCreate && {
-          type: (
-            <Divider orientation="left">
-              {i18n.t('pages.AccessCreate.DataStream.config.DataInfo')}
-            </Divider>
-          ),
-        },
-        isCreate && 'dataType',
-        isCreate && 'dataEncoding',
-        isCreate && 'dataSeparator',
-        isCreate && 'rowTypeFields',
-        isCreate && {
-          type: (
-            <Divider orientation="left">
-              {i18n.t('pages.AccessCreate.Business.config.AccessScale')}
-            </Divider>
-          ),
-          visible: mqType === 'PULSAR',
-        },
-      ],
-      currentValues,
-      extraParams,
-    ),
-    ...genBusinessFields(['dailyRecords', 'dailyStorage', 'peakRecords', 'maxLength']).map(
-      item =>
-        isCreate && {
-          ...item,
-          visible: mqType === 'PULSAR',
-        },
-    ),
-    // ...genDataFields(
-    //   [
-    //     {
-    //       type: (
-    //         <Divider orientation="left">
-    //           {i18n.t('pages.AccessCreate.DataStream.config.DataStorages')}
-    //         </Divider>
-    //       ),
-    //     },
-    //     'streamSink',
-    //     ...Storages.map(item => `streamSink${item.value}`),
-    //   ],
-    //   currentValues,
-    //   extraParams,
-    // ),
-  ]
-    .filter(Boolean)
-    .map(item => {
-      if (
-        (editingId === true && currentValues?.id === undefined) ||
-        (item.name === 'streamSink' && !readonly)
-      ) {
-        return item;
-      }
-
-      const obj = { ...item };
-
-      if (!editingId || editingId !== currentValues?.id) {
-        // Nothing is being edited, or the current line is not being edited
-        delete obj.extra;
-        delete obj.rules;
-        if (typeof obj.type === 'string') {
-          obj.type = 'text';
-          obj.props = { options: obj.props?.options };
-        }
-
-        if ((obj.suffix as any)?.type) {
-          (obj.suffix as any).type = 'text';
-        }
-      } else {
-        // Current edit line
-        if (['inlongStreamId', 'dataSourceType', 'dataType'].includes(obj.name as string)) {
-          obj.type = 'text';
-        }
-      }
-
-      return obj;
-    });
-};
diff --git a/inlong-dashboard/src/pages/AccessDetail/DataStream/index.module.less b/inlong-dashboard/src/pages/AccessDetail/DataStream/index.module.less
deleted file mode 100644
index 06660a476..000000000
--- a/inlong-dashboard/src/pages/AccessDetail/DataStream/index.module.less
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*   http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-* KIND, either express or implied.  See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-
-.topFilterContainer {
-  display: flex;
-  justify-content: space-between;
-  margin-bottom: 20px;
-}
-
-.collapseHeader {
-  display: inline-flex;
-  justify-content: space-between;
-  width: calc(100% - 200px);
-}
diff --git a/inlong-dashboard/src/pages/AccessDetail/DataStream/index.tsx b/inlong-dashboard/src/pages/AccessDetail/DataStream/index.tsx
index c4b1c5a98..d3aff1797 100644
--- a/inlong-dashboard/src/pages/AccessDetail/DataStream/index.tsx
+++ b/inlong-dashboard/src/pages/AccessDetail/DataStream/index.tsx
@@ -17,49 +17,35 @@
  * under the License.
  */
 
-import React, { useState, useRef, useImperativeHandle, forwardRef } from 'react';
-import ReactDom from 'react-dom';
-import { Form, Collapse, Button, Empty, Modal, Space, message } from 'antd';
-import FormGenerator, { FormItemContent } from '@/components/FormGenerator';
+import React, { useState, useImperativeHandle, forwardRef } from 'react';
+import { Button, Modal, message } from 'antd';
+import HighTable from '@/components/HighTable';
 import { defaultSize } from '@/configs/pagination';
-import { useRequest, useEventEmitter } from '@/hooks';
+import { useRequest } from '@/hooks';
 import request from '@/utils/request';
 import { useTranslation } from 'react-i18next';
-import { dataToValues, valuesToData } from './helper';
 import { CommonInterface } from '../common';
 import StreamItemModal from './StreamItemModal';
-import { getFilterFormContent, genExtraContent, genFormContent } from './config';
+import { getFilterFormContent } from './config';
 import { genStatusTag } from './status';
-import styles from './index.module.less';
 
 type Props = CommonInterface;
 
 const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
   const { t } = useTranslation();
 
-  const [form] = Form.useForm();
-
-  const [activeKey, setActiveKey] = useState('0');
-
   const [options, setOptions] = useState({
     pageSize: defaultSize,
     pageNum: 1,
   });
 
-  // False means there is no data being edited, true means it is adding, and the real ID corresponds to the data being edited
-  const [editingId, setEditingId] = useState<number | boolean>(false);
-
-  const [realTimeValues, setRealTimeValues] = useState({ list: [] });
-
-  const topRightRef = useRef();
-
   const [streamItemModal, setStreamItemModal] = useState({
     visible: false,
-    record: {},
+    inlongStreamId: '',
     inlongGroupId,
   });
 
-  const { data = realTimeValues, run: getList, mutate } = useRequest(
+  const { data, loading, run: getList } = useRequest(
     {
       url: '/stream/list',
       method: 'POST',
@@ -70,94 +56,27 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
     },
     {
       refreshDeps: [options],
-      formatResult: result => ({
-        list: dataToValues(result.list),
-        total: result.total,
-      }),
-      onSuccess: data => {
-        form.setFieldsValue({ list: data.list });
-        setRealTimeValues({ list: data.list });
-        setEditingId(false);
-      },
     },
   );
 
-  const onFilter = values => {
-    setOptions(prev => ({
-      ...prev,
-      ...values,
-    }));
-  };
-
-  const getTouchedValues = async () => {
-    const { list } = await form.validateFields();
-    // The necessary key, which must be transmitted every time the interface is adjusted
-    const reservedFields = new Set([
-      'id',
-      'inlongGroupId',
-      'inlongStreamId',
-      'dataSourceType',
-      'havePredefinedFields',
-    ]);
-    const output = list.map((item, index) => {
-      return Object.entries(item).reduce((acc, [key, value]) => {
-        if (form.isFieldTouched(['list', index, key]) || reservedFields.has(key)) {
-          acc[key] = value;
-        }
-        return acc;
-      }, {});
-    });
-    return { list: output };
-  };
-
-  const onSave = async record => {
-    if (record.id) {
-      // update
-      const { list } = await getTouchedValues();
-      const values = list.find(item => item.id === record.id);
-      const data = valuesToData(values ? [values] : [], inlongGroupId);
-      await request({
-        url: '/stream/update',
-        method: 'POST',
-        data: data?.[0],
-      });
-    } else {
-      // create
-      const { list } = await form.validateFields();
-      const values = list?.[0];
-      const data = valuesToData(values ? [values] : [], inlongGroupId);
-      await request({
-        url: '/stream/save',
-        method: 'POST',
-        data: data?.[0],
-      });
-    }
-    await getList();
-    setEditingId(false);
-    message.success(t('basic.OperatingSuccess'));
-  };
-
   const onOk = () => {
-    if (editingId) {
-      return Promise.reject('Please save the data');
-    } else {
-      return Promise.resolve();
-    }
+    return Promise.resolve();
   };
 
   useImperativeHandle(ref, () => ({
     onOk,
   }));
 
-  const onEdit = record => {
-    // setEditingId(record.id);
-    // setActiveKey(index.toString());
-    setStreamItemModal(prev => ({ ...prev, visible: true, record }));
+  const onCreate = () => {
+    setStreamItemModal(prev => ({
+      ...prev,
+      visible: true,
+      inlongStreamId: '',
+    }));
   };
 
-  const onCancel = async () => {
-    setEditingId(false);
-    await getList();
+  const onEdit = ({ inlongStreamId }) => {
+    setStreamItemModal(prev => ({ ...prev, visible: true, inlongStreamId }));
   };
 
   const onDelete = record => {
@@ -178,153 +97,98 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
     });
   };
 
-  const genExtra = (record = {}, index) => {
-    const list = genExtraContent({
-      editingId,
-      record,
-      mqType,
-      onSave,
-      onEdit,
-      onCancel,
-      onDelete,
-    });
-    return (
-      <>
-        {list.map((item, k) => (
-          <Button
-            size="small"
-            type="link"
-            key={k}
-            disabled={item.disabled}
-            onClick={e => {
-              e.stopPropagation();
-              item.onRun(record, index);
-            }}
-          >
-            {item.label}
-          </Button>
-        ))}
-      </>
-    );
+  const onChange = ({ current: pageNum, pageSize }) => {
+    setOptions(prev => ({
+      ...prev,
+      pageNum,
+      pageSize,
+    }));
   };
 
-  const genHeader = (record = {}, index) => {
-    return (
-      <div className={styles.collapseHeader}>
-        {(record as any).inlongStreamId ? (
-          ['inlongStreamId', 'name', 'modifier', 'createTime', 'status'].map(key => (
-            <div key={key}>{key === 'status' ? genStatusTag(record?.[key]) : record?.[key]}</div>
-          ))
-        ) : (
-          <div>{t('pages.AccessDetail.DataStream.NewDataStream')}</div>
-        )}
-      </div>
-    );
+  const onFilter = allValues => {
+    setOptions(prev => ({
+      ...prev,
+      ...allValues,
+      pageNum: 1,
+    }));
   };
 
-  const event$ = useEventEmitter();
+  const pagination = {
+    pageSize: options.pageSize,
+    current: options.pageNum,
+    total: data?.total,
+  };
 
-  event$.useSubscription(() => {
-    setTimeout(() => {
-      setRealTimeValues(form.getFieldsValue());
-    }, 0);
-  });
+  const columns = [
+    {
+      title: 'ID',
+      dataIndex: 'inlongStreamId',
+    },
+    {
+      title: t('pages.AccessDetail.DataStream.Name'),
+      dataIndex: 'name',
+    },
+    {
+      title: t('basic.Creator'),
+      dataIndex: 'creator',
+    },
+    {
+      title: t('basic.CreateTime'),
+      dataIndex: 'createTime',
+    },
+    {
+      title: t('basic.Status'),
+      dataIndex: 'status',
+      render: text => genStatusTag(text),
+    },
+    {
+      title: t('basic.Operating'),
+      dataIndex: 'action',
+      render: (text, record) =>
+        readonly ? (
+          '-'
+        ) : (
+          <>
+            <Button type="link" onClick={() => onEdit(record)}>
+              {t('basic.Edit')}
+            </Button>
+            <Button type="link" onClick={() => onDelete(record)}>
+              {t('basic.Delete')}
+            </Button>
+          </>
+        ),
+    },
+  ];
 
   return (
     <>
-      <div className={styles.topFilterContainer}>
-        <FormGenerator layout="inline" content={getFilterFormContent()} onFilter={onFilter} />
-        <div ref={topRightRef} />
-      </div>
-
-      <Form
-        form={form}
-        labelAlign="left"
-        labelCol={{ xs: 6, sm: 4 }}
-        wrapperCol={{ xs: 18, sm: 20 }}
-        onValuesChange={(c, v) => setRealTimeValues(v)}
-      >
-        <Form.List name="list" initialValue={data.list}>
-          {(fields, { add }) => (
-            <>
-              {topRightRef.current &&
-                !readonly &&
-                ReactDom.createPortal(
-                  <Space>
-                    <Button
-                      type="primary"
-                      disabled={!!editingId}
-                      onClick={async () => {
-                        setEditingId(true);
-                        await add({}, 0);
-                        event$.emit();
-                        setActiveKey('isAdd');
-                        mutate({ list: [{}].concat(data.list), total: data.list.length + 1 });
-                      }}
-                    >
-                      {t('pages.AccessDetail.DataStream.CreateDataStream')}
-                    </Button>
-                  </Space>,
-                  topRightRef.current,
-                )}
-
-              {fields.length ? (
-                <Collapse
-                  accordion
-                  activeKey={activeKey}
-                  onChange={key => setActiveKey(key as any)}
-                  style={{ backgroundColor: 'transparent', border: 'none' }}
-                >
-                  {fields.map((field, index) => (
-                    <Collapse.Panel
-                      header={genHeader(data?.list?.[index], index)}
-                      extra={!readonly && genExtra(data?.list?.[index], index)}
-                      key={editingId === true && index === 0 ? 'isAdd' : field.key.toString()}
-                      style={{
-                        marginBottom: 10,
-                        border: '1px solid #e5e5e5',
-                        backgroundColor: '#f6f7fb',
-                      }}
-                    >
-                      <FormItemContent
-                        values={realTimeValues.list?.[index]}
-                        content={genFormContent(
-                          editingId,
-                          { ...realTimeValues.list?.[index] },
-                          inlongGroupId,
-                          readonly,
-                          mqType,
-                        ).map(item => {
-                          const obj = { ...item } as any;
-                          if (obj.name) {
-                            obj.name = [field.name, obj.name];
-                            obj.fieldKey = [field.fieldKey, obj.name];
-                          }
-                          if (obj.suffix && obj.suffix.name) {
-                            obj.suffix.name = [field.name, obj.suffix.name];
-                            obj.suffix.fieldKey = [field.fieldKey, obj.suffix.name];
-                          }
-
-                          return obj;
-                        })}
-                      />
-                    </Collapse.Panel>
-                  ))}
-                </Collapse>
-              ) : (
-                <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
-              )}
-            </>
-          )}
-        </Form.List>
-      </Form>
+      <HighTable
+        filterForm={{
+          content: getFilterFormContent(),
+          onFilter,
+        }}
+        suffix={
+          !readonly && (
+            <Button type="primary" onClick={onCreate}>
+              {t('pages.AccessDetail.DataStream.CreateDataStream')}
+            </Button>
+          )
+        }
+        table={{
+          columns,
+          rowKey: 'id',
+          dataSource: data?.list,
+          pagination,
+          loading,
+          onChange,
+        }}
+      />
 
       <StreamItemModal
         {...streamItemModal}
         mqType={mqType}
         onOk={async () => {
           await getList();
-          setEditingId(false);
           setStreamItemModal(prev => ({ ...prev, visible: false }));
         }}
         onCancel={() => setStreamItemModal(prev => ({ ...prev, visible: false }))}