You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hugegraph.apache.org by ji...@apache.org on 2022/05/10 14:49:14 UTC

[incubator-hugegraph-toolchain] branch master updated: feat:supplementary algorithms UI (#270)

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

jin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph-toolchain.git


The following commit(s) were added to refs/heads/master by this push:
     new 10c020c  feat:supplementary algorithms UI (#270)
10c020c is described below

commit 10c020cc2d952ce4a4e4a14e7cad48204bbedf5d
Author: Crayon <we...@gmail.com>
AuthorDate: Tue May 10 22:49:08 2022 +0800

    feat:supplementary algorithms UI (#270)
---
 .../graph-management/GraphManagementList.tsx       |   22 +-
 .../graph-management/GraphManagementSidebar.tsx    |   11 +-
 .../async-tasks/AsyncTaskList.less                 |    3 +-
 .../graph-management/async-tasks/AsyncTaskList.tsx |   17 +-
 .../graph-management/data-analyze/DataAnalyze.less |   92 +-
 .../graph-management/data-analyze/DataAnalyze.tsx  |    7 +-
 .../data-analyze/DataAnalyzeInfoDrawer.tsx         |    2 +-
 .../data-analyze/ExecLogAndQueryCollections.tsx    |  438 +++++-
 .../data-analyze/QueryAndAlgorithmLibrary.tsx      |  608 ++------
 .../data-analyze/algorithm/AllPath.tsx             |  118 +-
 .../data-analyze/algorithm/CustomPath.tsx          | 1098 ++++++++++++++
 .../data-analyze/algorithm/FocusDetection.tsx      |   86 +-
 .../data-analyze/algorithm/Jaccard.tsx             |  261 ++++
 .../algorithm/{ShortestPathAll.tsx => KHop.tsx}    |  307 ++--
 .../{LoopDetection.tsx => KStepNeighbor.tsx}       |  202 ++-
 .../data-analyze/algorithm/LoopDetection.tsx       |   59 +-
 .../data-analyze/algorithm/ModelSimilarity.tsx     | 1536 ++++++++++----------
 .../data-analyze/algorithm/NeighborRank.tsx        |  196 +--
 .../{ShortestPathAll.tsx => PersonalRank.tsx}      |  332 +++--
 ...rtestPathAll.tsx => RadiographicInspection.tsx} |  327 ++---
 .../{LoopDetection.tsx => SameNeighbor.tsx}        |  214 +--
 .../{ShortestPathAll.tsx => ShortestPath.tsx}      |  267 ++--
 .../data-analyze/algorithm/ShortestPathAll.tsx     |   70 +-
 ...ll.tsx => SingleSourceWeightedShortestPath.tsx} |  411 ++++--
 ...hortestPathAll.tsx => WeightedShortestPath.tsx} |  353 +++--
 .../data-analyze/query-result/GraphPopOver.tsx     |   52 +-
 .../query-result/QueryFilterOptions.tsx            |    2 +-
 .../data-analyze/query-result/QueryResult.tsx      |    4 -
 .../data-analyze/query-result/TableQueryResult.tsx |    4 +
 .../data-import/import-tasks/ImportTasks.less      |    5 -
 .../import-tasks/datamap-configs/EdgeMap.tsx       |   26 +-
 .../import-tasks/datamap-configs/FileConfigs.tsx   |    3 +
 .../import-tasks/datamap-configs/VertexMap.tsx     |   40 +-
 .../metadata-configs/MetadataConfigs.tsx           |   19 +-
 .../metadata-configs/edge-type/EdgeTypeList.tsx    |  202 +--
 .../metadata-configs/edge-type/ReuseEdgeTypes.tsx  |   70 +-
 .../graph-view/CheckAndEditEdge.tsx                |  114 +-
 .../graph-view/CheckAndEditVertex.tsx              |  108 +-
 .../metadata-configs/graph-view/CheckProperty.tsx  |    1 +
 .../metadata-configs/graph-view/CreateVertex.tsx   |  109 +-
 .../metadata-configs/graph-view/GraphView.less     |    7 +-
 .../metadata-configs/graph-view/GraphView.tsx      |   11 +-
 .../metadata-configs/property/ReuseProperties.tsx  |   48 +-
 .../vertex-type/ReuseVertexTypes.tsx               |   63 +-
 .../vertex-type/VertexTypeList.tsx                 |  174 ++-
 .../resources/en-US/graph-managment/addition.json  |    3 +-
 .../resources/zh-CN/graph-managment/addition.json  |    3 +-
 .../data-import/import-tasks/ImportTasks.json      |    3 +-
 .../zh-CN/graph-managment/dataAnalyze.json         |  449 +++++-
 hugegraph-hubble/hubble-fe/src/index.less          |    9 +-
 .../dataAnalyzeStore/algorithmAnalyzerStore.ts     | 1480 ++++++++++++++++---
 .../dataAnalyzeStore/dataAnalyzeStore.ts           |  612 +++++---
 .../dataImportStore/dataMapStore.ts                |   42 +-
 .../GraphManagementStore/graphManagementStore.ts   |   44 +-
 .../metadataConfigsStore/edgeTypeStore.ts          |  295 ++--
 .../metadataConfigsStore/graphViewStore.ts         |    9 +-
 .../metadataConfigsStore/metadataConfigsStore.ts   |   70 +-
 .../metadataConfigsStore/vertexTypeStore.ts        |  244 ++--
 .../factory/dataAnalyzeStore/algorithmStore.ts     |  284 +++-
 .../factory/dataAnalyzeStore/dataAnalyzeStore.ts   |    5 +
 .../types/GraphManagementStore/dataAnalyzeStore.ts |  134 +-
 .../hubble-fe/src/stores/utils/index.ts            |   18 +
 .../hubble-fe/src/utils/calcAlgorithmFormWidth.ts  |    7 +
 .../src/utils/filterEmptyAlgorightmParams.ts       |   19 +
 .../src/utils/formatAlgorithmStatement.ts          |  254 ++++
 hugegraph-hubble/hubble-fe/src/utils/index.ts      |   21 +-
 .../hubble-fe/src/utils/isDataTypeNumeric.ts       |   10 +
 67 files changed, 8098 insertions(+), 4016 deletions(-)

diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/GraphManagementList.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/GraphManagementList.tsx
index 73b5789..3b645c1 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/GraphManagementList.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/GraphManagementList.tsx
@@ -26,7 +26,6 @@ import HintIcon from '../../assets/imgs/ic_question_mark.svg';
 import { GraphData } from '../../stores/types/GraphManagementStore/graphManagementStore';
 import { useTranslation } from 'react-i18next';
 
-
 const commonInputProps = {
   size: 'medium',
   width: 420
@@ -234,7 +233,7 @@ const GraphManagementListItem: React.FC<
       value: 'delete'
     }
   ];
-  
+
   const disabledDropdownList = [
     {
       label: t('addition.common.edit'),
@@ -338,6 +337,9 @@ const GraphManagementListItem: React.FC<
                 'password',
                 'edit'
               )}
+              originInputProps={{
+                type: 'password'
+              }}
             />
           </div>
           <div>
