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

jiafengzheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris-manager.git


The following commit(s) were added to refs/heads/master by this push:
     new 4987e02  [fix] fix manager1.0.0 frontend bugs (#13)
4987e02 is described below

commit 4987e024dadb60808f184b8eadd484cdf5fc218a
Author: zhengbowen <[email protected]>
AuthorDate: Wed Mar 23 16:12:44 2022 +0800

    [fix] fix manager1.0.0 frontend bugs (#13)
    
    [fix] fix manager1.0.0 frontend bugs
---
 frontend/src/components/sidebar/sidebar.tsx        | 16 +++--
 .../index.module.less => cluster/cluster.utils.ts} | 28 ++------
 .../routes/cluster/configuration/check-modal.tsx   |  4 +-
 .../routes/cluster/configuration/edit-modal.tsx    | 31 ++++++---
 .../routes/space/access-cluster/access-cluster.tsx | 79 +++++++++++++++-------
 .../steps/cluster-verify/cluster-verify.tsx        | 65 +++++++++++-------
 .../steps/connect-cluster/connect-cluster.tsx      | 50 +++++++-------
 .../space/components/node-verify/node-verify.tsx   | 60 ++++++++++++----
 .../src/routes/space/new-cluster/new-cluster.tsx   | 36 +++++++---
 .../space/new-cluster/steps/add-node/add-node.tsx  | 38 +++++------
 .../steps/add-node/node-list/node-list.tsx         | 29 ++++++--
 .../steps/cluster-deploy/cluster-deploy.tsx        |  6 +-
 .../steps/cluster-plan/cluster-plan.tsx            | 56 +++++++++++++--
 .../steps/install-options/install-options.tsx      | 11 ---
 .../index.module.less => space/space.utils.ts}     | 32 +++------
 frontend/src/routes/user-setting/index.module.less |  1 -
 16 files changed, 335 insertions(+), 207 deletions(-)

diff --git a/frontend/src/components/sidebar/sidebar.tsx 
b/frontend/src/components/sidebar/sidebar.tsx
index 2cebec4..6cc564c 100644
--- a/frontend/src/components/sidebar/sidebar.tsx
+++ b/frontend/src/components/sidebar/sidebar.tsx
@@ -25,14 +25,14 @@ import {
     TableOutlined,
     AppstoreOutlined,
 } from '@ant-design/icons';
-import { Link, useHistory } from 'react-router-dom';
-import React, { useState, useEffect, useContext } from 'react';
+import { Link, useHistory, useLocation } from 'react-router-dom';
+import React, { useState, useEffect, useContext, useMemo } from 'react';
 
 import { useTranslation } from 'react-i18next';
 import styles from './sidebar.less';
 import { UserInfoContext } from '@src/common/common.context';
 