@@ -368,7 +370,9 @@ const GraphManagementListItem: React.FC<
   ) : (
     <div className="graph-management-list" key={id}>
       <div className="graph-management-list-item">
-        <div className="graph-management-list-title">{t('addition.graphManagementList.id')}</div>
+        <div className="graph-management-list-title">
+          {t('addition.graphManagementList.id')}
+        </div>
         <div className="graph-management-list-data">
           <span title={name}>
             <Highlighter
@@ -381,7 +385,9 @@ const GraphManagementListItem: React.FC<
         </div>
       </div>
       <div className="graph-management-list-item">
-        <div className="graph-management-list-title">{t('addition.graphManagementList.name')}</div>
+        <div className="graph-management-list-title">
+          {t('addition.graphManagementList.name')}
+        </div>
         <div className="graph-management-list-data">
           <span title={graph}>
             <Highlighter
@@ -394,7 +400,9 @@ const GraphManagementListItem: React.FC<
         </div>
       </div>
       <div className="graph-management-list-item">
-        <div className="graph-management-list-title">{t('addition.graphManagementList.host')}</div>
+        <div className="graph-management-list-title">
+          {t('addition.graphManagementList.host')}
+        </div>
         <div className="graph-management-list-data" title={host}>
           {host}
         </div>
@@ -408,7 +416,9 @@ const GraphManagementListItem: React.FC<
         </div>
       </div>
       <div className="graph-management-list-item">
-        <div className="graph-management-list-title">{t('addition.graphManagementList.creation-time')}</div>
+        <div className="graph-management-list-title">
+          {t('addition.graphManagementList.creation-time')}
+        </div>
         <div className="graph-management-list-data" title={create_time}>
           {create_time}
         </div>
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/GraphManagementSidebar.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/GraphManagementSidebar.tsx
index 7363ea6..eb48501 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/GraphManagementSidebar.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/GraphManagementSidebar.tsx
@@ -10,7 +10,6 @@ import {
   ImportManagerStoreContext
 } from '../../stores';
 
-import BackIcon from '../../assets/imgs/ic_topback.svg';
 import ArrowIcon from '../../assets/imgs/ic_arrow_white.svg';
 import DataAnalyzeIconNormal from '../../assets/imgs/ic_shuju_normal.svg';
 import DataAnalyzeIconPressed from '../../assets/imgs/ic_shuju_pressed.svg';
@@ -43,11 +42,6 @@ const GraphManagementSidebar: React.FC = observer(() => {
     expand: graphManagementStore.isExpanded
   });
 
-  const sidebarGoBackClassName = classnames({
-    'data-analyze-sidebar-go-back': true,
-    expand: graphManagementStore.isExpanded
-  });
-
   const sidebarGraphSelectionClassName = classnames({
     'data-analyze-sidebar-graph-selection': true,
     expand: graphManagementStore.isExpanded
@@ -91,9 +85,8 @@ const GraphManagementSidebar: React.FC = observer(() => {
 
   const handleSelectId = useCallback(
     (value: string) => {
-      const id = graphManagementStore.idList.find(
-        ({ name }) => name === value
-      )!.id;
+      const id = graphManagementStore.idList.find(({ name }) => name === value)!
+        .id;
 
       dataAnalyzeStore.resetIdState();
       setLocation(`/graph-management/${id}/data-analyze`);
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/async-tasks/AsyncTaskList.less b/hugegraph-hubble/hubble-fe/src/components/graph-management/async-tasks/AsyncTaskList.less
index 7fa8e6e..b33bbe7 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/async-tasks/AsyncTaskList.less
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/async-tasks/AsyncTaskList.less
@@ -59,7 +59,8 @@
     line-height: 22px;
     text-align: center;
 
-    &.new,
+    &.scheduling,
+    &.scheduled,
     &.queued,
     &.restoring,
     &.running {
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/async-tasks/AsyncTaskList.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/async-tasks/AsyncTaskList.tsx
index 6a3f995..315dd30 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/async-tasks/AsyncTaskList.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/async-tasks/AsyncTaskList.tsx
@@ -10,14 +10,7 @@ import classnames from 'classnames';
 import { useRoute } from 'wouter';
 import { useTranslation } from 'react-i18next';
 import { isEmpty, size, intersection, without } from 'lodash-es';
-import {
-  Breadcrumb,
-  Input,
-  Button,
-  Message,
-  Table,
-  Loading
-} from 'hubble-ui';
+import { Breadcrumb, Input, Button, Message, Table, Loading } from 'hubble-ui';
 
 import {
   GraphManagementStoreContext,
@@ -151,7 +144,7 @@ const AsyncTaskList: React.FC = observer(() => {
             {t('async-tasks.table-filters.task-type.gremlin')}
           </div>
           <div onClick={handleFilterOptions('type', 'algorithm')}>
-            {t('async-tasks.table-filters.task-type.algorithm')}{' '}
+            {t('async-tasks.table-filters.task-type.algorithm')}
           </div>
           <div onClick={handleFilterOptions('type', 'remove_schema')}>
             {t('async-tasks.table-filters.task-type.remove-schema')}
@@ -231,6 +224,10 @@ const AsyncTaskList: React.FC = observer(() => {
           timeString += ' ' + restTime + 'ms';
         }
 
+        if (restTime <= 0) {
+          timeString = '0s';
+        }
+
         return <div className="no-line-break">{timeString}</div>;
       }
     },
@@ -412,7 +409,7 @@ const AsyncTaskList: React.FC = observer(() => {
         <div className="async-task-list-content-header">
           <Input.Search
             size="medium"
-            width={205}
+            width={215}
             placeholder={t('async-tasks.placeholders.search')}
             value={asyncTasksStore.searchWords}
             onChange={handleSearchChange}
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyze.less b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyze.less
index 559ac2d..76b6994 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyze.less
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyze.less
@@ -192,12 +192,33 @@
     }
   }
 
+  .query-tab-algorithm-wrapper,
   .query-tab-content-wrapper {
     padding: 16px;
     background: #fff;
     border-radius: 3px 3px 3px 3px;
   }
 
+  .query-tab-algorithm-wrapper {
+    // min-width: 1220px;
+    overflow: auto;
+
+    .new-fc-one-input-error.new-fc-one-input-error-right {
+      left: 0;
+      top: 30px;
+    }
+  }
+
+  .query-tab-algorithm-hint {
+    width: fit-content;
+    box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.15);
+    line-height: 18px;
+    padding: 16px;
+    color: #e64552;
+    font-size: 14px;
+    text-align: center;
+  }
+
   .query-tab-content {
     display: flex;
   }
@@ -238,15 +259,6 @@
         background-color: #f2f7ff;
         cursor: pointer;
       }
-
-      &.query-tab-content-menu-item-disabled {
-        color: #ccc;
-        cursor: not-allowed;
-
-        &:hover {
-          background-color: #fff;
-        }
-      }
     }
   }
 
@@ -303,10 +315,6 @@
     padding: 16px 8px;
     margin-bottom: 16px;
 
-    &-invalid {
-      border: 1px solid #e64552;
-    }
-
     &:last-child {
       margin-bottom: 0;
     }
@@ -322,6 +330,40 @@
     }
   }
 
+  .query-tab-content-internal-expand-row {
+    width: 390px;
+    display: flex;
+    // justify-content: space-between;
+    height: 32px;
+    margin-bottom: 16px;
+  }
+
+  .query-tab-content-internal-expand-input {
+    margin: 0 14px 0 16px;
+  }
+
+  .query-tab-content-internal-expand-manipulation {
+    &-enable,
+    &-disabled {
+      font-size: 14px;
+      line-height: 20px;
+      margin-bottom: 32px;
+      padding-left: 172px;
+
+      & span {
+        cursor: pointer;
+      }
+    }
+
+    &-enable {
+      color: #2b65ff;
+    }
+
+    &-disabled {
+      color: #999;
+    }
+  }
+
   .query-tab-code-edit {
     width: calc(100% - 55px);
 
@@ -441,6 +483,7 @@
       border-right: 1px solid #e0e0e0;
       display: flex;
       flex-direction: column;
+      overflow-y: auto;
 
       &-options {
         width: 61px;
@@ -595,6 +638,14 @@
         & > img {
           margin-bottom: 10px;
         }
+
+        & > span {
+          display: block;
+          width: 80%;
+          text-align: center;
+          max-height: 200px;
+          overflow: auto;
+        }
       }
     }
 
@@ -830,8 +881,12 @@
       }
 
       & > div {
-        flex-basis: 50%;
+        // flex-basis: 50%;
         line-height: 32px;
+
+        &:first-child {
+          width: 162px;
+        }
       }
     }
   }
@@ -1131,3 +1186,12 @@ div.vis-tooltip {
   pointer-events: none;
   z-index: 5;
 }
+
+// refer to index.less, this should be fixed in the future version
+.data-analyze-dynamic-add-options .new-fc-one-input-all-container {
+  position: relative;
+}
+
+.data-analyze-graph-node-info .new-fc-one-input-all-container {
+  position: relative;
+}
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyze.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyze.tsx
index cc65fdf..efa3cd3 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyze.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyze.tsx
@@ -44,6 +44,7 @@ const DataAnalyze: React.FC = observer(() => {
       dataAnalyzeStore.setCurrentId(Number(params.id));
       dataAnalyzeStore.fetchValueTypes();
       dataAnalyzeStore.fetchVertexTypes();
+      dataAnalyzeStore.fetchAllPropertyIndexes('vertex');
       dataAnalyzeStore.fetchEdgeTypes();
       dataAnalyzeStore.fetchAllNodeStyle();
       dataAnalyzeStore.fetchAllEdgeStyle();
@@ -70,9 +71,9 @@ const DataAnalyze: React.FC = observer(() => {
             {t('addition.dataAnalyze.return-home')}
           </Button>
         ]}
-        visible={Object.values(dataAnalyzeStore.errorInfo)
-          .map(({ code }) => code)
-          .includes(401)}
+        visible={graphManagementStore.graphData.some(
+          ({ id, enabled }) => dataAnalyzeStore.currentId === id && !enabled
+        )}
         destroyOnClose
         needCloseIcon={false}
       >
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyzeInfoDrawer.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyzeInfoDrawer.tsx
index eef6d43..541b97d 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyzeInfoDrawer.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/DataAnalyzeInfoDrawer.tsx
@@ -299,7 +299,7 @@ const DataAnalyzeInfoDrawer: React.FC = observer(() => {
                 marginTop: !isEdit ? 0 : nullableIndex === 0 ? 8 : 32
               }}
             >
-              <div>{key}: </div>
+              <div title={key}>{key}: </div>
               {!isEdit ? (
                 <div>{convertArrayToString(value)}</div>
               ) : (
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/ExecLogAndQueryCollections.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/ExecLogAndQueryCollections.tsx
index 23ed923..10aa402 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/ExecLogAndQueryCollections.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/ExecLogAndQueryCollections.tsx
@@ -1,10 +1,12 @@
 import React, { useState, useContext, useEffect, useCallback } from 'react';
 import { observer } from 'mobx-react';
 import classnames from 'classnames';
-import { isUndefined } from 'lodash-es';
+import { isUndefined, cloneDeep, isEmpty, isNull } from 'lodash-es';
 import Highlighter from 'react-highlight-words';
 import { useRoute, useLocation } from 'wouter';
 import { useTranslation } from 'react-i18next';
+
+import { v4 } from 'uuid';
 import { Table, Input, Button, Message } from 'hubble-ui';
 
 import { Tooltip } from '../../common';
@@ -13,16 +15,53 @@ import {
   DataAnalyzeStoreContext,
   AsyncTasksStoreContext
 } from '../../../stores';
+import { formatAlgorithmStatement } from '../../../utils';
 
-import type { TFunction } from 'i18next';
 import type {
   ExecutionLogs,
-  FavoriteQuery
+  FavoriteQuery,
+  LoopDetectionParams,
+  FocusDetectionParams,
+  ShortestPathAlgorithmParams,
+  ShortestPathAllAlgorithmParams,
+  AllPathAlgorithmParams,
+  KStepNeighbor,
+  KHop,
+  RadiographicInspection,
+  SameNeighbor,
+  Jaccard,
+  WeightedShortestPath,
+  SingleSourceWeightedShortestPath,
+  PersonalRank,
+  ModelSimilarityParams,
+  NeighborRankParams,
+  CustomPathParams,
+  CustomPathRule
 } from '../../../stores/types/GraphManagementStore/dataAnalyzeStore';
 import { Algorithm } from '../../../stores/factory/dataAnalyzeStore/algorithmStore';
 
 import ArrowIcon from '../../../assets/imgs/ic_arrow_16.svg';
 import EmptyIcon from '../../../assets/imgs/ic_sousuo_empty.svg';
+import { toJS } from 'mobx';
+
+export const AlgorithmInternalNameMapping: Record<string, string> = {
+  rings: 'loop-detection',
+  crosspoints: 'focus-detection',
+  shortpath: 'shortest-path',
+  allshortpath: 'shortest-path-all',
+  paths: 'all-path',
+  fsimilarity: 'model-similarity',
+  neighborrank: 'neighbor-rank',
+  kneighbor: 'k-step-neighbor',
+  kout: 'k-hop',
+  customizedpaths: 'custom-path',
+  rays: 'radiographic-inspection',
+  sameneighbors: 'same-neighbor',
+  weightedshortpath: 'weighted-shortest-path',
+  singleshortpath: 'single-source-weighted-shortest-path',
+  jaccardsimilarity: 'jaccard',
+  personalrank: 'personal-rank'
+};
 
 const styles = {
   tableCenter: {
@@ -39,6 +78,7 @@ const styles = {
 const ExecLogAndQueryCollections: React.FC = observer(() => {
   const asyncTasksStore = useContext(AsyncTasksStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStoreContext);
+  const { algorithmAnalyzerStore } = dataAnalyzeStore;
   const [tabIndex, setTabIndex] = useState(0);
   const [, params] = useRoute('/graph-management/:id/data-analyze');
   const { t } = useTranslation();
@@ -80,6 +120,7 @@ const ExecLogAndQueryCollections: React.FC = observer(() => {
           <ExecutionContent
             type={rowData.type}
             content={text}
+            algorithmName={rowData.algorithm_name}
             highlightText=""
           />
         );
@@ -208,7 +249,12 @@ const ExecLogAndQueryCollections: React.FC = observer(() => {
               className="exec-log-manipulation"
               onClick={loadStatements(
                 rowData.content,
-                rowData.type === 'GREMLIN_ASYNC' ? 'task' : 'query'
+                rowData.type === 'GREMLIN_ASYNC'
+                  ? 'task'
+                  : rowData.type === 'GREMLIN'
+                  ? 'query'
+                  : 'algorithm',
+                rowData.algorithm_name
               )}
             >
               {t('addition.operate.load-statement')}
@@ -383,8 +429,356 @@ const ExecLogAndQueryCollections: React.FC = observer(() => {
   );
 
   const loadStatements = useCallback(
-    (content: string, type?: 'query' | 'task') => () => {
+    (
+      content: string,
+      type?: 'query' | 'task' | 'algorithm',
+      algorithmName?: string
+    ) => () => {
       if (!dataAnalyzeStore.isLoadingGraph) {
+        if (type === 'algorithm') {
+          const params: Record<string, any> = JSON.parse(content);
+          dataAnalyzeStore.setCurrentTab('algorithm-analyze');
+
+          if (params.hasOwnProperty('direction')) {
+            params.direction = params.direction.toUpperCase();
+          }
+
+          if (params.hasOwnProperty('label')) {
+            params['label'] === null && (params['label'] = '__all__');
+          }
+
+          window.scrollTo(0, 0);
+
+          switch (algorithmName) {
+            case 'rings':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.loopDetection
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateLoopDetectionParams(
+                  key as keyof LoopDetectionParams,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'crosspoints':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.focusDetection
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateFocusDetectionParams(
+                  key as keyof FocusDetectionParams,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'shortpath':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.shortestPath
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateShortestPathParams(
+                  key as keyof ShortestPathAlgorithmParams,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'allshortpath':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.shortestPathAll
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateShortestPathAllParams(
+                  key as keyof ShortestPathAllAlgorithmParams,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'paths':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(Algorithm.allPath);
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateAllPathParams(
+                  key as keyof AllPathAlgorithmParams,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'fsimilarity': {
+              const clonedParams = cloneDeep(params);
+
+              if (isEmpty(params.sources.ids)) {
+                clonedParams.method = 'property';
+              } else {
+                clonedParams.method = 'id';
+              }
+
+              clonedParams.source = clonedParams.sources.ids.join(',');
+              clonedParams.vertexType = clonedParams.sources.label;
+              clonedParams.vertexProperty = Object.entries(
+                clonedParams.sources.properties
+              );
+
+              if (isEmpty(clonedParams.vertexProperty)) {
+                clonedParams.vertexProperty = [['', '']];
+              } else {
+                clonedParams.vertexProperty = clonedParams.vertexProperty.map(
+                  ([key, value]: [string, string[]]) => [key, value.join(',')]
+                );
+              }
+
+              clonedParams.least_neighbor = clonedParams.min_neighbors;
+              clonedParams.similarity = clonedParams.alpha;
+              clonedParams.least_similar = clonedParams.min_similars;
+              clonedParams.max_similar = clonedParams.top;
+              clonedParams.property_filter = clonedParams.group_property;
+              clonedParams.least_property_number = clonedParams.min_groups;
+              clonedParams.return_common_connection =
+                clonedParams.with_intermediary;
+              clonedParams.return_complete_info = clonedParams.with_vertex;
+
+              delete clonedParams.sources;
+              delete clonedParams.min_neighbors;
+              delete clonedParams.alpha;
+              delete clonedParams.min_similars;
+              delete clonedParams.top;
+              delete clonedParams.group_property;
+              delete clonedParams.min_groups;
+              delete clonedParams.with_intermediary;
+              delete clonedParams.with_vertex;
+
+              Object.keys(clonedParams).forEach((key) => {
+                algorithmAnalyzerStore.mutateModelSimilarityParams(
+                  key as keyof ModelSimilarityParams,
+                  clonedParams[key]
+                );
+              });
+
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.modelSimilarity
+              );
+
+              return;
+            }
+            case 'neighborrank': {
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.neighborRank
+              );
+
+              const clonedParams = cloneDeep(params) as NeighborRankParams;
+
+              // remove neighborrank validate rules first;
+              algorithmAnalyzerStore.removeValidateNeighborRankRule(0);
+              clonedParams.steps.forEach(({ labels }, index) => {
+                clonedParams.steps[index].uuid = v4();
+                // add neighborrank rule validation per each
+                algorithmAnalyzerStore.addValidateNeighborRankRule();
+
+                if (isEmpty(labels)) {
+                  clonedParams.steps[index].labels = ['__all__'];
+                }
+              });
+
+              Object.keys(clonedParams).forEach((key) => {
+                algorithmAnalyzerStore.mutateNeighborRankParams(
+                  key as keyof NeighborRankParams,
+                  // @ts-ignore
+                  clonedParams[key]
+                );
+              });
+
+              return;
+            }
+            case 'kneighbor':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.kStepNeighbor
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateKStepNeighborParams(
+                  key as keyof KStepNeighbor,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'kout':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(Algorithm.kHop);
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateKHopParams(
+                  key as keyof KHop,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'customizedpaths':
+              const clonedParams = cloneDeep(params);
+
+              if (isEmpty(params.sources.ids)) {
+                clonedParams.method = 'property';
+              } else {
+                clonedParams.method = 'id';
+              }
+              clonedParams.source = clonedParams.sources.ids.join(',');
+              clonedParams.vertexType = clonedParams.sources.label;
+              clonedParams.vertexProperty = Object.entries(
+                clonedParams.sources.properties
+              );
+
+              if (isEmpty(clonedParams.vertexProperty)) {
+                clonedParams.vertexProperty = [['', '']];
+              } else {
+                clonedParams.vertexProperty = clonedParams.vertexProperty.map(
+                  ([key, value]: [string, string[]]) => [key, value.join(',')]
+                );
+
+                clonedParams.vertexProperty = Object.keys(
+                  clonedParams.vertexProperty
+                ).map((key) => [
+                  key,
+                  clonedParams.vertexProperty[key].join(',')
+                ]);
+              }
+
+              clonedParams.steps.forEach((step: any, index: number) => {
+                const { labels, properties, weight_by, default_weight } = step;
+                clonedParams.steps[index].uuid = v4();
+
+                if (isEmpty(labels)) {
+                  step.labels = dataAnalyzeStore.edgeTypes.map(
+                    ({ name }) => name
+                  );
+                }
+
+                if (isEmpty(properties)) {
+                  step.properties = [['', '']];
+                } else {
+                  step.properties = Object.keys(step.properties).map((key) => [
+                    key,
+                    step.properties[key].join(',')
+                  ]);
+                }
+
+                if (clonedParams.sort_by === 'NONE') {
+                  step.weight_by = '';
+                  step.default_weight = '';
+                } else {
+                  if (!isNull(weight_by)) {
+                    step.default_weight = '';
+                  } else {
+                    // custom weight
+                    step.weight_by = '__CUSTOM_WEIGHT__';
+                    step.default_weight = default_weight;
+                  }
+                }
+              });
+
+              delete clonedParams.sources;
+
+              Object.keys(clonedParams).forEach((key) => {
+                algorithmAnalyzerStore.mutateCustomPathParams(
+                  key as keyof CustomPathParams,
+                  clonedParams[key]
+                );
+              });
+
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.customPath
+              );
+
+              return;
+            case 'rays':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.radiographicInspection
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateRadiographicInspectionParams(
+                  key as keyof RadiographicInspection,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'sameneighbors':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.sameNeighbor
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateSameNeighborParams(
+                  key as keyof SameNeighbor,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'weightedshortpath':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.weightedShortestPath
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateWeightedShortestPathParams(
+                  key as keyof WeightedShortestPath,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'singleshortpath':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.singleSourceWeightedShortestPath
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
+                  key as keyof SingleSourceWeightedShortestPath,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'jaccardsimilarity':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(Algorithm.jaccard);
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutateJaccardParams(
+                  key as keyof Jaccard,
+                  params[key]
+                );
+              });
+
+              return;
+            case 'personalrank':
+              algorithmAnalyzerStore.changeCurrentAlgorithm(
+                Algorithm.personalRankRecommendation
+              );
+
+              Object.keys(params).forEach((key) => {
+                algorithmAnalyzerStore.mutatePersonalRankParams(
+                  key as keyof PersonalRank,
+                  params[key]
+                );
+              });
+
+              return;
+            default:
+              return;
+          }
+        }
+
         if (!isUndefined(type)) {
           type === 'task'
             ? dataAnalyzeStore.setQueryMode('task')
@@ -556,13 +950,15 @@ const ExecutionContent: React.FC<{
   type: string;
   content: string;
   highlightText: string;
-}> = observer(({ type, content, highlightText }) => {
+  algorithmName?: string;
+}> = observer(({ type, content, highlightText, algorithmName }) => {
   const dataAnalyzeStore = useContext(DataAnalyzeStoreContext);
-  const { t } = useTranslation();
+  const { t, i18n } = useTranslation();
   const [isExpand, switchExpand] = useState(dataAnalyzeStore.isSearched.status);
+
   const statements =
     type === 'ALGORITHM'
-      ? formatAlgorithmStatement(content, Algorithm.shortestPath, t)
+      ? formatAlgorithmStatement(content, algorithmName, t, i18n)
       : content.split('\n').filter((statement) => statement !== '');
 
   const arrowIconClassName = classnames({
@@ -670,30 +1066,4 @@ export const DeleteConfirm: React.FC<DeleteConfirmProps> = observer(
   }
 );
 
-function formatAlgorithmStatement(
-  content: string,
-  algorithmType: string,
-  translator: TFunction
-) {
-  const convertedString = content
-    .replace(/^.*\(/, '')
-    .replace(/\)$/, '')
-    .replace(/ /g, '');
-  const statements: string[] = [
-    translator(`data-analyze.algorithm-list.${algorithmType}`)
-  ];
-
-  convertedString.split(',').forEach((item) => {
-    const [key, value] = item.split('=');
-
-    statements.push(
-      `${translator(
-        `data-analyze.algorithm-forms.shortest-path.options.${key}`
-      )} ${value}`
-    );
-  });
-
-  return statements;
-}
-
 export default ExecLogAndQueryCollections;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/QueryAndAlgorithmLibrary.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/QueryAndAlgorithmLibrary.tsx
index 0bfb56e..0fa932a 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/QueryAndAlgorithmLibrary.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/QueryAndAlgorithmLibrary.tsx
@@ -10,15 +10,7 @@ import { observer } from 'mobx-react';
 import CodeMirror from 'codemirror';
 import { useTranslation } from 'react-i18next';
 import classnames from 'classnames';
-import {
-  Button,
-  Tooltip,
-  Alert,
-  Dropdown,
-  Input,
-  Radio,
-  Select
-} from 'hubble-ui';
+import { Button, Tooltip, Alert, Dropdown } from 'hubble-ui';
 
 import 'codemirror/lib/codemirror.css';
 import 'react-popper-tooltip/dist/styles.css';
@@ -31,10 +23,20 @@ import { useMultiKeyPress } from '../../../hooks';
 
 import LoopDetection from './algorithm/LoopDetection';
 import FocusDetection from './algorithm/FocusDetection';
+import ShortestPath from './algorithm/ShortestPath';
 import ShortestPathAll from './algorithm/ShortestPathAll';
 import AllPath from './algorithm/AllPath';
 import ModelSimilarity from './algorithm/ModelSimilarity';
 import NeighborRank from './algorithm/NeighborRank';
+import KStepNeighbor from './algorithm/KStepNeighbor';
+import KHop from './algorithm/KHop';
+import CustomPath from './algorithm/CustomPath';
+import RadiographicInspection from './algorithm/RadiographicInspection';
+import SameNeighbor from './algorithm/SameNeighbor';
+import WeightedShortestPath from './algorithm/WeightedShortestPath';
+import SingleSourceWeightedShortestPath from './algorithm/SingleSourceWeightedShortestPath';
+import Jaccard from './algorithm/Jaccard';
+import PersonalRank from './algorithm/PersonalRank';
 
 import ArrowIcon from '../../../assets/imgs/ic_arrow_16.svg';
 import QuestionMarkIcon from '../../../assets/imgs/ic_question_mark.svg';
@@ -52,28 +54,32 @@ export const styles = {
 
 const codeRegexp = /[A-Za-z0-9]+/;
 
-const algorithmWhiteList: string[] = [
-  Algorithm.shortestPath,
-  Algorithm.loopDetection,
-  Algorithm.focusDetection,
-  Algorithm.shortestPathAll,
-  Algorithm.allPath,
-  Algorithm.modelSimilarity,
-  Algorithm.neighborRankRecommendation
-];
-
 const QueryAndAlgorithmLibrary: React.FC = observer(() => {
   const dataAnalyzeStore = useContext(DataAnalyzeStoreContext);
+  const { algorithmAnalyzerStore } = dataAnalyzeStore;
   const { t } = useTranslation();
 
   const handleTabChange = (tab: string) => () => {
     dataAnalyzeStore.resetSwitchTabState();
 
     if (tab !== dataAnalyzeStore.currentTab) {
+      // reset codeEditor value
       dataAnalyzeStore.mutateCodeEditorText('');
+
+      // reset default selection of edge labels
+      algorithmAnalyzerStore.mutateCustomPathRuleParams(
+        'labels',
+        dataAnalyzeStore.edgeTypes.map(({ name }) => name),
+        0
+      );
     }
 
     dataAnalyzeStore.setCurrentTab(tab);
+    // need manually set codeMirror text value to empty here
+    dataAnalyzeStore.codeEditorInstance?.setValue('');
+    // reset algorithm tab to list
+    algorithmAnalyzerStore.changeCurrentAlgorithm('');
+    algorithmAnalyzerStore.switchCollapse(false);
   };
 
   return (
@@ -202,6 +208,7 @@ export const GremlinQuery: React.FC = observer(() => {
         );
       };
 
+      dataAnalyzeStore.assignCodeEditorInstance(codeEditor.current);
       codeEditor.current.on('change', handleCodeEditorChange);
 
       reaction(
@@ -211,15 +218,6 @@ export const GremlinQuery: React.FC = observer(() => {
         }
       );
 
-      reaction(
-        () => dataAnalyzeStore.pulse,
-        () => {
-          (codeEditor.current as CodeMirror.Editor).setValue(
-            dataAnalyzeStore.codeEditorText
-          );
-        }
-      );
-
       return () => {
         (codeEditor.current as CodeMirror.Editor).off(
           'change',
@@ -229,6 +227,17 @@ export const GremlinQuery: React.FC = observer(() => {
     }
   }, [dataAnalyzeStore]);
 
+  // weird, mobx@reaction is not working when puluse changed, setValue()
+  // has no influence
+  useEffect(() => {
+    if (codeEditor?.current && dataAnalyzeStore.codeEditorText !== '') {
+      (codeEditor.current as CodeMirror.Editor).setValue(
+        dataAnalyzeStore.codeEditorText
+      );
+    }
+  }, [dataAnalyzeStore.pulse]);
+  // }, [dataAnalyzeStore.pulse, codeEditor?.current]);
+
   useEffect(() => {
     if (
       keyPressed.has('Tab') &&
@@ -429,465 +438,47 @@ export const AlgorithmQuery: React.FC = observer(() => {
     algorithmAnalyzerStore.shortestPathAlgorithmParams.max_depth !== '';
 
   const handleChangeAlgorithm = (algorithm: string) => () => {
-    // disable other algorithm now
-    if (algorithmWhiteList.includes(algorithm)) {
-      algorithmAnalyzerStore.changeCurrentAlgorithm(algorithm);
-    }
+    algorithmAnalyzerStore.changeCurrentAlgorithm(algorithm);
+  };
+
+  const handleExpandClick = () => {
+    algorithmAnalyzerStore.switchCollapse(!algorithmAnalyzerStore.isCollapse);
   };
 
   const renderForms = () => {
     switch (algorithmAnalyzerStore.currentAlgorithm) {
-      case Algorithm.shortestPath:
-        return (
-          <div className="query-tab-content-form">
-            <div className="query-tab-content-form-row">
-              <div className="query-tab-content-form-item">
-                <div className="query-tab-content-form-item-title">
-                  <i>*</i>
-                  <span>
-                    {t(
-                      'data-analyze.algorithm-forms.shortest-path.options.source'
-                    )}
-                  </span>
-                </div>
-                <Input
-                  width={400}
-                  size="medium"
-                  disabled={
-                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                  }
-                  placeholder={t(
-                    'data-analyze.algorithm-forms.shortest-path.placeholder.input-source-id'
-                  )}
-                  errorLocation="layer"
-                  errorMessage={
-                    algorithmAnalyzerStore
-                      .validateShortestPathParamsErrorMessage.source
-                  }
-                  value={
-                    algorithmAnalyzerStore.shortestPathAlgorithmParams.source
-                  }
-                  onChange={(e: any) => {
-                    algorithmAnalyzerStore.mutateShortestPathParams(
-                      'source',
-                      e.value as string
-                    );
-
-                    algorithmAnalyzerStore.validateShortestPathParams('source');
-                  }}
-                  originInputProps={{
-                    onBlur() {
-                      algorithmAnalyzerStore.validateShortestPathParams(
-                        'source'
-                      );
-                    }
-                  }}
-                />
-              </div>
-              <div className="query-tab-content-form-item">
-                <div className="query-tab-content-form-item-title">
-                  <span>
-                    {t(
-                      'data-analyze.algorithm-forms.shortest-path.options.label'
-                    )}
-                  </span>
-                </div>
-                <Select
-                  size="medium"
-                  trigger="click"
-                  value={
-                    algorithmAnalyzerStore.shortestPathAlgorithmParams.label
-                  }
-                  notFoundContent={t(
-                    'data-analyze.algorithm-forms.shortest-path.placeholder.no-edge-types'
-                  )}
-                  disabled={
-                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                  }
-                  width={400}
-                  onChange={(value: string) => {
-                    algorithmAnalyzerStore.mutateShortestPathParams(
-                      'label',
-                      value
-                    );
-                  }}
-                >
-                  <Select.Option value="__all__" key="__all__">
-                    {t('data-analyze.algorithm-forms.shortest-path.pre-value')}
-                  </Select.Option>
-                  {dataAnalyzeStore.edgeTypes.map(({ name }) => (
-                    <Select.Option value={name} key={name}>
-                      {name}
-                    </Select.Option>
-                  ))}
-                </Select>
-              </div>
-            </div>
-            <div className="query-tab-content-form-row">
-              <div className="query-tab-content-form-item">
-                <div className="query-tab-content-form-item-title">
-                  <i>*</i>
-                  <span>
-                    {t(
-                      'data-analyze.algorithm-forms.shortest-path.options.target'
-                    )}
-                  </span>
-                </div>
-                <Input
-                  width={400}
-                  size="medium"
-                  disabled={
-                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                  }
-                  placeholder={t(
-                    'data-analyze.algorithm-forms.shortest-path.placeholder.input-target-id'
-                  )}
-                  errorLocation="layer"
-                  errorMessage={
-                    algorithmAnalyzerStore
-                      .validateShortestPathParamsErrorMessage.target
-                  }
-                  value={
-                    algorithmAnalyzerStore.shortestPathAlgorithmParams.target
-                  }
-                  onChange={(e: any) => {
-                    algorithmAnalyzerStore.mutateShortestPathParams(
-                      'target',
-                      e.value as string
-                    );
-
-                    algorithmAnalyzerStore.validateShortestPathParams('target');
-                  }}
-                  originInputProps={{
-                    onBlur() {
-                      algorithmAnalyzerStore.validateShortestPathParams(
-                        'target'
-                      );
-                    }
-                  }}
-                />
-              </div>
-              <div className="query-tab-content-form-item">
-                <div className="query-tab-content-form-item-title">
-                  <span>
-                    {t(
-                      'data-analyze.algorithm-forms.shortest-path.options.max_degree'
-                    )}
-                  </span>
-                </div>
-                <Input
-                  width={400}
-                  size="medium"
-                  disabled={
-                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                  }
-                  placeholder={t(
-                    'data-analyze.algorithm-forms.shortest-path.placeholder.input-positive-integer'
-                  )}
-                  errorLocation="layer"
-                  errorMessage={
-                    algorithmAnalyzerStore
-                      .validateShortestPathParamsErrorMessage.max_degree
-                  }
-                  value={
-                    algorithmAnalyzerStore.shortestPathAlgorithmParams
-                      .max_degree
-                  }
-                  onChange={(e: any) => {
-                    algorithmAnalyzerStore.mutateShortestPathParams(
-                      'max_degree',
-                      e.value as string
-                    );
-
-                    algorithmAnalyzerStore.validateShortestPathParams(
-                      'max_degree'
-                    );
-                  }}
-                  originInputProps={{
-                    onBlur() {
-                      algorithmAnalyzerStore.validateShortestPathParams(
-                        'max_degree'
-                      );
-                    }
-                  }}
-                />
-              </div>
-            </div>
-            <div className="query-tab-content-form-row">
-              <div className="query-tab-content-form-item">
-                <div className="query-tab-content-form-item-title">
-                  <i>*</i>
-                  <span>
-                    {t(
-                      'data-analyze.algorithm-forms.shortest-path.options.direction'
-                    )}
-                  </span>
-                </div>
-                <Radio.Group
-                  disabled={
-                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                  }
-                  value={
-                    algorithmAnalyzerStore.shortestPathAlgorithmParams.direction
-                  }
-                  onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-                    algorithmAnalyzerStore.mutateShortestPathParams(
-                      'direction',
-                      e.target.value
-                    );
-                  }}
-                >
-                  <Radio value="BOTH">both</Radio>
-                  <Radio value="OUT">out</Radio>
-                  <Radio value="IN">in</Radio>
-                </Radio.Group>
-              </div>
-              <div className="query-tab-content-form-item">
-                <div className="query-tab-content-form-item-title">
-                  <span>
-                    {t(
-                      'data-analyze.algorithm-forms.shortest-path.options.skip_degree'
-                    )}
-                  </span>
-                  <CustomTooltip
-                    trigger="hover"
-                    placement="bottom-start"
-                    modifiers={{
-                      offset: {
-                        offset: '0, 8'
-                      }
-                    }}
-                    tooltipWrapperProps={{
-                      className: 'tooltips-dark',
-                      style: {
-                        zIndex: 7
-                      }
-                    }}
-                    tooltipWrapper={t(
-                      'data-analyze.algorithm-forms.shortest-path.hint.skip-degree'
-                    )}
-                    childrenProps={{
-                      src: QuestionMarkIcon,
-                      alt: 'hint',
-                      style: {
-                        marginLeft: 5
-                      }
-                    }}
-                    childrenWrapperElement="img"
-                  />
-                </div>
-                <Input
-                  width={400}
-                  size="medium"
-                  disabled={
-                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                  }
-                  placeholder={t(
-                    'data-analyze.algorithm-forms.shortest-path.placeholder.input-integer'
-                  )}
-                  errorLocation="layer"
-                  errorMessage={
-                    algorithmAnalyzerStore
-                      .validateShortestPathParamsErrorMessage.skip_degree
-                  }
-                  value={
-                    algorithmAnalyzerStore.shortestPathAlgorithmParams
-                      .skip_degree
-                  }
-                  onChange={(e: any) => {
-                    algorithmAnalyzerStore.mutateShortestPathParams(
-                      'skip_degree',
-                      e.value as string
-                    );
-
-                    algorithmAnalyzerStore.validateShortestPathParams(
-                      'skip_degree'
-                    );
-                  }}
-                  originInputProps={{
-                    onBlur() {
-                      algorithmAnalyzerStore.validateShortestPathParams(
-                        'skip_degree'
-                      );
-                    }
-                  }}
-                />
-              </div>
-            </div>
-            <div className="query-tab-content-form-row">
-              <div className="query-tab-content-form-item">
-                <div className="query-tab-content-form-item-title">
-                  <i>*</i>
-                  <span>
-                    {t(
-                      'data-analyze.algorithm-forms.shortest-path.options.max_depth'
-                    )}
-                  </span>
-                  <CustomTooltip
-                    trigger="hover"
-                    placement="bottom-start"
-                    modifiers={{
-                      offset: {
-                        offset: '0, 8'
-                      }
-                    }}
-                    tooltipWrapperProps={{
-                      className: 'tooltips-dark',
-                      style: {
-                        zIndex: 7
-                      }
-                    }}
-                    tooltipWrapper={t(
-                      'data-analyze.algorithm-forms.shortest-path.hint.max-depth'
-                    )}
-                    childrenProps={{
-                      src: QuestionMarkIcon,
-                      alt: 'hint',
-                      style: {
-                        marginLeft: 5
-                      }
-                    }}
-                    childrenWrapperElement="img"
-                  />
-                </div>
-                <Input
-                  width={400}
-                  size="medium"
-                  disabled={
-                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                  }
-                  placeholder={t(
-                    'data-analyze.algorithm-forms.shortest-path.placeholder.input-positive-integer'
-                  )}
-                  errorLocation="layer"
-                  errorMessage={
-                    algorithmAnalyzerStore
-                      .validateShortestPathParamsErrorMessage.max_depth
-                  }
-                  value={
-                    algorithmAnalyzerStore.shortestPathAlgorithmParams.max_depth
-                  }
-                  onChange={(e: any) => {
-                    algorithmAnalyzerStore.mutateShortestPathParams(
-                      'max_depth',
-                      e.value as string
-                    );
-
-                    algorithmAnalyzerStore.validateShortestPathParams(
-                      'max_depth'
-                    );
-                  }}
-                  originInputProps={{
-                    onBlur() {
-                      algorithmAnalyzerStore.validateShortestPathParams(
-                        'max_depth'
-                      );
-                    }
-                  }}
-                />
-              </div>
-              <div className="query-tab-content-form-item">
-                <div className="query-tab-content-form-item-title">
-                  <span>
-                    {t(
-                      'data-analyze.algorithm-forms.shortest-path.options.capacity'
-                    )}
-                  </span>
-                </div>
-                <Input
-                  width={400}
-                  size="medium"
-                  disabled={
-                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                  }
-                  placeholder={t(
-                    'data-analyze.algorithm-forms.shortest-path.placeholder.input-positive-integer'
-                  )}
-                  errorLocation="layer"
-                  errorMessage={
-                    algorithmAnalyzerStore
-                      .validateShortestPathParamsErrorMessage.capacity
-                  }
-                  value={
-                    algorithmAnalyzerStore.shortestPathAlgorithmParams.capacity
-                  }
-                  onChange={(e: any) => {
-                    algorithmAnalyzerStore.mutateShortestPathParams(
-                      'capacity',
-                      e.value as string
-                    );
-
-                    algorithmAnalyzerStore.validateShortestPathParams(
-                      'capacity'
-                    );
-                  }}
-                  originInputProps={{
-                    onBlur() {
-                      algorithmAnalyzerStore.validateShortestPathParams(
-                        'capacity'
-                      );
-                    }
-                  }}
-                />
-              </div>
-            </div>
-            <div
-              className="query-tab-content-form-row"
-              style={{ marginLeft: 92, justifyContent: 'flex-start' }}
-            >
-              <Button
-                type="primary"
-                style={styles.primaryButton}
-                disabled={
-                  !isValidExec ||
-                  dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                }
-                onClick={async () => {
-                  algorithmAnalyzerStore.switchCollapse(true);
-                  dataAnalyzeStore.switchGraphLoaded(false);
-
-                  const timerId = dataAnalyzeStore.addTempExecLog();
-                  await dataAnalyzeStore.fetchGraphs({
-                    url: 'shortpath',
-                    type: Algorithm.shortestPath
-                  });
-                  await dataAnalyzeStore.fetchExecutionLogs();
-                  window.clearTimeout(timerId);
-                }}
-              >
-                {t('data-analyze.manipulations.execution')}
-              </Button>
-              <Button
-                style={styles.primaryButton}
-                disabled={
-                  dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-                }
-                onClick={() => {
-                  algorithmAnalyzerStore.resetShortestPathParams();
-                  // temp solution
-                  algorithmAnalyzerStore.mutateShortestPathParams(
-                    'label',
-                    '__all__'
-                  );
-                }}
-              >
-                {t('data-analyze.manipulations.reset')}
-              </Button>
-            </div>
-          </div>
-        );
       case Algorithm.loopDetection:
         return <LoopDetection />;
       case Algorithm.focusDetection:
         return <FocusDetection />;
+      case Algorithm.shortestPath:
+        return <ShortestPath />;
       case Algorithm.shortestPathAll:
         return <ShortestPathAll />;
       case Algorithm.allPath:
         return <AllPath />;
       case Algorithm.modelSimilarity:
         return <ModelSimilarity />;
-      case Algorithm.neighborRankRecommendation:
+      case Algorithm.neighborRank:
         return <NeighborRank />;
+      case Algorithm.kStepNeighbor:
+        return <KStepNeighbor />;
+      case Algorithm.kHop:
+        return <KHop />;
+      case Algorithm.customPath:
+        return <CustomPath />;
+      case Algorithm.radiographicInspection:
+        return <RadiographicInspection />;
+      case Algorithm.sameNeighbor:
+        return <SameNeighbor />;
+      case Algorithm.weightedShortestPath:
+        return <WeightedShortestPath />;
+      case Algorithm.singleSourceWeightedShortestPath:
+        return <SingleSourceWeightedShortestPath />;
+      case Algorithm.jaccard:
+        return <Jaccard />;
+      case Algorithm.personalRankRecommendation:
+        return <PersonalRank />;
     }
   };
 
@@ -898,7 +489,7 @@ export const AlgorithmQuery: React.FC = observer(() => {
   }, []);
 
   return (
-    <div className="query-tab-content-wrapper">
+    <div className="query-tab-algorithm-wrapper">
       <div className="query-tab-content-title">
         {algorithmAnalyzerStore.currentAlgorithm === '' ? (
           <span>{t('data-analyze.algorithm-list.title')}</span>
@@ -912,16 +503,21 @@ export const AlgorithmQuery: React.FC = observer(() => {
                 marginRight: 12
               }}
               onClick={() => {
-                algorithmAnalyzerStore.dispose();
+                algorithmAnalyzerStore.switchCollapse(false);
+                algorithmAnalyzerStore.changeCurrentAlgorithm('');
               }}
             />
-            <span>
+            <span onClick={handleExpandClick} style={{ cursor: 'pointer' }}>
               {t(
                 `data-analyze.algorithm-list.${algorithmAnalyzerStore.currentAlgorithm}`
               )}
             </span>
           </div>
         )}
+        <div
+          style={{ flex: 'auto', height: 24, cursor: 'pointer' }}
+          onClick={handleExpandClick}
+        ></div>
         <img
           src={ArrowIcon}
           alt="expand-collpase"
@@ -930,11 +526,7 @@ export const AlgorithmQuery: React.FC = observer(() => {
               ? 'rotate(0deg)'
               : 'rotate(180deg)'
           }}
-          onClick={() => {
-            algorithmAnalyzerStore.switchCollapse(
-              !algorithmAnalyzerStore.isCollapse
-            );
-          }}
+          onClick={handleExpandClick}
         />
       </div>
       {algorithmAnalyzerStore.isCollapse ? null : algorithmAnalyzerStore.currentAlgorithm ===
@@ -948,14 +540,7 @@ export const AlgorithmQuery: React.FC = observer(() => {
               Algorithm.shortestPathAll,
               Algorithm.allPath
             ].map((algorithm) => (
-              <span
-                className={
-                  algorithmWhiteList.includes(algorithm)
-                    ? ''
-                    : 'query-tab-content-menu-item-disabled'
-                }
-                onClick={handleChangeAlgorithm(algorithm)}
-              >
+              <span onClick={handleChangeAlgorithm(algorithm)} key={algorithm}>
                 {t(`data-analyze.algorithm-list.${algorithm}`)}
               </span>
             ))}
@@ -963,57 +548,32 @@ export const AlgorithmQuery: React.FC = observer(() => {
           <div className="query-tab-content-menu">
             {[
               Algorithm.modelSimilarity,
-              Algorithm.neighborRankRecommendation,
-              Algorithm.realTimeRecommendation,
+              Algorithm.neighborRank,
               Algorithm.kStepNeighbor,
-              Algorithm.kHop
+              Algorithm.kHop,
+              Algorithm.customPath
             ].map((algorithm) => (
-              <span
-                className={
-                  algorithmWhiteList.includes(algorithm)
-                    ? ''
-                    : 'query-tab-content-menu-item-disabled'
-                }
-                onClick={handleChangeAlgorithm(algorithm)}
-              >
+              <span onClick={handleChangeAlgorithm(algorithm)} key={algorithm}>
                 {t(`data-analyze.algorithm-list.${algorithm}`)}
               </span>
             ))}
           </div>
           <div className="query-tab-content-menu">
             {[
-              Algorithm.customPath,
-              Algorithm.customIntersectionDetection,
               Algorithm.radiographicInspection,
-              Algorithm.commonNeighbor,
-              Algorithm.weightedShortestPath
+              Algorithm.sameNeighbor,
+              Algorithm.weightedShortestPath,
+              Algorithm.singleSourceWeightedShortestPath,
+              Algorithm.jaccard
             ].map((algorithm) => (
-              <span
-                className={
-                  algorithmWhiteList.includes(algorithm)
-                    ? ''
-                    : 'query-tab-content-menu-item-disabled'
-                }
-                onClick={handleChangeAlgorithm(algorithm)}
-              >
+              <span onClick={handleChangeAlgorithm(algorithm)} key={algorithm}>
                 {t(`data-analyze.algorithm-list.${algorithm}`)}
               </span>
             ))}
           </div>
           <div className="query-tab-content-menu">
-            {[
-              Algorithm.singleSourceWeightedPath,
-              Algorithm.jaccardSimilarity,
-              Algorithm.personalRankRecommendation
-            ].map((algorithm) => (
-              <span
-                className={
-                  algorithmWhiteList.includes(algorithm)
-                    ? ''
-                    : 'query-tab-content-menu-item-disabled'
-                }
-                onClick={() => {}}
-              >
+            {[Algorithm.personalRankRecommendation].map((algorithm) => (
+              <span onClick={handleChangeAlgorithm(algorithm)} key={algorithm}>
                 {t(`data-analyze.algorithm-list.${algorithm}`)}
               </span>
             ))}
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/AllPath.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/AllPath.tsx
index aab733e..cfc7f6d 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/AllPath.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/AllPath.tsx
@@ -1,23 +1,37 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
-import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
+import { Button, Radio, Input, Select } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
+
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { GraphManagementStoreContext } from '../../../../stores';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
 import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
 
 const AllPath = observer(() => {
-  const { t } = useTranslation();
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
 
-  const isValidExec = !Object.values(algorithmAnalyzerStore.allPathParams).some(
-    (value) => value === ''
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
   );
 
+  const isValidExec =
+    Object.values(
+      algorithmAnalyzerStore.validateAllPathParamsErrorMessage
+    ).every((value) => value === '') &&
+    algorithmAnalyzerStore.allPathParams.source !== '' &&
+    algorithmAnalyzerStore.allPathParams.target !== '' &&
+    algorithmAnalyzerStore.allPathParams.max_depth !== '';
+
   return (
     <div className="query-tab-content-form">
       <div className="query-tab-content-form-row">
@@ -25,15 +39,15 @@ const AllPath = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t('data-analyze.algorithm-forms.focus-detection.options.source')}
+              {t('data-analyze.algorithm-forms.all-path.options.source')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.all-path.placeholder.input-source-id'
             )}
             errorLocation="layer"
             errorMessage={
@@ -58,7 +72,7 @@ const AllPath = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t('data-analyze.algorithm-forms.focus-detection.options.label')}
+              {t('data-analyze.algorithm-forms.all-path.options.label')}
             </span>
           </div>
           <Select
@@ -66,16 +80,16 @@ const AllPath = observer(() => {
             trigger="click"
             value={algorithmAnalyzerStore.allPathParams.label}
             notFoundContent={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.no-edge-types'
+              'data-analyze.algorithm-forms.all-path.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
               algorithmAnalyzerStore.mutateAllPathParams('label', value);
             }}
           >
             <Select.Option value="__all__" key="__all__">
-              {t('data-analyze.algorithm-forms.focus-detection.pre-value')}
+              {t('data-analyze.algorithm-forms.all-path.pre-value')}
             </Select.Option>
             {dataAnalyzeStore.edgeTypes.map(({ name }) => (
               <Select.Option value={name} key={name}>
@@ -90,15 +104,15 @@ const AllPath = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t('data-analyze.algorithm-forms.focus-detection.options.target')}
+              {t('data-analyze.algorithm-forms.all-path.options.target')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.all-path.placeholder.input-target-id'
             )}
             errorLocation="layer"
             errorMessage={
@@ -123,17 +137,41 @@ const AllPath = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.focus-detection.options.max_degree'
-              )}
+              {t('data-analyze.algorithm-forms.all-path.options.max_degree')}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.all-path.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.input-integer'
+              'data-analyze.algorithm-forms.all-path.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
@@ -162,9 +200,7 @@ const AllPath = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.focus-detection.options.direction'
-              )}
+              {t('data-analyze.algorithm-forms.all-path.options.direction')}
             </span>
           </div>
           <Radio.Group
@@ -185,17 +221,15 @@ const AllPath = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.focus-detection.options.capacity'
-              )}
+              {t('data-analyze.algorithm-forms.all-path.options.capacity')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.all-path.placeholder.input-positive-integer-or-negative-one-capacity'
             )}
             errorLocation="layer"
             errorMessage={
@@ -223,9 +257,7 @@ const AllPath = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.focus-detection.options.max_depth'
-              )}
+              {t('data-analyze.algorithm-forms.all-path.options.max_depth')}
             </span>
             <CustomTooltip
               trigger="hover"
@@ -242,7 +274,7 @@ const AllPath = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.focus-detection.hint.max-depth'
+                'data-analyze.algorithm-forms.all-path.hint.max-depth'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -255,11 +287,11 @@ const AllPath = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.all-path.placeholder.input-positive-integer'
             )}
             errorLocation="layer"
             errorMessage={
@@ -284,34 +316,32 @@ const AllPath = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.focus-detection.options.capacity'
-              )}
+              {t('data-analyze.algorithm-forms.all-path.options.limit')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.all-path.placeholder.input-positive-integer-or-negative-one-limit'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateAllPathParamsErrorMessage.capacity
+              algorithmAnalyzerStore.validateAllPathParamsErrorMessage.limit
             }
-            value={algorithmAnalyzerStore.allPathParams.capacity}
+            value={algorithmAnalyzerStore.allPathParams.limit}
             onChange={(e: any) => {
               algorithmAnalyzerStore.mutateAllPathParams(
-                'capacity',
+                'limit',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateAllPathParams('capacity');
+              algorithmAnalyzerStore.validateAllPathParams('limit');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateAllPathParams('capacity');
+                algorithmAnalyzerStore.validateAllPathParams('limit');
               }
             }}
           />
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/CustomPath.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/CustomPath.tsx
new file mode 100644
index 0000000..92c3733
--- /dev/null
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/CustomPath.tsx
@@ -0,0 +1,1098 @@
+import React, { useContext } from 'react';
+import { observer } from 'mobx-react';
+import {
+  size,
+  flatten,
+  flattenDeep,
+  uniq,
+  isEmpty,
+  cloneDeep,
+  fromPairs
+} from 'lodash-es';
+import { Button, Radio, Input, Select } from 'hubble-ui';
+import { useTranslation } from 'react-i18next';
+
+import { styles } from '../QueryAndAlgorithmLibrary';
+import { GraphManagementStoreContext } from '../../../../stores';
+import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { isDataTypeNumeric, calcAlgorithmFormWidth } from '../../../../utils';
+
+const CustomPath = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
+  const dataAnalyzeStore = useContext(DataAnalyzeStore);
+  const { t } = useTranslation();
+  const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    390
+  );
+
+  const formWidthInStep = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    310,
+    380
+  );
+
+  const formSmallWidthInStep = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    150,
+    160
+  );
+
+  const sourceType = algorithmAnalyzerStore.customPathParams.method;
+
+  const allowAddNewProperty = !flatten(
+    algorithmAnalyzerStore.customPathParams.vertexProperty
+  ).some((value) => value === '');
+
+  const addNewPropertyClassName =
+    allowAddNewProperty &&
+    dataAnalyzeStore.requestStatus.fetchGraphs !== 'pending'
+      ? 'query-tab-content-internal-expand-manipulation-enable'
+      : 'query-tab-content-internal-expand-manipulation-disabled';
+
+  const allowAddNewRuleProperty = !flattenDeep(
+    algorithmAnalyzerStore.customPathParams.steps.map(
+      ({ properties }) => properties
+    )
+  ).some((value) => value === '');
+
+  const addNewRulePropertyClassName =
+    allowAddNewRuleProperty &&
+    dataAnalyzeStore.requestStatus.fetchGraphs !== 'pending'
+      ? 'query-tab-content-internal-expand-manipulation-enable'
+      : 'query-tab-content-internal-expand-manipulation-disabled';
+
+  const isValidSourceId =
+    algorithmAnalyzerStore.customPathParams.method === 'id' &&
+    algorithmAnalyzerStore.customPathParams.source !== '';
+
+  const isValidProperty =
+    algorithmAnalyzerStore.customPathParams.method === 'property' &&
+    !(
+      isEmpty(algorithmAnalyzerStore.customPathParams.vertexType) &&
+      flatten(
+        algorithmAnalyzerStore.customPathParams.vertexProperty
+      ).every((value) => isEmpty(value))
+    ) &&
+    algorithmAnalyzerStore.customPathParams.vertexProperty.every(
+      ([key, value]) => (!isEmpty(key) ? !isEmpty(value) : true)
+    );
+
+  const isValidateRuleProperties = algorithmAnalyzerStore.customPathParams.steps.every(
+    ({ properties }) => {
+      if (size(properties) === 1) {
+        return (
+          (isEmpty(properties[0][0]) && isEmpty(properties[0][1])) ||
+          (!isEmpty(properties[0][0]) && !isEmpty(properties[0][1]))
+        );
+      } else {
+        return properties.every(([, value]) => !isEmpty(value));
+      }
+    }
+  );
+
+  const isValidRuleWeight = algorithmAnalyzerStore.customPathParams.steps.every(
+    ({ weight_by, default_weight }) =>
+      algorithmAnalyzerStore.customPathParams.sort_by === 'NONE' ||
+      (weight_by === '__CUSTOM_WEIGHT__' && default_weight !== '') ||
+      (weight_by !== '__CUSTOM_WEIGHT__' && !isEmpty(weight_by))
+  );
+
+  const isValidExec =
+    Object.values(
+      algorithmAnalyzerStore.validateCustomPathParmasErrorMessage
+    ).every((value) => Array.isArray(value) || value === '') &&
+    algorithmAnalyzerStore.validateCustomPathParmasErrorMessage.steps.every(
+      (step) => Object.values(step).every((value) => value === '')
+    ) &&
+    (algorithmAnalyzerStore.customPathParams.method === 'id'
+      ? algorithmAnalyzerStore.customPathParams.source !== ''
+      : true) &&
+    (isValidSourceId || isValidProperty) &&
+    isValidateRuleProperties &&
+    isValidRuleWeight;
+
+  const isValidAddRule = algorithmAnalyzerStore.validateCustomPathParmasErrorMessage.steps.every(
+    (step) => Object.values(step).every((value) => value === '')
+  );
+
+  return (
+    <div style={{ display: 'flex' }}>
+      <div className="query-tab-content-form" style={{ width: '50%' }}>
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <i>*</i>
+              <span>
+                {t('data-analyze.algorithm-forms.custom-path.options.method')}
+              </span>
+            </div>
+            <Radio.Group
+              disabled={
+                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+              }
+              value={algorithmAnalyzerStore.customPathParams.method}
+              onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
+                algorithmAnalyzerStore.switchCustomPathMethod(e.target.value);
+              }}
+            >
+              <Radio value="id">
+                {t(
+                  'data-analyze.algorithm-forms.custom-path.radio-value.specific-id'
+                )}
+              </Radio>
+              <Radio value="property">
+                {t(
+                  'data-analyze.algorithm-forms.custom-path.radio-value.filtered-type-property'
+                )}
+              </Radio>
+            </Radio.Group>
+          </div>
+        </div>
+
+        {sourceType === 'id' && (
+          <div className="query-tab-content-form-row">
+            <div className="query-tab-content-form-item">
+              <div className="query-tab-content-form-item-title large">
+                <i>*</i>
+                <span>
+                  {t('data-analyze.algorithm-forms.custom-path.options.source')}
+                </span>
+              </div>
+
+              <Input
+                width={formWidth}
+                size="medium"
+                disabled={
+                  dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                }
+                placeholder={t(
+                  'data-analyze.algorithm-forms.custom-path.placeholder.input-source-id'
+                )}
+                errorLocation="layer"
+                errorMessage={
+                  algorithmAnalyzerStore.validateCustomPathParmasErrorMessage
+                    .source
+                }
+                value={algorithmAnalyzerStore.customPathParams.source}
+                onChange={(e: any) => {
+                  algorithmAnalyzerStore.mutateCustomPathParams(
+                    'source',
+                    e.value as string
+                  );
+
+                  algorithmAnalyzerStore.validateCustomPathParams('source');
+                }}
+                originInputProps={{
+                  onBlur() {
+                    algorithmAnalyzerStore.validateCustomPathParams('source');
+                  }
+                }}
+              />
+            </div>
+          </div>
+        )}
+
+        {sourceType !== 'id' && (
+          <>
+            <div className="query-tab-content-form-row">
+              <div className="query-tab-content-form-item">
+                <div className="query-tab-content-form-item-title large">
+                  <span>
+                    {t(
+                      'data-analyze.algorithm-forms.custom-path.options.vertex-type'
+                    )}
+                  </span>
+                </div>
+                <Select
+                  size="medium"
+                  trigger="click"
+                  selectorName={t(
+                    'data-analyze.algorithm-forms.custom-path.placeholder.select-vertex-type'
+                  )}
+                  value={algorithmAnalyzerStore.customPathParams.vertexType}
+                  notFoundContent={t(
+                    'data-analyze.algorithm-forms.custom-path.placeholder.no-vertex-type'
+                  )}
+                  disabled={
+                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                  }
+                  width={formWidth}
+                  onChange={(value: string) => {
+                    // switch property selections from properties of index to certain properties
+                    if (
+                      isEmpty(
+                        algorithmAnalyzerStore.customPathParams.vertexType
+                      )
+                    ) {
+                      algorithmAnalyzerStore.mutateCustomPathParams(
+                        'vertexProperty',
+                        [['', '']]
+                      );
+                    }
+
+                    algorithmAnalyzerStore.mutateCustomPathParams(
+                      'vertexType',
+                      value
+                    );
+                  }}
+                >
+                  {dataAnalyzeStore.vertexTypes.map(({ name }) => (
+                    <Select.Option value={name} key={name}>
+                      {name}
+                    </Select.Option>
+                  ))}
+                </Select>
+              </div>
+            </div>
+
+            <div
+              className="query-tab-content-form-row"
+              style={{ marginBottom: 0 }}
+            >
+              <div
+                className="query-tab-content-form-item"
+                style={{ alignItems: 'start' }}
+              >
+                <div
+                  className="query-tab-content-form-item-title large"
+                  style={{ lineHeight: '32px' }}
+                >
+                  <span>
+                    {t(
+                      'data-analyze.algorithm-forms.custom-path.options.vertex-property'
+                    )}
+                  </span>
+                </div>
+
+                <div>
+                  {algorithmAnalyzerStore.customPathParams.vertexProperty.map(
+                    ([key, value], propertyIndex) => {
+                      const currentVertexType = dataAnalyzeStore.vertexTypes.find(
+                        ({ name }) =>
+                          name ===
+                          algorithmAnalyzerStore.customPathParams.vertexType
+                      );
+
+                      return (
+                        <div className="query-tab-content-internal-expand-row">
+                          <Select
+                            width={161}
+                            size="medium"
+                            trigger="click"
+                            selectorName={t(
+                              'data-analyze.algorithm-forms.custom-path.placeholder.select-vertex-property'
+                            )}
+                            value={key}
+                            notFoundContent={t(
+                              'data-analyze.algorithm-forms.custom-path.placeholder.no-properties'
+                            )}
+                            disabled={
+                              dataAnalyzeStore.requestStatus.fetchGraphs ===
+                              'pending'
+                            }
+                            onChange={(value: string) => {
+                              const vertexProperty = cloneDeep(
+                                algorithmAnalyzerStore.customPathParams
+                                  .vertexProperty
+                              );
+
+                              vertexProperty[propertyIndex][0] = value;
+
+                              algorithmAnalyzerStore.mutateCustomPathParams(
+                                'vertexProperty',
+                                vertexProperty
+                              );
+                            }}
+                          >
+                            {!isEmpty(
+                              algorithmAnalyzerStore.customPathParams.vertexType
+                            )
+                              ? flatten(
+                                  currentVertexType?.property_indexes.map(
+                                    ({ fields }) => fields
+                                  )
+                                )
+                                  .concat(currentVertexType!.primary_keys)
+                                  .filter(
+                                    (property) =>
+                                      !algorithmAnalyzerStore.customPathParams.vertexProperty
+                                        .map(([key]) => key)
+                                        .includes(property)
+                                  )
+                                  .map((property) => (
+                                    <Select.Option
+                                      value={property}
+                                      key={property}
+                                    >
+                                      {property}
+                                    </Select.Option>
+                                  ))
+                              : algorithmAnalyzerStore.allPropertyIndexProperty.map(
+                                  (property) => (
+                                    <Select.Option
+                                      value={property}
+                                      key={property}
+                                    >
+                                      {property}
+                                    </Select.Option>
+                                  )
+                                )}
+                          </Select>
+                          <div className="query-tab-content-internal-expand-input">
+                            <Input
+                              width={161}
+                              size="medium"
+                              disabled={
+                                dataAnalyzeStore.requestStatus.fetchGraphs ===
+                                'pending'
+                              }
+                              placeholder={t(
+                                'data-analyze.algorithm-forms.custom-path.placeholder.input-multiple-properties'
+                              )}
+                              errorLocation="layer"
+                              errorMessage={
+                                algorithmAnalyzerStore
+                                  .validateCustomPathParmasErrorMessage
+                                  .vertexProperty
+                              }
+                              value={value}
+                              onChange={(e: any) => {
+                                const vertexProperty = cloneDeep(
+                                  algorithmAnalyzerStore.customPathParams
+                                    .vertexProperty
+                                );
+
+                                vertexProperty[propertyIndex][1] = e.value;
+
+                                algorithmAnalyzerStore.mutateCustomPathParams(
+                                  'vertexProperty',
+                                  vertexProperty
+                                );
+
+                                algorithmAnalyzerStore.validateCustomPathParams(
+                                  'vertexProperty'
+                                );
+                              }}
+                              originInputProps={{
+                                onBlur() {
+                                  algorithmAnalyzerStore.validateCustomPathParams(
+                                    'vertexProperty'
+                                  );
+                                }
+                              }}
+                            />
+                          </div>
+                          {size(
+                            algorithmAnalyzerStore.customPathParams
+                              .vertexProperty
+                          ) > 1 && (
+                            <div
+                              style={{
+                                fontSize: 14,
+                                lineHeight: '32px',
+                                color: '#2b65ff',
+                                cursor: 'pointer'
+                              }}
+                              onClick={() => {
+                                algorithmAnalyzerStore.removeCustomPathVertexProperty(
+                                  propertyIndex
+                                );
+                              }}
+                            >
+                              {t(
+                                'data-analyze.algorithm-forms.custom-path.delete'
+                              )}
+                            </div>
+                          )}
+                        </div>
+                      );
+                    }
+                  )}
+                </div>
+              </div>
+            </div>
+            {algorithmAnalyzerStore.customPathParams.vertexType === '' &&
+            !allowAddNewProperty &&
+            size(algorithmAnalyzerStore.customPathParams.vertexProperty) ===
+              1 ? (
+              <div
+                className="query-tab-algorithm-hint"
+                style={{ margin: '0 0 16px 172px' }}
+              >
+                <span>
+                  {t(
+                    'data-analyze.algorithm-forms.custom-path.hint.vertex_type_or_property'
+                  )}
+                </span>
+              </div>
+            ) : (
+              <div className={addNewPropertyClassName}>
+                <span
+                  onClick={() => {
+                    if (
+                      allowAddNewProperty &&
+                      dataAnalyzeStore.requestStatus.fetchGraphs !== 'pending'
+                    ) {
+                      algorithmAnalyzerStore.addCustomPathVertexProperty();
+                    }
+                  }}
+                >
+                  {t('data-analyze.algorithm-forms.custom-path.add')}
+                </span>
+              </div>
+            )}
+          </>
+        )}
+
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <i>*</i>
+              <span>
+                {t('data-analyze.algorithm-forms.custom-path.options.sort_by')}
+              </span>
+            </div>
+            <Radio.Group
+              disabled={
+                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+              }
+              value={algorithmAnalyzerStore.customPathParams.sort_by}
+              onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
+                algorithmAnalyzerStore.mutateCustomPathParams(
+                  'sort_by',
+                  e.target.value
+                );
+
+                if (e.target.value === 'NONE') {
+                  algorithmAnalyzerStore.customPathParams.steps.forEach(
+                    (_, ruleIndex) => {
+                      algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                        'weight_by',
+                        '',
+                        ruleIndex
+                      );
+
+                      algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                        'default_weight',
+                        '',
+                        ruleIndex
+                      );
+                    }
+                  );
+                }
+              }}
+            >
+              <Radio value="NONE">
+                {t('data-analyze.algorithm-forms.custom-path.radio-value.none')}
+              </Radio>
+              <Radio value="INCR">
+                {t(
+                  'data-analyze.algorithm-forms.custom-path.radio-value.ascend'
+                )}
+              </Radio>
+              <Radio value="DECR">
+                {t(
+                  'data-analyze.algorithm-forms.custom-path.radio-value.descend'
+                )}
+              </Radio>
+            </Radio.Group>
+          </div>
+        </div>
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t('data-analyze.algorithm-forms.custom-path.options.capacity')}
+              </span>
+            </div>
+            <Input
+              width={formWidth}
+              size="medium"
+              disabled={
+                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+              }
+              placeholder={t(
+                'data-analyze.algorithm-forms.custom-path.placeholder.input-positive-integer-or-negative-one-capacity'
+              )}
+              errorLocation="layer"
+              errorMessage={
+                algorithmAnalyzerStore.validateCustomPathParmasErrorMessage
+                  .capacity
+              }
+              value={algorithmAnalyzerStore.customPathParams.capacity}
+              onChange={(e: any) => {
+                algorithmAnalyzerStore.mutateCustomPathParams(
+                  'capacity',
+                  e.value as string
+                );
+
+                algorithmAnalyzerStore.validateCustomPathParams('capacity');
+              }}
+              originInputProps={{
+                onBlur() {
+                  algorithmAnalyzerStore.validateCustomPathParams('capacity');
+                }
+              }}
+            />
+          </div>
+        </div>
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t('data-analyze.algorithm-forms.custom-path.options.limit')}
+              </span>
+            </div>
+            <Input
+              width={formWidth}
+              size="medium"
+              disabled={
+                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+              }
+              placeholder={t(
+                'data-analyze.algorithm-forms.custom-path.placeholder.input-positive-integer-or-negative-one-limit'
+              )}
+              errorLocation="layer"
+              errorMessage={
+                algorithmAnalyzerStore.validateCustomPathParmasErrorMessage
+                  .limit
+              }
+              value={algorithmAnalyzerStore.customPathParams.limit}
+              onChange={(e: any) => {
+                algorithmAnalyzerStore.mutateCustomPathParams(
+                  'limit',
+                  e.value as string
+                );
+
+                algorithmAnalyzerStore.validateCustomPathParams('limit');
+              }}
+              originInputProps={{
+                onBlur() {
+                  algorithmAnalyzerStore.validateCustomPathParams('limit');
+                }
+              }}
+            />
+          </div>
+        </div>
+        <div
+          className="query-tab-content-form-row"
+          style={{ marginLeft: 92, justifyContent: 'flex-start' }}
+        >
+          <Button
+            type="primary"
+            style={styles.primaryButton}
+            disabled={
+              !isValidExec ||
+              dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+            }
+            onClick={async () => {
+              algorithmAnalyzerStore.switchCollapse(true);
+              dataAnalyzeStore.switchGraphLoaded(false);
+
+              const timerId = dataAnalyzeStore.addTempExecLog();
+              await dataAnalyzeStore.fetchGraphs({
+                url: 'customizedpaths',
+                type: Algorithm.customPath
+              });
+              await dataAnalyzeStore.fetchExecutionLogs();
+              window.clearTimeout(timerId);
+            }}
+          >
+            {t('data-analyze.manipulations.execution')}
+          </Button>
+          <Button
+            style={styles.primaryButton}
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            onClick={() => {
+              algorithmAnalyzerStore.resetCustomPathParams();
+            }}
+          >
+            {t('data-analyze.manipulations.reset')}
+          </Button>
+        </div>
+      </div>
+
+      <div
+        className="query-tab-content-form-expand-wrapper"
+        style={{ width: '50%' }}
+      >
+        {algorithmAnalyzerStore.customPathParams.steps.map(
+          (
+            {
+              uuid,
+              direction,
+              labels,
+              degree,
+              sample,
+              properties,
+              weight_by,
+              default_weight
+            },
+            ruleIndex
+          ) => {
+            return (
+              <div className="query-tab-content-form-expand-items" key={uuid}>
+                <div className="query-tab-content-form-expand-item">
+                  <div className="query-tab-content-form-item-title query-tab-content-form-expand-title">
+                    <i>*</i>
+                    <span>
+                      {t(
+                        'data-analyze.algorithm-forms.custom-path.options.direction'
+                      )}
+                    </span>
+                  </div>
+                  <Radio.Group
+                    disabled={
+                      dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                    }
+                    value={direction}
+                    onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
+                      algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                        'direction',
+                        e.target.value,
+                        ruleIndex
+                      );
+                    }}
+                  >
+                    <Radio value="BOTH">both</Radio>
+                    <Radio value="OUT">out</Radio>
+                    <Radio value="IN">in</Radio>
+                  </Radio.Group>
+                  {size(algorithmAnalyzerStore.customPathParams.steps) > 1 && (
+                    <div
+                      style={{
+                        marginLeft: 175,
+                        fontSize: 14,
+                        color: '#2b65ff',
+                        cursor: 'pointer',
+                        lineHeight: '22px'
+                      }}
+                      onClick={() => {
+                        algorithmAnalyzerStore.removeCustomPathRule(ruleIndex);
+                      }}
+                    >
+                      删除
+                    </div>
+                  )}
+                </div>
+                <div className="query-tab-content-form-expand-item">
+                  <div className="query-tab-content-form-item-title query-tab-content-form-expand-title">
+                    <span>
+                      {t(
+                        'data-analyze.algorithm-forms.custom-path.options.labels'
+                      )}
+                    </span>
+                  </div>
+                  <Select
+                    size="medium"
+                    trigger="click"
+                    value={labels}
+                    mode="multiple"
+                    showSearch={false}
+                    placeholder={t(
+                      'data-analyze.algorithm-forms.custom-path.placeholder.select-edge-type'
+                    )}
+                    notFoundContent={t(
+                      'data-analyze.algorithm-forms.custom-path.placeholder.no-edge-type'
+                    )}
+                    disabled={
+                      dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                    }
+                    width={formWidthInStep}
+                    onChange={(value: string[]) => {
+                      algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                        'labels',
+                        value,
+                        ruleIndex
+                      );
+                    }}
+                  >
+                    {dataAnalyzeStore.edgeTypes.map(({ name }) => (
+                      <Select.Option value={name} key={name}>
+                        {name}
+                      </Select.Option>
+                    ))}
+                  </Select>
+                </div>
+
+                <div
+                  className="query-tab-content-form-expand-item"
+                  style={{ alignItems: 'start', marginBottom: 16 }}
+                >
+                  <div
+                    className="query-tab-content-form-item-title query-tab-content-form-expand-title"
+                    style={{ lineHeight: '32px' }}
+                  >
+                    <span>
+                      {t(
+                        'data-analyze.algorithm-forms.custom-path.options.properties'
+                      )}
+                    </span>
+                  </div>
+                  <div>
+                    <>
+                      {properties.map(([key, value], propertyIndex) => {
+                        return (
+                          <div
+                            style={{ display: 'flex', marginBottom: 16 }}
+                            key={key}
+                          >
+                            <div style={{ marginRight: 8 }}>
+                              <Select
+                                size="medium"
+                                trigger="click"
+                                value={key}
+                                selectorName={t(
+                                  'data-analyze.algorithm-forms.custom-path.placeholder.select-edge-property'
+                                )}
+                                notFoundContent={t(
+                                  'data-analyze.algorithm-forms.custom-path.placeholder.no-edge-property'
+                                )}
+                                disabled={
+                                  dataAnalyzeStore.requestStatus.fetchGraphs ===
+                                  'pending'
+                                }
+                                width={formSmallWidthInStep}
+                                onChange={(value: string) => {
+                                  const clonedRuleProperties = cloneDeep(
+                                    properties
+                                  );
+
+                                  clonedRuleProperties[
+                                    propertyIndex
+                                  ][0] = value;
+
+                                  algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                                    'properties',
+                                    clonedRuleProperties,
+                                    ruleIndex
+                                  );
+                                }}
+                              >
+                                {uniq(
+                                  flatten(
+                                    dataAnalyzeStore.edgeTypes
+                                      .filter(({ name }) =>
+                                        labels.includes(name)
+                                      )
+                                      .map(({ properties }) =>
+                                        properties.map(({ name }) => name)
+                                      )
+                                  )
+                                )
+                                  .filter(
+                                    (name) =>
+                                      !Object.keys(
+                                        fromPairs(properties)
+                                      ).includes(name)
+                                  )
+                                  .map((name) => (
+                                    <Select.Option value={name} key={name}>
+                                      {name}
+                                    </Select.Option>
+                                  ))}
+                              </Select>
+                            </div>
+
+                            <div style={{ marginRight: 8 }}>
+                              <Input
+                                width={formSmallWidthInStep}
+                                size="medium"
+                                disabled={
+                                  dataAnalyzeStore.requestStatus.fetchGraphs ===
+                                  'pending'
+                                }
+                                placeholder={t(
+                                  'data-analyze.algorithm-forms.custom-path.placeholder.input-multiple-properties'
+                                )}
+                                value={value}
+                                onChange={(e: any) => {
+                                  const clonedRuleProperties = cloneDeep(
+                                    properties
+                                  );
+
+                                  clonedRuleProperties[propertyIndex][1] =
+                                    e.value;
+
+                                  algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                                    'properties',
+                                    clonedRuleProperties,
+                                    ruleIndex
+                                  );
+                                }}
+                              />
+                            </div>
+
+                            {size(properties) > 1 && (
+                              <div
+                                style={{
+                                  fontSize: 14,
+                                  lineHeight: '32px',
+                                  color: '#2b65ff',
+                                  cursor: 'pointer'
+                                }}
+                                onClick={() => {
+                                  algorithmAnalyzerStore.removeCustomPathRuleProperty(
+                                    ruleIndex,
+                                    propertyIndex
+                                  );
+                                }}
+                              >
+                                {t(
+                                  'data-analyze.algorithm-forms.custom-path.delete'
+                                )}
+                              </div>
+                            )}
+                          </div>
+                        );
+                      })}
+
+                      <div
+                        className={addNewRulePropertyClassName}
+                        style={{
+                          marginTop: 8,
+                          marginBottom: 0,
+                          paddingLeft: 0
+                        }}
+                      >
+                        <span
+                          onClick={() => {
+                            if (
+                              allowAddNewRuleProperty &&
+                              dataAnalyzeStore.requestStatus.fetchGraphs !==
+                                'pending'
+                            ) {
+                              algorithmAnalyzerStore.addCustomPathRuleProperty(
+                                ruleIndex
+                              );
+                            }
+                          }}
+                        >
+                          {t('data-analyze.algorithm-forms.custom-path.add')}
+                        </span>
+                      </div>
+                    </>
+                  </div>
+                </div>
+
+                {algorithmAnalyzerStore.customPathParams.sort_by !== 'NONE' && (
+                  <div className="query-tab-content-form-expand-item">
+                    <div className="query-tab-content-form-item-title query-tab-content-form-expand-title">
+                      <i>*</i>
+                      <span>
+                        {t(
+                          'data-analyze.algorithm-forms.custom-path.options.weight_by'
+                        )}
+                      </span>
+                    </div>
+                    <Select
+                      size="medium"
+                      trigger="click"
+                      value={weight_by}
+                      selectorName={t(
+                        'data-analyze.algorithm-forms.custom-path.placeholder.select-property'
+                      )}
+                      notFoundContent={t(
+                        'data-analyze.algorithm-forms.custom-path.placeholder.no-property'
+                      )}
+                      disabled={
+                        dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                      }
+                      width={formWidthInStep}
+                      onChange={(value: string) => {
+                        algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                          'weight_by',
+                          value,
+                          ruleIndex
+                        );
+                      }}
+                    >
+                      <Select.Option
+                        value="__CUSTOM_WEIGHT__"
+                        key="__CUSTOM_WEIGHT__"
+                      >
+                        {t(
+                          'data-analyze.algorithm-forms.custom-path.custom-weight'
+                        )}
+                      </Select.Option>
+                      {dataAnalyzeStore.allPropertiesFromEdge.map(
+                        (property) => (
+                          <Select.Option value={property} property={property}>
+                            {property}
+                          </Select.Option>
+                        )
+                      )}
+                    </Select>
+                  </div>
+                )}
+                {algorithmAnalyzerStore.customPathParams.steps[ruleIndex]
+                  .weight_by === '__CUSTOM_WEIGHT__' && (
+                  <div className="query-tab-content-form-expand-item">
+                    <div className="query-tab-content-form-item-title query-tab-content-form-expand-title">
+                      <span></span>
+                    </div>
+                    <Input
+                      width={formWidthInStep}
+                      size="medium"
+                      disabled={
+                        dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                      }
+                      placeholder={t(
+                        'data-analyze.algorithm-forms.custom-path.placeholder.input-number'
+                      )}
+                      errorLocation="layer"
+                      errorMessage={
+                        algorithmAnalyzerStore
+                          .validateCustomPathParmasErrorMessage.steps[ruleIndex]
+                          .default_weight
+                      }
+                      value={default_weight}
+                      onChange={(e: any) => {
+                        algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                          'default_weight',
+                          e.value as string,
+                          ruleIndex
+                        );
+
+                        algorithmAnalyzerStore.validateCustomPathRules(
+                          'default_weight',
+                          ruleIndex
+                        );
+                      }}
+                      originInputProps={{
+                        onBlur() {
+                          algorithmAnalyzerStore.validateCustomPathRules(
+                            'default_weight',
+                            ruleIndex
+                          );
+                        }
+                      }}
+                    />
+                  </div>
+                )}
+                <div className="query-tab-content-form-expand-item">
+                  <div className="query-tab-content-form-item-title query-tab-content-form-expand-title">
+                    <span>
+                      {t(
+                        'data-analyze.algorithm-forms.custom-path.options.degree'
+                      )}
+                    </span>
+                  </div>
+                  <Input
+                    width={formWidthInStep}
+                    size="medium"
+                    disabled={
+                      dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                    }
+                    placeholder={t(
+                      'data-analyze.algorithm-forms.custom-path.placeholder.input-positive-integer-or-negative-one-degree'
+                    )}
+                    errorLocation="layer"
+                    errorMessage={
+                      algorithmAnalyzerStore
+                        .validateCustomPathParmasErrorMessage.steps[ruleIndex]
+                        .degree
+                    }
+                    value={degree}
+                    onChange={(e: any) => {
+                      algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                        'degree',
+                        e.value as string,
+                        ruleIndex
+                      );
+
+                      algorithmAnalyzerStore.validateCustomPathRules(
+                        'degree',
+                        ruleIndex
+                      );
+                    }}
+                    originInputProps={{
+                      onBlur() {
+                        algorithmAnalyzerStore.validateCustomPathRules(
+                          'degree',
+                          ruleIndex
+                        );
+                      }
+                    }}
+                  />
+                </div>
+                <div className="query-tab-content-form-expand-item">
+                  <div className="query-tab-content-form-item-title query-tab-content-form-expand-title">
+                    <span>
+                      {t(
+                        'data-analyze.algorithm-forms.custom-path.options.sample'
+                      )}
+                    </span>
+                  </div>
+                  <Input
+                    width={formWidthInStep}
+                    size="medium"
+                    disabled={
+                      dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                    }
+                    placeholder={t(
+                      'data-analyze.algorithm-forms.custom-path.placeholder.input-integer'
+                    )}
+                    errorLocation="layer"
+                    errorMessage={
+                      algorithmAnalyzerStore
+                        .validateCustomPathParmasErrorMessage.steps[ruleIndex]
+                        .sample
+                    }
+                    value={sample}
+                    onChange={(e: any) => {
+                      algorithmAnalyzerStore.mutateCustomPathRuleParams(
+                        'sample',
+                        e.value as string,
+                        ruleIndex
+                      );
+
+                      algorithmAnalyzerStore.validateCustomPathRules(
+                        'sample',
+                        ruleIndex
+                      );
+                    }}
+                    originInputProps={{
+                      onBlur() {
+                        algorithmAnalyzerStore.validateCustomPathRules(
+                          'sample',
+                          ruleIndex
+                        );
+                      }
+                    }}
+                  />
+                </div>
+              </div>
+            );
+          }
+        )}
+        <div
+          style={{
+            width: 'fix-content',
+            fontSize: 14,
+            color: isValidAddRule ? '#2b65ff' : '#999',
+            marginTop: 8
+          }}
+        >
+          <span
+            style={{ cursor: 'pointer' }}
+            onClick={() => {
+              if (isValidAddRule) {
+                algorithmAnalyzerStore.addCustomPathRule();
+              }
+            }}
+          >
+            {t('data-analyze.algorithm-forms.custom-path.add-new-rule')}
+          </span>
+        </div>
+      </div>
+    </div>
+  );
+});
+
+export default CustomPath;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/FocusDetection.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/FocusDetection.tsx
index f73f592..cbf4e57 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/FocusDetection.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/FocusDetection.tsx
@@ -2,16 +2,26 @@ import React, { useContext, createContext } from 'react';
 import { observer } from 'mobx-react';
 import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
+
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { GraphManagementStoreContext } from '../../../../stores';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 const FocusDetection = observer(() => {
-  const { t } = useTranslation();
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
 
   const isValidExec =
     Object.values(
@@ -32,7 +42,7 @@ const FocusDetection = observer(() => {
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
@@ -73,7 +83,7 @@ const FocusDetection = observer(() => {
               'data-analyze.algorithm-forms.focus-detection.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
               algorithmAnalyzerStore.mutateFocusDetectionParams('label', value);
             }}
@@ -98,7 +108,7 @@ const FocusDetection = observer(() => {
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
@@ -132,13 +142,39 @@ const FocusDetection = observer(() => {
                 'data-analyze.algorithm-forms.focus-detection.options.max_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.focus-detection.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.input-integer'
+              'data-analyze.algorithm-forms.focus-detection.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
@@ -192,33 +228,35 @@ const FocusDetection = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t('data-analyze.algorithm-forms.focus-detection.options.limit')}
+              {t(
+                'data-analyze.algorithm-forms.focus-detection.options.capacity'
+              )}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.focus-detection.placeholder.input-positive-integer-or-negative-one-capacity'
             )}
             errorLocation="layer"
             errorMessage={
               algorithmAnalyzerStore.validateFocusDetectionParamsErrorMessage
-                .limit
+                .capacity
             }
-            value={algorithmAnalyzerStore.focusDetectionParams.limit}
+            value={algorithmAnalyzerStore.focusDetectionParams.capacity}
             onChange={(e: any) => {
               algorithmAnalyzerStore.mutateFocusDetectionParams(
-                'limit',
+                'capacity',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateFocusDetectionParams('limit');
+              algorithmAnalyzerStore.validateFocusDetectionParams('capacity');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateFocusDetectionParams('limit');
+                algorithmAnalyzerStore.validateFocusDetectionParams('capacity');
               }
             }}
           />
@@ -261,7 +299,7 @@ const FocusDetection = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
@@ -293,35 +331,33 @@ const FocusDetection = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.focus-detection.options.capacity'
-              )}
+              {t('data-analyze.algorithm-forms.focus-detection.options.limit')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.focus-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.focus-detection.placeholder.input-positive-integer-or-negative-one-limit'
             )}
             errorLocation="layer"
             errorMessage={
               algorithmAnalyzerStore.validateFocusDetectionParamsErrorMessage
-                .capacity
+                .limit
             }
-            value={algorithmAnalyzerStore.focusDetectionParams.capacity}
+            value={algorithmAnalyzerStore.focusDetectionParams.limit}
             onChange={(e: any) => {
               algorithmAnalyzerStore.mutateFocusDetectionParams(
-                'capacity',
+                'limit',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateFocusDetectionParams('capacity');
+              algorithmAnalyzerStore.validateFocusDetectionParams('limit');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateFocusDetectionParams('capacity');
+                algorithmAnalyzerStore.validateFocusDetectionParams('limit');
               }
             }}
           />
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/Jaccard.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/Jaccard.tsx
new file mode 100644
index 0000000..12764d5
--- /dev/null
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/Jaccard.tsx
@@ -0,0 +1,261 @@
+import React, { useContext } from 'react';
+import { observer } from 'mobx-react';
+import { Button, Radio, Input, Select } from 'hubble-ui';
+import { useTranslation } from 'react-i18next';
+
+import { styles } from '../QueryAndAlgorithmLibrary';
+import { Tooltip as CustomTooltip } from '../../../common';
+import { GraphManagementStoreContext } from '../../../../stores';
+import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
+
+import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
+
+const Jaccard = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
+  const dataAnalyzeStore = useContext(DataAnalyzeStore);
+  const { t } = useTranslation();
+  const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+
+  const isValidExec =
+    Object.values(
+      algorithmAnalyzerStore.validateJaccardParamsErrorMessage
+    ).every((value) => value === '') &&
+    algorithmAnalyzerStore.jaccardParams.vertex !== '' &&
+    algorithmAnalyzerStore.jaccardParams.other !== '';
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
+
+  return (
+    <div className="query-tab-content-form">
+      <div className="query-tab-content-form-row">
+        <div className="query-tab-content-form-item">
+          <div className="query-tab-content-form-item-title">
+            <i>*</i>
+            <span>
+              {t('data-analyze.algorithm-forms.jaccard.options.vertex')}
+            </span>
+          </div>
+          <Input
+            width={formWidth}
+            size="medium"
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            placeholder={t(
+              'data-analyze.algorithm-forms.jaccard.placeholder.input-source-id'
+            )}
+            errorLocation="layer"
+            errorMessage={
+              algorithmAnalyzerStore.validateJaccardParamsErrorMessage.vertex
+            }
+            value={algorithmAnalyzerStore.jaccardParams.vertex}
+            onChange={(e: any) => {
+              algorithmAnalyzerStore.mutateJaccardParams(
+                'vertex',
+                e.value as string
+              );
+
+              algorithmAnalyzerStore.validateJaccardParams('vertex');
+            }}
+            originInputProps={{
+              onBlur() {
+                algorithmAnalyzerStore.validateJaccardParams('vertex');
+              }
+            }}
+          />
+        </div>
+        <div className="query-tab-content-form-item">
+          <div className="query-tab-content-form-item-title">
+            <span>
+              {t('data-analyze.algorithm-forms.jaccard.options.label')}
+            </span>
+          </div>
+          <Select
+            size="medium"
+            trigger="click"
+            value={algorithmAnalyzerStore.jaccardParams.label}
+            notFoundContent={t(
+              'data-analyze.algorithm-forms.jaccard.placeholder.no-edge-types'
+            )}
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            width={formWidth}
+            onChange={(value: string) => {
+              algorithmAnalyzerStore.mutateJaccardParams('label', value);
+            }}
+          >
+            <Select.Option value="__all__" key="__all__">
+              {t('data-analyze.algorithm-forms.jaccard.pre-value')}
+            </Select.Option>
+            {dataAnalyzeStore.edgeTypes.map(({ name }) => (
+              <Select.Option value={name} key={name}>
+                {name}
+              </Select.Option>
+            ))}
+          </Select>
+        </div>
+      </div>
+      <div className="query-tab-content-form-row">
+        <div className="query-tab-content-form-item">
+          <div className="query-tab-content-form-item-title">
+            <i>*</i>
+            <span>
+              {t('data-analyze.algorithm-forms.jaccard.options.other')}
+            </span>
+          </div>
+          <Input
+            width={formWidth}
+            size="medium"
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            placeholder={t(
+              'data-analyze.algorithm-forms.jaccard.placeholder.input-other-id'
+            )}
+            errorLocation="layer"
+            errorMessage={
+              algorithmAnalyzerStore.validateJaccardParamsErrorMessage.other
+            }
+            value={algorithmAnalyzerStore.jaccardParams.other}
+            onChange={(e: any) => {
+              algorithmAnalyzerStore.mutateJaccardParams(
+                'other',
+                e.value as string
+              );
+
+              algorithmAnalyzerStore.validateJaccardParams('other');
+            }}
+            originInputProps={{
+              onBlur() {
+                algorithmAnalyzerStore.validateJaccardParams('other');
+              }
+            }}
+          />
+        </div>
+        <div className="query-tab-content-form-item">
+          <div className="query-tab-content-form-item-title">
+            <span>
+              {t('data-analyze.algorithm-forms.jaccard.options.max_degree')}
+            </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.jaccard.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
+          </div>
+          <Input
+            width={formWidth}
+            size="medium"
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            placeholder={t(
+              'data-analyze.algorithm-forms.jaccard.placeholder.input-positive-integer-or-negative-one-max-degree'
+            )}
+            errorLocation="layer"
+            errorMessage={
+              algorithmAnalyzerStore.validateJaccardParamsErrorMessage
+                .max_degree
+            }
+            value={algorithmAnalyzerStore.jaccardParams.max_degree}
+            onChange={(e: any) => {
+              algorithmAnalyzerStore.mutateJaccardParams(
+                'max_degree',
+                e.value as string
+              );
+
+              algorithmAnalyzerStore.validateJaccardParams('max_degree');
+            }}
+            originInputProps={{
+              onBlur() {
+                algorithmAnalyzerStore.validateJaccardParams('max_degree');
+              }
+            }}
+          />
+        </div>
+      </div>
+      <div className="query-tab-content-form-row">
+        <div className="query-tab-content-form-item">
+          <div className="query-tab-content-form-item-title">
+            <i>*</i>
+            <span>
+              {t('data-analyze.algorithm-forms.jaccard.options.direction')}
+            </span>
+          </div>
+          <Radio.Group
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            value={algorithmAnalyzerStore.jaccardParams.direction}
+            onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
+              algorithmAnalyzerStore.mutateJaccardParams(
+                'direction',
+                e.target.value
+              );
+            }}
+          >
+            <Radio value="BOTH">both</Radio>
+            <Radio value="OUT">out</Radio>
+            <Radio value="IN">in</Radio>
+          </Radio.Group>
+        </div>
+      </div>
+      <div
+        className="query-tab-content-form-row"
+        style={{ marginLeft: 92, justifyContent: 'flex-start' }}
+      >
+        <Button
+          type="primary"
+          style={styles.primaryButton}
+          disabled={
+            !isValidExec ||
+            dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+          }
+          onClick={async () => {
+            algorithmAnalyzerStore.switchCollapse(true);
+            dataAnalyzeStore.switchGraphLoaded(false);
+
+            const timerId = dataAnalyzeStore.addTempExecLog();
+            await dataAnalyzeStore.fetchGraphs({
+              url: 'jaccardsimilarity',
+              type: Algorithm.jaccard
+            });
+            await dataAnalyzeStore.fetchExecutionLogs();
+            window.clearTimeout(timerId);
+          }}
+        >
+          {t('data-analyze.manipulations.execution')}
+        </Button>
+        <Button
+          style={styles.primaryButton}
+          disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+          onClick={() => {
+            algorithmAnalyzerStore.resetJaccardParams();
+          }}
+        >
+          {t('data-analyze.manipulations.reset')}
+        </Button>
+      </div>
+    </div>
+  );
+});
+
+export default Jaccard;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/KHop.tsx
similarity index 59%
copy from hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
copy to hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/KHop.tsx
index 82ec79a..20d434e 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/KHop.tsx
@@ -1,22 +1,35 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
 import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
 import { styles } from '../QueryAndAlgorithmLibrary';
+
 import { Tooltip as CustomTooltip } from '../../../common';
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
-import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
 
-const ShortestPathAll = observer(() => {
-  const { t } = useTranslation();
+const KHop = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
 
-  const isValidExec = !Object.values(
-    algorithmAnalyzerStore.shortestPathAllParams
-  ).some((value) => value === '');
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
+
+  const isValidExec =
+    Object.values(algorithmAnalyzerStore.validateKHopParamsErrorMessage).every(
+      (value) => value === ''
+    ) &&
+    algorithmAnalyzerStore.kHopParams.source !== '' &&
+    algorithmAnalyzerStore.kHopParams.max_depth !== '';
 
   return (
     <div className="query-tab-content-form">
@@ -25,65 +38,55 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.source'
-              )}
+              {t('data-analyze.algorithm-forms.k-hop.options.source')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.k-hop.placeholder.input-source-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .source
+              algorithmAnalyzerStore.validateKHopParamsErrorMessage.source
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.source}
+            value={algorithmAnalyzerStore.kHopParams.source}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateKHopParams(
                 'source',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('source');
+              algorithmAnalyzerStore.validateKHopParams('source');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('source');
+                algorithmAnalyzerStore.validateKHopParams('source');
               }
             }}
           />
         </div>
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.label'
-              )}
-            </span>
+            <span>{t('data-analyze.algorithm-forms.k-hop.options.label')}</span>
           </div>
           <Select
             size="medium"
             trigger="click"
-            value={algorithmAnalyzerStore.shortestPathAllParams.label}
+            value={algorithmAnalyzerStore.kHopParams.label}
             notFoundContent={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.no-edge-types'
+              'data-analyze.algorithm-forms.k-hop.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'label',
-                value
-              );
+              algorithmAnalyzerStore.mutateKHopParams('label', value);
             }}
           >
             <Select.Option value="__all__" key="__all__">
-              {t('data-analyze.algorithm-forms.shortest-path-all.pre-value')}
+              {t('data-analyze.algorithm-forms.k-hop.pre-value')}
             </Select.Option>
             {dataAnalyzeStore.edgeTypes.map(({ name }) => (
               <Select.Option value={name} key={name}>
@@ -98,95 +101,14 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.target'
-              )}
-            </span>
-          </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .target
-            }
-            value={algorithmAnalyzerStore.shortestPathAllParams.target}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'target',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateShortestPathAllParams('target');
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('target');
-              }
-            }}
-          />
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_degree'
-              )}
-            </span>
-          </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .max_degree
-            }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_degree}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'max_degree',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateShortestPathAllParams(
-                'max_degree'
-              );
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'max_degree'
-                );
-              }
-            }}
-          />
-        </div>
-      </div>
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <i>*</i>
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.direction'
-              )}
+              {t('data-analyze.algorithm-forms.k-hop.options.direction')}
             </span>
           </div>
           <Radio.Group
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            value={algorithmAnalyzerStore.shortestPathAllParams.direction}
+            value={algorithmAnalyzerStore.kHopParams.direction}
             onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateKHopParams(
                 'direction',
                 e.target.value
               );
@@ -200,37 +122,58 @@ const ShortestPathAll = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.capacity'
-              )}
+              {t('data-analyze.algorithm-forms.k-hop.options.max_degree')}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.k-hop.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.k-hop.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .capacity
+              algorithmAnalyzerStore.validateKHopParamsErrorMessage.max_degree
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.capacity}
+            value={algorithmAnalyzerStore.kHopParams.max_degree}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'capacity',
+              algorithmAnalyzerStore.mutateKHopParams(
+                'max_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('capacity');
+              algorithmAnalyzerStore.validateKHopParams('max_degree');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'capacity'
-                );
+                algorithmAnalyzerStore.validateKHopParams('max_degree');
               }
             }}
           />
@@ -241,9 +184,7 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_depth'
-              )}
+              {t('data-analyze.algorithm-forms.k-hop.options.max_depth')}
             </span>
             <CustomTooltip
               trigger="hover"
@@ -260,7 +201,7 @@ const ShortestPathAll = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.max-depth'
+                'data-analyze.algorithm-forms.k-hop.hint.max-depth'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -273,31 +214,28 @@ const ShortestPathAll = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.k-hop.placeholder.input-positive-integer'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .max_depth
+              algorithmAnalyzerStore.validateKHopParamsErrorMessage.max_depth
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_depth}
+            value={algorithmAnalyzerStore.kHopParams.max_depth}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateKHopParams(
                 'max_depth',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('max_depth');
+              algorithmAnalyzerStore.validateKHopParams('max_depth');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'max_depth'
-                );
+                algorithmAnalyzerStore.validateKHopParams('max_depth');
               }
             }}
           />