-const GLOBAL_PATHS = ['/settings', '/space'];
+const GLOBAL_PATHS = ['/settings', '/space', '/user-setting'];
 
 export function Sidebar(props: any) {
     const { t } = useTranslation();
@@ -42,9 +42,14 @@ export function Sidebar(props: any) {
     const user = useContext(UserInfoContext);
 
     const history = useHistory();
+    const { pathname } = useLocation();
     const isSuperAdmin = user?.is_super_admin;
     const isSpaceAdmin = user?.is_admin;
     const isInSpace = !GLOBAL_PATHS.includes(selectedKeys);
+    const logoRoute = useMemo(
+        () => (GLOBAL_PATHS.some(path => pathname.startsWith(path)) ? '/space' 
: '/cluster'),
+        [pathname],
+    );
     useEffect(() => {
         if (history.location.pathname.includes('configuration')) {
             setSelectedKeys('/configuration');
@@ -130,10 +135,9 @@ export function Sidebar(props: any) {
                             alignItems: 'center',
                         }}
                         key="/logo"
+                        onClick={() => history.push(logoRoute)}
                     >
-                        <div
-                            className={collapsed ? styles['logo-collapsed'] : 
styles['logo']}
-                        />
+                        <div className={collapsed ? styles['logo-collapsed'] : 
styles['logo']} />
                     </Menu.Item>
                     {isInSpace && (
                         <>
diff --git a/frontend/src/routes/user-setting/index.module.less 
b/frontend/src/routes/cluster/cluster.utils.ts
similarity index 66%
copy from frontend/src/routes/user-setting/index.module.less
copy to frontend/src/routes/cluster/cluster.utils.ts
index 9d2eaba..522dbf7 100644
--- a/frontend/src/routes/user-setting/index.module.less
+++ b/frontend/src/routes/cluster/cluster.utils.ts
@@ -14,29 +14,9 @@
 // KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
-.tabs {
-  transform: translate(35em, 0);
-}
-
-.input-gird {
-  margin: 0 auto;
-  width: 420px;
-  // padding: 32px;
- 
-  line-height: 24px;
-  background-color: #fff;
-  border-radius: 6px;
-  box-shadow: rgb(0 0 0 / 8%) 0 7px 20px;
-  transition: all 0.2s linear 0s;
-
-  input {
-    width: 100%;
-    padding: 0.75em;
-    background: '#e8f0fe';
-    border-radius: 4px;
-  }
-}
 
-.input-pass {
-  background: '#e8f0fe';
+export function transformHostToIp(host: string) {
+    if (!host.includes(':')) return host;
+    const sliceIndex = host.indexOf(':');
+    return host.slice(0, sliceIndex);
 }
diff --git a/frontend/src/routes/cluster/configuration/check-modal.tsx 
b/frontend/src/routes/cluster/configuration/check-modal.tsx
index b6209bd..6d4ad96 100644
--- a/frontend/src/routes/cluster/configuration/check-modal.tsx
+++ b/frontend/src/routes/cluster/configuration/check-modal.tsx
@@ -15,10 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-import React, { useState } from 'react';
+import React from 'react';
 import { Button, Modal, Table } from 'antd';
 import { useTranslation } from 'react-i18next';
 import { ConfigurationItem } from '.';
+import { transformHostToIp } from '../cluster.utils';
 
 interface CheckModalProps {
     visible: boolean;
@@ -38,6 +39,7 @@ export default function CheckModal(props: CheckModalProps) {
         {
             title: t`hostIp`,
             dataIndex: 'host',
+            render: (host: string) => transformHostToIp(host),
         },
         {
             title: t`currentValue`,
diff --git a/frontend/src/routes/cluster/configuration/edit-modal.tsx 
b/frontend/src/routes/cluster/configuration/edit-modal.tsx
index 38f33f3..d09d861 100644
--- a/frontend/src/routes/cluster/configuration/edit-modal.tsx
+++ b/frontend/src/routes/cluster/configuration/edit-modal.tsx
@@ -21,6 +21,7 @@ import { useTranslation } from 'react-i18next';
 import { ConfigurationItem } from '.';
 import { useAsync } from '@src/hooks/use-async';
 import * as ClusterAPI from '../cluster.api';
+import { transformHostToIp } from '../cluster.utils';
 
 interface EditModalProps {
     visible: boolean;
@@ -33,12 +34,18 @@ interface FormInstanceProps {
     value: string;
     persist: boolean;
     range: 'all' | 'part';
-    nodes: number[];
+    nodes: string[];
+}
+
+const enum RangeEnum {
+    ALL = 'ALL',
+    PART = 'PART',
 }
 
 export default function EditModal(props: EditModalProps) {
     const { t } = useTranslation();
     const { visible, currentParameter, onOk, onCancel } = props;
+    const [range, setRange] = useState<RangeEnum>(RangeEnum.ALL);
     const { loading: confirmLoading, run: runChangeConfiguration } = 
useAsync();
     const [form] = Form.useForm<FormInstanceProps>();
 
@@ -48,7 +55,7 @@ export default function EditModal(props: EditModalProps) {
                 runChangeConfiguration(
                     ClusterAPI.changeConfiguration(currentParameter.type === 
'Frontend' ? 'fe' : 'be', {
                         [currentParameter.name]: {
-                            node: [...currentParameter.nodes],
+                            node: [...(range === RangeEnum.ALL ? 
currentParameter.nodes : values.nodes)],
                             value: values.value,
                             persist: values.persist ? 'true' : 'false',
                         },
@@ -68,7 +75,7 @@ export default function EditModal(props: EditModalProps) {
 
     const handleCancel = () => {
         form.resetFields();
-        // setRange('all');
+        setRange(RangeEnum.ALL);
         onCancel();
     };
 
@@ -99,7 +106,7 @@ export default function EditModal(props: EditModalProps) {
                         <Radio value={false}>{t`onceEffective`}</Radio>
                     </Radio.Group>
                 </Form.Item>
-                {/* <Form.Item
+                <Form.Item
                     name="range"
                     label={t`effectiveRange`}
                     rules={[{ required: true, message: 
t`effectiveRangeRequiredMessage` }]}
@@ -109,21 +116,25 @@ export default function EditModal(props: EditModalProps) {
                             setRange(e.target.value);
                         }}
                     >
-                        <Radio value="all">{t`allNodes`}</Radio>
-                        <Radio value="part">{t`certainNodes`}</Radio>
+                        <Radio value={RangeEnum.ALL}>{t`allNodes`}</Radio>
+                        <Radio value={RangeEnum.PART}>{t`certainNodes`}</Radio>
                     </Radio.Group>
-                </Form.Item> */}
-                {/* {range === 'part' && (
+                </Form.Item>
+                {range === RangeEnum.PART && (
                     <Form.Item
                         name="nodes"
                         label={t`effectiveNodes`}
                         rules={[{ required: true, message: 
t`effectiveNodesPlaceholder` }]}
                     >
                         <Select mode="multiple" 
placeholder={t`effectiveNodesPlaceholder`}>
-                            <Select.Option value="1">127.0.0.1</Select.Option>
+                            {currentParameter.nodes.map(nodeHost => (
+                                <Select.Option key={nodeHost} value={nodeHost}>
+                                    {transformHostToIp(nodeHost)}
+                                </Select.Option>
+                            ))}
                         </Select>
                     </Form.Item>
-                )} */}
+                )}
             </Form>
         </Modal>
     );
diff --git a/frontend/src/routes/space/access-cluster/access-cluster.tsx 
b/frontend/src/routes/space/access-cluster/access-cluster.tsx
index 0fa5bf0..eefec29 100644
--- a/frontend/src/routes/space/access-cluster/access-cluster.tsx
+++ b/frontend/src/routes/space/access-cluster/access-cluster.tsx
@@ -35,16 +35,22 @@ import { useRecoilState, useRecoilValue } from 'recoil';
 import { requestInfoState, stepDisabledState } from './access-cluster.recoil';
 import { ClusterVerify } from './steps/cluster-verify/cluster-verify';
 import { SpaceAccessFinish } from './steps/finish/finish';
+import { checkParam } from '../space.utils';
 const { Step } = Steps;
 
 export function AccessCluster(props: any) {
-    const match = useRouteMatch<{requestId: string}>();
+    const match = useRouteMatch<{ requestId: string }>();
     const history = useHistory();
     const [step, setStep] = React.useState(0);
     const [loading, setLoading] = useState(false);
     const [requestInfo, setRequestInfo] = useRecoilState(requestInfoState);
     const [stepDisabled, setStepDisabled] = useRecoilState(stepDisabledState);
-    const hidePrevSteps = [AccessClusterStepsEnum['space-register'], 
AccessClusterStepsEnum['node-verify'], 
AccessClusterStepsEnum['cluster-verify'], AccessClusterStepsEnum.finish];
+    const hidePrevSteps = [
+        AccessClusterStepsEnum['space-register'],
+        AccessClusterStepsEnum['node-verify'],
+        AccessClusterStepsEnum['cluster-verify'],
+        AccessClusterStepsEnum.finish,
+    ];
 
     useEffect(() => {
         if (history.location.pathname === '/space/list') {
@@ -55,9 +61,9 @@ export function AccessCluster(props: any) {
         const step = (paths as string[])[2];
         setStep(AccessClusterStepsEnum[step]);
 
-        setStepDisabled({...stepDisabled, next: false});
+        setStepDisabled({ ...stepDisabled, next: false });
 
-        if (match.params.requestId && +match.params.requestId !== 0)  {
+        if (match.params.requestId && +match.params.requestId !== 0) {
             getRequestInfo();
         }
     }, [history.location.pathname]);
@@ -74,20 +80,23 @@ export function AccessCluster(props: any) {
 
     async function nextStep() {
         const value = form.getFieldsValue();
+        let isParamsValid = true;
         const newStep = step + 1;
-        setLoading(true);
         const params: ClusterAccessParams = {
             ...requestInfo.reqInfo,
             cluster_id: requestInfo.clusterId,
             request_id: requestInfo.requestId,
             event_type: (step + 1).toString(),
-        }
-        if (value &&  step === AccessClusterStepsEnum['space-register']) {
+        };
+        if (value && step === AccessClusterStepsEnum['space-register']) {
             params.spaceInfo = {
                 describe: value.describe,
                 name: value.name,
                 spaceAdminUsers: value.spaceAdminUsers,
-            }
+            };
+            isParamsValid =
+                checkParam(params.spaceInfo.name, '请填写空间名称') &&
+                checkParam(params.spaceInfo.spaceAdminUsers, '请填写管理员姓名');
         }
         if (value && step === AccessClusterStepsEnum['connect-cluster']) {
             params.clusterAccessInfo = {
@@ -97,7 +106,12 @@ export function AccessCluster(props: any) {
                 queryPort: value.queryPort,
                 type: value.type,
                 user: value.user,
-            }
+            };
+            isParamsValid =
+                checkParam(params.clusterAccessInfo.address, '请填写集群地址') &&
+                checkParam(params.clusterAccessInfo.httpPort, '请填写HTTP端口') &&
+                checkParam(params.clusterAccessInfo.queryPort, '请填写JDBC端口') &&
+                checkParam(params.clusterAccessInfo.user, '请填写集群用户名');
         }
 
         if (value && step === AccessClusterStepsEnum['managed-options']) {
@@ -105,30 +119,34 @@ export function AccessCluster(props: any) {
                 sshKey: value.sshKey,
                 sshPort: value.sshPort,
                 sshUser: value.sshUser,
-            }
-            params.installInfo = value.installInfo
+            };
+            params.installInfo = value.installInfo;
+            isParamsValid =
+                checkParam(params.authInfo.sshUser, '请填写SSH用户') &&
+                checkParam(params.authInfo.sshPort, '请填写SSH端口') &&
+                checkParam(params.authInfo.sshKey, '请填写SSH私钥') && 
+                checkParam(params.installInfo, '请填写安装路径')
         }
-
+        if (!isParamsValid) return;
+        setLoading(true);
         const res = await SpaceAPI.accessCluster(params);
         setLoading(false);
         if (isSuccess(res)) {
             setRequestInfo(res.data);
             setStep(newStep);
-            setStepDisabled({...stepDisabled, next: false});
+            setStepDisabled({ ...stepDisabled, next: false });
             setTimeout(() => {
                 
history.push(`/space/access/${res.data.requestId}/${AccessClusterStepsEnum[newStep]}`);
-            }, 0)
-            
+            }, 0);
         } else {
             message.error(res.msg);
         }
     }
-    
 
     function prevStep() {
         const newStep = step - 1;
         setStep(newStep);
-        setStepDisabled({...stepDisabled, prev: false});
+        setStepDisabled({ ...stepDisabled, prev: false });
         
history.push(`/space/access/${requestInfo.requestId}/${AccessClusterStepsEnum[newStep]}`);
     }
 
@@ -138,11 +156,13 @@ export function AccessCluster(props: any) {
 
     return (
         <>
-            <NewSpaceInfoContext.Provider value={{
-                step,
-                form,
-                reqInfo: requestInfo.reqInfo || {authInfo: {}, spaceInfo: {}, 
clusterAccessInfo: {} }
-            }}>
+            <NewSpaceInfoContext.Provider
+                value={{
+                    step,
+                    form,
+                    reqInfo: requestInfo.reqInfo || { authInfo: {}, spaceInfo: 
{}, clusterAccessInfo: {} },
+                }}
+            >
                 <ProCard style={{ marginTop: 20 }}>
                     <div style={{ position: 'fixed', top: 80, right: 80 }}>
                         <Steps direction="vertical" current={step} style={{ 
padding: '20px 0 40px 0' }}>
@@ -157,11 +177,20 @@ export function AccessCluster(props: any) {
                     <div style={{ marginRight: 240 }}>
                         <CacheSwitch>
                             <CacheRoute 
path={`${match.path}/${AccessClusterStepsEnum[0]}`} component={SpaceRegister} />
-                            <CacheRoute 
path={`${match.path}/${AccessClusterStepsEnum[1]}`} component={ConnectCluster} 
/>
-                            <CacheRoute 
path={`${match.path}/${AccessClusterStepsEnum[2]}`} component={ManagedOptions} 
/>
+                            <CacheRoute
+                                
path={`${match.path}/${AccessClusterStepsEnum[1]}`}
+                                component={ConnectCluster}
+                            />
+                            <CacheRoute
+                                
path={`${match.path}/${AccessClusterStepsEnum[2]}`}
+                                component={ManagedOptions}
+                            />
                             <CacheRoute 
path={`${match.path}/${AccessClusterStepsEnum[3]}`} component={NodeVerify} />
                             <CacheRoute 
path={`${match.path}/${AccessClusterStepsEnum[4]}`} component={ClusterVerify} />
-                            <CacheRoute 
path={`${match.path}/${AccessClusterStepsEnum[5]}`} 
component={SpaceAccessFinish} />
+                            <CacheRoute
+                                
path={`${match.path}/${AccessClusterStepsEnum[5]}`}
+                                component={SpaceAccessFinish}
+                            />
                             <Redirect 
to={`${match.path}/${AccessClusterStepsEnum[0]}`} />
                         </CacheSwitch>
                         <Row justify="end" style={{ marginTop: 20 }}>
diff --git 
a/frontend/src/routes/space/access-cluster/steps/cluster-verify/cluster-verify.tsx
 
b/frontend/src/routes/space/access-cluster/steps/cluster-verify/cluster-verify.tsx
index e46e891..20143ef 100644
--- 
a/frontend/src/routes/space/access-cluster/steps/cluster-verify/cluster-verify.tsx
+++ 
b/frontend/src/routes/space/access-cluster/steps/cluster-verify/cluster-verify.tsx
@@ -30,12 +30,15 @@ import { IResult } from '@src/interfaces/http.interface';
 import { OperateStatusEnum } from '@src/routes/space/space.data';
 import { useRecoilState } from 'recoil';
 import { stepDisabledState } from '../../access-cluster.recoil';
+import { LoadingOutlined } from '@ant-design/icons';
 const Step = Steps.Step;
 
+const ERROR_STATUS = [OperateStatusEnum.FAIL, OperateStatusEnum.CANCEL];
+
 export function ClusterVerify(props: any) {
     const [activeKey, setActiveKey] = useState(DorisNodeTypeEnum.FE);
-    const {reqInfo} = useContext(NewSpaceInfoContext);
-    const match = useRouteMatch<{spaceId: string}>();
+    const { reqInfo } = useContext(NewSpaceInfoContext);
+    const match = useRouteMatch<{ spaceId: string }>();
     const [instance, setInstance] = useState([]);
     const [nodeTypes, setNodeTypes] = useState<any[]>([]);
     const [feNodes, setFENodes] = useState([]);
@@ -43,7 +46,6 @@ export function ClusterVerify(props: any) {
     const [brokerNodes, setBrokerNodes] = useState([]);
     const [stepDisabled, setStepDisabled] = useRecoilState(stepDisabledState);
 
-
     const columns = [
         {
             title: '序号',
@@ -60,16 +62,25 @@ export function ClusterVerify(props: any) {
             key: 'operateStatus',
             render: (record: any) => {
                 return (
-                    <Steps progressDot current={record.operateStage - 1} 
percent={60} size="small" style={{marginLeft: -50}} 
status={OperateStatusEnum.getStepStatus(record.operateStatus)}>
-                        <Step style={{width: 80}} />
+                    <Steps
+                        progressDot={(iconDot, { status }) => {
+                            if (status === 'process') return <LoadingOutlined 
style={{ color: '#1890ff' }} />;
+                            return iconDot;
+                        }}
+                        current={record.operateStage - 1}
+                        size="small"
+                        style={{ marginLeft: -50 }}
+                        
status={OperateStatusEnum.getStepStatus(record.operateStatus)}
+                    >
+                        <Step style={{ width: 80 }} />
                     </Steps>
-                )
-            }
+                );
+            },
         },
     ];
     const getClusterInstance = useRequest<IResult<any>, any>(
         (clusterId: string) => {
-            return SpaceAPI.getClusterInstance<any>({clusterId});
+            return SpaceAPI.getClusterInstance<any>({ clusterId });
         },
         {
             manual: true,
@@ -81,28 +92,38 @@ export function ClusterVerify(props: any) {
                     const types = [];
                     const feNodes = res.data.filter(item => 
item.moduleName?.toUpperCase() === DorisNodeTypeEnum.FE);
                     const beNodes = res.data.filter(item => 
item.moduleName?.toUpperCase() === DorisNodeTypeEnum.BE);
-                    const brokerNodes = res.data.filter(item => 
item.moduleName?.toUpperCase() === DorisNodeTypeEnum.BROKER);
+                    const brokerNodes = res.data.filter(
+                        item => item.moduleName?.toUpperCase() === 
DorisNodeTypeEnum.BROKER,
+                    );
                     setFENodes(feNodes);
                     setBENodes(beNodes);
                     setBrokerNodes(brokerNodes);
                     if (feNodes.length > 0) {
-                        types.push({key: DorisNodeTypeEnum.FE, tab: 'FE节点', 
moduleName: DorisNodeTypeEnum.FE });
+                        types.push({ key: DorisNodeTypeEnum.FE, tab: 'FE节点', 
moduleName: DorisNodeTypeEnum.FE });
                     }
                     if (beNodes.length > 0) {
-                        types.push({key: DorisNodeTypeEnum.BE, tab: 'BE节点', 
moduleName: DorisNodeTypeEnum.BE });
+                        types.push({ key: DorisNodeTypeEnum.BE, tab: 'BE节点', 
moduleName: DorisNodeTypeEnum.BE });
                     }
                     if (brokerNodes.length > 0) {
-                        types.push({key: DorisNodeTypeEnum.BROKER, tab: 
'Broker节点', moduleName: DorisNodeTypeEnum.BROKER });
+                        types.push({
+                            key: DorisNodeTypeEnum.BROKER,
+                            tab: 'Broker节点',
+                            moduleName: DorisNodeTypeEnum.BROKER,
+                        });
                     }
                     setNodeTypes(types);
+                    const failedInstance = data.find(item => 
ERROR_STATUS.includes(item.operateStatus));
+                    if (failedInstance) {
+                        message.error(failedInstance.operateResult);
+                    }
                     const CANCEL_STATUS = [OperateStatusEnum.PROCESSING, 
OperateStatusEnum.INIT];
                     if (data.filter(item => 
CANCEL_STATUS.includes(item.operateStatus)).length === 0) {
                         getClusterInstance.cancel();
                     }
                     if (data.filter(item => item.operateStatus !== 
OperateStatusEnum.SUCCESS).length > 0) {
-                        setStepDisabled({...stepDisabled, next: true});
+                        setStepDisabled({ ...stepDisabled, next: true });
                     } else {
-                        setStepDisabled({...stepDisabled, next: false});
+                        setStepDisabled({ ...stepDisabled, next: false });
                     }
                 }
             },
@@ -115,15 +136,12 @@ export function ClusterVerify(props: any) {
         },
     );
 
-
     useEffect(() => {
         if (reqInfo.cluster_id) {
-            console.log(reqInfo.cluster_id)
             getClusterInstance.run(reqInfo.cluster_id);
         }
     }, [reqInfo.cluster_id]);
 
-
     return (
         <PageContainer
             header={{
@@ -132,18 +150,13 @@ export function ClusterVerify(props: any) {
         >
             <Tabs activeKey={activeKey} onChange={(key: any) => 
setActiveKey(key)} type="card">
                 {nodeTypes.map(item => (
-                    <TabPane tab={item.tab} key={item.key}>
-                    </TabPane>
+                    <TabPane tab={item.tab} key={item.key}></TabPane>
                 ))}
             </Tabs>
-            {activeKey === DorisNodeTypeEnum.FE && (
-                 <Table columns={columns} dataSource={feNodes} 
rowKey="instanceId" />
-            )}
-            {activeKey === DorisNodeTypeEnum.BE && (
-                 <Table columns={columns} dataSource={beNodes} 
rowKey="instanceId" />
-            )}
+            {activeKey === DorisNodeTypeEnum.FE && <Table columns={columns} 
dataSource={feNodes} rowKey="instanceId" />}
+            {activeKey === DorisNodeTypeEnum.BE && <Table columns={columns} 
dataSource={beNodes} rowKey="instanceId" />}
             {activeKey === DorisNodeTypeEnum.BROKER && (
-                 <Table columns={columns} dataSource={brokerNodes} 
rowKey="instanceId" />
+                <Table columns={columns} dataSource={brokerNodes} 
rowKey="instanceId" />
             )}
         </PageContainer>
     );
diff --git 
a/frontend/src/routes/space/access-cluster/steps/connect-cluster/connect-cluster.tsx
 
b/frontend/src/routes/space/access-cluster/steps/connect-cluster/connect-cluster.tsx
index 8dc7d9d..17283aa 100644
--- 
a/frontend/src/routes/space/access-cluster/steps/connect-cluster/connect-cluster.tsx
+++ 
b/frontend/src/routes/space/access-cluster/steps/connect-cluster/connect-cluster.tsx
@@ -23,22 +23,25 @@ import { SpaceAPI } from '@src/routes/space/space.api';
 import styles from '../../../space.less';
 import { stepDisabledState } from '../../access-cluster.recoil';
 import { useRecoilState } from 'recoil';
+import { useLocation } from 'react-router';
+import { AccessClusterStepsEnum } from '../../access-cluster.data';
 
 const tip = {
     default: '请进行链接测试',
-    fault: '链接测试未通过'
-}
+    fault: '链接测试未通过',
+};
 
 export function ConnectCluster(props: any) {
-    const { form, reqInfo, step } = useContext(NewSpaceInfoContext);
+    const { form, reqInfo } = useContext(NewSpaceInfoContext);
     const [testFlag, setTestFlag] = useState<any>('none');
     const [stepDisabled, setStepDisabled] = useRecoilState(stepDisabledState);
-
+    const { pathname } = useLocation();
     useEffect(() => {
-        form.setFieldsValue({...reqInfo.clusterAccessInfo});
-        setStepDisabled({...stepDisabled, next: true});
-    }, [reqInfo.cluster_id, step]);
-
+        if (pathname.includes(AccessClusterStepsEnum[1])) {
+            form.setFieldsValue({ ...reqInfo.clusterAccessInfo });
+            setStepDisabled({ ...stepDisabled, next: true });
+        }
+    }, [reqInfo.cluster_id, pathname]);
 
     const handleLinkTest = () => {
         const values = form.getFieldsValue();
@@ -52,21 +55,21 @@ export function ConnectCluster(props: any) {
             const { msg, data, code } = res;
             if (code === 0) {
                 Modal.success({
-                    title: "集群连接成功",
+                    title: '集群连接成功',
                     content: msg,
                 });
-                setStepDisabled({...stepDisabled, next: false});
-                setTestFlag('success')
+                setStepDisabled({ ...stepDisabled, next: false });
+                setTestFlag('success');
             } else {
                 Modal.error({
-                    title: "集群连接失败",
+                    title: '集群连接失败',
                     content: msg,
                 });
-                setStepDisabled({...stepDisabled, next: true});
+                setStepDisabled({ ...stepDisabled, next: true });
                 setTestFlag('failed');
             }
         });
-    }
+    };
 
     return (
         <PageContainer
@@ -93,10 +96,10 @@ export function ConnectCluster(props: any) {
                     httpPort: reqInfo.clusterAccessInfo?.httpPort,
                     queryPort: reqInfo.clusterAccessInfo?.queryPort,
                     user: reqInfo.clusterAccessInfo?.user,
-                    passwd: reqInfo.clusterAccessInfo?.passwd
+                    passwd: reqInfo.clusterAccessInfo?.passwd,
                 }}
             >
-                <Form.Item name="address" label="集群地址" required >
+                <Form.Item name="address" label="集群地址" required>
                     <Input placeholder="please input cluster address" />
                 </Form.Item>
                 <Form.Item name="httpPort" label="HTTP端口" required>
@@ -110,21 +113,20 @@ export function ConnectCluster(props: any) {
                 </Form.Item>
                 <Form.Item name="passwd" label="集群密码">
                     <Form.Item name="passwd" noStyle>
-                        <Input.Password  placeholder="please input cluster 
user password"/>
+                        <Input.Password placeholder="please input cluster user 
password" />
                     </Form.Item>
                 </Form.Item>
             </Form>
-            <Space style={{marginTop: 20, marginLeft: 82}}>
+            <Space style={{ marginTop: 20, marginLeft: 82 }}>
                 <Button onClick={() => handleLinkTest()}>链接测试</Button>
-                    &nbsp;  
-                {
-                    (testFlag !== 'success') && <Space>
+                &nbsp;
+                {testFlag !== 'success' && (
+                    <Space>
                         <div className={styles['light']}></div>
-                        <div className={styles['light-tip']}>{testFlag === 
'failed' ? tip.fault: tip.default}</div> 
+                        <div className={styles['light-tip']}>{testFlag === 
'failed' ? tip.fault : tip.default}</div>
                     </Space>
-                }
+                )}
             </Space>
         </PageContainer>
     );
 }
-
diff --git a/frontend/src/routes/space/components/node-verify/node-verify.tsx 
b/frontend/src/routes/space/components/node-verify/node-verify.tsx
index 6b0837a..c7648f5 100644
--- a/frontend/src/routes/space/components/node-verify/node-verify.tsx
+++ b/frontend/src/routes/space/components/node-verify/node-verify.tsx
@@ -27,16 +27,19 @@ import { IResult } from '@src/interfaces/http.interface';
 import { OperateStatusEnum } from '../../space.data';
 import { useRecoilState } from 'recoil';
 import { stepDisabledState } from '../../access-cluster/access-cluster.recoil';
+import { LoadingOutlined } from '@ant-design/icons';
 const Step = Steps.Step;
 
+const ERROR_STATUS = [OperateStatusEnum.FAIL, OperateStatusEnum.CANCEL];
+
 export function NodeVerify(props: any) {
-    const {reqInfo} = useContext(NewSpaceInfoContext);
+    const { reqInfo } = useContext(NewSpaceInfoContext);
     const [nodes, setNodes] = useState<any[]>([]);
     const [stepDisabled, setStepDisabled] = useRecoilState(stepDisabledState);
 
     const getClusterNodes = useRequest<IResult<any>, any>(
         (clusterId: string) => {
-            return SpaceAPI.getClusterNodes<any>({clusterId});
+            return SpaceAPI.getClusterNodes<any>({ clusterId });
         },
         {
             manual: true,
@@ -45,13 +48,17 @@ export function NodeVerify(props: any) {
                 if (isSuccess(res)) {
                     const data: any[] = res.data;
                     setNodes(data);
+                    const failedNode = data.find(item => 
ERROR_STATUS.includes(item.operateStatus));
+                    if (failedNode) {
+                        message.error(failedNode.operateResult);
+                    }
                     if (data.filter(item => item.operateStatus === 
OperateStatusEnum.PROCESSING).length === 0) {
                         getClusterNodes.cancel();
                     }
                     if (data.filter(item => item.operateStatus !== 
OperateStatusEnum.SUCCESS).length > 0) {
-                        setStepDisabled({...stepDisabled, next: true});
+                        setStepDisabled({ ...stepDisabled, next: true });
                     } else {
-                        setStepDisabled({...stepDisabled, next: false});
+                        setStepDisabled({ ...stepDisabled, next: false });
                     }
                 }
             },
@@ -63,7 +70,6 @@ export function NodeVerify(props: any) {
         },
     );
 
-
     useLayoutEffect(() => {
         if (reqInfo.cluster_id) {
             getClusterNodes.run(reqInfo.cluster_id);
@@ -86,17 +92,41 @@ export function NodeVerify(props: any) {
             key: 'operateStage',
             render: (record: any) => {
                 return (
-                    <Steps progressDot 
status={OperateStatusEnum.getStepStatus(record.operateStatus)} percent={70} 
current={record.operateStage - 1} size="small" style={{marginLeft: -50}}>
-                        <Step style={{width: 80}} 
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.ACCESS_AUTH)} />
-                        <Step style={{width: 80}} 
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.INSTALL_DIR_CHECK)} />
-                        <Step style={{width: 80}} 
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.JDK_CHECK)} />
-                        <Step style={{width: 80}} 
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.AGENT_DEPLOY)} />
-                        <Step style={{width: 80}} 
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.AGENT_START)} />
-                        <Step style={{width: 80}} 
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.AGENT_REGISTER)} />
+                    <Steps
+                        progressDot={(iconDot, { status }) => {
+                            if (status === 'process') return <LoadingOutlined 
style={{ color: '#1890ff' }} />;
+                            return iconDot;
+                        }}
+                        
status={OperateStatusEnum.getStepStatus(record.operateStatus)}
+                        current={record.operateStage - 1}
+                        size="small"
+                        style={{ marginLeft: -50 }}
+                    >
+                        <Step
+                            style={{ width: 80 }}
+                            
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.ACCESS_AUTH)}
+                        />
+                        <Step
+                            style={{ width: 80 }}
+                            
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.INSTALL_DIR_CHECK)}
+                        />
+                        <Step style={{ width: 80 }} 
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.JDK_CHECK)} />
+                        <Step
+                            style={{ width: 80 }}
+                            
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.AGENT_DEPLOY)}
+                        />
+                        <Step
+                            style={{ width: 80 }}
+                            
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.AGENT_START)}
+                        />
+                        <Step
+                            style={{ width: 80 }}
+                            
title={NodeVerifyStepEnum.getTitle(NodeVerifyStepEnum.AGENT_REGISTER)}
+                        />
                     </Steps>
-                )
-            }
-        }
+                );
+            },
+        },
     ];
     return (
         <PageContainer
diff --git a/frontend/src/routes/space/new-cluster/new-cluster.tsx 
b/frontend/src/routes/space/new-cluster/new-cluster.tsx
index 830c2e8..582de4f 100644
--- a/frontend/src/routes/space/new-cluster/new-cluster.tsx
+++ b/frontend/src/routes/space/new-cluster/new-cluster.tsx
@@ -38,6 +38,7 @@ import { NodeVerify } from 
'../components/node-verify/node-verify';
 import { SpaceAPI } from '../space.api';
 import { isSuccess } from '@src/utils/http';
 import { requestInfoState, stepDisabledState } from 
'../access-cluster/access-cluster.recoil';
+import { checkParam } from '../space.utils';
 const { Step } = Steps;
 
 const PREV_DISABLED_STEPS = [NewClusterStepsEnum[3], NewClusterStepsEnum[6], 
NewClusterStepsEnum[7]];
@@ -52,6 +53,7 @@ export function NewCluster(props: any) {
     const [curProcessId, setProcessId] = useRecoilState(processId);
     const [requestInfo, setRequestInfo] = useRecoilState(requestInfoState);
     const [loading, setLoading] = useState(false);
+    const [form] = useForm();
 
     useEffect(() => {
         if (history.location.pathname === '/space/list') {
@@ -69,9 +71,7 @@ export function NewCluster(props: any) {
         if (match.params.requestId && +match.params.requestId !== 0) {
             getRequestInfo();
         }
-    }, [history.location.pathname, step]);
-
-    const [form] = useForm();
+    }, [history.location.pathname]);
 
     async function getRequestInfo() {
         const requestId = match.params.requestId;
@@ -84,7 +84,7 @@ export function NewCluster(props: any) {
     async function nextStep() {
         const value = form.getFieldsValue();
         const newStep = step + 1;
-        setLoading(true);
+        let isParamsValid = true;
         const params = {
             ...requestInfo.reqInfo,
             cluster_id: requestInfo.clusterId,
@@ -97,26 +97,45 @@ export function NewCluster(props: any) {
                 name: value.name,
                 spaceAdminUsers: value.spaceAdminUsers,
             };
+            isParamsValid =
+                checkParam(params.spaceInfo.name, '请填写空间名称') &&
+                checkParam(params.spaceInfo.spaceAdminUsers, '请填写管理员姓名');
         }
         if (value && step === NewClusterStepsEnum['add-node']) {
             params.authInfo = {
                 sshKey: value.sshKey,
-                sshPort: parseInt(value.sshPort),
+                sshPort: value.sshPort ? parseInt(value.sshPort) : 
value.sshPort,
                 sshUser: value.sshUser,
             };
             params.hosts = value.hosts;
+            isParamsValid =
+                checkParam(params.authInfo.sshUser, '请填写SSH用户') &&
+                checkParam(params.authInfo.sshPort, '请填写SSH端口') &&
+                checkParam(params.authInfo.sshKey, '请填写SSH私钥') &&
+                checkParam(params.hosts, '请填写节点列表');
         }
         if (value && step === NewClusterStepsEnum['install-options']) {
             params.installInfo = value.installDir;
             params.packageInfo = value.packageUrl;
+            isParamsValid =
+                checkParam(params.installInfo, '请填写代码包路径') && 
checkParam(params.packageInfo, '请填写安装路径');
         }
         if (value && step === NewClusterStepsEnum['cluster-plan']) {
             params.nodeConfig = value.nodeConfig;
+            isParamsValid =
+                checkParam(params.nodeConfig?.[0]?.nodeIds, '请分配FE节点') &&
+                checkParam(params.nodeConfig?.[1]?.nodeIds, '请分配BE节点');
         }
         if (value && step === NewClusterStepsEnum['node-config']) {
             params.deployConfigs = value.deployConfigs;
+            isParamsValid = params.deployConfigs.every((node: any) => {
+                return node.configs.every((config: any) => {
+                    return checkParam(config.value, 
`请完整配置${node.moduleName.toUpperCase()}节点参数`);
+                });
+            });
         }
-        console.log(params);
+        if (!isParamsValid) return;
+        setLoading(true);
         const res = await SpaceAPI.createCluster(params);
         setLoading(false);
         if (isSuccess(res)) {
@@ -138,7 +157,6 @@ export function NewCluster(props: any) {
 
     async function finish() {
         const value = form.getFieldsValue();
-        setLoading(true);
         const params = {
             ...requestInfo.reqInfo,
             cluster_id: requestInfo.clusterId,
@@ -146,7 +164,9 @@ export function NewCluster(props: any) {
             event_type: (step + 1).toString(),
         };
         params.clusterPassword = value.clusterPassword;
-        console.log(params);
+        const isFinishParamValid = checkParam(params.clusterPassword, 
'请设定集群root密码');
+        if (!isFinishParamValid) return;
+        setLoading(true);
         const res = await SpaceAPI.createCluster(params);
         setLoading(false);
         if (isSuccess(res)) {
diff --git a/frontend/src/routes/space/new-cluster/steps/add-node/add-node.tsx 
b/frontend/src/routes/space/new-cluster/steps/add-node/add-node.tsx
index 1d370de..f3c6b5f 100644
--- a/frontend/src/routes/space/new-cluster/steps/add-node/add-node.tsx
+++ b/frontend/src/routes/space/new-cluster/steps/add-node/add-node.tsx
@@ -16,36 +16,34 @@
 // under the License.
 
 import { Button, Divider, Form, Input, message, Modal, PageHeader, Row, Space, 
Steps, Table } from 'antd';
-import React, { useContext, useMemo, useRef, useState } from 'react';
+import React, { useContext, useMemo, useRef, useState, useEffect } from 
'react';
 import ProCard from '@ant-design/pro-card';
 import { NewSpaceInfoContext, UserInfoContext } from 
'@src/common/common.context';
-import {NodeList} from './node-list/node-list';
+import { NodeList } from './node-list/node-list';
 
 const { TextArea } = Input;
 
 export function AddNode(props: any) {
     const userInfo = useContext(UserInfoContext);
-    const {form} = useContext(NewSpaceInfoContext);
+    const { reqInfo, form } = useContext(NewSpaceInfoContext);
+    useEffect(() => {
+        const { sshUser, sshPort, sshKey } = reqInfo.authInfo || {};
+        form.setFieldsValue({
+            ...form.getFieldsValue(),
+            sshUser,
+            sshPort,
+            sshKey,
+            hosts: reqInfo.hosts,
+        });
+    }, [form, reqInfo.authInfo, reqInfo.hosts]);
     return (
         <ProCard title={<h2>添加节点</h2>} headerBordered>
             <PageHeader className="site-page-header" title="SSH信任" style={{ 
paddingLeft: 0 }} />
-            
<span>请提前完成Manager节点与其他节点间SSH信任,并在下方填入Manager节点的SSH信息。<a>如何进行SSH信任?</a></span>
+            <span>
+                
请提前完成Manager节点与其他节点间SSH信任,并在下方填入Manager节点的SSH信息。<a>如何进行SSH信任?</a>
+            </span>
             <Divider style={{ margin: 0, marginBottom: 24 }} />
-            <Form
-                form={form}
-                name="basic"
-                labelCol={{ span: 2 }}
-                wrapperCol={{ span: 10 }}
-                initialValues={{
-                    remember: true,
-                    user: 'root',
-                    sshPort: 8022,
-                    sshKey: '',
-                    installDir: '/usr/local/doris',
-                    packageUrl: 
'http://172.16.0.4:8002/PALO-0.15.1-rc09-binary.tar.gz',
-                }}
-                autoComplete="off"
-            >
+            <Form form={form} name="basic" labelCol={{ span: 2 }} 
wrapperCol={{ span: 10 }} autoComplete="off">
                 <Form.Item label="SSH用户" name="sshUser" rules={[{ required: 
true, message: '请输入SSH用户!' }]}>
                     <Input />
                 </Form.Item>
@@ -57,7 +55,7 @@ export function AddNode(props: any) {
                 </Form.Item>
                 <PageHeader className="site-page-header" title="节点列表" style={{ 
paddingLeft: 0 }} />
                 <Divider style={{ margin: 0, marginBottom: 24 }} />
-                <Form.Item name="hosts" style={{width: '100%'}} 
wrapperCol={{span: 24}}>
+                <Form.Item name="hosts" style={{ width: '100%' }} 
wrapperCol={{ span: 24 }}>
                     <NodeList />
                 </Form.Item>
             </Form>
diff --git 
a/frontend/src/routes/space/new-cluster/steps/add-node/node-list/node-list.tsx 
b/frontend/src/routes/space/new-cluster/steps/add-node/node-list/node-list.tsx
index 2e028d4..de8b204 100644
--- 
a/frontend/src/routes/space/new-cluster/steps/add-node/node-list/node-list.tsx
+++ 
b/frontend/src/routes/space/new-cluster/steps/add-node/node-list/node-list.tsx
@@ -16,7 +16,7 @@
 // under the License.
 
 import { EditableProTable, ProColumns } from '@ant-design/pro-table';
-import { Row, Button, Input, message, Modal } from 'antd';
+import { Row, Button, Input, message, Modal, InputRef } from 'antd';
 import TextArea from 'antd/lib/input/TextArea';
 import React, { useEffect, useRef, useState } from 'react';
 type DataSourceType = {
@@ -47,7 +47,9 @@ export function NodeList(props: { value?: any; onChange?: any 
}) {
         {
             title: 'IP地址',
             dataIndex: 'ip',
-            renderFormItem: (dom, rowData, index) => <IpInput 
value={rowData.ip} />,
+            renderFormItem: (dom, rowData, index) => {
+                return <IpInput value={rowData.record?.ip} 
id={rowData.record?.id as string} />;
+            },
             render: (dom, rowData, index) => {
                 return <span className="customRender">{`${rowData.ip}`}</span>;
             },
@@ -78,13 +80,14 @@ export function NodeList(props: { value?: any; onChange?: 
any }) {
     ];
 
     const IpInput: React.FC<{
+        id: string;
         value?: string;
         onChange?: (value: string) => void;
-    }> = ({ value, onChange }) => {
-        const ref = useRef<Input | null>(null);
+    }> = ({ value, id, onChange }) => {
+        const ref = useRef<InputRef | null>(null);
         const handleInputConfirm = (val: string) => {
             if (reg.test(val)) {
-                if (dataSource.filter(item => item.ip === val).length) {
+                if (dataSource.filter(item => item.ip === val && item.id !== 
id).length) {
                     message.error('此ip已存在!');
                 } else {
                     onChange?.(val);
@@ -106,7 +109,21 @@ export function NodeList(props: { value?: any; onChange?: 
any }) {
 
     useEffect(() => {
         props?.onChange(dataSource.map(item => item.ip));
-    }, [dataSource.length]);
+    }, [dataSource]);
+
+    useEffect(() => {
+        if (props.value && dataSource.length === 0) {
+            const dataSource = props.value.map((item: string, index: number) 
=> ({
+                id: index.toString(),
+                order: index + 1,
+                index,
+                ip: item,
+            }));
+            if (dataSource.length) {
+                setDataSource(dataSource);
+            }
+        }
+    }, [props.value]);
 
     function handleOk() {
         let baseLength = dataSource.length || 0;
diff --git 
a/frontend/src/routes/space/new-cluster/steps/cluster-deploy/cluster-deploy.tsx 
b/frontend/src/routes/space/new-cluster/steps/cluster-deploy/cluster-deploy.tsx
index 4efae58..3542362 100644
--- 
a/frontend/src/routes/space/new-cluster/steps/cluster-deploy/cluster-deploy.tsx
+++ 
b/frontend/src/routes/space/new-cluster/steps/cluster-deploy/cluster-deploy.tsx
@@ -85,14 +85,16 @@ export function ClusterDeploy(props: any) {
                 if (isSuccess(res)) {
                     const data: any[] = res.data;
                     setInstances(data);
-                    if (data.some(item => 
ERROR_STATUS.includes(item.operateStatus))) {
+                    const failedInstance = data.find(item => 
ERROR_STATUS.includes(item.operateStatus));
+                    if (failedInstance) {
+                        message.error(failedInstance.operateResult);
                         getClusterInstances.cancel();
                     }
                     if (
                         data.every(item => item.operateStatus === 
OperateStatusEnum.SUCCESS && item.operateStage === 3)
                     ) {
                         getClusterInstances.cancel();
-                        getJDBCReady.run(reqInfo.cluster_id)
+                        getJDBCReady.run(reqInfo.cluster_id);
                     }
                 }
             },
diff --git 
a/frontend/src/routes/space/new-cluster/steps/cluster-plan/cluster-plan.tsx 
b/frontend/src/routes/space/new-cluster/steps/cluster-plan/cluster-plan.tsx
index 4d2db95..049da81 100644
--- a/frontend/src/routes/space/new-cluster/steps/cluster-plan/cluster-plan.tsx
+++ b/frontend/src/routes/space/new-cluster/steps/cluster-plan/cluster-plan.tsx
@@ -35,7 +35,13 @@ const { confirm } = Modal;
 const { TabPane } = Tabs;
 
 export function ClusterPlan() {
-    const { form } = useContext(NewSpaceInfoContext);
+    const { form, reqInfo } = useContext(NewSpaceInfoContext);
+    useEffect(() => {
+        form.setFieldsValue({
+            ...form.getFieldsValue(),
+            nodeConfig: reqInfo.nodeConfig || [],
+        });
+    }, [form, reqInfo.nodeConfig]);
     return (
         <Form form={form} name="basic" labelCol={{ span: 2 }} wrapperCol={{ 
span: 10 }} autoComplete="off">
             <Form.Item name="nodeConfig" style={{ width: '100%' }} 
wrapperCol={{ span: 24 }}>
@@ -58,7 +64,7 @@ export function ClusterPlanContent(props: any) {
     const [mixMode, setMixMode] = useState(false);
     const [modal, setModal] = useRecoilState(modalState);
     const processID = useRecoilValue(processId);
-    const { data, run: runGetClusterNodes } = useAsync<any[]>({ data: [] });
+    const { data, run: runGetClusterNodes, loading } = useAsync<any[]>({ data: 
[] });
     const [modalAllData, setModalAllData] = useState<any[]>(data || []);
     const [activeKey, setActiveKey] = useState(DorisNodeTypeEnum.FE);
 
@@ -75,6 +81,42 @@ export function ClusterPlanContent(props: any) {
     }, [runGetClusterNodes, reqInfo.cluster_id]);
 
     useEffect(() => {
+        if (loading) return;
+        if (props.value && feData.length === 0 && beData.length === 0 && data) 
{
+            const feNodes = props.value.find((item: any) => 
item.moduleName.toUpperCase() === DorisNodeTypeEnum.FE);
+            const beNodes = props.value.find((item: any) => 
item.moduleName.toUpperCase() === DorisNodeTypeEnum.BE);
+            if (feNodes && feNodes.nodeIds && feNodes.nodeIds.length > 0) {
+                const feHosts = feNodes.nodeIds.map(
+                    (nodeId: number) => data.find(item => item.nodeId === 
nodeId)?.host,
+                );
+                setFeChecked(feNodes.nodeIds);
+                setFeData(
+                    feNodes.nodeIds.map((nodeId: number, index: number) => {
+                        return {
+                            nodeId: nodeId,
+                            host: feHosts[index],
+                        };
+                    }),
+                );
+            }
+            if (beNodes && beNodes.nodeIds && beNodes.nodeIds.length > 0) {
+                const beHosts = beNodes.nodeIds.map(
+                    (nodeId: number) => data.find(item => item.nodeId === 
nodeId)?.host,
+                );
+                setBeChecked(beNodes.nodeIds);
+                setBeData(
+                    beNodes.nodeIds.map((nodeId: number, index: number) => {
+                        return {
+                            nodeId: nodeId,
+                            host: beHosts[index],
+                        };
+                    }),
+                );
+            }
+        }
+    }, [props.value, data, loading]);
+
+    useEffect(() => {
         props?.onChange([
             {
                 moduleName: 'fe',
@@ -130,13 +172,13 @@ export function ClusterPlanContent(props: any) {
                 const feIndex = feData.findIndex(item => item.nodeId === 
record.nodeId);
                 feData.splice(feIndex, 1);
                 setFeData([...feData]);
-                setFeChecked(feChecked.filter(item => item !== record.host));
+                setFeChecked(feChecked.filter(item => item !== record.nodeId));
                 break;
             case 'be':
                 const beIndex = beData.findIndex(item => item.nodeId === 
record.nodeId);
                 beData.splice(beIndex, 1);
                 setBeData([...beData]);
-                setBeChecked(beChecked.filter(item => item !== record.host));
+                setBeChecked(beChecked.filter(item => item !== record.nodeId));
                 break;
             default:
                 break;
@@ -159,12 +201,12 @@ export function ClusterPlanContent(props: any) {
 
         if (roleType === DorisNodeTypeEnum.FE) {
             setFeChecked(selectedRowKeys);
-            let tempFeData = data?.filter(item => 
selectedRowKeys.includes(item.host));
+            let tempFeData = data?.filter(item => 
selectedRowKeys.includes(item.nodeId));
             setFeData(tempFeData || []);
         }
         if (roleType === DorisNodeTypeEnum.BE) {
             setBeChecked(selectedRowKeys);
-            let tempBeData = data?.filter(item => 
selectedRowKeys.includes(item.host));
+            let tempBeData = data?.filter(item => 
selectedRowKeys.includes(item.nodeId));
             setBeData(tempBeData || []);
         }
     };
@@ -243,7 +285,7 @@ export function ClusterPlanContent(props: any) {
                             rowSelection={rowSelection}
                             columns={nodeColumns}
                             dataSource={modalAllData}
-                            rowKey={'host'}
+                            rowKey={'nodeId'}
                         />
                     </>
                 </Modal>
diff --git 
a/frontend/src/routes/space/new-cluster/steps/install-options/install-options.tsx
 
b/frontend/src/routes/space/new-cluster/steps/install-options/install-options.tsx
index a238108..962b1a8 100644
--- 
a/frontend/src/routes/space/new-cluster/steps/install-options/install-options.tsx
+++ 
b/frontend/src/routes/space/new-cluster/steps/install-options/install-options.tsx
@@ -36,14 +36,6 @@ export function InstallOptions(props: any) {
                 name="basic"
                 labelCol={{ span: 2 }}
                 wrapperCol={{ span: 10 }}
-                initialValues={{
-                    remember: true,
-                    user: 'root',
-                    sshPort: 8022,
-                    sshKey: '',
-                    installDir: '/usr/local/doris',
-                    packageUrl: 
'http://10.193.215.27:8091/download/PALO-0.15.1-rc09-binary.tar.gz',
-                }}
                 autoComplete="off"
             >
                 <Form.Item label="代码包路径" name="packageUrl" rules={[{ required: 
true, message: '请输入安装路径' }]}>
@@ -59,9 +51,6 @@ export function InstallOptions(props: any) {
                 name="basic"
                 labelCol={{ span: 2 }}
                 wrapperCol={{ span: 10 }}
-                initialValues={{
-                    installDir: '/usr/local/doris',
-                }}
                 autoComplete="off"
             >
                 <Form.Item label="安装路径" name="installDir" rules={[{ required: 
true, message: '请输入安装路径' }]}>
diff --git a/frontend/src/routes/user-setting/index.module.less 
b/frontend/src/routes/space/space.utils.ts
similarity index 66%
copy from frontend/src/routes/user-setting/index.module.less
copy to frontend/src/routes/space/space.utils.ts
index 9d2eaba..00712e9 100644
--- a/frontend/src/routes/user-setting/index.module.less
+++ b/frontend/src/routes/space/space.utils.ts
@@ -14,29 +14,19 @@
 // KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
-.tabs {
-  transform: translate(35em, 0);
-}
 
-.input-gird {
-  margin: 0 auto;
-  width: 420px;
-  // padding: 32px;
- 
-  line-height: 24px;
-  background-color: #fff;
-  border-radius: 6px;
-  box-shadow: rgb(0 0 0 / 8%) 0 7px 20px;
-  transition: all 0.2s linear 0s;
+import { message } from 'antd';
 
-  input {
-    width: 100%;
-    padding: 0.75em;
-    background: '#e8f0fe';
-    border-radius: 4px;
-  }
+export function isVoid<T extends any>(val: T) {
+    if (val == null || val === '') return true;
+    if (Array.isArray(val)) return val.length === 0;
+    return false;
 }
 
-.input-pass {
-  background: '#e8f0fe';
+export function checkParam<T extends any>(param: T, errorMessage: string) {
+    const isValid = !isVoid(param);
+    if (!isValid) {
+        message.error(errorMessage);
+    }
+    return isValid;
 }
diff --git a/frontend/src/routes/user-setting/index.module.less 
b/frontend/src/routes/user-setting/index.module.less
index 9d2eaba..8751f12 100644
--- a/frontend/src/routes/user-setting/index.module.less
+++ b/frontend/src/routes/user-setting/index.module.less
@@ -26,7 +26,6 @@
   line-height: 24px;
   background-color: #fff;
   border-radius: 6px;
-  box-shadow: rgb(0 0 0 / 8%) 0 7px 20px;
   transition: all 0.2s linear 0s;
 
   input {

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to