@@ -305,9 +243,42 @@ const ShortestPathAll = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.skip_degree'
-              )}
+              {t('data-analyze.algorithm-forms.k-hop.options.capacity')}
+            </span>
+          </div>
+          <Input
+            width={formWidth}
+            size="medium"
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            placeholder={t(
+              'data-analyze.algorithm-forms.k-hop.placeholder.input-positive-integer-or-negative-one-capacity'
+            )}
+            errorLocation="layer"
+            errorMessage={
+              algorithmAnalyzerStore.validateKHopParamsErrorMessage.capacity
+            }
+            value={algorithmAnalyzerStore.kHopParams.capacity}
+            onChange={(e: any) => {
+              algorithmAnalyzerStore.mutateKHopParams(
+                'capacity',
+                e.value as string
+              );
+
+              algorithmAnalyzerStore.validateKHopParams('capacity');
+            }}
+            originInputProps={{
+              onBlur() {
+                algorithmAnalyzerStore.validateKHopParams('capacity');
+              }
+            }}
+          />
+        </div>
+      </div>
+      <div className="query-tab-content-form-row">
+        <div className="query-tab-content-form-item">
+          <div className="query-tab-content-form-item-title">
+            <span>
+              {t('data-analyze.algorithm-forms.k-hop.options.nearest')}
             </span>
             <CustomTooltip
               trigger="hover"
@@ -324,7 +295,7 @@ const ShortestPathAll = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.skip-degree'
+                'data-analyze.algorithm-forms.k-hop.hint.shortest-path'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -336,34 +307,42 @@ const ShortestPathAll = observer(() => {
               childrenWrapperElement="img"
             />
           </div>
+          <Switch
+            size="medium"
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            checked={algorithmAnalyzerStore.kHopParams.nearest}
+            onChange={(checked: boolean) => {
+              algorithmAnalyzerStore.mutateKHopParams('nearest', checked);
+            }}
+          />
+        </div>
+        <div className="query-tab-content-form-item">
+          <div className="query-tab-content-form-item-title">
+            <span>{t('data-analyze.algorithm-forms.k-hop.options.limit')}</span>
+          </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.k-hop.placeholder.input-positive-integer-or-negative-one-limit'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .skip_degree
+              algorithmAnalyzerStore.validateKHopParamsErrorMessage.limit
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.skip_degree}
+            value={algorithmAnalyzerStore.kHopParams.limit}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'skip_degree',
+              algorithmAnalyzerStore.mutateKHopParams(
+                'limit',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams(
-                'skip_degree'
-              );
+              algorithmAnalyzerStore.validateKHopParams('limit');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'skip_degree'
-                );
+                algorithmAnalyzerStore.validateKHopParams('limit');
               }
             }}
           />
@@ -386,8 +365,8 @@ const ShortestPathAll = observer(() => {
 
             const timerId = dataAnalyzeStore.addTempExecLog();
             await dataAnalyzeStore.fetchGraphs({
-              url: 'allshortpath',
-              type: Algorithm.shortestPathAll
+              url: 'kout',
+              type: Algorithm.kHop
             });
             await dataAnalyzeStore.fetchExecutionLogs();
             window.clearTimeout(timerId);
@@ -399,7 +378,7 @@ const ShortestPathAll = observer(() => {
           style={styles.primaryButton}
           disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
           onClick={() => {
-            algorithmAnalyzerStore.resetShortestPathAllParams();
+            algorithmAnalyzerStore.resetKHopParams();
           }}
         >
           {t('data-analyze.manipulations.reset')}
@@ -409,4 +388,4 @@ const ShortestPathAll = observer(() => {
   );
 });
 
-export default ShortestPathAll;
+export default KHop;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/KStepNeighbor.tsx
similarity index 57%
copy from hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx
copy to hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/KStepNeighbor.tsx
index 50f62eb..4f22cdb 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/KStepNeighbor.tsx
@@ -1,25 +1,35 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
-import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
+import { Button, Radio, Input, Select } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
+
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
 import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
 
-const LoopDetection = observer(() => {
-  const { t } = useTranslation();
+const KStepNeighbor = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
 
   const isValidExec =
     Object.values(
-      algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
+      algorithmAnalyzerStore.validateKStepNeighborParamsErrorMessage
     ).every((value) => value === '') &&
-    algorithmAnalyzerStore.loopDetectionParams.source !== '' &&
-    algorithmAnalyzerStore.loopDetectionParams.max_depth !== '';
+    algorithmAnalyzerStore.kStepNeighborParams.source !== '' &&
+    algorithmAnalyzerStore.kStepNeighborParams.max_depth !== '';
 
   return (
     <div className="query-tab-content-form">
@@ -28,33 +38,33 @@ const LoopDetection = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t('data-analyze.algorithm-forms.loop-detection.options.source')}
+              {t('data-analyze.algorithm-forms.k-step-neighbor.options.source')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.k-step-neighbor.placeholder.input-source-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
+              algorithmAnalyzerStore.validateKStepNeighborParamsErrorMessage
                 .source
             }
-            value={algorithmAnalyzerStore.loopDetectionParams.source}
+            value={algorithmAnalyzerStore.kStepNeighborParams.source}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
+              algorithmAnalyzerStore.mutateKStepNeighborParams(
                 'source',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateLoopDetectionParams('source');
+              algorithmAnalyzerStore.validateKStepNeighborParams('source');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams('source');
+                algorithmAnalyzerStore.validateKStepNeighborParams('source');
               }
             }}
           />
@@ -62,24 +72,24 @@ const LoopDetection = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t('data-analyze.algorithm-forms.loop-detection.options.label')}
+              {t('data-analyze.algorithm-forms.k-step-neighbor.options.label')}
             </span>
           </div>
           <Select
             size="medium"
             trigger="click"
-            value={algorithmAnalyzerStore.loopDetectionParams.label}
+            value={algorithmAnalyzerStore.kStepNeighborParams.label}
             notFoundContent={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.no-edge-types'
+              'data-analyze.algorithm-forms.k-step-neighbor.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams('label', value);
+              algorithmAnalyzerStore.mutateKStepNeighborParams('label', value);
             }}
           >
             <Select.Option value="__all__" key="__all__">
-              {t('data-analyze.algorithm-forms.loop-detection.pre-value')}
+              {t('data-analyze.algorithm-forms.k-step-neighbor.pre-value')}
             </Select.Option>
             {dataAnalyzeStore.edgeTypes.map(({ name }) => (
               <Select.Option value={name} key={name}>
@@ -95,15 +105,15 @@ const LoopDetection = observer(() => {
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.loop-detection.options.direction'
+                'data-analyze.algorithm-forms.k-step-neighbor.options.direction'
               )}
             </span>
           </div>
           <Radio.Group
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            value={algorithmAnalyzerStore.loopDetectionParams.direction}
+            value={algorithmAnalyzerStore.kStepNeighborParams.direction}
             onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
+              algorithmAnalyzerStore.mutateKStepNeighborParams(
                 'direction',
                 e.target.value
               );
@@ -118,34 +128,60 @@ const LoopDetection = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.loop-detection.options.max_degree'
+                'data-analyze.algorithm-forms.k-step-neighbor.options.max_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.k-step-neighbor.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-integer'
+              'data-analyze.algorithm-forms.k-step-neighbor.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
+              algorithmAnalyzerStore.validateKStepNeighborParamsErrorMessage
                 .max_degree
             }
-            value={algorithmAnalyzerStore.loopDetectionParams.max_degree}
+            value={algorithmAnalyzerStore.kStepNeighborParams.max_degree}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
+              algorithmAnalyzerStore.mutateKStepNeighborParams(
                 'max_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateLoopDetectionParams('max_degree');
+              algorithmAnalyzerStore.validateKStepNeighborParams('max_degree');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams(
+                algorithmAnalyzerStore.validateKStepNeighborParams(
                   'max_degree'
                 );
               }
@@ -159,7 +195,7 @@ const LoopDetection = observer(() => {
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.loop-detection.options.max_depth'
+                'data-analyze.algorithm-forms.k-step-neighbor.options.max_depth'
               )}
             </span>
             <CustomTooltip
@@ -177,7 +213,7 @@ const LoopDetection = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.loop-detection.hint.max-depth'
+                'data-analyze.algorithm-forms.k-step-neighbor.hint.max-depth'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -190,29 +226,29 @@ const LoopDetection = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.k-step-neighbor.placeholder.input-positive-integer'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
+              algorithmAnalyzerStore.validateKStepNeighborParamsErrorMessage
                 .max_depth
             }
-            value={algorithmAnalyzerStore.loopDetectionParams.max_depth}
+            value={algorithmAnalyzerStore.kStepNeighborParams.max_depth}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
+              algorithmAnalyzerStore.mutateKStepNeighborParams(
                 'max_depth',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateLoopDetectionParams('max_depth');
+              algorithmAnalyzerStore.validateKStepNeighborParams('max_depth');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams('max_depth');
+                algorithmAnalyzerStore.validateKStepNeighborParams('max_depth');
               }
             }}
           />
@@ -220,93 +256,33 @@ const LoopDetection = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t('data-analyze.algorithm-forms.loop-detection.options.limit')}
+              {t('data-analyze.algorithm-forms.k-step-neighbor.options.limit')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.k-step-neighbor.placeholder.input-positive-integer-or-negative-one-limit'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
+              algorithmAnalyzerStore.validateKStepNeighborParamsErrorMessage
                 .limit
             }
-            value={algorithmAnalyzerStore.loopDetectionParams.limit}
+            value={algorithmAnalyzerStore.kStepNeighborParams.limit}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
+              algorithmAnalyzerStore.mutateKStepNeighborParams(
                 'limit',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateLoopDetectionParams('limit');
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams('limit');
-              }
-            }}
-          />
-        </div>
-      </div>
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <i>*</i>
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.loop-detection.options.source_in_ring'
-              )}
-            </span>
-          </div>
-          <Switch
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            checked={algorithmAnalyzerStore.loopDetectionParams.source_in_ring}
-            onChange={(checked: boolean) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
-                'source_in_ring',
-                checked
-              );
-            }}
-          />
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.loop-detection.options.capacity'
-              )}
-            </span>
-          </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
-                .capacity
-            }
-            value={algorithmAnalyzerStore.loopDetectionParams.capacity}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
-                'capacity',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateLoopDetectionParams('capacity');
+              algorithmAnalyzerStore.validateKStepNeighborParams('limit');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams('capacity');
+                algorithmAnalyzerStore.validateKStepNeighborParams('limit');
               }
             }}
           />
@@ -329,8 +305,8 @@ const LoopDetection = observer(() => {
 
             const timerId = dataAnalyzeStore.addTempExecLog();
             await dataAnalyzeStore.fetchGraphs({
-              url: 'rings',
-              type: Algorithm.loopDetection
+              url: 'kneighbor',
+              type: Algorithm.kStepNeighbor
             });
             await dataAnalyzeStore.fetchExecutionLogs();
             window.clearTimeout(timerId);
@@ -342,7 +318,7 @@ const LoopDetection = observer(() => {
           style={styles.primaryButton}
           disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
           onClick={() => {
-            algorithmAnalyzerStore.resetLoopDetectionParams();
+            algorithmAnalyzerStore.resetKStepNeighborParams();
           }}
         >
           {t('data-analyze.manipulations.reset')}
@@ -352,4 +328,4 @@ const LoopDetection = observer(() => {
   );
 });
 
-export default LoopDetection;
+export default KStepNeighbor;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx
index 50f62eb..0e24bd9 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx
@@ -1,18 +1,28 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
 import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
+
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
 import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { GraphManagementStoreContext } from '../../../../stores';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
 
 const LoopDetection = observer(() => {
-  const { t } = useTranslation();
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
 
   const isValidExec =
     Object.values(
@@ -32,7 +42,7 @@ const LoopDetection = observer(() => {
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
@@ -73,7 +83,7 @@ const LoopDetection = observer(() => {
               'data-analyze.algorithm-forms.loop-detection.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
               algorithmAnalyzerStore.mutateLoopDetectionParams('label', value);
             }}
@@ -121,13 +131,39 @@ const LoopDetection = observer(() => {
                 'data-analyze.algorithm-forms.loop-detection.options.max_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.loop-detection.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-integer'
+              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
@@ -190,7 +226,7 @@ const LoopDetection = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
@@ -224,11 +260,11 @@ const LoopDetection = observer(() => {
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer-or-negative-one-limit'
             )}
             errorLocation="layer"
             errorMessage={
@@ -263,7 +299,6 @@ const LoopDetection = observer(() => {
             </span>
           </div>
           <Switch
-            width={400}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             checked={algorithmAnalyzerStore.loopDetectionParams.source_in_ring}
@@ -284,11 +319,11 @@ const LoopDetection = observer(() => {
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer-or-negative-one-capacity'
             )}
             errorLocation="layer"
             errorMessage={
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ModelSimilarity.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ModelSimilarity.tsx
index af4c7bc..554a456 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ModelSimilarity.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ModelSimilarity.tsx
@@ -1,266 +1,427 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
-import { size } from 'lodash-es';
+import { flatten, cloneDeep, size, isEmpty } from 'lodash-es';
 import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
+
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
 import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
 
 const ModelSimilarity = observer(() => {
-  const { t } = useTranslation();
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    390
+  );
 
   const sourceType = algorithmAnalyzerStore.modelSimilarityParams.method;
 
+  const allowAddNewProperty = !flatten(
+    algorithmAnalyzerStore.modelSimilarityParams.vertexProperty
+  ).some((value) => value === '');
+
+  const addNewPropertyClassName =
+    allowAddNewProperty &&
+    dataAnalyzeStore.requestStatus.fetchGraphs !== 'pending'
+      ? 'query-tab-content-internal-expand-manipulation-enable'
+      : 'query-tab-content-internal-expand-manipulation-disabled';
+
+  const isValidSourceId =
+    algorithmAnalyzerStore.modelSimilarityParams.method === 'id' &&
+    algorithmAnalyzerStore.modelSimilarityParams.source !== '';
+
+  const isValidProperty =
+    algorithmAnalyzerStore.modelSimilarityParams.method === 'property' &&
+    !(
+      isEmpty(algorithmAnalyzerStore.modelSimilarityParams.vertexType) &&
+      flatten(
+        algorithmAnalyzerStore.modelSimilarityParams.vertexProperty
+      ).every((value) => isEmpty(value))
+    ) &&
+    algorithmAnalyzerStore.modelSimilarityParams.vertexProperty.every(
+      ([key, value]) => (!isEmpty(key) ? !isEmpty(value) : true)
+    );
+
   const isValidExec =
     Object.values(
       algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
     ).every((value) => value === '') &&
     algorithmAnalyzerStore.modelSimilarityParams.least_neighbor !== '' &&
     algorithmAnalyzerStore.modelSimilarityParams.similarity !== '' &&
-    (algorithmAnalyzerStore.modelSimilarityParams.property_filter !== ''
+    (!isEmpty(algorithmAnalyzerStore.modelSimilarityParams.property_filter)
       ? algorithmAnalyzerStore.modelSimilarityParams.least_property_number !==
         ''
       : true) &&
-    ((algorithmAnalyzerStore.modelSimilarityParams.method === 'id' &&
-      algorithmAnalyzerStore.modelSimilarityParams.source !== '') ||
-      algorithmAnalyzerStore.modelSimilarityParams.method === 'property');
+    (isValidSourceId || isValidProperty);
 
   return (
-    <div className="query-tab-content-form">
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <i>*</i>
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.options.method'
-              )}
-            </span>
-          </div>
-          <Radio.Group
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            value={algorithmAnalyzerStore.modelSimilarityParams.method}
-            onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-              algorithmAnalyzerStore.switchModelSimilarityMethod(
-                e.target.value
-              );
-            }}
-          >
-            <Radio value="id">
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.radio-value.specific-id'
-              )}
-            </Radio>
-            <Radio value="property">
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.radio-value.filtered-type-property'
-              )}
-            </Radio>
-          </Radio.Group>
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.options.property_filter'
-              )}
-            </span>
-          </div>
-          <Select
-            size="medium"
-            trigger="click"
-            selectorName={t(
-              'data-analyze.algorithm-forms.model-similarity.placeholder.input-filtered-property'
-            )}
-            value={algorithmAnalyzerStore.modelSimilarityParams.property_filter}
-            notFoundContent={t(
-              'data-analyze.algorithm-forms.model-similarity.placeholder.no-properties'
-            )}
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
-            onChange={(value: string) => {
-              algorithmAnalyzerStore.mutateModelSimilarityParams(
-                'property_filter',
-                value
-              );
-            }}
-          >
-            {dataAnalyzeStore.properties.map(({ name }) => (
-              <Select.Option value={name} key={name}>
-                {name}
-              </Select.Option>
-            ))}
-          </Select>
-        </div>
-      </div>
-
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            {sourceType === 'id' && <i>*</i>}
-            <span>
-              {sourceType === 'id'
-                ? t(
-                    'data-analyze.algorithm-forms.model-similarity.options.source'
-                  )
-                : t(
-                    'data-analyze.algorithm-forms.model-similarity.options.vertex-type'
-                  )}
-            </span>
-          </div>
-          {sourceType === 'id' ? (
-            <Input
-              width={400}
-              size="medium"
-              disabled={
-                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-              }
-              placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-source-id'
-              )}
-              errorLocation="layer"
-              errorMessage={
-                algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                  .source
-              }
-              value={algorithmAnalyzerStore.modelSimilarityParams.source}
-              onChange={(e: any) => {
-                algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'source',
-                  e.value as string
-                );
-
-                algorithmAnalyzerStore.validateModelSimilarityParams('source');
-              }}
-              originInputProps={{
-                onBlur() {
-                  algorithmAnalyzerStore.validateModelSimilarityParams(
-                    'source'
-                  );
-                }
-              }}
-            />
-          ) : (
-            <Select
-              size="medium"
-              trigger="click"
-              selectorName={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-vertex-type'
-              )}
-              value={algorithmAnalyzerStore.modelSimilarityParams.vertexType}
-              notFoundContent={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.no-vertex-type'
-              )}
+    <div style={{ display: 'flex' }}>
+      <div className="query-tab-content-form" style={{ width: '50%' }}>
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div
+              className="query-tab-content-form-item-title large"
+              style={{ lineHeight: '32px' }}
+            >
+              <i>*</i>
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.method'
+                )}
+              </span>
+            </div>
+            <Radio.Group
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
-              width={400}
-              onChange={(value: string) => {
-                algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'vertexType',
-                  value
+              value={algorithmAnalyzerStore.modelSimilarityParams.method}
+              onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
+                algorithmAnalyzerStore.switchModelSimilarityMethod(
+                  e.target.value
                 );
               }}
             >
-              {dataAnalyzeStore.vertexTypes.map(({ name }) => (
-                <Select.Option value={name} key={name}>
-                  {name}
-                </Select.Option>
-              ))}
-            </Select>
-          )}
+              <Radio value="id">
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.radio-value.specific-id'
+                )}
+              </Radio>
+              <Radio value="property">
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.radio-value.filtered-type-property'
+                )}
+              </Radio>
+            </Radio.Group>
+          </div>
         </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.options.least_property_number'
-              )}
-            </span>
-            <CustomTooltip
-              trigger="hover"
-              placement="bottom-start"
-              modifiers={{
-                offset: {
-                  offset: '0, 8'
-                }
-              }}
-              tooltipWrapperProps={{
-                className: 'tooltips-dark',
-                style: {
-                  zIndex: 7
+
+        {sourceType === 'id' && (
+          <div className="query-tab-content-form-row">
+            <div className="query-tab-content-form-item">
+              <div className="query-tab-content-form-item-title large">
+                <i>*</i>
+                <span>
+                  {t(
+                    'data-analyze.algorithm-forms.model-similarity.options.source'
+                  )}
+                </span>
+              </div>
+
+              <Input
+                width={formWidth}
+                size="medium"
+                disabled={
+                  dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
                 }
-              }}
-              tooltipWrapper={t(
-                'data-analyze.algorithm-forms.model-similarity.hint.least_property_number'
-              )}
-              childrenProps={{
-                src: QuestionMarkIcon,
-                alt: 'hint',
-                style: {
-                  marginLeft: 5
+                placeholder={t(
+                  'data-analyze.algorithm-forms.model-similarity.placeholder.input-source-id'
+                )}
+                errorLocation="layer"
+                errorMessage={
+                  algorithmAnalyzerStore
+                    .validateModelSimilartiyParamsErrorMessage.source
                 }
-              }}
-              childrenWrapperElement="img"
-            />
+                value={algorithmAnalyzerStore.modelSimilarityParams.source}
+                onChange={(e: any) => {
+                  algorithmAnalyzerStore.mutateModelSimilarityParams(
+                    'source',
+                    e.value as string
+                  );
+
+                  algorithmAnalyzerStore.validateModelSimilarityParams(
+                    'source'
+                  );
+                }}
+                originInputProps={{
+                  onBlur() {
+                    algorithmAnalyzerStore.validateModelSimilarityParams(
+                      'source'
+                    );
+                  }
+                }}
+              />
+            </div>
           </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer-gt-1'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                .least_property_number
-            }
-            value={
-              algorithmAnalyzerStore.modelSimilarityParams.least_property_number
-            }
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateModelSimilarityParams(
-                'least_property_number',
-                e.value as string
-              );
+        )}
 
-              algorithmAnalyzerStore.validateModelSimilarityParams(
-                'least_property_number'
-              );
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'least_property_number'
-                );
-              }
-            }}
-          />
-        </div>
-      </div>
+        {sourceType !== 'id' && (
+          <>
+            <div className="query-tab-content-form-row">
+              <div className="query-tab-content-form-item">
+                <div className="query-tab-content-form-item-title large">
+                  <span>
+                    {t(
+                      'data-analyze.algorithm-forms.model-similarity.options.vertex-type'
+                    )}
+                  </span>
+                </div>
+                <Select
+                  size="medium"
+                  trigger="click"
+                  selectorName={t(
+                    'data-analyze.algorithm-forms.model-similarity.placeholder.input-vertex-type'
+                  )}
+                  value={
+                    algorithmAnalyzerStore.modelSimilarityParams.vertexType
+                  }
+                  notFoundContent={t(
+                    'data-analyze.algorithm-forms.model-similarity.placeholder.no-vertex-type'
+                  )}
+                  disabled={
+                    dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                  }
+                  width={formWidth}
+                  onChange={(value: string) => {
+                    // switch property selections from properties of index to certain properties
+                    if (
+                      isEmpty(
+                        algorithmAnalyzerStore.modelSimilarityParams.vertexType
+                      )
+                    ) {
+                      algorithmAnalyzerStore.mutateModelSimilarityParams(
+                        'vertexProperty',
+                        [['', '']]
+                      );
+                    }
+
+                    algorithmAnalyzerStore.mutateModelSimilarityParams(
+                      'vertexType',
+                      value
+                    );
+                  }}
+                >
+                  {dataAnalyzeStore.vertexTypes.map(({ name }) => (
+                    <Select.Option value={name} key={name}>
+                      {name}
+                    </Select.Option>
+                  ))}
+                </Select>
+              </div>
+            </div>
+
+            <div
+              className="query-tab-content-form-row"
+              style={{ marginBottom: 0 }}
+            >
+              <div
+                className="query-tab-content-form-item"
+                style={{ alignItems: 'start' }}
+              >
+                <div
+                  className="query-tab-content-form-item-title large"
+                  style={{ lineHeight: '32px' }}
+                >
+                  <span>
+                    {t(
+                      'data-analyze.algorithm-forms.model-similarity.options.vertex-property'
+                    )}
+                  </span>
+                </div>
+
+                <div>
+                  {algorithmAnalyzerStore.modelSimilarityParams.vertexProperty.map(
+                    ([key, value], propertyIndex) => {
+                      const currentVertexType = dataAnalyzeStore.vertexTypes.find(
+                        ({ name }) =>
+                          name ===
+                          algorithmAnalyzerStore.modelSimilarityParams
+                            .vertexType
+                      );
 
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            {sourceType === 'id' && <i>*</i>}
-            <span>
-              {sourceType === 'id'
-                ? t(
-                    'data-analyze.algorithm-forms.model-similarity.options.direction'
-                  )
-                : t(
-                    'data-analyze.algorithm-forms.model-similarity.options.vertex-property'
+                      return (
+                        <div className="query-tab-content-internal-expand-row">
+                          <Select
+                            width={161}
+                            size="medium"
+                            trigger="click"
+                            placeholder={t(
+                              'data-analyze.algorithm-forms.model-similarity.placeholder.select-vertex-property'
+                            )}
+                            value={key}
+                            notFoundContent={t(
+                              'data-analyze.algorithm-forms.model-similarity.placeholder.no-properties'
+                            )}
+                            disabled={
+                              dataAnalyzeStore.requestStatus.fetchGraphs ===
+                              'pending'
+                            }
+                            onChange={(value: string) => {
+                              const vertexProperty = cloneDeep(
+                                algorithmAnalyzerStore.modelSimilarityParams
+                                  .vertexProperty
+                              );
+
+                              vertexProperty[propertyIndex][0] = value;
+
+                              algorithmAnalyzerStore.mutateModelSimilarityParams(
+                                'vertexProperty',
+                                vertexProperty
+                              );
+                            }}
+                          >
+                            {!isEmpty(
+                              algorithmAnalyzerStore.modelSimilarityParams
+                                .vertexType
+                            )
+                              ? flatten(
+                                  currentVertexType?.property_indexes.map(
+                                    ({ fields }) => fields
+                                  )
+                                )
+                                  .concat(currentVertexType!.primary_keys)
+                                  .filter(
+                                    (property) =>
+                                      !algorithmAnalyzerStore.modelSimilarityParams.vertexProperty
+                                        .map(([key]) => key)
+                                        .includes(property)
+                                  )
+                                  .map((property) => (
+                                    <Select.Option
+                                      value={property}
+                                      key={property}
+                                    >
+                                      {property}
+                                    </Select.Option>
+                                  ))
+                              : algorithmAnalyzerStore.allPropertyIndexProperty.map(
+                                  (property) => (
+                                    <Select.Option
+                                      value={property}
+                                      key={property}
+                                    >
+                                      {property}
+                                    </Select.Option>
+                                  )
+                                )}
+                          </Select>
+                          <div className="query-tab-content-internal-expand-input">
+                            <Input
+                              width={161}
+                              size="medium"
+                              disabled={
+                                dataAnalyzeStore.requestStatus.fetchGraphs ===
+                                'pending'
+                              }
+                              placeholder={t(
+                                'data-analyze.algorithm-forms.model-similarity.placeholder.input-vertex-property'
+                              )}
+                              errorLocation="layer"
+                              errorMessage={
+                                algorithmAnalyzerStore
+                                  .validateModelSimilartiyParamsErrorMessage
+                                  .vertexProperty
+                              }
+                              value={value}
+                              onChange={(e: any) => {
+                                const vertexProperty = cloneDeep(
+                                  algorithmAnalyzerStore.modelSimilarityParams
+                                    .vertexProperty
+                                );
+
+                                vertexProperty[propertyIndex][1] = e.value;
+
+                                algorithmAnalyzerStore.mutateModelSimilarityParams(
+                                  'vertexProperty',
+                                  vertexProperty
+                                );
+
+                                algorithmAnalyzerStore.validateModelSimilarityParams(
+                                  'vertexProperty'
+                                );
+                              }}
+                              originInputProps={{
+                                onBlur() {
+                                  algorithmAnalyzerStore.validateModelSimilarityParams(
+                                    'vertexProperty'
+                                  );
+                                }
+                              }}
+                            />
+                          </div>
+                          {size(
+                            algorithmAnalyzerStore.modelSimilarityParams
+                              .vertexProperty
+                          ) > 1 && (
+                            <div
+                              style={{
+                                fontSize: 14,
+                                lineHeight: '32px',
+                                color: '#2b65ff',
+                                cursor: 'pointer'
+                              }}
+                              onClick={() => {
+                                algorithmAnalyzerStore.removeModelSimilarityVertexProperty(
+                                  propertyIndex
+                                );
+                              }}
+                            >
+                              {t(
+                                'data-analyze.algorithm-forms.model-similarity.delete'
+                              )}
+                            </div>
+                          )}
+                        </div>
+                      );
+                    }
                   )}
-            </span>
-          </div>
-          {sourceType === 'id' ? (
+                </div>
+              </div>
+            </div>
+            {algorithmAnalyzerStore.modelSimilarityParams.vertexType === '' &&
+            !allowAddNewProperty &&
+            size(
+              algorithmAnalyzerStore.modelSimilarityParams.vertexProperty
+            ) === 1 ? (
+              <div
+                className="query-tab-algorithm-hint"
+                style={{ margin: '0 0 16px 172px' }}
+              >
+                <span>
+                  {t(
+                    'data-analyze.algorithm-forms.model-similarity.hint.vertex_type_or_property'
+                  )}
+                </span>
+              </div>
+            ) : (
+              <div className={addNewPropertyClassName}>
+                <span
+                  onClick={() => {
+                    if (
+                      allowAddNewProperty &&
+                      dataAnalyzeStore.requestStatus.fetchGraphs !== 'pending'
+                    ) {
+                      algorithmAnalyzerStore.addModelSimilarityVertexProperty();
+                    }
+                  }}
+                >
+                  {t('data-analyze.algorithm-forms.model-similarity.add')}
+                </span>
+              </div>
+            )}
+          </>
+        )}
+
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <i>*</i>
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.direction'
+                )}
+              </span>
+            </div>
             <Radio.Group
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
@@ -277,101 +438,18 @@ const ModelSimilarity = observer(() => {
               <Radio value="OUT">out</Radio>
               <Radio value="IN">in</Radio>
             </Radio.Group>
-          ) : (
-            <Select
-              width={400}
-              mode="multiple"
-              size="medium"
-              trigger="click"
-              placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-vertex-property'
-              )}
-              value={
-                algorithmAnalyzerStore.modelSimilarityParams.vertexProperty
-              }
-              notFoundContent={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.no-properties'
-              )}
-              disabled={
-                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-              }
-              onChange={(value: string[]) => {
-                algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'vertexProperty',
-                  value
-                );
-              }}
-            >
-              {dataAnalyzeStore.vertexTypes
-                .find(
-                  ({ name }) =>
-                    name ===
-                    algorithmAnalyzerStore.modelSimilarityParams.vertexType
-                )
-                ?.properties.map(({ name }) => (
-                  <Select.Option value={name} key={name}>
-                    {name}
-                  </Select.Option>
-                ))}
-            </Select>
-          )}
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.options.max_degree'
-              )}
-            </span>
           </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                .max_degree
-            }
-            value={algorithmAnalyzerStore.modelSimilarityParams.max_degree}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateModelSimilarityParams(
-                'max_degree',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateModelSimilarityParams(
-                'max_degree'
-              );
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'max_degree'
-                );
-              }
-            }}
-          />
         </div>
-      </div>
 
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <i>*</i>
-            <span>
-              {sourceType === 'id'
-                ? t(
-                    'data-analyze.algorithm-forms.model-similarity.options.least_neighbor'
-                  )
-                : t(
-                    'data-analyze.algorithm-forms.model-similarity.options.direction'
-                  )}
-            </span>
-            {sourceType === 'id' && (
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <i>*</i>
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.least_neighbor'
+                )}
+              </span>
               <CustomTooltip
                 trigger="hover"
                 placement="bottom-start"
@@ -398,17 +476,15 @@ const ModelSimilarity = observer(() => {
                 }}
                 childrenWrapperElement="img"
               />
-            )}
-          </div>
-          {sourceType === 'id' ? (
+            </div>
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
               placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-source-id'
+                'data-analyze.algorithm-forms.model-similarity.placeholder.input-positive-integer'
               )}
               errorLocation="layer"
               errorMessage={
@@ -436,120 +512,54 @@ const ModelSimilarity = observer(() => {
                 }
               }}
             />
-          ) : (
-            <Radio.Group
-              disabled={
-                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-              }
-              value={algorithmAnalyzerStore.modelSimilarityParams.direction}
-              onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-                algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'direction',
-                  e.target.value
-                );
-              }}
-            >
-              <Radio value="BOTH">both</Radio>
-              <Radio value="OUT">out</Radio>
-              <Radio value="IN">in</Radio>
-            </Radio.Group>
-          )}
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.options.capacity'
-              )}
-            </span>
           </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.model-similarity.placeholder.input-source-id'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                .capacity
-            }
-            value={algorithmAnalyzerStore.modelSimilarityParams.capacity}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateModelSimilarityParams(
-                'capacity',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateModelSimilarityParams('capacity');
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'capacity'
-                );
-              }
-            }}
-          />
         </div>
-      </div>
 
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <i>*</i>
-            <span>
-              {sourceType === 'id'
-                ? t(
-                    'data-analyze.algorithm-forms.model-similarity.options.similarity'
-                  )
-                : t(
-                    'data-analyze.algorithm-forms.model-similarity.options.least_neighbor'
-                  )}
-            </span>
-            <CustomTooltip
-              trigger="hover"
-              placement="bottom-start"
-              modifiers={{
-                offset: {
-                  offset: '0, 8'
-                }
-              }}
-              tooltipWrapperProps={{
-                className: 'tooltips-dark',
-                style: {
-                  zIndex: 7
-                }
-              }}
-              tooltipWrapper={
-                sourceType === 'id'
-                  ? t(
-                      'data-analyze.algorithm-forms.model-similarity.hint.similarity'
-                    )
-                  : t(
-                      'data-analyze.algorithm-forms.model-similarity.hint.least_neighbor'
-                    )
-              }
-              childrenProps={{
-                src: QuestionMarkIcon,
-                alt: 'hint',
-                style: {
-                  marginLeft: 5
-                }
-              }}
-              childrenWrapperElement="img"
-            />
-          </div>
-          {sourceType === 'id' ? (
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <i>*</i>
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.similarity'
+                )}
+              </span>
+              <CustomTooltip
+                trigger="hover"
+                placement="bottom-start"
+                modifiers={{
+                  offset: {
+                    offset: '0, 8'
+                  }
+                }}
+                tooltipWrapperProps={{
+                  className: 'tooltips-dark',
+                  style: {
+                    zIndex: 7
+                  }
+                }}
+                tooltipWrapper={t(
+                  'data-analyze.algorithm-forms.model-similarity.hint.similarity'
+                )}
+                childrenProps={{
+                  src: QuestionMarkIcon,
+                  alt: 'hint',
+                  style: {
+                    marginLeft: 5
+                  }
+                }}
+                childrenWrapperElement="img"
+              />
+            </div>
+
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
               placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-source-id'
+                'data-analyze.algorithm-forms.model-similarity.placeholder.similarity'
               )}
               errorLocation="layer"
               errorMessage={
@@ -575,100 +585,56 @@ const ModelSimilarity = observer(() => {
                 }
               }}
             />
-          ) : (
-            <Input
-              width={400}
+          </div>
+        </div>
+
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.label'
+                )}
+              </span>
+            </div>
+            <Select
               size="medium"
+              trigger="click"
+              value={algorithmAnalyzerStore.modelSimilarityParams.label}
+              notFoundContent={t(
+                'data-analyze.algorithm-forms.model-similarity.placeholder.no-edge-types'
+              )}
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
-              placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-source-id'
-              )}
-              errorLocation="layer"
-              errorMessage={
-                algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                  .least_neighbor
-              }
-              value={
-                algorithmAnalyzerStore.modelSimilarityParams.least_neighbor
-              }
-              onChange={(e: any) => {
+              width={formWidth}
+              onChange={(value: string) => {
                 algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'least_neighbor',
-                  e.value as string
-                );
-
-                algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'least_neighbor'
+                  'label',
+                  value
                 );
               }}
-              originInputProps={{
-                onBlur() {
-                  algorithmAnalyzerStore.validateModelSimilarityParams(
-                    'least_neighbor'
-                  );
-                }
-              }}
-            />
-          )}
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.options.skip_degree'
-              )}
-            </span>
+            >
+              <Select.Option value="__all__" key="__all__">
+                {t('data-analyze.algorithm-forms.model-similarity.pre-value')}
+              </Select.Option>
+              {dataAnalyzeStore.edgeTypes.map(({ name }) => (
+                <Select.Option value={name} key={name}>
+                  {name}
+                </Select.Option>
+              ))}
+            </Select>
           </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                .skip_degree
-            }
-            value={algorithmAnalyzerStore.modelSimilarityParams.skip_degree}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateModelSimilarityParams(
-                'skip_degree',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateModelSimilarityParams(
-                'skip_degree'
-              );
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'skip_degree'
-                );
-              }
-            }}
-          />
         </div>
-      </div>
 
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            {sourceType !== 'id' && <i>*</i>}
-            <span>
-              {sourceType === 'id'
-                ? t(
-                    'data-analyze.algorithm-forms.model-similarity.options.label'
-                  )
-                : t(
-                    'data-analyze.algorithm-forms.model-similarity.options.similarity'
-                  )}
-            </span>
-            {sourceType !== 'id' && (
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.max_similar'
+                )}
+              </span>
               <CustomTooltip
                 trigger="hover"
                 placement="bottom-start"
@@ -684,7 +650,7 @@ const ModelSimilarity = observer(() => {
                   }
                 }}
                 tooltipWrapper={t(
-                  'data-analyze.algorithm-forms.model-similarity.hint.similarity'
+                  'data-analyze.algorithm-forms.model-similarity.hint.max_similar'
                 )}
                 childrenProps={{
                   src: QuestionMarkIcon,
@@ -695,122 +661,176 @@ const ModelSimilarity = observer(() => {
                 }}
                 childrenWrapperElement="img"
               />
-            )}
-          </div>
-          {sourceType === 'id' ? (
-            <Select
+            </div>
+            <Input
+              width={formWidth}
               size="medium"
-              trigger="click"
-              value={algorithmAnalyzerStore.modelSimilarityParams.label}
-              notFoundContent={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.no-edge-types'
-              )}
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
-              width={400}
-              onChange={(value: string) => {
+              placeholder={t(
+                'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer'
+              )}
+              errorLocation="layer"
+              errorMessage={
+                algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
+                  .max_similar
+              }
+              value={algorithmAnalyzerStore.modelSimilarityParams.max_similar}
+              onChange={(e: any) => {
                 algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'label',
-                  value
+                  'max_similar',
+                  e.value as string
+                );
+
+                algorithmAnalyzerStore.validateModelSimilarityParams(
+                  'max_similar'
                 );
               }}
-            >
-              <Select.Option value="__all__" key="__all__">
-                {t('data-analyze.algorithm-forms.model-similarity.pre-value')}
-              </Select.Option>
-              {dataAnalyzeStore.edgeTypes.map(({ name }) => (
-                <Select.Option value={name} key={name}>
-                  {name}
-                </Select.Option>
-              ))}
-            </Select>
-          ) : (
+              originInputProps={{
+                onBlur() {
+                  algorithmAnalyzerStore.validateModelSimilarityParams(
+                    'max_similar'
+                  );
+                }
+              }}
+            />
+          </div>
+        </div>
+
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.least_similar'
+                )}
+              </span>
+            </div>
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
               placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-source-id'
+                'data-analyze.algorithm-forms.model-similarity.placeholder.input-positive-integer'
               )}
               errorLocation="layer"
               errorMessage={
                 algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                  .similarity
+                  .least_similar
               }
-              value={algorithmAnalyzerStore.modelSimilarityParams.similarity}
+              value={algorithmAnalyzerStore.modelSimilarityParams.least_similar}
               onChange={(e: any) => {
                 algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'similarity',
+                  'least_similar',
                   e.value as string
                 );
 
                 algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'similarity'
+                  'least_similar'
                 );
               }}
               originInputProps={{
                 onBlur() {
                   algorithmAnalyzerStore.validateModelSimilarityParams(
-                    'similarity'
+                    'least_similar'
                   );
                 }
               }}
             />
-          )}
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <span>
-              {t('data-analyze.algorithm-forms.model-similarity.options.limit')}
-            </span>
           </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                .limit
+        </div>
+
+        <div
+          className="query-tab-content-form-row"
+          style={{ marginLeft: 92, justifyContent: 'flex-start' }}
+        >
+          <Button
+            type="primary"
+            style={styles.primaryButton}
+            disabled={
+              !isValidExec ||
+              dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
             }
-            value={algorithmAnalyzerStore.modelSimilarityParams.limit}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateModelSimilarityParams(
-                'limit',
-                e.value as string
-              );
+            onClick={async () => {
+              algorithmAnalyzerStore.switchCollapse(true);
+              dataAnalyzeStore.switchGraphLoaded(false);
 
-              algorithmAnalyzerStore.validateModelSimilarityParams('limit');
+              const timerId = dataAnalyzeStore.addTempExecLog();
+              await dataAnalyzeStore.fetchGraphs({
+                url: 'fsimilarity',
+                type: Algorithm.modelSimilarity
+              });
+              await dataAnalyzeStore.fetchExecutionLogs();
+              window.clearTimeout(timerId);
             }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateModelSimilarityParams('limit');
-              }
+          >
+            {t('data-analyze.manipulations.execution')}
+          </Button>
+          <Button
+            style={styles.primaryButton}
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            onClick={() => {
+              algorithmAnalyzerStore.resetModelSimilarityParams();
             }}
-          />
+          >
+            {t('data-analyze.manipulations.reset')}
+          </Button>
         </div>
       </div>
 
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            {sourceType === 'id' && <i>*</i>}
-            <span>
-              {sourceType === 'id'
-                ? t(
-                    'data-analyze.algorithm-forms.model-similarity.options.max_similar'
-                  )
-                : t(
-                    'data-analyze.algorithm-forms.model-similarity.options.label'
-                  )}
-            </span>
-            {sourceType === 'id' && (
+      <div className="query-tab-content-form" style={{ width: '50%' }}>
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.property_filter'
+                )}
+              </span>
+            </div>
+            <Select
+              size="medium"
+              trigger="click"
+              selectorName={t(
+                'data-analyze.algorithm-forms.model-similarity.placeholder.input-filtered-property'
+              )}
+              value={
+                algorithmAnalyzerStore.modelSimilarityParams.property_filter
+              }
+              notFoundContent={t(
+                'data-analyze.algorithm-forms.model-similarity.placeholder.no-properties'
+              )}
+              disabled={
+                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+              }
+              width={formWidth}
+              onChange={(value: string) => {
+                algorithmAnalyzerStore.mutateModelSimilarityParams(
+                  'property_filter',
+                  value
+                );
+              }}
+            >
+              {dataAnalyzeStore.properties.map(({ name }) => (
+                <Select.Option value={name} key={name}>
+                  {name}
+                </Select.Option>
+              ))}
+            </Select>
+          </div>
+        </div>
+
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.least_property_number'
+                )}
+              </span>
               <CustomTooltip
                 trigger="hover"
                 placement="bottom-start"
@@ -826,7 +846,7 @@ const ModelSimilarity = observer(() => {
                   }
                 }}
                 tooltipWrapper={t(
-                  'data-analyze.algorithm-forms.model-similarity.hint.max_similar'
+                  'data-analyze.algorithm-forms.model-similarity.hint.least_property_number'
                 )}
                 childrenProps={{
                   src: QuestionMarkIcon,
@@ -837,142 +857,54 @@ const ModelSimilarity = observer(() => {
                 }}
                 childrenWrapperElement="img"
               />
-            )}
-          </div>
-          {sourceType === 'id' ? (
+            </div>
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
               placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer'
+                'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer-gt-1'
               )}
               errorLocation="layer"
               errorMessage={
                 algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                  .max_similar
+                  .least_property_number
+              }
+              value={
+                algorithmAnalyzerStore.modelSimilarityParams
+                  .least_property_number
               }
-              value={algorithmAnalyzerStore.modelSimilarityParams.max_similar}
               onChange={(e: any) => {
                 algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'max_similar',
+                  'least_property_number',
                   e.value as string
                 );
 
                 algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'max_similar'
+                  'least_property_number'
                 );
               }}
               originInputProps={{
                 onBlur() {
                   algorithmAnalyzerStore.validateModelSimilarityParams(
-                    'max_similar'
+                    'least_property_number'
                   );
                 }
               }}
             />
-          ) : (
-            <Select
-              size="medium"
-              trigger="click"
-              value={algorithmAnalyzerStore.modelSimilarityParams.label}
-              notFoundContent={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.no-edge-types'
-              )}
-              disabled={
-                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-              }
-              width={400}
-              onChange={(value: string) => {
-                algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'label',
-                  value
-                );
-              }}
-            >
-              <Select.Option value="__all__" key="__all__">
-                {t('data-analyze.algorithm-forms.model-similarity.pre-value')}
-              </Select.Option>
-              {dataAnalyzeStore.edgeTypes.map(({ name }) => (
-                <Select.Option value={name} key={name}>
-                  {name}
-                </Select.Option>
-              ))}
-            </Select>
-          )}
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.options.return_common_connection'
-              )}
-            </span>
-            <CustomTooltip
-              trigger="hover"
-              placement="bottom-start"
-              modifiers={{
-                offset: {
-                  offset: '0, 8'
-                }
-              }}
-              tooltipWrapperProps={{
-                className: 'tooltips-dark',
-                style: {
-                  zIndex: 7
-                }
-              }}
-              tooltipWrapper={t(
-                'data-analyze.algorithm-forms.model-similarity.hint.return_common_connection'
-              )}
-              childrenProps={{
-                src: QuestionMarkIcon,
-                alt: 'hint',
-                style: {
-                  marginLeft: 5
-                }
-              }}
-              childrenWrapperElement="img"
-            />
-          </div>
-          <div style={{ width: 400 }}>
-            <Switch
-              width={40}
-              size="medium"
-              disabled={
-                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-              }
-              checked={
-                algorithmAnalyzerStore.modelSimilarityParams
-                  .return_common_connection
-              }
-              onChange={(checked: boolean) => {
-                algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'return_common_connection',
-                  checked
-                );
-              }}
-            />
           </div>
         </div>
-      </div>
 
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            {sourceType !== 'id' && <i>*</i>}
-            <span>
-              {sourceType === 'id'
-                ? t(
-                    'data-analyze.algorithm-forms.model-similarity.options.least_similar'
-                  )
-                : t(
-                    'data-analyze.algorithm-forms.model-similarity.options.max_similar'
-                  )}
-            </span>
-            {sourceType !== 'id' && (
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.max_degree'
+                )}
+              </span>
               <CustomTooltip
                 trigger="hover"
                 placement="bottom-start"
@@ -988,7 +920,7 @@ const ModelSimilarity = observer(() => {
                   }
                 }}
                 tooltipWrapper={t(
-                  'data-analyze.algorithm-forms.model-similarity.hint.max_similar'
+                  'data-analyze.algorithm-forms.model-similarity.hint.max-degree'
                 )}
                 childrenProps={{
                   src: QuestionMarkIcon,
@@ -999,190 +931,216 @@ const ModelSimilarity = observer(() => {
                 }}
                 childrenWrapperElement="img"
               />
-            )}
-          </div>
-          {sourceType === 'id' ? (
+            </div>
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
               placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer'
+                'data-analyze.algorithm-forms.model-similarity.placeholder.input-positive-integer-or-negative-one-max-degree'
               )}
               errorLocation="layer"
               errorMessage={
                 algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                  .least_similar
+                  .max_degree
               }
-              value={algorithmAnalyzerStore.modelSimilarityParams.least_similar}
+              value={algorithmAnalyzerStore.modelSimilarityParams.max_degree}
               onChange={(e: any) => {
                 algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'least_similar',
+                  'max_degree',
                   e.value as string
                 );
 
                 algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'least_similar'
+                  'max_degree'
                 );
               }}
               originInputProps={{
                 onBlur() {
                   algorithmAnalyzerStore.validateModelSimilarityParams(
-                    'least_similar'
+                    'max_degree'
                   );
                 }
               }}
             />
-          ) : (
+          </div>
+        </div>
+
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.capacity'
+                )}
+              </span>
+            </div>
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
               placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer'
+                'data-analyze.algorithm-forms.model-similarity.placeholder.input-positive-integer-or-negative-one-capacity'
               )}
               errorLocation="layer"
               errorMessage={
                 algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                  .max_similar
+                  .capacity
               }
-              value={algorithmAnalyzerStore.modelSimilarityParams.max_similar}
+              value={algorithmAnalyzerStore.modelSimilarityParams.capacity}
               onChange={(e: any) => {
                 algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'max_similar',
+                  'capacity',
                   e.value as string
                 );
 
                 algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'max_similar'
+                  'capacity'
                 );
               }}
               originInputProps={{
                 onBlur() {
                   algorithmAnalyzerStore.validateModelSimilarityParams(
-                    'max_similar'
+                    'capacity'
                   );
                 }
               }}
             />
-          )}
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title large">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.model-similarity.options.return_complete_info'
-              )}
-            </span>
-          </div>
-          <div style={{ width: 400 }}>
-            <Switch
-              width={40}
-              size="medium"
-              disabled={
-                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-              }
-              checked={
-                algorithmAnalyzerStore.modelSimilarityParams
-                  .return_complete_info
-              }
-              onChange={(checked: boolean) => {
-                algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'return_complete_info',
-                  checked
-                );
-              }}
-            />
           </div>
         </div>
-      </div>
 
-      {sourceType !== 'id' && (
         <div className="query-tab-content-form-row">
           <div className="query-tab-content-form-item">
             <div className="query-tab-content-form-item-title large">
               <span>
                 {t(
-                  'data-analyze.algorithm-forms.model-similarity.options.least_similar'
+                  'data-analyze.algorithm-forms.model-similarity.options.limit'
                 )}
               </span>
             </div>
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
               placeholder={t(
-                'data-analyze.algorithm-forms.model-similarity.placeholder.input-integer'
+                'data-analyze.algorithm-forms.model-similarity.placeholder.input-positive-integer-or-negative-one-limit'
               )}
               errorLocation="layer"
               errorMessage={
                 algorithmAnalyzerStore.validateModelSimilartiyParamsErrorMessage
-                  .least_similar
+                  .limit
               }
-              value={algorithmAnalyzerStore.modelSimilarityParams.least_similar}
+              value={algorithmAnalyzerStore.modelSimilarityParams.limit}
               onChange={(e: any) => {
                 algorithmAnalyzerStore.mutateModelSimilarityParams(
-                  'least_similar',
+                  'limit',
                   e.value as string
                 );
 
-                algorithmAnalyzerStore.validateModelSimilarityParams(
-                  'least_similar'
-                );
+                algorithmAnalyzerStore.validateModelSimilarityParams('limit');
               }}
               originInputProps={{
                 onBlur() {
-                  algorithmAnalyzerStore.validateModelSimilarityParams(
-                    'least_similar'
-                  );
+                  algorithmAnalyzerStore.validateModelSimilarityParams('limit');
                 }
               }}
             />
           </div>
         </div>
-      )}
 
-      <div
-        className="query-tab-content-form-row"
-        style={{ marginLeft: 92, justifyContent: 'flex-start' }}
-      >
-        <Button
-          type="primary"
-          style={styles.primaryButton}
-          disabled={
-            !isValidExec ||
-            dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-          }
-          onClick={async () => {
-            algorithmAnalyzerStore.switchCollapse(true);
-            dataAnalyzeStore.switchGraphLoaded(false);
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.return_common_connection'
+                )}
+              </span>
+              <CustomTooltip
+                trigger="hover"
+                placement="bottom-start"
+                modifiers={{
+                  offset: {
+                    offset: '0, 8'
+                  }
+                }}
+                tooltipWrapperProps={{
+                  className: 'tooltips-dark',
+                  style: {
+                    zIndex: 7
+                  }
+                }}
+                tooltipWrapper={t(
+                  'data-analyze.algorithm-forms.model-similarity.hint.return_common_connection'
+                )}
+                childrenProps={{
+                  src: QuestionMarkIcon,
+                  alt: 'hint',
+                  style: {
+                    marginLeft: 5
+                  }
+                }}
+                childrenWrapperElement="img"
+              />
+            </div>
+            <div style={{ width: formWidth }}>
+              <Switch
+                width={40}
+                size="medium"
+                disabled={
+                  dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                }
+                checked={
+                  algorithmAnalyzerStore.modelSimilarityParams
+                    .return_common_connection
+                }
+                onChange={(checked: boolean) => {
+                  algorithmAnalyzerStore.mutateModelSimilarityParams(
+                    'return_common_connection',
+                    checked
+                  );
+                }}
+              />
+            </div>
+          </div>
+        </div>
 
-            const timerId = dataAnalyzeStore.addTempExecLog();
-            await dataAnalyzeStore.fetchGraphs({
-              url: 'fsimilarity',
-              type: Algorithm.modelSimilarity
-            });
-            await dataAnalyzeStore.fetchExecutionLogs();
-            window.clearTimeout(timerId);
-          }}
-        >
-          {t('data-analyze.manipulations.execution')}
-        </Button>
-        <Button
-          style={styles.primaryButton}
-          disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-          onClick={() => {
-            algorithmAnalyzerStore.resetShortestPathAllParams();
-          }}
-        >
-          {t('data-analyze.manipulations.reset')}
-        </Button>
+        <div className="query-tab-content-form-row">
+          <div className="query-tab-content-form-item">
+            <div className="query-tab-content-form-item-title large">
+              <span>
+                {t(
+                  'data-analyze.algorithm-forms.model-similarity.options.return_complete_info'
+                )}
+              </span>
+            </div>
+            <div style={{ width: formWidth }}>
+              <Switch
+                width={40}
+                size="medium"
+                disabled={
+                  dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
+                }
+                checked={
+                  algorithmAnalyzerStore.modelSimilarityParams
+                    .return_complete_info
+                }
+                onChange={(checked: boolean) => {
+                  algorithmAnalyzerStore.mutateModelSimilarityParams(
+                    'return_complete_info',
+                    checked
+                  );
+                }}
+              />
+            </div>
+          </div>
+        </div>
       </div>
     </div>
   );
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/NeighborRank.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/NeighborRank.tsx
index 5341571..472919d 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/NeighborRank.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/NeighborRank.tsx
@@ -1,22 +1,35 @@
 import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
-import { size, last } from 'lodash-es';
+import { size } from 'lodash-es';
 import { useTranslation } from 'react-i18next';
-import classnames from 'classnames';
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Button, Radio, Input, Select } from 'hubble-ui';
 
 import { Tooltip as CustomTooltip } from '../../../common';
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
 import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
-import { NeighborRankRule } from '../../../../stores/types/GraphManagementStore/dataAnalyzeStore';
 
 const NeighborRank = observer(() => {
-  const { t } = useTranslation();
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
+
+  const formWidthInStep = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    310,
+    380
+  );
 
   const isValidExec =
     Object.values(
@@ -28,17 +41,9 @@ const NeighborRank = observer(() => {
     algorithmAnalyzerStore.neighborRankParams.source !== '' &&
     algorithmAnalyzerStore.neighborRankParams.alpha !== '';
 
-  const isValidAddRule =
-    algorithmAnalyzerStore.validateNeighborRankParamsParamsErrorMessage.steps.every(
-      (step) => Object.values(step).every((value) => value === '')
-    ) && algorithmAnalyzerStore.duplicateNeighborRankRuleSet.size === 0;
-
-  const invalidExtendFormClassname = (flag: boolean) => {
-    return classnames({
-      'query-tab-content-form-expand-items': true,
-      'query-tab-content-form-expand-items-invalid': flag
-    });
-  };
+  const isValidAddRule = algorithmAnalyzerStore.validateNeighborRankParamsParamsErrorMessage.steps.every(
+    (step) => Object.values(step).every((value) => value === '')
+  );
 
   return (
     <div style={{ display: 'flex' }}>
@@ -55,7 +60,7 @@ const NeighborRank = observer(() => {
               </span>
             </div>
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
@@ -97,7 +102,7 @@ const NeighborRank = observer(() => {
               </span>
             </div>
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
@@ -127,37 +132,6 @@ const NeighborRank = observer(() => {
             />
           </div>
         </div>
-        <div className="query-tab-content-form-row">
-          <div className="query-tab-content-form-item">
-            <div
-              className="query-tab-content-form-item-title"
-              style={{ width: 105 }}
-            >
-              <i>*</i>
-              <span>
-                {t(
-                  'data-analyze.algorithm-forms.neighbor-rank.options.direction'
-                )}
-              </span>
-            </div>
-            <Radio.Group
-              disabled={
-                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
-              }
-              value={algorithmAnalyzerStore.neighborRankParams.direction}
-              onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-                algorithmAnalyzerStore.mutateNeighborRankParams(
-                  'direction',
-                  e.target.value
-                );
-              }}
-            >
-              <Radio value="BOTH">both</Radio>
-              <Radio value="OUT">out</Radio>
-              <Radio value="IN">in</Radio>
-            </Radio.Group>
-          </div>
-        </div>
         <div className="query-tab-content-form-row">
           <div className="query-tab-content-form-item">
             <div
@@ -171,13 +145,13 @@ const NeighborRank = observer(() => {
               </span>
             </div>
             <Input
-              width={400}
+              width={formWidth}
               size="medium"
               disabled={
                 dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
               placeholder={t(
-                'data-analyze.algorithm-forms.neighbor-rank.placeholder.input-positive-integer'
+                'data-analyze.algorithm-forms.neighbor-rank.placeholder.input-positive-integer-or-negative-one-capacity'
               )}
               errorLocation="layer"
               errorMessage={
@@ -219,7 +193,7 @@ const NeighborRank = observer(() => {
               const timerId = dataAnalyzeStore.addTempExecLog();
               await dataAnalyzeStore.fetchGraphs({
                 url: 'neighborrank',
-                type: Algorithm.neighborRankRecommendation
+                type: Algorithm.neighborRank
               });
               await dataAnalyzeStore.fetchExecutionLogs();
               window.clearTimeout(timerId);
@@ -231,7 +205,7 @@ const NeighborRank = observer(() => {
             style={styles.primaryButton}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             onClick={() => {
-              algorithmAnalyzerStore.resetShortestPathAllParams();
+              algorithmAnalyzerStore.resetNeighborRankParams();
             }}
           >
             {t('data-analyze.manipulations.reset')}
@@ -244,13 +218,9 @@ const NeighborRank = observer(() => {
         style={{ width: '50%' }}
       >
         {algorithmAnalyzerStore.neighborRankParams.steps.map(
-          ({ uuid, direction, label, degree, top }, ruleIndex) => {
+          ({ uuid, direction, labels, degree, top }, ruleIndex) => {
             return (
-              <div
-                className={invalidExtendFormClassname(
-                  algorithmAnalyzerStore.duplicateNeighborRankRuleSet.has(uuid)
-                )}
-              >
+              <div className="query-tab-content-form-expand-items">
                 <div className="query-tab-content-form-expand-item">
                   <div className="query-tab-content-form-item-title query-tab-content-form-expand-title">
                     <i>*</i>
@@ -271,10 +241,6 @@ const NeighborRank = observer(() => {
                         e.target.value,
                         ruleIndex
                       );
-
-                      algorithmAnalyzerStore.validateDuplicateNeighborRankRules(
-                        uuid
-                      );
                     }}
                   >
                     <Radio value="BOTH">both</Radio>
@@ -285,7 +251,7 @@ const NeighborRank = observer(() => {
                     1 && (
                     <div
                       style={{
-                        marginLeft: 198,
+                        marginLeft: 175,
                         fontSize: 14,
                         color: '#2b65ff',
                         cursor: 'pointer',
@@ -295,10 +261,6 @@ const NeighborRank = observer(() => {
                         algorithmAnalyzerStore.removeNeighborRankRule(
                           ruleIndex
                         );
-
-                        algorithmAnalyzerStore.validateDuplicateNeighborRankRules(
-                          uuid
-                        );
                       }}
                     >
                       {t('addition.common.del')}
@@ -316,24 +278,20 @@ const NeighborRank = observer(() => {
                   <Select
                     size="medium"
                     trigger="click"
-                    value={label}
+                    value={labels[0]}
                     notFoundContent={t(
                       'data-analyze.algorithm-forms.neighbor-rank.placeholder.no-edge-types'
                     )}
                     disabled={
                       dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
                     }
-                    width={400}
+                    width={formWidthInStep}
                     onChange={(value: string) => {
                       algorithmAnalyzerStore.mutateNeighborRankRuleParams(
-                        'label',
-                        value,
+                        'labels',
+                        [value],
                         ruleIndex
                       );
-
-                      algorithmAnalyzerStore.validateDuplicateNeighborRankRules(
-                        uuid
-                      );
                     }}
                   >
                     <Select.Option value="__all__" key="__all__">
@@ -355,15 +313,41 @@ const NeighborRank = observer(() => {
                         'data-analyze.algorithm-forms.neighbor-rank.options.degree'
                       )}
                     </span>
+                    <CustomTooltip
+                      trigger="hover"
+                      placement="bottom-start"
+                      modifiers={{
+                        offset: {
+                          offset: '0, 8'
+                        }
+                      }}
+                      tooltipWrapperProps={{
+                        className: 'tooltips-dark',
+                        style: {
+                          zIndex: 7
+                        }
+                      }}
+                      tooltipWrapper={t(
+                        'data-analyze.algorithm-forms.neighbor-rank.hint.max-degree'
+                      )}
+                      childrenProps={{
+                        src: QuestionMarkIcon,
+                        alt: 'hint',
+                        style: {
+                          marginLeft: 5
+                        }
+                      }}
+                      childrenWrapperElement="img"
+                    />
                   </div>
                   <Input
-                    width={400}
+                    width={formWidthInStep}
                     size="medium"
                     disabled={
                       dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
                     }
                     placeholder={t(
-                      'data-analyze.algorithm-forms.neighbor-rank.placeholder.input-integer'
+                      'data-analyze.algorithm-forms.neighbor-rank.placeholder.input-positive-integer-or-negative-one-max-degree'
                     )}
                     errorLocation="layer"
                     errorMessage={
@@ -384,10 +368,6 @@ const NeighborRank = observer(() => {
                         'degree',
                         ruleIndex
                       );
-
-                      algorithmAnalyzerStore.validateDuplicateNeighborRankRules(
-                        uuid
-                      );
                     }}
                     originInputProps={{
                       onBlur() {
@@ -434,13 +414,13 @@ const NeighborRank = observer(() => {
                     />
                   </div>
                   <Input
-                    width={400}
+                    width={formWidthInStep}
                     size="medium"
                     disabled={
                       dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
                     }
                     placeholder={t(
-                      'data-analyze.algorithm-forms.neighbor-rank.placeholder.input-integer'
+                      'data-analyze.algorithm-forms.neighbor-rank.placeholder.input-integer-lt-1000'
                     )}
                     errorLocation="layer"
                     errorMessage={
@@ -461,10 +441,6 @@ const NeighborRank = observer(() => {
                         'top',
                         ruleIndex
                       );
-
-                      algorithmAnalyzerStore.validateDuplicateNeighborRankRules(
-                        uuid
-                      );
                     }}
                     originInputProps={{
                       onBlur() {
@@ -488,42 +464,16 @@ const NeighborRank = observer(() => {
             marginTop: 8
           }}
         >
-          {algorithmAnalyzerStore.duplicateNeighborRankRuleSet.size === 0 ? (
-            <span
-              style={{ cursor: 'pointer' }}
-              onClick={() => {
-                if (isValidAddRule) {
-                  algorithmAnalyzerStore.addNeighborRankRule();
-
-                  algorithmAnalyzerStore.validateDuplicateNeighborRankRules(
-                    (
-                      last(
-                        algorithmAnalyzerStore.neighborRankParams.steps
-                      ) as NeighborRankRule
-                    ).uuid
-                  );
-                }
-              }}
-            >
-              {t('data-analyze.algorithm-forms.neighbor-rank.add-new-rule')}
-            </span>
-          ) : (
-            <div
-              style={{
-                width: 150,
-                boxShadow: '0 1px 4px 0 rgba(0, 0, 0, 0.15)',
-                lineHeight: '18px',
-                padding: '16px',
-                color: '#e64552',
-                fontSize: 14,
-                textAlign: 'center'
-              }}
-            >
-              {t(
-                'data-analyze.algorithm-forms.neighbor-rank.validations.input-chars'
-              )}
-            </div>
-          )}
+          <span
+            style={{ cursor: 'pointer' }}
+            onClick={() => {
+              if (isValidAddRule) {
+                algorithmAnalyzerStore.addNeighborRankRule();
+              }
+            }}
+          >
+            {t('data-analyze.algorithm-forms.neighbor-rank.add-new-rule')}
+          </span>
         </div>
       </div>
     </div>
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/PersonalRank.tsx
similarity index 53%
copy from hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
copy to hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/PersonalRank.tsx
index 82ec79a..a83ba4a 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/PersonalRank.tsx
@@ -1,90 +1,101 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
 import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
+
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
-import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
 
-const ShortestPathAll = observer(() => {
-  const { t } = useTranslation();
+const PersonalRank = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
 
-  const isValidExec = !Object.values(
-    algorithmAnalyzerStore.shortestPathAllParams
-  ).some((value) => value === '');
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
+
+  const isValidExec =
+    Object.values(
+      algorithmAnalyzerStore.validatePersonalRankErrorMessage
+    ).every((value) => value === '') &&
+    algorithmAnalyzerStore.personalRankParams.source !== '' &&
+    algorithmAnalyzerStore.personalRankParams.alpha !== '' &&
+    algorithmAnalyzerStore.personalRankParams.label !== '' &&
+    algorithmAnalyzerStore.personalRankParams.max_depth !== '';
 
   return (
     <div className="query-tab-content-form">
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 112 }}
+          >
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.source'
-              )}
+              {t('data-analyze.algorithm-forms.personal-rank.options.source')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.personal-rank.placeholder.input-source-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .source
+              algorithmAnalyzerStore.validatePersonalRankErrorMessage.source
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.source}
+            value={algorithmAnalyzerStore.personalRankParams.source}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutatePersonalRankParams(
                 'source',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('source');
+              algorithmAnalyzerStore.validatePersonalRankParams('source');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('source');
+                algorithmAnalyzerStore.validatePersonalRankParams('source');
               }
             }}
           />
         </div>
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
+            <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.label'
-              )}
+              {t('data-analyze.algorithm-forms.personal-rank.options.label')}
             </span>
           </div>
           <Select
             size="medium"
             trigger="click"
-            value={algorithmAnalyzerStore.shortestPathAllParams.label}
+            value={algorithmAnalyzerStore.personalRankParams.label}
+            selectorName={t(
+              'data-analyze.algorithm-forms.personal-rank.placeholder.select-edge'
+            )}
             notFoundContent={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.no-edge-types'
+              'data-analyze.algorithm-forms.personal-rank.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'label',
-                value
-              );
+              algorithmAnalyzerStore.mutatePersonalRankParams('label', value);
             }}
           >
-            <Select.Option value="__all__" key="__all__">
-              {t('data-analyze.algorithm-forms.shortest-path-all.pre-value')}
-            </Select.Option>
             {dataAnalyzeStore.edgeTypes.map(({ name }) => (
               <Select.Option value={name} key={name}>
                 {name}
@@ -95,38 +106,38 @@ const ShortestPathAll = observer(() => {
       </div>
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 112 }}
+          >
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.target'
-              )}
+              {t('data-analyze.algorithm-forms.personal-rank.options.alpha')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.personal-rank.placeholder.alpha'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .target
+              algorithmAnalyzerStore.validatePersonalRankErrorMessage.alpha
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.target}
+            value={algorithmAnalyzerStore.personalRankParams.alpha}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'target',
+              algorithmAnalyzerStore.mutatePersonalRankParams(
+                'alpha',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('target');
+              algorithmAnalyzerStore.validatePersonalRankParams('alpha');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('target');
+                algorithmAnalyzerStore.validatePersonalRankParams('alpha');
               }
             }}
           />
@@ -134,39 +145,58 @@ const ShortestPathAll = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_degree'
-              )}
+              {t('data-analyze.algorithm-forms.personal-rank.options.degree')}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.personal-rank.hint.degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-integer'
+              'data-analyze.algorithm-forms.personal-rank.placeholder.input-positive-integer-or-negative-one-degree'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .max_degree
+              algorithmAnalyzerStore.validatePersonalRankErrorMessage.degree
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_degree}
+            value={algorithmAnalyzerStore.personalRankParams.degree}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'max_degree',
+              algorithmAnalyzerStore.mutatePersonalRankParams(
+                'degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams(
-                'max_degree'
-              );
+              algorithmAnalyzerStore.validatePersonalRankParams('degree');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'max_degree'
-                );
+                algorithmAnalyzerStore.validatePersonalRankParams('degree');
               }
             }}
           />
@@ -174,63 +204,73 @@ const ShortestPathAll = observer(() => {
       </div>
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 112 }}
+          >
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.direction'
+                'data-analyze.algorithm-forms.personal-rank.options.max_depth'
               )}
             </span>
           </div>
-          <Radio.Group
+          <Input
+            width={formWidth}
+            size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            value={algorithmAnalyzerStore.shortestPathAllParams.direction}
-            onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'direction',
-                e.target.value
+            placeholder={t(
+              'data-analyze.algorithm-forms.personal-rank.placeholder.max_depth'
+            )}
+            errorLocation="layer"
+            errorMessage={
+              algorithmAnalyzerStore.validatePersonalRankErrorMessage.max_depth
+            }
+            value={algorithmAnalyzerStore.personalRankParams.max_depth}
+            onChange={(e: any) => {
+              algorithmAnalyzerStore.mutatePersonalRankParams(
+                'max_depth',
+                e.value as string
               );
+
+              algorithmAnalyzerStore.validatePersonalRankParams('max_depth');
             }}
-          >
-            <Radio value="BOTH">both</Radio>
-            <Radio value="OUT">out</Radio>
-            <Radio value="IN">in</Radio>
-          </Radio.Group>
+            originInputProps={{
+              onBlur() {
+                algorithmAnalyzerStore.validatePersonalRankParams('max_depth');
+              }
+            }}
+          />
         </div>
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.capacity'
-              )}
+              {t('data-analyze.algorithm-forms.personal-rank.options.limit')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.personal-rank.placeholder.input-positive-integer-or-negative-one-limit'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .capacity
+              algorithmAnalyzerStore.validatePersonalRankErrorMessage.limit
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.capacity}
+            value={algorithmAnalyzerStore.personalRankParams.limit}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'capacity',
+              algorithmAnalyzerStore.mutatePersonalRankParams(
+                'limit',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('capacity');
+              algorithmAnalyzerStore.validatePersonalRankParams('limit');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'capacity'
-                );
+                algorithmAnalyzerStore.validatePersonalRankParams('limit');
               }
             }}
           />
@@ -238,11 +278,14 @@ const ShortestPathAll = observer(() => {
       </div>
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 112 }}
+          >
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_depth'
+                'data-analyze.algorithm-forms.personal-rank.options.with_label'
               )}
             </span>
             <CustomTooltip
@@ -260,7 +303,7 @@ const ShortestPathAll = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.max-depth'
+                'data-analyze.algorithm-forms.personal-rank.hint.with-label'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -272,42 +315,37 @@ const ShortestPathAll = observer(() => {
               childrenWrapperElement="img"
             />
           </div>
-          <Input
-            width={400}
-            size="medium"
+          <Radio.Group
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .max_depth
-            }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_depth}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'max_depth',
-                e.value as string
+            value={algorithmAnalyzerStore.personalRankParams.with_label}
+            onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
+              algorithmAnalyzerStore.mutatePersonalRankParams(
+                'with_label',
+                e.target.value
               );
-
-              algorithmAnalyzerStore.validateShortestPathAllParams('max_depth');
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'max_depth'
-                );
-              }
             }}
-          />
+          >
+            <Radio value="SAME_LABEL">
+              {t(
+                'data-analyze.algorithm-forms.personal-rank.with-label-radio-value.same_label'
+              )}
+            </Radio>
+            <Radio value="OTHER_LABEL">
+              {t(
+                'data-analyze.algorithm-forms.personal-rank.with-label-radio-value.other_label'
+              )}
+            </Radio>
+            <Radio value="BOTH_LABEL">
+              {t(
+                'data-analyze.algorithm-forms.personal-rank.with-label-radio-value.both_label'
+              )}
+            </Radio>
+          </Radio.Group>
         </div>
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.skip_degree'
-              )}
+              {t('data-analyze.algorithm-forms.personal-rank.options.sorted')}
             </span>
             <CustomTooltip
               trigger="hover"
@@ -324,7 +362,7 @@ const ShortestPathAll = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.skip-degree'
+                'data-analyze.algorithm-forms.personal-rank.hint.sorted'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -336,37 +374,21 @@ const ShortestPathAll = observer(() => {
               childrenWrapperElement="img"
             />
           </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .skip_degree
-            }
-            value={algorithmAnalyzerStore.shortestPathAllParams.skip_degree}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'skip_degree',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateShortestPathAllParams(
-                'skip_degree'
-              );
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'skip_degree'
-                );
+          <div style={{ width: formWidth }}>
+            <Switch
+              size="medium"
+              disabled={
+                dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'
               }
-            }}
-          />
+              checked={algorithmAnalyzerStore.personalRankParams.sorted}
+              onChange={(checked: boolean) => {
+                algorithmAnalyzerStore.mutatePersonalRankParams(
+                  'sorted',
+                  checked
+                );
+              }}
+            />
+          </div>
         </div>
       </div>
       <div
@@ -386,8 +408,8 @@ const ShortestPathAll = observer(() => {
 
             const timerId = dataAnalyzeStore.addTempExecLog();
             await dataAnalyzeStore.fetchGraphs({
-              url: 'allshortpath',
-              type: Algorithm.shortestPathAll
+              url: 'personalrank',
+              type: Algorithm.personalRankRecommendation
             });
             await dataAnalyzeStore.fetchExecutionLogs();
             window.clearTimeout(timerId);
@@ -399,7 +421,7 @@ const ShortestPathAll = observer(() => {
           style={styles.primaryButton}
           disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
           onClick={() => {
-            algorithmAnalyzerStore.resetShortestPathAllParams();
+            algorithmAnalyzerStore.resetPersonalRankParams();
           }}
         >
           {t('data-analyze.manipulations.reset')}
@@ -409,4 +431,4 @@ const ShortestPathAll = observer(() => {
   );
 });
 
-export default ShortestPathAll;
+export default PersonalRank;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/RadiographicInspection.tsx
similarity index 61%
copy from hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
copy to hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/RadiographicInspection.tsx
index 82ec79a..6eec096 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/RadiographicInspection.tsx
@@ -1,22 +1,35 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
-import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
+import { Button, Radio, Input, Select } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
+
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
-import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
 
-const ShortestPathAll = observer(() => {
-  const { t } = useTranslation();
+const RadiographicInspection = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
 
-  const isValidExec = !Object.values(
-    algorithmAnalyzerStore.shortestPathAllParams
-  ).some((value) => value === '');
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
+
+  const isValidExec =
+    Object.values(
+      algorithmAnalyzerStore.validateRadiographicInspectionParamsErrorMessage
+    ).every((value) => value === '') &&
+    algorithmAnalyzerStore.radiographicInspectionParams.source !== '' &&
+    algorithmAnalyzerStore.radiographicInspectionParams.max_depth !== '';
 
   return (
     <div className="query-tab-content-form">
@@ -26,34 +39,38 @@ const ShortestPathAll = observer(() => {
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.source'
+                'data-analyze.algorithm-forms.radiographic-inspection.options.source'
               )}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.radiographic-inspection.placeholder.input-source-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .source
+              algorithmAnalyzerStore
+                .validateRadiographicInspectionParamsErrorMessage.source
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.source}
+            value={algorithmAnalyzerStore.radiographicInspectionParams.source}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateRadiographicInspectionParams(
                 'source',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('source');
+              algorithmAnalyzerStore.validateRadiographicInspectionParams(
+                'source'
+              );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('source');
+                algorithmAnalyzerStore.validateRadiographicInspectionParams(
+                  'source'
+                );
               }
             }}
           />
@@ -62,28 +79,30 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.label'
+                'data-analyze.algorithm-forms.radiographic-inspection.options.label'
               )}
             </span>
           </div>
           <Select
             size="medium"
             trigger="click"
-            value={algorithmAnalyzerStore.shortestPathAllParams.label}
+            value={algorithmAnalyzerStore.radiographicInspectionParams.label}
             notFoundContent={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.no-edge-types'
+              'data-analyze.algorithm-forms.radiographic-inspection.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateRadiographicInspectionParams(
                 'label',
                 value
               );
             }}
           >
             <Select.Option value="__all__" key="__all__">
-              {t('data-analyze.algorithm-forms.shortest-path-all.pre-value')}
+              {t(
+                'data-analyze.algorithm-forms.radiographic-inspection.pre-value'
+              )}
             </Select.Option>
             {dataAnalyzeStore.edgeTypes.map(({ name }) => (
               <Select.Option value={name} key={name}>
@@ -99,94 +118,17 @@ const ShortestPathAll = observer(() => {
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.target'
-              )}
-            </span>
-          </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .target
-            }
-            value={algorithmAnalyzerStore.shortestPathAllParams.target}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'target',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateShortestPathAllParams('target');
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('target');
-              }
-            }}
-          />
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_degree'
-              )}
-            </span>
-          </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .max_degree
-            }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_degree}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'max_degree',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateShortestPathAllParams(
-                'max_degree'
-              );
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'max_degree'
-                );
-              }
-            }}
-          />
-        </div>
-      </div>
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <i>*</i>
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.direction'
+                'data-analyze.algorithm-forms.radiographic-inspection.options.direction'
               )}
             </span>
           </div>
           <Radio.Group
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            value={algorithmAnalyzerStore.shortestPathAllParams.direction}
+            value={
+              algorithmAnalyzerStore.radiographicInspectionParams.direction
+            }
             onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateRadiographicInspectionParams(
                 'direction',
                 e.target.value
               );
@@ -201,35 +143,65 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.capacity'
+                'data-analyze.algorithm-forms.radiographic-inspection.options.max_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.radiographic-inspection.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.radiographic-inspection.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .capacity
+              algorithmAnalyzerStore
+                .validateRadiographicInspectionParamsErrorMessage.max_degree
+            }
+            value={
+              algorithmAnalyzerStore.radiographicInspectionParams.max_degree
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.capacity}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'capacity',
+              algorithmAnalyzerStore.mutateRadiographicInspectionParams(
+                'max_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('capacity');
+              algorithmAnalyzerStore.validateRadiographicInspectionParams(
+                'max_degree'
+              );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'capacity'
+                algorithmAnalyzerStore.validateRadiographicInspectionParams(
+                  'max_degree'
                 );
               }
             }}
@@ -242,7 +214,7 @@ const ShortestPathAll = observer(() => {
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_depth'
+                'data-analyze.algorithm-forms.radiographic-inspection.options.max_depth'
               )}
             </span>
             <CustomTooltip
@@ -260,7 +232,7 @@ const ShortestPathAll = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.max-depth'
+                'data-analyze.algorithm-forms.radiographic-inspection.hint.max-depth'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -273,29 +245,33 @@ const ShortestPathAll = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.radiographic-inspection.placeholder.input-positive-integer'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .max_depth
+              algorithmAnalyzerStore
+                .validateRadiographicInspectionParamsErrorMessage.max_depth
+            }
+            value={
+              algorithmAnalyzerStore.radiographicInspectionParams.max_depth
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_depth}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateRadiographicInspectionParams(
                 'max_depth',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('max_depth');
+              algorithmAnalyzerStore.validateRadiographicInspectionParams(
+                'max_depth'
+              );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
+                algorithmAnalyzerStore.validateRadiographicInspectionParams(
                   'max_depth'
                 );
               }
@@ -306,63 +282,80 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.skip_degree'
+                'data-analyze.algorithm-forms.radiographic-inspection.options.capacity'
               )}
             </span>
-            <CustomTooltip
-              trigger="hover"
-              placement="bottom-start"
-              modifiers={{
-                offset: {
-                  offset: '0, 8'
-                }
-              }}
-              tooltipWrapperProps={{
-                className: 'tooltips-dark',
-                style: {
-                  zIndex: 7
-                }
-              }}
-              tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.skip-degree'
+          </div>
+          <Input
+            width={formWidth}
+            size="medium"
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            placeholder={t(
+              'data-analyze.algorithm-forms.radiographic-inspection.placeholder.input-positive-integer-or-negative-one-capacity'
+            )}
+            errorLocation="layer"
+            errorMessage={
+              algorithmAnalyzerStore
+                .validateRadiographicInspectionParamsErrorMessage.capacity
+            }
+            value={algorithmAnalyzerStore.radiographicInspectionParams.capacity}
+            onChange={(e: any) => {
+              algorithmAnalyzerStore.mutateRadiographicInspectionParams(
+                'capacity',
+                e.value as string
+              );
+
+              algorithmAnalyzerStore.validateRadiographicInspectionParams(
+                'capacity'
+              );
+            }}
+            originInputProps={{
+              onBlur() {
+                algorithmAnalyzerStore.validateRadiographicInspectionParams(
+                  'capacity'
+                );
+              }
+            }}
+          />
+        </div>
+      </div>
+      <div className="query-tab-content-form-row">
+        <div className="query-tab-content-form-item"></div>
+        <div className="query-tab-content-form-item">
+          <div className="query-tab-content-form-item-title">
+            <span>
+              {t(
+                'data-analyze.algorithm-forms.radiographic-inspection.options.limit'
               )}
-              childrenProps={{
-                src: QuestionMarkIcon,
-                alt: 'hint',
-                style: {
-                  marginLeft: 5
-                }
-              }}
-              childrenWrapperElement="img"
-            />
+            </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.radiographic-inspection.placeholder.input-positive-integer-or-negative-one-limit'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .skip_degree
+              algorithmAnalyzerStore
+                .validateRadiographicInspectionParamsErrorMessage.limit
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.skip_degree}
+            value={algorithmAnalyzerStore.radiographicInspectionParams.limit}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'skip_degree',
+              algorithmAnalyzerStore.mutateRadiographicInspectionParams(
+                'limit',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams(
-                'skip_degree'
+              algorithmAnalyzerStore.validateRadiographicInspectionParams(
+                'limit'
               );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'skip_degree'
+                algorithmAnalyzerStore.validateRadiographicInspectionParams(
+                  'limit'
                 );
               }
             }}
@@ -386,8 +379,8 @@ const ShortestPathAll = observer(() => {
 
             const timerId = dataAnalyzeStore.addTempExecLog();
             await dataAnalyzeStore.fetchGraphs({
-              url: 'allshortpath',
-              type: Algorithm.shortestPathAll
+              url: 'rays',
+              type: Algorithm.radiographicInspection
             });
             await dataAnalyzeStore.fetchExecutionLogs();
             window.clearTimeout(timerId);
@@ -399,7 +392,7 @@ const ShortestPathAll = observer(() => {
           style={styles.primaryButton}
           disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
           onClick={() => {
-            algorithmAnalyzerStore.resetShortestPathAllParams();
+            algorithmAnalyzerStore.resetRadiographicInspectionParams();
           }}
         >
           {t('data-analyze.manipulations.reset')}
@@ -409,4 +402,4 @@ const ShortestPathAll = observer(() => {
   );
 });
 
-export default ShortestPathAll;
+export default RadiographicInspection;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/SameNeighbor.tsx
similarity index 54%
copy from hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx
copy to hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/SameNeighbor.tsx
index 50f62eb..d7afc70 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/SameNeighbor.tsx
@@ -1,25 +1,35 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
-import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
+import { Button, Radio, Input, Select } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
+
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
 import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
 
-const LoopDetection = observer(() => {
-  const { t } = useTranslation();
+const SameNeighbor = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
 
   const isValidExec =
     Object.values(
-      algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
+      algorithmAnalyzerStore.validateSameNeighborParamsErrorMessage
     ).every((value) => value === '') &&
-    algorithmAnalyzerStore.loopDetectionParams.source !== '' &&
-    algorithmAnalyzerStore.loopDetectionParams.max_depth !== '';
+    algorithmAnalyzerStore.sameNeighborParams.vertex !== '' &&
+    algorithmAnalyzerStore.sameNeighborParams.other !== '';
 
   return (
     <div className="query-tab-content-form">
@@ -28,33 +38,33 @@ const LoopDetection = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t('data-analyze.algorithm-forms.loop-detection.options.source')}
+              {t('data-analyze.algorithm-forms.same-neighbor.options.vertex')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.same-neighbor.placeholder.input-source-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
-                .source
+              algorithmAnalyzerStore.validateSameNeighborParamsErrorMessage
+                .vertex
             }
-            value={algorithmAnalyzerStore.loopDetectionParams.source}
+            value={algorithmAnalyzerStore.sameNeighborParams.vertex}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
-                'source',
+              algorithmAnalyzerStore.mutateSameNeighborParams(
+                'vertex',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateLoopDetectionParams('source');
+              algorithmAnalyzerStore.validateSameNeighborParams('vertex');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams('source');
+                algorithmAnalyzerStore.validateSameNeighborParams('vertex');
               }
             }}
           />
@@ -62,24 +72,24 @@ const LoopDetection = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t('data-analyze.algorithm-forms.loop-detection.options.label')}
+              {t('data-analyze.algorithm-forms.same-neighbor.options.label')}
             </span>
           </div>
           <Select
             size="medium"
             trigger="click"
-            value={algorithmAnalyzerStore.loopDetectionParams.label}
+            value={algorithmAnalyzerStore.sameNeighborParams.label}
             notFoundContent={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.no-edge-types'
+              'data-analyze.algorithm-forms.same-neighbor.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams('label', value);
+              algorithmAnalyzerStore.mutateSameNeighborParams('label', value);
             }}
           >
             <Select.Option value="__all__" key="__all__">
-              {t('data-analyze.algorithm-forms.loop-detection.pre-value')}
+              {t('data-analyze.algorithm-forms.same-neighbor.pre-value')}
             </Select.Option>
             {dataAnalyzeStore.edgeTypes.map(({ name }) => (
               <Select.Option value={name} key={name}>
@@ -94,72 +104,42 @@ const LoopDetection = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.loop-detection.options.direction'
-              )}
-            </span>
-          </div>
-          <Radio.Group
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            value={algorithmAnalyzerStore.loopDetectionParams.direction}
-            onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
-                'direction',
-                e.target.value
-              );
-            }}
-          >
-            <Radio value="BOTH">both</Radio>
-            <Radio value="OUT">out</Radio>
-            <Radio value="IN">in</Radio>
-          </Radio.Group>
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.loop-detection.options.max_degree'
-              )}
+              {t('data-analyze.algorithm-forms.same-neighbor.options.other')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-integer'
+              'data-analyze.algorithm-forms.same-neighbor.placeholder.input-other-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
-                .max_degree
+              algorithmAnalyzerStore.validateSameNeighborParamsErrorMessage
+                .other
             }
-            value={algorithmAnalyzerStore.loopDetectionParams.max_degree}
+            value={algorithmAnalyzerStore.sameNeighborParams.other}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
-                'max_degree',
+              algorithmAnalyzerStore.mutateSameNeighborParams(
+                'other',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateLoopDetectionParams('max_degree');
+              algorithmAnalyzerStore.validateSameNeighborParams('other');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams(
-                  'max_degree'
-                );
+                algorithmAnalyzerStore.validateSameNeighborParams('other');
               }
             }}
           />
         </div>
-      </div>
-      <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
-            <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.loop-detection.options.max_depth'
+                'data-analyze.algorithm-forms.same-neighbor.options.max_degree'
               )}
             </span>
             <CustomTooltip
@@ -177,7 +157,7 @@ const LoopDetection = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.loop-detection.hint.max-depth'
+                'data-analyze.algorithm-forms.same-neighbor.hint.max-degree'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -190,63 +170,29 @@ const LoopDetection = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.same-neighbor.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
-                .max_depth
-            }
-            value={algorithmAnalyzerStore.loopDetectionParams.max_depth}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
-                'max_depth',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateLoopDetectionParams('max_depth');
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams('max_depth');
-              }
-            }}
-          />
-        </div>
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <span>
-              {t('data-analyze.algorithm-forms.loop-detection.options.limit')}
-            </span>
-          </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
-                .limit
+              algorithmAnalyzerStore.validateSameNeighborParamsErrorMessage
+                .max_degree
             }
-            value={algorithmAnalyzerStore.loopDetectionParams.limit}
+            value={algorithmAnalyzerStore.sameNeighborParams.max_degree}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
-                'limit',
+              algorithmAnalyzerStore.mutateSameNeighborParams(
+                'max_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateLoopDetectionParams('limit');
+              algorithmAnalyzerStore.validateSameNeighborParams('max_degree');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams('limit');
+                algorithmAnalyzerStore.validateSameNeighborParams('max_degree');
               }
             }}
           />
@@ -258,55 +204,55 @@ const LoopDetection = observer(() => {
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.loop-detection.options.source_in_ring'
+                'data-analyze.algorithm-forms.same-neighbor.options.direction'
               )}
             </span>
           </div>
-          <Switch
-            width={400}
-            size="medium"
+          <Radio.Group
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            checked={algorithmAnalyzerStore.loopDetectionParams.source_in_ring}
-            onChange={(checked: boolean) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
-                'source_in_ring',
-                checked
+            value={algorithmAnalyzerStore.sameNeighborParams.direction}
+            onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
+              algorithmAnalyzerStore.mutateSameNeighborParams(
+                'direction',
+                e.target.value
               );
             }}
-          />
+          >
+            <Radio value="BOTH">both</Radio>
+            <Radio value="OUT">out</Radio>
+            <Radio value="IN">in</Radio>
+          </Radio.Group>
         </div>
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.loop-detection.options.capacity'
-              )}
+              {t('data-analyze.algorithm-forms.same-neighbor.options.limit')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.same-neighbor.placeholder.input-positive-integer-or-negative-one-limit'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage
-                .capacity
+              algorithmAnalyzerStore.validateSameNeighborParamsErrorMessage
+                .limit
             }
-            value={algorithmAnalyzerStore.loopDetectionParams.capacity}
+            value={algorithmAnalyzerStore.sameNeighborParams.limit}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateLoopDetectionParams(
-                'capacity',
+              algorithmAnalyzerStore.mutateSameNeighborParams(
+                'limit',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateLoopDetectionParams('capacity');
+              algorithmAnalyzerStore.validateSameNeighborParams('limit');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateLoopDetectionParams('capacity');
+                algorithmAnalyzerStore.validateSameNeighborParams('limit');
               }
             }}
           />
@@ -329,8 +275,8 @@ const LoopDetection = observer(() => {
 
             const timerId = dataAnalyzeStore.addTempExecLog();
             await dataAnalyzeStore.fetchGraphs({
-              url: 'rings',
-              type: Algorithm.loopDetection
+              url: 'sameneighbors',
+              type: Algorithm.sameNeighbor
             });
             await dataAnalyzeStore.fetchExecutionLogs();
             window.clearTimeout(timerId);
@@ -342,7 +288,7 @@ const LoopDetection = observer(() => {
           style={styles.primaryButton}
           disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
           onClick={() => {
-            algorithmAnalyzerStore.resetLoopDetectionParams();
+            algorithmAnalyzerStore.resetSameNeighborParams();
           }}
         >
           {t('data-analyze.manipulations.reset')}
@@ -352,4 +298,4 @@ const LoopDetection = observer(() => {
   );
 });
 
-export default LoopDetection;
+export default SameNeighbor;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPath.tsx
similarity index 59%
copy from hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
copy to hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPath.tsx
index 82ec79a..3e1507b 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPath.tsx
@@ -1,22 +1,36 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
-import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
+import { Button, Radio, Input, Select } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
+
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
 import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
-const ShortestPathAll = observer(() => {
-  const { t } = useTranslation();
+const ShortestPath = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
 
-  const isValidExec = !Object.values(
-    algorithmAnalyzerStore.shortestPathAllParams
-  ).some((value) => value === '');
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
+
+  const isValidExec =
+    Object.values(
+      algorithmAnalyzerStore.validateShortestPathParamsErrorMessage
+    ).every((value) => value === '') &&
+    algorithmAnalyzerStore.shortestPathAlgorithmParams.source !== '' &&
+    algorithmAnalyzerStore.shortestPathAlgorithmParams.target !== '' &&
+    algorithmAnalyzerStore.shortestPathAlgorithmParams.max_depth !== '';
 
   return (
     <div className="query-tab-content-form">
@@ -25,35 +39,33 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.source'
-              )}
+              {t('data-analyze.algorithm-forms.shortest-path.options.source')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.shortest-path.placeholder.input-source-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
+              algorithmAnalyzerStore.validateShortestPathParamsErrorMessage
                 .source
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.source}
+            value={algorithmAnalyzerStore.shortestPathAlgorithmParams.source}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateShortestPathParams(
                 'source',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('source');
+              algorithmAnalyzerStore.validateShortestPathParams('source');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('source');
+                algorithmAnalyzerStore.validateShortestPathParams('source');
               }
             }}
           />
@@ -61,29 +73,24 @@ const ShortestPathAll = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.label'
-              )}
+              {t('data-analyze.algorithm-forms.shortest-path.options.label')}
             </span>
           </div>
           <Select
             size="medium"
             trigger="click"
-            value={algorithmAnalyzerStore.shortestPathAllParams.label}
+            value={algorithmAnalyzerStore.shortestPathAlgorithmParams.label}
             notFoundContent={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.no-edge-types'
+              'data-analyze.algorithm-forms.shortest-path.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'label',
-                value
-              );
+              algorithmAnalyzerStore.mutateShortestPathParams('label', value);
             }}
           >
             <Select.Option value="__all__" key="__all__">
-              {t('data-analyze.algorithm-forms.shortest-path-all.pre-value')}
+              {t('data-analyze.algorithm-forms.shortest-path.pre-value')}
             </Select.Option>
             {dataAnalyzeStore.edgeTypes.map(({ name }) => (
               <Select.Option value={name} key={name}>
@@ -98,35 +105,33 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <i>*</i>
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.target'
-              )}
+              {t('data-analyze.algorithm-forms.shortest-path.options.target')}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.shortest-path.placeholder.input-target-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
+              algorithmAnalyzerStore.validateShortestPathParamsErrorMessage
                 .target
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.target}
+            value={algorithmAnalyzerStore.shortestPathAlgorithmParams.target}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateShortestPathParams(
                 'target',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('target');
+              algorithmAnalyzerStore.validateShortestPathParams('target');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('target');
+                algorithmAnalyzerStore.validateShortestPathParams('target');
               }
             }}
           />
@@ -135,38 +140,62 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_degree'
+                'data-analyze.algorithm-forms.shortest-path.options.max_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.shortest-path.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-integer'
+              'data-analyze.algorithm-forms.shortest-path.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
+              algorithmAnalyzerStore.validateShortestPathParamsErrorMessage
                 .max_degree
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_degree}
+            value={
+              algorithmAnalyzerStore.shortestPathAlgorithmParams.max_degree
+            }
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateShortestPathParams(
                 'max_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams(
-                'max_degree'
-              );
+              algorithmAnalyzerStore.validateShortestPathParams('max_degree');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'max_degree'
-                );
+                algorithmAnalyzerStore.validateShortestPathParams('max_degree');
               }
             }}
           />
@@ -178,15 +207,15 @@ const ShortestPathAll = observer(() => {
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.direction'
+                'data-analyze.algorithm-forms.shortest-path.options.direction'
               )}
             </span>
           </div>
           <Radio.Group
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            value={algorithmAnalyzerStore.shortestPathAllParams.direction}
+            value={algorithmAnalyzerStore.shortestPathAlgorithmParams.direction}
             onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateShortestPathParams(
                 'direction',
                 e.target.value
               );
@@ -201,35 +230,63 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.capacity'
+                'data-analyze.algorithm-forms.shortest-path.options.skip_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.shortest-path.hint.skip-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.shortest-path.placeholder.input-integer'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .capacity
+              algorithmAnalyzerStore.validateShortestPathParamsErrorMessage
+                .skip_degree
+            }
+            value={
+              algorithmAnalyzerStore.shortestPathAlgorithmParams.skip_degree
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.capacity}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'capacity',
+              algorithmAnalyzerStore.mutateShortestPathParams(
+                'skip_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('capacity');
+              algorithmAnalyzerStore.validateShortestPathParams('skip_degree');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'capacity'
+                algorithmAnalyzerStore.validateShortestPathParams(
+                  'skip_degree'
                 );
               }
             }}
@@ -242,7 +299,7 @@ const ShortestPathAll = observer(() => {
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_depth'
+                'data-analyze.algorithm-forms.shortest-path.options.max_depth'
               )}
             </span>
             <CustomTooltip
@@ -260,7 +317,7 @@ const ShortestPathAll = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.max-depth'
+                'data-analyze.algorithm-forms.shortest-path.hint.max-depth'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -273,31 +330,29 @@ const ShortestPathAll = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.shortest-path.placeholder.input-positive-integer'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
+              algorithmAnalyzerStore.validateShortestPathParamsErrorMessage
                 .max_depth
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_depth}
+            value={algorithmAnalyzerStore.shortestPathAlgorithmParams.max_depth}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateShortestPathParams(
                 'max_depth',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('max_depth');
+              algorithmAnalyzerStore.validateShortestPathParams('max_depth');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'max_depth'
-                );
+                algorithmAnalyzerStore.validateShortestPathParams('max_depth');
               }
             }}
           />
@@ -305,65 +360,33 @@ const ShortestPathAll = observer(() => {
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.skip_degree'
-              )}
+              {t('data-analyze.algorithm-forms.shortest-path.options.capacity')}
             </span>
-            <CustomTooltip
-              trigger="hover"
-              placement="bottom-start"
-              modifiers={{
-                offset: {
-                  offset: '0, 8'
-                }
-              }}
-              tooltipWrapperProps={{
-                className: 'tooltips-dark',
-                style: {
-                  zIndex: 7
-                }
-              }}
-              tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.skip-degree'
-              )}
-              childrenProps={{
-                src: QuestionMarkIcon,
-                alt: 'hint',
-                style: {
-                  marginLeft: 5
-                }
-              }}
-              childrenWrapperElement="img"
-            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.shortest-path.placeholder.input-positive-integer-or-negative-one-capacity'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .skip_degree
+              algorithmAnalyzerStore.validateShortestPathParamsErrorMessage
+                .capacity
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.skip_degree}
+            value={algorithmAnalyzerStore.shortestPathAlgorithmParams.capacity}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'skip_degree',
+              algorithmAnalyzerStore.mutateShortestPathParams(
+                'capacity',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams(
-                'skip_degree'
-              );
+              algorithmAnalyzerStore.validateShortestPathParams('capacity');
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'skip_degree'
-                );
+                algorithmAnalyzerStore.validateShortestPathParams('capacity');
               }
             }}
           />
@@ -386,8 +409,8 @@ const ShortestPathAll = observer(() => {
 
             const timerId = dataAnalyzeStore.addTempExecLog();
             await dataAnalyzeStore.fetchGraphs({
-              url: 'allshortpath',
-              type: Algorithm.shortestPathAll
+              url: 'shortpath',
+              type: Algorithm.shortestPath
             });
             await dataAnalyzeStore.fetchExecutionLogs();
             window.clearTimeout(timerId);
@@ -399,7 +422,9 @@ const ShortestPathAll = observer(() => {
           style={styles.primaryButton}
           disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
           onClick={() => {
-            algorithmAnalyzerStore.resetShortestPathAllParams();
+            algorithmAnalyzerStore.resetShortestPathParams();
+            // temp solution
+            algorithmAnalyzerStore.mutateShortestPathParams('label', '__all__');
           }}
         >
           {t('data-analyze.manipulations.reset')}
@@ -409,4 +434,4 @@ const ShortestPathAll = observer(() => {
   );
 });
 
-export default ShortestPathAll;
+export default ShortestPath;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
index 82ec79a..ff2caed 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
@@ -2,21 +2,35 @@ import React, { useContext, createContext } from 'react';
 import { observer } from 'mobx-react';
 import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
+
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
 import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
 
 const ShortestPathAll = observer(() => {
-  const { t } = useTranslation();
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    400
+  );
 
-  const isValidExec = !Object.values(
-    algorithmAnalyzerStore.shortestPathAllParams
-  ).some((value) => value === '');
+  const isValidExec =
+    Object.values(
+      algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
+    ).every((value) => value === '') &&
+    algorithmAnalyzerStore.shortestPathAllParams.source !== '' &&
+    algorithmAnalyzerStore.shortestPathAllParams.target !== '' &&
+    algorithmAnalyzerStore.shortestPathAllParams.max_depth !== '';
 
   return (
     <div className="query-tab-content-form">
@@ -31,7 +45,7 @@ const ShortestPathAll = observer(() => {
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
@@ -74,7 +88,7 @@ const ShortestPathAll = observer(() => {
               'data-analyze.algorithm-forms.shortest-path-all.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
               algorithmAnalyzerStore.mutateShortestPathAllParams(
                 'label',
@@ -104,11 +118,11 @@ const ShortestPathAll = observer(() => {
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-target-id'
             )}
             errorLocation="layer"
             errorMessage={
@@ -138,13 +152,39 @@ const ShortestPathAll = observer(() => {
                 'data-analyze.algorithm-forms.shortest-path-all.options.max_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.shortest-path-all.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-integer'
+              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
@@ -206,11 +246,11 @@ const ShortestPathAll = observer(() => {
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer-or-negative-one-capacity'
             )}
             errorLocation="layer"
             errorMessage={
@@ -273,7 +313,7 @@ const ShortestPathAll = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
@@ -337,11 +377,11 @@ const ShortestPathAll = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-integer'
             )}
             errorLocation="layer"
             errorMessage={
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/SingleSourceWeightedShortestPath.tsx
similarity index 51%
copy from hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
copy to hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/SingleSourceWeightedShortestPath.tsx
index 82ec79a..342f951 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/SingleSourceWeightedShortestPath.tsx
@@ -1,59 +1,82 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
 import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
+
+import { GraphManagementStoreContext } from '../../../../stores';
+import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { isDataTypeNumeric, calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
-import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
 
-const ShortestPathAll = observer(() => {
-  const { t } = useTranslation();
+const SingleSourceWeightedShortestPath = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
+
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    340,
+    380
+  );
 
-  const isValidExec = !Object.values(
-    algorithmAnalyzerStore.shortestPathAllParams
-  ).some((value) => value === '');
+  const isValidExec =
+    Object.values(
+      algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParamsErrorMessage
+    ).every((value) => value === '') &&
+    algorithmAnalyzerStore.singleSourceWeightedShortestPathParams.source !== '';
 
   return (
     <div className="query-tab-content-form">
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 118 }}
+          >
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.source'
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.options.source'
               )}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.single-source-weighted-shortest-path.placeholder.input-source-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
+              algorithmAnalyzerStore
+                .validateSingleSourceWeightedShortestPathParamsErrorMessage
+                .source
+            }
+            value={
+              algorithmAnalyzerStore.singleSourceWeightedShortestPathParams
                 .source
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.source}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
                 'source',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('source');
+              algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
+                'source'
+              );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('source');
+                algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
+                  'source'
+                );
               }
             }}
           />
@@ -62,28 +85,33 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.label'
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.options.label'
               )}
             </span>
           </div>
           <Select
             size="medium"
             trigger="click"
-            value={algorithmAnalyzerStore.shortestPathAllParams.label}
+            value={
+              algorithmAnalyzerStore.singleSourceWeightedShortestPathParams
+                .label
+            }
             notFoundContent={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.no-edge-types'
+              'data-analyze.algorithm-forms.single-source-weighted-shortest-path.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
                 'label',
                 value
               );
             }}
           >
             <Select.Option value="__all__" key="__all__">
-              {t('data-analyze.algorithm-forms.shortest-path-all.pre-value')}
+              {t(
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.pre-value'
+              )}
             </Select.Option>
             {dataAnalyzeStore.edgeTypes.map(({ name }) => (
               <Select.Option value={name} key={name}>
@@ -95,76 +123,99 @@ const ShortestPathAll = observer(() => {
       </div>
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 118 }}
+          >
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.target'
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.options.direction'
               )}
             </span>
           </div>
-          <Input
-            width={400}
-            size="medium"
+          <Radio.Group
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .target
+            value={
+              algorithmAnalyzerStore.singleSourceWeightedShortestPathParams
+                .direction
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.target}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'target',
-                e.value as string
+            onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
+              algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
+                'direction',
+                e.target.value
               );
-
-              algorithmAnalyzerStore.validateShortestPathAllParams('target');
             }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('target');
-              }
-            }}
-          />
+          >
+            <Radio value="BOTH">both</Radio>
+            <Radio value="OUT">out</Radio>
+            <Radio value="IN">in</Radio>
+          </Radio.Group>
         </div>
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_degree'
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.options.max_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-integer'
+              'data-analyze.algorithm-forms.single-source-weighted-shortest-path.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
+              algorithmAnalyzerStore
+                .validateSingleSourceWeightedShortestPathParamsErrorMessage
+                .max_degree
+            }
+            value={
+              algorithmAnalyzerStore.singleSourceWeightedShortestPathParams
                 .max_degree
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_degree}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
                 'max_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams(
+              algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
                 'max_degree'
               );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
+                algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
                   'max_degree'
                 );
               }
@@ -174,62 +225,118 @@ const ShortestPathAll = observer(() => {
       </div>
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <i>*</i>
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 118 }}
+          >
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.direction'
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.options.weight'
               )}
             </span>
           </div>
-          <Radio.Group
+          <Select
+            size="medium"
+            trigger="click"
+            value={
+              algorithmAnalyzerStore.singleSourceWeightedShortestPathParams
+                .weight
+            }
+            notFoundContent={t(
+              'data-analyze.algorithm-forms.single-source-weighted-shortest-path.placeholder.no-edge-types'
+            )}
+            selectorName={t(
+              'data-analyze.algorithm-forms.single-source-weighted-shortest-path.placeholder.no-property'
+            )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            value={algorithmAnalyzerStore.shortestPathAllParams.direction}
-            onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'direction',
-                e.target.value
+            width={formWidth}
+            onChange={(value: string) => {
+              algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
+                'weight',
+                value
               );
             }}
           >
-            <Radio value="BOTH">both</Radio>
-            <Radio value="OUT">out</Radio>
-            <Radio value="IN">in</Radio>
-          </Radio.Group>
+            {dataAnalyzeStore.allPropertiesFromEdge
+              .filter((propertyName) =>
+                isDataTypeNumeric(
+                  dataAnalyzeStore.properties.find(
+                    ({ name }) => name === propertyName
+                  )?.data_type
+                )
+              )
+              .map((propertyName) => (
+                <Select.Option value={propertyName} key={propertyName}>
+                  {propertyName}
+                </Select.Option>
+              ))}
+          </Select>
         </div>
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.capacity'
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.options.skip_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.hint.skip-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.single-source-weighted-shortest-path.placeholder.input-integer'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .capacity
+              algorithmAnalyzerStore
+                .validateSingleSourceWeightedShortestPathParamsErrorMessage
+                .skip_degree
+            }
+            value={
+              algorithmAnalyzerStore.singleSourceWeightedShortestPathParams
+                .skip_degree
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.capacity}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'capacity',
+              algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
+                'skip_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('capacity');
+              algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
+                'skip_degree'
+              );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'capacity'
+                algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
+                  'skip_degree'
                 );
               }
             }}
@@ -238,131 +345,117 @@ const ShortestPathAll = observer(() => {
       </div>
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <i>*</i>
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 118 }}
+          >
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_depth'
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.options.with_vertex'
               )}
             </span>
-            <CustomTooltip
-              trigger="hover"
-              placement="bottom-start"
-              modifiers={{
-                offset: {
-                  offset: '0, 8'
-                }
-              }}
-              tooltipWrapperProps={{
-                className: 'tooltips-dark',
-                style: {
-                  zIndex: 7
-                }
-              }}
-              tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.max-depth'
+          </div>
+          <Switch
+            size="medium"
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            checked={
+              algorithmAnalyzerStore.singleSourceWeightedShortestPathParams
+                .with_vertex
+            }
+            onChange={(checked: boolean) => {
+              algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
+                'with_vertex',
+                checked
+              );
+            }}
+          />
+        </div>
+        <div className="query-tab-content-form-item">
+          <div className="query-tab-content-form-item-title">
+            <span>
+              {t(
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.options.capacity'
               )}
-              childrenProps={{
-                src: QuestionMarkIcon,
-                alt: 'hint',
-                style: {
-                  marginLeft: 5
-                }
-              }}
-              childrenWrapperElement="img"
-            />
+            </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.single-source-weighted-shortest-path.placeholder.input-positive-integer-or-negative-one-capacity'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .max_depth
+              algorithmAnalyzerStore
+                .validateSingleSourceWeightedShortestPathParamsErrorMessage
+                .capacity
+            }
+            value={
+              algorithmAnalyzerStore.singleSourceWeightedShortestPathParams
+                .capacity
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_depth}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'max_depth',
+              algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
+                'capacity',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('max_depth');
+              algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
+                'capacity'
+              );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'max_depth'
+                algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
+                  'capacity'
                 );
               }
             }}
           />
         </div>
+      </div>
+      <div className="query-tab-content-form-row">
+        <div className="query-tab-content-form-item"></div>
         <div className="query-tab-content-form-item">
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.skip_degree'
+                'data-analyze.algorithm-forms.single-source-weighted-shortest-path.options.limit'
               )}
             </span>
-            <CustomTooltip
-              trigger="hover"
-              placement="bottom-start"
-              modifiers={{
-                offset: {
-                  offset: '0, 8'
-                }
-              }}
-              tooltipWrapperProps={{
-                className: 'tooltips-dark',
-                style: {
-                  zIndex: 7
-                }
-              }}
-              tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.skip-degree'
-              )}
-              childrenProps={{
-                src: QuestionMarkIcon,
-                alt: 'hint',
-                style: {
-                  marginLeft: 5
-                }
-              }}
-              childrenWrapperElement="img"
-            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.single-source-weighted-shortest-path.placeholder.input-positive-integer-or-negative-one-limit'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .skip_degree
+              algorithmAnalyzerStore
+                .validateSingleSourceWeightedShortestPathParamsErrorMessage
+                .limit
+            }
+            value={
+              algorithmAnalyzerStore.singleSourceWeightedShortestPathParams
+                .limit
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.skip_degree}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'skip_degree',
+              algorithmAnalyzerStore.mutateSingleSourceWeightedShortestPathParams(
+                'limit',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams(
-                'skip_degree'
+              algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
+                'limit'
               );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'skip_degree'
+                algorithmAnalyzerStore.validateSingleSourceWeightedShortestPathParams(
+                  'limit'
                 );
               }
             }}
@@ -386,8 +479,8 @@ const ShortestPathAll = observer(() => {
 
             const timerId = dataAnalyzeStore.addTempExecLog();
             await dataAnalyzeStore.fetchGraphs({
-              url: 'allshortpath',
-              type: Algorithm.shortestPathAll
+              url: 'singleshortpath',
+              type: Algorithm.singleSourceWeightedShortestPath
             });
             await dataAnalyzeStore.fetchExecutionLogs();
             window.clearTimeout(timerId);
@@ -399,7 +492,7 @@ const ShortestPathAll = observer(() => {
           style={styles.primaryButton}
           disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
           onClick={() => {
-            algorithmAnalyzerStore.resetShortestPathAllParams();
+            algorithmAnalyzerStore.resetSingleSourceWeightedShortestPathParams();
           }}
         >
           {t('data-analyze.manipulations.reset')}
@@ -409,4 +502,4 @@ const ShortestPathAll = observer(() => {
   );
 });
 
-export default ShortestPathAll;
+export default SingleSourceWeightedShortestPath;
diff --git a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/WeightedShortestPath.tsx
similarity index 53%
copy from hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
copy to hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/WeightedShortestPath.tsx
index 82ec79a..07fcdc2 100644
--- a/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/ShortestPathAll.tsx
+++ b/hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/WeightedShortestPath.tsx
@@ -1,59 +1,80 @@
-import React, { useContext, createContext } from 'react';
+import React, { useContext } from 'react';
 import { observer } from 'mobx-react';
 import { Button, Radio, Input, Select, Switch } from 'hubble-ui';
 import { useTranslation } from 'react-i18next';
 import { styles } from '../QueryAndAlgorithmLibrary';
 import { Tooltip as CustomTooltip } from '../../../common';
+
+import { GraphManagementStoreContext } from '../../../../stores';
 import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore';
+import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
+import { isDataTypeNumeric, calcAlgorithmFormWidth } from '../../../../utils';
 
 import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg';
-import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore';
 
-const ShortestPathAll = observer(() => {
-  const { t } = useTranslation();
+const WeightedShortestPath = observer(() => {
+  const graphManagementStore = useContext(GraphManagementStoreContext);
   const dataAnalyzeStore = useContext(DataAnalyzeStore);
   const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore;
+  const { t } = useTranslation();
 
-  const isValidExec = !Object.values(
-    algorithmAnalyzerStore.shortestPathAllParams
-  ).some((value) => value === '');
+  const formWidth = calcAlgorithmFormWidth(
+    graphManagementStore.isExpanded,
+    320,
+    390
+  );
+
+  const isValidExec =
+    Object.values(
+      algorithmAnalyzerStore.validateWeightedShortestPathParamsErrorMessage
+    ).every((value) => value === '') &&
+    algorithmAnalyzerStore.weightedShortestPathParams.source !== '' &&
+    algorithmAnalyzerStore.weightedShortestPathParams.target !== '' &&
+    algorithmAnalyzerStore.weightedShortestPathParams.weight !== '';
 
   return (
     <div className="query-tab-content-form">
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 118 }}
+          >
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.source'
+                'data-analyze.algorithm-forms.weighted-shortest-path.options.source'
               )}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.weighted-shortest-path.placeholder.input-source-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .source
+              algorithmAnalyzerStore
+                .validateWeightedShortestPathParamsErrorMessage.source
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.source}
+            value={algorithmAnalyzerStore.weightedShortestPathParams.source}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateWeightedShortestPathParams(
                 'source',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('source');
+              algorithmAnalyzerStore.validateWeightedShortestPathParams(
+                'source'
+              );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('source');
+                algorithmAnalyzerStore.validateWeightedShortestPathParams(
+                  'source'
+                );
               }
             }}
           />
@@ -62,28 +83,30 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.label'
+                'data-analyze.algorithm-forms.weighted-shortest-path.options.label'
               )}
             </span>
           </div>
           <Select
             size="medium"
             trigger="click"
-            value={algorithmAnalyzerStore.shortestPathAllParams.label}
+            value={algorithmAnalyzerStore.weightedShortestPathParams.label}
             notFoundContent={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.no-edge-types'
+              'data-analyze.algorithm-forms.weighted-shortest-path.placeholder.no-edge-types'
             )}
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            width={400}
+            width={formWidth}
             onChange={(value: string) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateWeightedShortestPathParams(
                 'label',
                 value
               );
             }}
           >
             <Select.Option value="__all__" key="__all__">
-              {t('data-analyze.algorithm-forms.shortest-path-all.pre-value')}
+              {t(
+                'data-analyze.algorithm-forms.weighted-shortest-path.pre-value'
+              )}
             </Select.Option>
             {dataAnalyzeStore.edgeTypes.map(({ name }) => (
               <Select.Option value={name} key={name}>
@@ -95,38 +118,45 @@ const ShortestPathAll = observer(() => {
       </div>
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 118 }}
+          >
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.target'
+                'data-analyze.algorithm-forms.weighted-shortest-path.options.target'
               )}
             </span>
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-source-id'
+              'data-analyze.algorithm-forms.weighted-shortest-path.placeholder.input-target-id'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .target
+              algorithmAnalyzerStore
+                .validateWeightedShortestPathParamsErrorMessage.target
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.target}
+            value={algorithmAnalyzerStore.weightedShortestPathParams.target}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateWeightedShortestPathParams(
                 'target',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('target');
+              algorithmAnalyzerStore.validateWeightedShortestPathParams(
+                'target'
+              );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams('target');
+                algorithmAnalyzerStore.validateWeightedShortestPathParams(
+                  'target'
+                );
               }
             }}
           />
@@ -135,36 +165,62 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_degree'
+                'data-analyze.algorithm-forms.weighted-shortest-path.options.max_degree'
               )}
             </span>
+            <CustomTooltip
+              trigger="hover"
+              placement="bottom-start"
+              modifiers={{
+                offset: {
+                  offset: '0, 8'
+                }
+              }}
+              tooltipWrapperProps={{
+                className: 'tooltips-dark',
+                style: {
+                  zIndex: 7
+                }
+              }}
+              tooltipWrapper={t(
+                'data-analyze.algorithm-forms.weighted-shortest-path.hint.max-degree'
+              )}
+              childrenProps={{
+                src: QuestionMarkIcon,
+                alt: 'hint',
+                style: {
+                  marginLeft: 5
+                }
+              }}
+              childrenWrapperElement="img"
+            />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-integer'
+              'data-analyze.algorithm-forms.weighted-shortest-path.placeholder.input-positive-integer-or-negative-one-max-degree'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .max_degree
+              algorithmAnalyzerStore
+                .validateWeightedShortestPathParamsErrorMessage.max_degree
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_degree}
+            value={algorithmAnalyzerStore.weightedShortestPathParams.max_degree}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateWeightedShortestPathParams(
                 'max_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams(
+              algorithmAnalyzerStore.validateWeightedShortestPathParams(
                 'max_degree'
               );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
+                algorithmAnalyzerStore.validateWeightedShortestPathParams(
                   'max_degree'
                 );
               }
@@ -174,19 +230,22 @@ const ShortestPathAll = observer(() => {
       </div>
       <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 118 }}
+          >
             <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.direction'
+                'data-analyze.algorithm-forms.weighted-shortest-path.options.direction'
               )}
             </span>
           </div>
           <Radio.Group
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            value={algorithmAnalyzerStore.shortestPathAllParams.direction}
+            value={algorithmAnalyzerStore.weightedShortestPathParams.direction}
             onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
+              algorithmAnalyzerStore.mutateWeightedShortestPathParams(
                 'direction',
                 e.target.value
               );
@@ -201,48 +260,7 @@ const ShortestPathAll = observer(() => {
           <div className="query-tab-content-form-item-title">
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.capacity'
-              )}
-            </span>
-          </div>
-          <Input
-            width={400}
-            size="medium"
-            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
-            placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
-            )}
-            errorLocation="layer"
-            errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .capacity
-            }
-            value={algorithmAnalyzerStore.shortestPathAllParams.capacity}
-            onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'capacity',
-                e.value as string
-              );
-
-              algorithmAnalyzerStore.validateShortestPathAllParams('capacity');
-            }}
-            originInputProps={{
-              onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'capacity'
-                );
-              }
-            }}
-          />
-        </div>
-      </div>
-      <div className="query-tab-content-form-row">
-        <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
-            <i>*</i>
-            <span>
-              {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.max_depth'
+                'data-analyze.algorithm-forms.weighted-shortest-path.options.skip_degree'
               )}
             </span>
             <CustomTooltip
@@ -260,7 +278,7 @@ const ShortestPathAll = observer(() => {
                 }
               }}
               tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.max-depth'
+                'data-analyze.algorithm-forms.weighted-shortest-path.hint.skip-degree'
               )}
               childrenProps={{
                 src: QuestionMarkIcon,
@@ -273,102 +291,155 @@ const ShortestPathAll = observer(() => {
             />
           </div>
           <Input
-            width={400}
+            width={formWidth}
             size="medium"
             disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
             placeholder={t(
-              'data-analyze.algorithm-forms.shortest-path-all.placeholder.input-positive-integer'
+              'data-analyze.algorithm-forms.weighted-shortest-path.placeholder.input-integer'
             )}
             errorLocation="layer"
             errorMessage={
-              algorithmAnalyzerStore.validateShortestPathAllParamsErrorMessage
-                .max_depth
+              algorithmAnalyzerStore
+                .validateWeightedShortestPathParamsErrorMessage.skip_degree
+            }
+            value={
+              algorithmAnalyzerStore.weightedShortestPathParams.skip_degree
             }
-            value={algorithmAnalyzerStore.shortestPathAllParams.max_depth}
             onChange={(e: any) => {
-              algorithmAnalyzerStore.mutateShortestPathAllParams(
-                'max_depth',
+              algorithmAnalyzerStore.mutateWeightedShortestPathParams(
+                'skip_degree',
                 e.value as string
               );
 
-              algorithmAnalyzerStore.validateShortestPathAllParams('max_depth');
+              algorithmAnalyzerStore.validateWeightedShortestPathParams(
+                'skip_degree'
+              );
             }}
             originInputProps={{
               onBlur() {
-                algorithmAnalyzerStore.validateShortestPathAllParams(
-                  'max_depth'
+                algorithmAnalyzerStore.validateWeightedShortestPathParams(
+                  'skip_degree'
                 );
               }
             }}
           />
         </div>
+      </div>
+      <div className="query-tab-content-form-row">
         <div className="query-tab-content-form-item">
-          <div className="query-tab-content-form-item-title">
+          <div
+            className="query-tab-content-form-item-title"
+            style={{ minWidth: 118 }}
+          >
+            <i>*</i>
             <span>
               {t(
-                'data-analyze.algorithm-forms.shortest-path-all.options.skip_degree'
+                'data-analyze.algorithm-forms.weighted-shortest-path.options.weight'
               )}
             </span>
-            <CustomTooltip
-              trigger="hover"
-              placement="bottom-start"
-              modifiers={{
-                offset: {
-                  offset: '0, 8'
-                }
-              }}
-              tooltipWrapperProps={{
-                className: 'tooltips-dark',
-                style: {
-                  zIndex: 7
-                }
-              }}
-              tooltipWrapper={t(
-                'data-analyze.algorithm-forms.shortest-path-all.hint.skip-degree'
+          </div>
+          <Select
+            size="medium"
+            trigger="click"
+            value={algorithmAnalyzerStore.weightedShortestPathParams.weight}
+            notFoundContent={t(
+              'data-analyze.algorithm-forms.weighted-shortest-path.placeholder.no-property'
+            )}
+            selectorName={t(
+              'data-analyze.algorithm-forms.weighted-shortest-path.placeholder.select-property'
+            )}
+            disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'}
+            width={formWidth}
+            onChange={(value: string) => {
+              algorithmAnalyzerStore.mutateWeightedShortestPathParams(
+                'weight',
... 7832 lines suppressed ...