You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bigtop.apache.org by wu...@apache.org on 2024/10/28 15:07:16 UTC

(bigtop-manager) branch main updated: BIGTOP-4255: Refactor layout page (#94)

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

wuzhiguo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/bigtop-manager.git


The following commit(s) were added to refs/heads/main by this push:
     new 5451f3f  BIGTOP-4255: Refactor layout page (#94)
5451f3f is described below

commit 5451f3fd7e7e929eddd98013ca1151bae5151ce1
Author: Fdefined <55...@users.noreply.github.com>
AuthorDate: Mon Oct 28 23:07:11 2024 +0800

    BIGTOP-4255: Refactor layout page (#94)
---
 bigtop-manager-ui/.env.development                 |   1 +
 bigtop-manager-ui/.env.production                  |   1 +
 bigtop-manager-ui/src/App.vue                      |  18 +-
 bigtop-manager-ui/src/assets/images/svg/avatar.svg |  26 ++
 .../src/assets/images/svg/big-manager-logo.svg     | 189 ++++++++
 .../assets/images/svg/{history.svg => book.svg}    |  15 +-
 .../src/assets/images/svg/carbon-language.svg      |  23 -
 .../src/assets/images/svg/clusters.svg             |  44 ++
 .../src/assets/images/svg/clusters_activated.svg   |  44 ++
 .../src/assets/images/svg/communication.svg        |  37 ++
 .../images/svg/{full-screen.svg => components.svg} |  11 +-
 .../svg/{home.svg => components_activated.svg}     |  11 +-
 bigtop-manager-ui/src/assets/images/svg/github.svg |  30 ++
 bigtop-manager-ui/src/assets/images/svg/hosts.svg  |  31 ++
 .../src/assets/images/svg/hosts_activated.svg      |  31 ++
 .../src/assets/images/svg/infrastructures.svg      |  38 ++
 .../images/svg/infrastructures_activated.svg       |  38 ++
 .../src/assets/images/svg/language.svg             |  37 ++
 bigtop-manager-ui/src/assets/images/svg/model.svg  |  44 ++
 .../src/assets/images/svg/model_activated.svg      |  44 ++
 bigtop-manager-ui/src/assets/images/svg/plus.svg   |  19 +-
 .../src/assets/images/svg/restart.svg              |  26 --
 bigtop-manager-ui/src/assets/images/svg/robot.svg  |  31 --
 .../src/assets/images/svg/square-filled.svg        |  23 -
 bigtop-manager-ui/src/assets/images/svg/start.svg  |  26 --
 bigtop-manager-ui/src/assets/images/svg/stop.svg   |  26 --
 .../src/components/alert-info/index.vue            | 143 ------
 .../src/components/cluster-create/choose-stack.vue | 122 -----
 .../src/components/cluster-create/finish.vue       |  55 ---
 .../src/components/cluster-create/index.vue        | 242 ----------
 .../src/components/cluster-create/install.vue      | 154 -------
 .../components/cluster-create/set-cluster-name.vue |  80 ----
 .../src/components/cluster-create/set-hosts.vue    | 174 -------
 .../components/cluster-create/set-repository.vue   | 173 -------
 .../src/components/cluster-info/index.vue          |  68 ---
 .../src/components/common/dot-state/index.vue      |  77 ----
 bigtop-manager-ui/src/components/common/index.ts   |   2 -
 .../src/components/common/svg-icon/index.vue       |  12 +-
 .../src/components/dashboard/index.vue             | 325 --------------
 .../src/components/dashboard/tips.vue              |  49 --
 .../src/components/job-info/custom-progress.vue    | 103 -----
 .../src/components/job-info/index.vue              |  55 ---
 bigtop-manager-ui/src/components/job-info/job.vue  | 326 --------------
 .../src/components/job-info/stage.vue              |  82 ----
 .../src/components/job-info/task-log.vue           | 155 -------
 bigtop-manager-ui/src/components/job-info/task.vue |  91 ----
 .../src/components/select-lang/index.vue           |  19 +-
 .../components/service-add/assign-components.vue   | 207 ---------
 .../src/components/service-add/choose-services.vue | 167 -------
 .../components/service-add/configure-services.vue  | 157 -------
 .../src/components/service-add/finish.vue          |  55 ---
 .../src/components/service-add/index.vue           | 282 ------------
 .../src/components/service-add/install.vue         | 190 --------
 .../src/components/service/service-dropdown.vue    | 142 ------
 .../send.svg => components/theme-switch/index.vue} |  19 +-
 .../src/components/user-avatar/index.vue           |  25 +-
 bigtop-manager-ui/src/layouts/content.vue          |  60 ---
 .../images/svg/left.svg => layouts/default.vue}    |  15 +-
 bigtop-manager-ui/src/layouts/footer.vue           |  12 +-
 bigtop-manager-ui/src/layouts/header.vue           | 100 +++--
 bigtop-manager-ui/src/layouts/index.vue            |  64 ++-
 bigtop-manager-ui/src/layouts/sider.vue            | 184 ++++----
 bigtop-manager-ui/src/locales/en_US/ai.ts          |  33 --
 bigtop-manager-ui/src/locales/en_US/cluster.ts     |  40 --
 bigtop-manager-ui/src/locales/en_US/hosts.ts       |  32 --
 bigtop-manager-ui/src/locales/en_US/index.ts       |  14 +-
 .../src/locales/en_US/{job.ts => menu.ts}          |   9 +-
 bigtop-manager-ui/src/locales/en_US/service.ts     |  52 ---
 bigtop-manager-ui/src/locales/zh_CN/ai.ts          |  32 --
 bigtop-manager-ui/src/locales/zh_CN/cluster.ts     |  40 --
 bigtop-manager-ui/src/locales/zh_CN/hosts.ts       |  32 --
 bigtop-manager-ui/src/locales/zh_CN/index.ts       |  14 +-
 .../src/locales/zh_CN/{job.ts => menu.ts}          |   9 +-
 bigtop-manager-ui/src/locales/zh_CN/service.ts     |  52 ---
 bigtop-manager-ui/src/main.ts                      |   4 -
 .../cluster-mange/cluster/create.vue}              |  30 +-
 .../cluster-mange/cluster/detail.vue}              |  13 +-
 .../cluster-mange/cluster/index.vue}               |  17 +-
 .../cluster-mange/components/index.vue}            |  15 +-
 .../cluster-mange/hosts/create.vue}                |  15 +-
 .../{dashboard => cluster-mange/hosts}/index.vue   |  18 +-
 .../cluster-mange/infrastructures/index.vue}       |  15 +-
 .../src/pages/cluster/account/index.vue            |  71 ---
 .../src/pages/cluster/stack/index.vue              | 104 -----
 bigtop-manager-ui/src/pages/hosts/index.vue        | 194 --------
 bigtop-manager-ui/src/pages/login/index.vue        |   2 +-
 bigtop-manager-ui/src/pages/service/index.vue      | 498 ---------------------
 .../system-mange/model/index.vue}                  |  15 +-
 bigtop-manager-ui/src/router/guard.ts              |  27 +-
 bigtop-manager-ui/src/router/routes/index.ts       |  10 +-
 .../src/router/routes/modules/clusters.ts          |  97 +++-
 .../src/router/routes/modules/dashboard.ts         |  35 --
 .../src/router/routes/modules/hosts.ts             |  35 --
 .../routes/modules/{services.ts => system.ts}      |  25 +-
 .../src/router/routes/modules/user.ts              |  17 +-
 bigtop-manager-ui/src/store/cluster/index.ts       |  64 ++-
 bigtop-manager-ui/src/store/component/index.ts     |  63 ---
 bigtop-manager-ui/src/store/config/index.ts        |  55 ---
 bigtop-manager-ui/src/store/host/index.ts          |  75 ----
 bigtop-manager-ui/src/store/job/index.ts           |  78 ----
 bigtop-manager-ui/src/store/menu/index.ts          | 178 ++++++++
 bigtop-manager-ui/src/store/service/index.ts       |  84 ----
 bigtop-manager-ui/src/store/service/types.ts       |  24 -
 bigtop-manager-ui/src/store/stack/index.ts         | 109 -----
 bigtop-manager-ui/src/store/stack/types.ts         |  31 --
 bigtop-manager-ui/src/store/theme/index.ts         |  87 ++++
 bigtop-manager-ui/src/store/user/index.ts          |  71 +--
 bigtop-manager-ui/src/store/user/types.ts          |  32 --
 bigtop-manager-ui/src/styles/ant-design-vue.scss   | 383 ++++++++++++++++
 bigtop-manager-ui/src/styles/common/index.scss     |  21 -
 bigtop-manager-ui/src/styles/common/variables.scss |  18 -
 .../src/styles/{main.css => index.scss}            |  49 +-
 .../styles/{common/mixins.scss => variables.scss}  |  10 +
 bigtop-manager-ui/src/types/route.d.ts             |   8 +-
 bigtop-manager-ui/src/utils/router-util.ts         |  35 +-
 .../tests/__components__/svg-icon.test.ts          |   4 +-
 bigtop-manager-ui/vite.config.ts                   |   2 +-
 117 files changed, 1905 insertions(+), 6242 deletions(-)

diff --git a/bigtop-manager-ui/.env.development b/bigtop-manager-ui/.env.development
index 66fd985..6346532 100644
--- a/bigtop-manager-ui/.env.development
+++ b/bigtop-manager-ui/.env.development
@@ -18,3 +18,4 @@ NODE_ENV=development
 VITE_APP_BASE='/'
 VITE_APP_BASE_URL='http://localhost:8080'
 VITE_APP_BASE_API='/api'
+VITE_GITHUB_URL='https://github.com/apache/bigtop-manager'
diff --git a/bigtop-manager-ui/.env.production b/bigtop-manager-ui/.env.production
index 7fba695..90729cf 100644
--- a/bigtop-manager-ui/.env.production
+++ b/bigtop-manager-ui/.env.production
@@ -18,3 +18,4 @@ NODE_ENV=production
 VITE_APP_BASE='/ui/'
 VITE_APP_BASE_URL=''
 VITE_APP_BASE_API='/api'
+VITE_GITHUB_URL='https://github.com/apache/bigtop-manager'
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/App.vue b/bigtop-manager-ui/src/App.vue
index e63893e..e9506d8 100644
--- a/bigtop-manager-ui/src/App.vue
+++ b/bigtop-manager-ui/src/App.vue
@@ -18,15 +18,22 @@
 -->
 
 <script setup lang="ts">
-  import { useLocaleStore } from '@/store/locale'
   import { storeToRefs } from 'pinia'
-
+  import { onMounted } from 'vue'
+  import { useLocaleStore } from '@/store/locale'
+  import { useTheme } from './store/theme'
+  const themeStore = useTheme()
   const localeStore = useLocaleStore()
   const { antd } = storeToRefs(localeStore)
+  const { themeConfig } = storeToRefs(themeStore)
+
+  onMounted(() => {
+    themeStore.initTheme()
+  })
 </script>
 
 <template>
-  <a-config-provider :locale="antd">
+  <a-config-provider :locale="antd" :theme="themeConfig">
     <a-app class="app">
       <router-view />
     </a-app>
@@ -35,9 +42,6 @@
 
 <style scoped lang="scss">
   .app {
-    height: 100%;
-    > section {
-      height: 100%;
-    }
+    overflow: hidden;
   }
 </style>
diff --git a/bigtop-manager-ui/src/assets/images/svg/avatar.svg b/bigtop-manager-ui/src/assets/images/svg/avatar.svg
new file mode 100644
index 0000000..958ac8f
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/avatar.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="17.5008544921875"
+  height="17.498071670532227" viewBox="0 0 17.5008544921875 17.498071670532227" fill="none">
+  <path
+    d="M0.835292 16.3444C0.835292 16.5213 0.982937 16.6647 1.16508 16.6647L16.3347 16.6647C16.5168 16.6647 16.6645 16.5213 16.6645 16.3444L16.6645 15.9619C16.6721 15.8466 16.6875 15.2712 16.3082 14.6351C16.0691 14.234 15.722 13.8875 15.2766 13.6053C14.7377 13.2638 14.0523 13.0164 13.2232 12.8674C13.2171 12.8667 12.6023 12.7852 11.9725 12.6243C10.8758 12.3442 10.7799 12.0963 10.7793 12.0939C10.7729 12.0694 10.7635 12.0458 10.7516 12.0237C10.7426 11.9774 10.7204 11.8034 10.7628 11.3371C10. [...]
+    stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/big-manager-logo.svg b/bigtop-manager-ui/src/assets/images/svg/big-manager-logo.svg
new file mode 100644
index 0000000..33a68d1
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/big-manager-logo.svg
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="180.00015258789062"
+  height="30" viewBox="0 0 180.00015258789062 30" fill="none">
+  <path
+    d="M19.2294 21.6913C17.363 21.6913 16.0815 24.0504 16.0815 24.0504L16.0815 29.2344L21.9753 29.4561L21.9753 24.2689C21.9753 24.2689 21.0957 21.6913 19.2294 21.6913Z"
+    fill="#221F20">
+  </path>
+  <path
+    d="M0 12.8259C0.604261 12.8259 1.21001 12.8259 1.81427 12.8131C2.46318 12.8035 3.11358 12.7988 3.76101 12.762C5.07966 12.6839 6.39981 12.6233 7.71252 12.4877C8.11575 12.4513 8.51751 12.4011 8.91777 12.3371C9.31802 12.2731 9.716 12.1954 10.1117 12.1041C10.5073 12.0127 10.8998 11.9079 11.2891 11.7897C11.6785 11.6713 12.0639 11.5398 12.4454 11.3951C13.9531 10.8033 15.3238 9.94515 16.4297 8.5686C16.5173 8.46184 16.6027 8.35322 16.6862 8.24273C16.7696 8.13214 16.8509 8.01975 16.9299 7.905 [...]
+    fill="#ED1D25">
+  </path>
+  <path
+    d="M50.1299 26.7557L50.541 26.2559C50.5537 26.2794 50.568 26.3019 50.5837 26.3233C50.5995 26.3449 50.6165 26.3653 50.6348 26.3846C50.6533 26.4038 50.6728 26.4217 50.6936 26.4383C50.7143 26.4548 50.736 26.47 50.7586 26.4838C50.7813 26.4974 50.8048 26.5095 50.829 26.5201C50.8533 26.5306 50.8782 26.5395 50.9036 26.5467C50.929 26.5538 50.9548 26.5593 50.9809 26.5629C51.007 26.5667 51.0332 26.5686 51.0597 26.5688C51.2091 26.5688 51.3467 26.5035 51.3467 26.3744C51.3467 26.2103 51.0836 26.0 [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M56.0583 24.9098L55.4454 24.9098L55.4454 27.2919L54.7638 27.2919L54.7638 24.9098L54.1494 24.9098L54.1494 24.1243L56.0583 24.1243L56.0583 24.9098Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M59.6802 27.2919L58.9956 25.9155L58.9956 27.2919L58.3154 27.2919L58.3154 24.1243L59.2871 24.1243C59.8401 24.1243 60.2363 24.5801 60.2363 25.1544C60.237 25.1757 60.237 25.1971 60.2364 25.2183C60.2358 25.2397 60.2345 25.261 60.2325 25.2823C60.2305 25.3035 60.2279 25.3246 60.2246 25.3456C60.2212 25.3668 60.2172 25.3878 60.2126 25.4085C60.2079 25.4294 60.2026 25.45 60.1966 25.4704C60.1906 25.4908 60.1839 25.5111 60.1766 25.5311C60.1693 25.5512 60.1614 25.5709 60.1528 25.5904C60.1444 2 [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M63.3572 24.9067L63.3572 25.3488L64.1704 25.3488L64.1704 26.0492L63.3572 26.0492L63.3572 26.5049L64.3453 26.5049L64.3453 27.2934L62.6846 27.2934L62.6846 24.1243L64.3453 24.1243L64.3453 24.9067L63.3572 24.9067Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M68.3292 26.9213L67.3726 26.9213L67.2425 27.292L66.4951 27.292L67.691 24.0849L68.0138 24.0849L69.2097 27.292L68.4623 27.292L68.3292 26.9213ZM68.1125 26.3136L67.8509 25.5631L67.5938 26.3075L68.1125 26.3136Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M74.1706 24.0941L74.1706 27.2844L73.492 27.2844L73.492 26.028L72.8014 27.2312L72.1108 26.028L72.1108 27.2844L71.4307 27.2844L71.4307 24.0941L71.7042 24.0941L72.8029 25.9566L73.9031 24.0941L74.1706 24.0941Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M78.2354 26.5019L78.2354 27.2919L76.5762 27.2919L76.5762 24.1243L77.2563 24.1243L77.2563 26.5019L78.2354 26.5019Z"
+    fill="#FFFFFF">
+  </path>
+  <path d="M80.4893 24.1243L81.1694 24.1243L81.1694 27.2919L80.4893 27.2919L80.4893 24.1243Z" fill="#FFFFFF">
+  </path>
+  <path
+    d="M85.7914 24.1153L85.7914 27.3178L85.5762 27.3178L84.2592 25.7408L84.2592 27.2889L83.5791 27.2889L83.5791 24.0925L83.7988 24.0925L85.1098 25.6649L85.1098 24.1153L85.7914 24.1153Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M88.8737 24.9067L88.8737 25.3488L89.6869 25.3488L89.6869 26.0492L88.8737 26.0492L88.8737 26.5049L89.8663 26.5049L89.8663 27.2934L88.207 27.2934L88.207 24.1243L89.8663 24.1243L89.8663 24.9067L88.8737 24.9067Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M97.3837 25.712C97.3837 26.6949 96.8516 27.292 95.9816 27.292L95.146 27.292L95.146 24.1259L95.9816 24.1259C96.8516 24.1153 97.3837 24.723 97.3837 25.712ZM96.7021 25.712C96.7021 25.2137 96.4226 24.9114 95.9637 24.9114L95.8142 24.9114L95.8142 26.5005L95.9771 26.5005C96.4256 26.499 96.7021 26.2012 96.7021 25.7105L96.7021 25.712Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M101.323 26.9213L100.368 26.9213L100.238 27.292L99.4902 27.292L100.686 24.0849L101.009 24.0849L102.205 27.292L101.457 27.292L101.323 26.9213ZM101.108 26.3136L100.846 25.5631L100.581 26.3136L101.108 26.3136Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M106.171 24.9098L105.562 24.9098L105.562 27.2919L104.881 27.2919L104.881 24.9098L104.262 24.9098L104.262 24.1243L106.171 24.1243L106.171 24.9098Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M110.064 26.9213L109.109 26.9213L108.979 27.292L108.231 27.292L109.427 24.0849L109.747 24.0849L110.943 27.292L110.196 27.292L110.064 26.9213ZM109.849 26.3136L109.587 25.5631L109.323 26.3136L109.849 26.3136Z"
+    fill="#FFFFFF">
+  </path>
+  <path d="M116.102 24.1243L116.78 24.1243L116.78 27.2919L116.102 27.2919L116.102 24.1243Z" fill="#FFFFFF">
+  </path>
+  <path
+    d="M121.407 24.1153L121.407 27.3178L121.19 27.3178L119.873 25.7408L119.873 27.2889L119.194 27.2889L119.194 24.0925L119.413 24.0925L120.725 25.6649L120.725 24.1153L121.407 24.1153Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M124.485 24.9068L124.485 25.4188L125.293 25.4188L125.293 26.1222L124.48 26.1222L124.48 27.295L123.813 27.295L123.813 24.1153L125.473 24.1153L125.473 24.9053L124.485 24.9068Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M129.095 27.2919L128.41 25.9155L128.41 27.2919L127.73 27.2919L127.73 24.1243L128.702 24.1243C129.255 24.1243 129.649 24.5801 129.649 25.1544C129.65 25.1757 129.65 25.1971 129.649 25.2183C129.649 25.2397 129.648 25.261 129.646 25.2823C129.644 25.3036 129.641 25.3247 129.637 25.3458C129.634 25.3669 129.63 25.3878 129.625 25.4085C129.621 25.4294 129.616 25.4501 129.61 25.4705C129.604 25.491 129.597 25.5112 129.59 25.5313C129.583 25.5512 129.575 25.571 129.566 25.5905C129.558 25.61 12 [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M133.739 26.9213L132.784 26.9213L132.654 27.292L131.906 27.292L133.102 24.0849L133.425 24.0849L134.621 27.292L133.873 27.292L133.739 26.9213ZM133.524 26.3136L133.262 25.5631L132.997 26.3136L133.524 26.3136Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M136.7 26.7557L137.111 26.2559C137.124 26.2794 137.139 26.3019 137.155 26.3235C137.171 26.3451 137.187 26.3655 137.205 26.3847C137.224 26.4041 137.244 26.422 137.264 26.4386C137.285 26.4552 137.307 26.4704 137.329 26.4841C137.352 26.4977 137.376 26.5098 137.4 26.5204C137.425 26.5309 137.45 26.5398 137.475 26.5469C137.5 26.554 137.526 26.5595 137.552 26.5632C137.578 26.5669 137.605 26.5687 137.631 26.5688C137.781 26.5688 137.917 26.5035 137.917 26.3744C137.917 26.2103 137.654 26.07 [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M142.633 24.9098L142.021 24.9098L142.021 27.2919L141.339 27.2919L141.339 24.9098L140.725 24.9098L140.725 24.1243L142.633 24.1243L142.633 24.9098Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M146.251 27.2919L145.566 25.9155L145.566 27.2919L144.886 27.2919L144.886 24.1243L145.859 24.1243C146.41 24.1243 146.807 24.5801 146.807 25.1544C146.808 25.1757 146.808 25.1971 146.807 25.2183C146.807 25.2397 146.806 25.261 146.804 25.2823C146.802 25.3035 146.799 25.3246 146.795 25.3456C146.792 25.3668 146.788 25.3878 146.783 25.4085C146.778 25.4294 146.772 25.4501 146.766 25.4705C146.76 25.4909 146.754 25.5111 146.747 25.5311C146.74 25.5512 146.732 25.5709 146.723 25.5904C146.715  [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M149.234 26.1403L149.234 24.1243L149.917 24.1243L149.917 26.1373C149.917 26.1508 149.916 26.1642 149.916 26.1777C149.917 26.1913 149.918 26.2048 149.919 26.2181C149.921 26.2315 149.923 26.2448 149.926 26.2579C149.929 26.2711 149.933 26.2841 149.937 26.297C149.941 26.3097 149.946 26.3223 149.952 26.3346C149.957 26.347 149.963 26.359 149.97 26.3707C149.977 26.3824 149.984 26.3938 149.991 26.4048C149.999 26.4159 150.007 26.4265 150.016 26.4366C150.025 26.4467 150.034 26.4564 150.043  [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M153.635 25.7075C153.635 24.7701 154.248 24.05 155.044 24.05C155.089 24.0528 155.134 24.058 155.179 24.0655C155.224 24.0729 155.268 24.0826 155.312 24.0945C155.356 24.1065 155.399 24.1205 155.442 24.1367C155.484 24.1531 155.525 24.1715 155.566 24.192C155.607 24.2125 155.646 24.235 155.684 24.2595C155.723 24.284 155.76 24.3104 155.795 24.3386C155.831 24.3669 155.865 24.3969 155.898 24.4286C155.931 24.4603 155.962 24.4936 155.992 24.5285L155.6 25.1499C155.583 25.1289 155.566 25.1089 [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M159.998 24.9098L159.385 24.9098L159.385 27.2919L158.704 27.2919L158.704 24.9098L158.089 24.9098L158.089 24.1243L159.998 24.1243L159.998 24.9098Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M162.23 26.1403L162.23 24.1243L162.915 24.1243L162.915 26.1373C162.914 26.1508 162.914 26.1643 162.914 26.1779C162.915 26.1913 162.916 26.2048 162.917 26.2183C162.919 26.2316 162.921 26.2449 162.924 26.2581C162.927 26.2713 162.931 26.2844 162.935 26.2971C162.939 26.31 162.943 26.3226 162.949 26.3349C162.954 26.3473 162.96 26.3594 162.967 26.3711C162.973 26.3829 162.98 26.3942 162.988 26.4051C162.996 26.4162 163.004 26.4268 163.012 26.437C163.021 26.4472 163.031 26.4569 163.041 26. [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M168.111 27.2919L167.426 25.9155L167.426 27.2919L166.746 27.2919L166.746 24.1243L167.718 24.1243C168.271 24.1243 168.665 24.5801 168.665 25.1544C168.666 25.1757 168.666 25.1971 168.665 25.2183C168.665 25.2397 168.664 25.261 168.662 25.2823C168.66 25.3036 168.657 25.3247 168.653 25.3458C168.65 25.3669 168.646 25.3878 168.641 25.4085C168.638 25.4294 168.633 25.4501 168.627 25.4705C168.621 25.491 168.614 25.5112 168.606 25.5313C168.599 25.5512 168.591 25.571 168.582 25.5905C168.574 2 [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M171.782 24.9067L171.782 25.3488L172.595 25.3488L172.595 26.0492L171.782 26.0492L171.782 26.5049L172.77 26.5049L172.77 27.2934L171.111 27.2934L171.111 24.1243L172.77 24.1243L172.77 24.9067L171.782 24.9067Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M43.4537 20.9378L44.0122 14.0193L51.0619 14.0193L51.1487 12.8465L44.0961 12.8465L42.9102 9.98122L53.5056 9.98122L53.1792 14.0937C53.1701 14.1657 53.1541 14.2361 53.1313 14.3049C53.0983 14.4204 53.0609 14.5495 53.016 14.6893C52.971 14.829 52.9261 14.9658 52.8752 15.0934C52.8413 15.1878 52.7978 15.2774 52.7449 15.3623C52.7853 15.4656 52.8177 15.5714 52.8423 15.6798C52.8722 15.8013 52.8977 15.9198 52.9186 16.0353C52.9411 16.1508 52.9576 16.2556 52.968 16.3528C52.9785 16.45 52.9845 16 [...]
+    fill="#FFFFFF">
+  </path>
+  <path d="M54.334 9.98122L57.8693 9.98122L56.9978 20.9363L54.8775 20.9363L55.5184 12.8449L54.334 9.98122Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M67.768 14.4416L67.2454 20.9377L58.0425 20.9377L58.7388 12.1931C58.7459 12.0524 58.7618 11.9128 58.7862 11.7741C58.8107 11.6355 58.8435 11.4989 58.8848 11.3644C58.9261 11.2299 58.9755 11.0985 59.033 10.9703C59.0905 10.8421 59.1556 10.718 59.2284 10.5979C59.4959 10.1928 59.9127 9.99025 60.4787 9.99025L68.1153 9.99025L67.8877 12.854L60.8276 12.854L60.4143 18.0618L65.3557 18.0618L65.6552 14.4492L67.768 14.4416Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M73.1959 12.8465L70.1278 12.8465L68.9419 9.98122L78.9504 9.98122L78.7228 12.8449L75.3282 12.8449L74.6858 20.9363L72.5536 20.9363L73.1959 12.8465Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M87.6324 9.98122C88.1969 9.98122 88.5878 10.1863 88.8019 10.5889C89.016 10.9915 89.1014 11.5308 89.0355 12.1841L88.5234 18.545C88.4665 19.2758 88.2658 19.8561 87.9244 20.2845C87.9051 20.3102 87.885 20.3352 87.8642 20.3596C87.8434 20.384 87.8219 20.4077 87.7997 20.4308C87.7775 20.454 87.7547 20.4765 87.7311 20.4983C87.7076 20.52 87.6836 20.541 87.6589 20.5613C87.6342 20.5817 87.6089 20.6013 87.583 20.6201C87.5573 20.6389 87.5309 20.6569 87.504 20.6742C87.4771 20.6914 87.4498 20.707 [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M91.0913 14.4992L97.6079 14.4992L97.7382 12.8463L91.2216 12.8463L90.0356 9.98109L98.6665 9.98109C98.7251 9.97866 98.7836 9.98029 98.842 9.98595C98.9004 9.99163 98.9582 10.0014 99.0153 10.0151C99.0724 10.0288 99.1283 10.0464 99.183 10.068C99.2376 10.0895 99.2906 10.1147 99.3419 10.1437C99.3853 10.1709 99.4266 10.2011 99.4658 10.2343C99.505 10.2676 99.5416 10.3035 99.5757 10.3421C99.6098 10.3806 99.641 10.4215 99.6693 10.4645C99.6976 10.5077 99.7227 10.5526 99.7447 10.5994C99.7948 1 [...]
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M105.353 9.98122L108.421 9.98122L111.245 14.9217L114.861 9.98122L116.536 9.98122L115.666 20.9363L113.534 20.9363L113.983 15.2666L110.882 19.5204L108.446 15.2666L107.997 20.9363L105.875 20.9363L106.517 12.807L105.353 9.98122Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M119.799 9.98122L123.28 9.98122L126.575 20.9363L124.179 20.9363L123.28 18.0498L120.257 18.0498L118.875 20.9363L116.493 20.9363L119.136 15.1891L122.454 15.1891L122.025 13.7306L119.842 13.7306L120.615 11.982L119.799 9.98122Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M128.056 9.98122L131.091 9.98122L135.352 15.9411L135.821 9.98274L137.964 9.98274L137.094 20.9378L135.487 20.9378L131.19 15.0372L130.721 20.9378L128.601 20.9378L129.242 12.8465L128.056 9.98122Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M141.219 9.98122L144.701 9.98122L147.995 20.9363L145.599 20.9363L144.701 18.0498L141.676 18.0498L140.295 20.9363L137.913 20.9363L140.556 15.1891L143.874 15.1891L143.45 13.7291L141.263 13.7291L142.035 11.9805L141.219 9.98122Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M158.548 14.4416L158.027 20.9377L148.829 20.9377L149.523 12.1931C149.531 12.0525 149.547 11.9129 149.571 11.7743C149.596 11.6357 149.629 11.4992 149.67 11.3647C149.712 11.2302 149.761 11.0988 149.818 10.9706C149.875 10.8423 149.94 10.7181 150.013 10.5979C150.283 10.1928 150.7 9.99025 151.265 9.99025L158.901 9.99025L158.672 12.854L151.612 12.854L151.199 18.0618L156.14 18.0618L156.44 14.4492L158.548 14.4416Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M169.319 9.98122L169.09 12.8449L160.91 12.8449L159.724 9.98122L169.319 9.98122ZM160.496 18.0331L168.666 18.0331L168.437 20.9348L160.267 20.9348L160.496 18.0331ZM160.823 13.9965L166.926 13.9965L166.697 16.883L160.594 16.883L160.823 13.9965Z"
+    fill="#FFFFFF">
+  </path>
+  <path
+    d="M178.696 9.98122C179.219 9.98122 179.578 10.1838 179.774 10.5889C179.969 10.994 180.038 11.5258 179.98 12.1841L179.762 14.9703C179.704 15.7016 179.501 16.2657 179.152 16.6627C179.11 16.7109 179.066 16.7567 179.019 16.8001C178.972 16.8434 178.923 16.8841 178.872 16.9222C178.82 16.9602 178.767 16.9953 178.714 17.0276C178.659 17.0599 178.602 17.089 178.543 17.1152C178.485 17.1413 178.426 17.1642 178.366 17.184C178.305 17.2037 178.244 17.2201 178.182 17.233C178.12 17.2461 178.058 17.2 [...]
+    fill="#FFFFFF">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/history.svg b/bigtop-manager-ui/src/assets/images/svg/book.svg
similarity index 57%
rename from bigtop-manager-ui/src/assets/images/svg/history.svg
rename to bigtop-manager-ui/src/assets/images/svg/book.svg
index 4c40a45..cba3653 100644
--- a/bigtop-manager-ui/src/assets/images/svg/history.svg
+++ b/bigtop-manager-ui/src/assets/images/svg/book.svg
@@ -17,11 +17,14 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="20" height="20" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
-  <path d="M5.81836 6.72729V14H13.0911" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20"
+  viewBox="0 0 20 20" fill="none">
   <path
-    d="M4 24C4 35.0457 12.9543 44 24 44V44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C16.598 4 10.1351 8.02111 6.67677 13.9981"
-    stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-  <path d="M24.005 12L24.0038 24.0088L32.4832 32.4882" stroke="#333" stroke-width="4" stroke-linecap="round"
-    stroke-linejoin="round" />
+    d="M2.08337 2.91666L6.66671 2.91666C8.50767 2.91666 10 4.40904 10 6.25L10 17.5C10 16.1193 8.88075 15 7.50004 15L2.08337 15L2.08337 2.91666Z"
+    stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round">
+  </path>
+  <path
+    d="M17.9167 2.91666L13.3333 2.91666C11.4924 2.91666 10 4.40904 10 6.25L10 17.5C10 16.1193 11.1193 15 12.5 15L17.9167 15L17.9167 2.91666Z"
+    stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round">
+  </path>
 </svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/carbon-language.svg b/bigtop-manager-ui/src/assets/images/svg/carbon-language.svg
deleted file mode 100644
index 3398805..0000000
--- a/bigtop-manager-ui/src/assets/images/svg/carbon-language.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 32 32">
-  <path fill="currentColor"
-    d="M27.85 29H30l-6-15h-2.35l-6 15h2.15l1.6-4h6.85zm-7.65-6l2.62-6.56L25.45 23zM18 7V5h-7V2H9v3H2v2h10.74a14.71 14.71 0 0 1-3.19 6.18A13.5 13.5 0 0 1 7.26 9h-2.1a16.47 16.47 0 0 0 3 5.58A16.84 16.84 0 0 1 3 18l.75 1.86A18.47 18.47 0 0 0 9.53 16a16.92 16.92 0 0 0 5.76 3.84L16 18a14.48 14.48 0 0 1-5.12-3.37A17.64 17.64 0 0 0 14.8 7z" />
-</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/clusters.svg b/bigtop-manager-ui/src/assets/images/svg/clusters.svg
new file mode 100644
index 0000000..e2b9874
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/clusters.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path d="M14.6667 1.33334L1.33333 1.33334L1.33333 6.66668L14.6667 6.66668L14.6667 1.33334Z"
+    stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
+  <path d="M14.6667 9.33334L1.33333 9.33334L1.33333 14.6667L14.6667 14.6667L14.6667 9.33334Z"
+    stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
+  <path
+    d="M4.33333 3.33334L3.66667 3.33334C3.48257 3.33334 3.33333 3.48258 3.33333 3.66668L3.33333 4.33334C3.33333 4.51744 3.48257 4.66668 3.66667 4.66668L4.33333 4.66668C4.51743 4.66668 4.66667 4.51744 4.66667 4.33334L4.66667 3.66668C4.66667 3.48258 4.51743 3.33334 4.33333 3.33334Z"
+    fill="#333333">
+  </path>
+  <path
+    d="M4.33333 11.3333L3.66667 11.3333C3.48257 11.3333 3.33333 11.4826 3.33333 11.6667L3.33333 12.3333C3.33333 12.5174 3.48257 12.6667 3.66667 12.6667L4.33333 12.6667C4.51743 12.6667 4.66667 12.5174 4.66667 12.3333L4.66667 11.6667C4.66667 11.4826 4.51743 11.3333 4.33333 11.3333Z"
+    fill="#333333">
+  </path>
+  <path
+    d="M7 3.33334L6.33333 3.33334C6.14923 3.33334 6 3.48258 6 3.66668L6 4.33334C6 4.51744 6.14923 4.66668 6.33333 4.66668L7 4.66668C7.1841 4.66668 7.33333 4.51744 7.33333 4.33334L7.33333 3.66668C7.33333 3.48258 7.1841 3.33334 7 3.33334Z"
+    fill="#333333">
+  </path>
+  <path
+    d="M7 11.3333L6.33333 11.3333C6.14923 11.3333 6 11.4826 6 11.6667L6 12.3333C6 12.5174 6.14923 12.6667 6.33333 12.6667L7 12.6667C7.1841 12.6667 7.33333 12.5174 7.33333 12.3333L7.33333 11.6667C7.33333 11.4826 7.1841 11.3333 7 11.3333Z"
+    fill="#333333">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/clusters_activated.svg b/bigtop-manager-ui/src/assets/images/svg/clusters_activated.svg
new file mode 100644
index 0000000..e554fc5
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/clusters_activated.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path d="M14.6666 1.33334L1.33331 1.33334L1.33331 6.66668L14.6666 6.66668L14.6666 1.33334Z"
+    stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
+  <path d="M14.6666 9.33334L1.33331 9.33334L1.33331 14.6667L14.6666 14.6667L14.6666 9.33334Z"
+    stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
+  <path
+    d="M4.33331 3.33334L3.66665 3.33334C3.48255 3.33334 3.33331 3.48258 3.33331 3.66668L3.33331 4.33334C3.33331 4.51744 3.48255 4.66668 3.66665 4.66668L4.33331 4.66668C4.51741 4.66668 4.66665 4.51744 4.66665 4.33334L4.66665 3.66668C4.66665 3.48258 4.51741 3.33334 4.33331 3.33334Z"
+    fill="#1677FF">
+  </path>
+  <path
+    d="M4.33331 11.3333L3.66665 11.3333C3.48255 11.3333 3.33331 11.4826 3.33331 11.6667L3.33331 12.3333C3.33331 12.5174 3.48255 12.6667 3.66665 12.6667L4.33331 12.6667C4.51741 12.6667 4.66665 12.5174 4.66665 12.3333L4.66665 11.6667C4.66665 11.4826 4.51741 11.3333 4.33331 11.3333Z"
+    fill="#1677FF">
+  </path>
+  <path
+    d="M7 3.33334L6.33333 3.33334C6.14923 3.33334 6 3.48258 6 3.66668L6 4.33334C6 4.51744 6.14923 4.66668 6.33333 4.66668L7 4.66668C7.1841 4.66668 7.33333 4.51744 7.33333 4.33334L7.33333 3.66668C7.33333 3.48258 7.1841 3.33334 7 3.33334Z"
+    fill="#1677FF">
+  </path>
+  <path
+    d="M7 11.3333L6.33333 11.3333C6.14923 11.3333 6 11.4826 6 11.6667L6 12.3333C6 12.5174 6.14923 12.6667 6.33333 12.6667L7 12.6667C7.1841 12.6667 7.33333 12.5174 7.33333 12.3333L7.33333 11.6667C7.33333 11.4826 7.1841 11.3333 7 11.3333Z"
+    fill="#1677FF">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/communication.svg b/bigtop-manager-ui/src/assets/images/svg/communication.svg
new file mode 100644
index 0000000..0489a2e
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/communication.svg
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20"
+  viewBox="0 0 20 20" fill="none">
+  <path
+    d="M13.75 15.8333L9.16663 15.8333L9.16663 12.5L15 12.5L15 9.16667L18.3333 9.16667L18.3333 15.8333L16.25 15.8333L15 17.0833L13.75 15.8333Z"
+    stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round" stroke-linecap="round">
+  </path>
+  <path d="M1.66663 2.5L15 2.5L15 12.5L7.08329 12.5L5.41663 14.1667L3.74996 12.5L1.66663 12.5L1.66663 2.5Z"
+    stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round" stroke-linecap="round">
+  </path>
+  <path stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linecap="round"
+    d="M7.91663 7.5L8.33329 7.5">
+  </path>
+  <path stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linecap="round"
+    d="M10.8334 7.5L11.25 7.5">
+  </path>
+  <path stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linecap="round" d="M5 7.5L5.41667 7.5">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/full-screen.svg b/bigtop-manager-ui/src/assets/images/svg/components.svg
similarity index 53%
rename from bigtop-manager-ui/src/assets/images/svg/full-screen.svg
rename to bigtop-manager-ui/src/assets/images/svg/components.svg
index a6b45d0..bb21514 100644
--- a/bigtop-manager-ui/src/assets/images/svg/full-screen.svg
+++ b/bigtop-manager-ui/src/assets/images/svg/components.svg
@@ -17,9 +17,10 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="20" height="20" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
-  <path d="M33 6H42V15" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-  <path d="M42 33V42H33" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-  <path d="M15 42H6V33" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-  <path d="M6 15V6H15" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path
+    d="M1.33333 8.00001L1.33333 4.00001L4.33333 4.00001L4.33333 3.33334C4.33333 2.22877 5.22877 1.33334 6.33333 1.33334C7.4379 1.33334 8.33333 2.22877 8.33333 3.33334L8.33333 4.00001L11.3333 4.00001L11.3333 8.00001L12.6667 8.00001C13.7712 8.00001 14.6667 8.89544 14.6667 10C14.6667 11.1046 13.7712 12 12.6667 12L11.3333 12L11.3333 14.6667L1.33333 14.6667L1.33333 12L2.66667 12C3.77123 12 4.66667 11.1046 4.66667 10C4.66667 8.89544 3.77123 8.00001 2.66667 8.00001L1.33333 8.00001Z"
+    stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
 </svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/home.svg b/bigtop-manager-ui/src/assets/images/svg/components_activated.svg
similarity index 53%
rename from bigtop-manager-ui/src/assets/images/svg/home.svg
rename to bigtop-manager-ui/src/assets/images/svg/components_activated.svg
index de12667..9e5e54d 100644
--- a/bigtop-manager-ui/src/assets/images/svg/home.svg
+++ b/bigtop-manager-ui/src/assets/images/svg/components_activated.svg
@@ -17,9 +17,10 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
-  <path d="M9 18V42H39V18L24 6L9 18Z" fill="none" stroke="#333" stroke-width="4" stroke-linecap="round"
-    stroke-linejoin="round" />
-  <path d="M19 29V42H29V29H19Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round" />
-  <path d="M9 42H39" stroke="#333" stroke-width="4" stroke-linecap="round" />
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path
+    d="M1.33334 8.00001L1.33334 4.00001L4.33334 4.00001L4.33334 3.33334C4.33334 2.22877 5.22878 1.33334 6.33334 1.33334C7.43791 1.33334 8.33334 2.22877 8.33334 3.33334L8.33334 4.00001L11.3333 4.00001L11.3333 8.00001L12.6667 8.00001C13.7712 8.00001 14.6667 8.89544 14.6667 10C14.6667 11.1046 13.7712 12 12.6667 12L11.3333 12L11.3333 14.6667L1.33334 14.6667L1.33334 12L2.66668 12C3.77124 12 4.66668 11.1046 4.66668 10C4.66668 8.89544 3.77124 8.00001 2.66668 8.00001L1.33334 8.00001Z"
+    stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
 </svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/github.svg b/bigtop-manager-ui/src/assets/images/svg/github.svg
new file mode 100644
index 0000000..e93a0ce
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/github.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20"
+  viewBox="0 0 20 20" fill="none">
+  <path
+    d="M10 1.66667C5.39762 1.66667 1.66667 5.39762 1.66667 10C1.66667 14.6024 5.39762 18.3333 10 18.3333C14.6024 18.3333 18.3333 14.6024 18.3333 10C18.3333 5.39762 14.6024 1.66667 10 1.66667ZM0 10C0 4.47717 4.47717 0 10 0C15.5228 0 20 4.47717 20 10C20 15.5228 15.5228 20 10 20C4.47717 20 0 15.5228 0 10Z"
+    fill-rule="evenodd" fill="#FFFFFF">
+  </path>
+  <path
+    d="M7.99304 18.9465C7.91242 18.8425 7.91242 17.9156 7.99304 16.1658C7.12975 16.1957 6.58433 16.1358 6.35679 15.9861C6.01542 15.7617 5.67371 15.0695 5.37046 14.5816C5.06725 14.0938 4.39429 14.0167 4.12252 13.9076C3.85076 13.7986 3.78254 13.354 4.87137 13.6902C5.96017 14.0264 6.01329 14.942 6.35679 15.1561C6.70025 15.3701 7.52146 15.2765 7.89367 15.105C8.26593 14.9335 8.23851 14.2949 8.30489 14.042C8.3888 13.8058 8.09304 13.7535 8.08654 13.7516C7.72312 13.7516 5.81412 13.3364 5.28979 1 [...]
+    fill-rule="evenodd" fill="#FFFFFF">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/hosts.svg b/bigtop-manager-ui/src/assets/images/svg/hosts.svg
new file mode 100644
index 0000000..3f0a9e8
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/hosts.svg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path fill="rgba(51, 51, 51, 1)"
+    d="M3 1.33333L13 1.33333C13.9205 1.33333 14.6667 2.07953 14.6667 3L14.6667 10.3333C14.6667 11.2538 13.9205 12 13 12L3 12C2.07953 12 1.33333 11.2538 1.33333 10.3333L1.33333 3C1.33333 2.07953 2.07953 1.33333 3 1.33333ZM3 2.66667C2.81591 2.66667 2.66667 2.81591 2.66667 3L2.66667 10.3333C2.66667 10.5174 2.81591 10.6667 3 10.6667L13 10.6667C13.1841 10.6667 13.3333 10.5174 13.3333 10.3333L13.3333 3C13.3333 2.81591 13.1841 2.66667 13 2.66667L3 2.66667Z">
+  </path>
+  <path stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M4.66667 14L11.3333 14">
+  </path>
+  <path stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M8 11.3333L8 14">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/hosts_activated.svg b/bigtop-manager-ui/src/assets/images/svg/hosts_activated.svg
new file mode 100644
index 0000000..503b72c
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/hosts_activated.svg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path fill="rgba(22, 119, 255, 1)"
+    d="M3 1.33333L13 1.33333C13.9205 1.33333 14.6667 2.07953 14.6667 3L14.6667 10.3333C14.6667 11.2538 13.9205 12 13 12L3 12C2.07953 12 1.33333 11.2538 1.33333 10.3333L1.33333 3C1.33333 2.07953 2.07953 1.33333 3 1.33333ZM3 2.66667C2.81591 2.66667 2.66667 2.81591 2.66667 3L2.66667 10.3333C2.66667 10.5174 2.81591 10.6667 3 10.6667L13 10.6667C13.1841 10.6667 13.3333 10.5174 13.3333 10.3333L13.3333 3C13.3333 2.81591 13.1841 2.66667 13 2.66667L3 2.66667Z">
+  </path>
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M4.66666 14L11.3333 14">
+  </path>
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M8 11.3333L8 14">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/infrastructures.svg b/bigtop-manager-ui/src/assets/images/svg/infrastructures.svg
new file mode 100644
index 0000000..78a64da
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/infrastructures.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path
+    d="M6 2L2.66667 2C2.29848 2 2 2.29848 2 2.66667L2 6C2 6.3682 2.29848 6.66667 2.66667 6.66667L6 6.66667C6.3682 6.66667 6.66667 6.3682 6.66667 6L6.66667 2.66667C6.66667 2.29848 6.3682 2 6 2Z"
+    stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
+  <path
+    d="M6 9.33334L2.66667 9.33334C2.29848 9.33334 2 9.63181 2 10L2 13.3333C2 13.7015 2.29848 14 2.66667 14L6 14C6.3682 14 6.66667 13.7015 6.66667 13.3333L6.66667 10C6.66667 9.63181 6.3682 9.33334 6 9.33334Z"
+    stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
+  <path
+    d="M13.3333 2L10 2C9.6318 2 9.33333 2.29848 9.33333 2.66667L9.33333 6C9.33333 6.3682 9.6318 6.66667 10 6.66667L13.3333 6.66667C13.7015 6.66667 14 6.3682 14 6L14 2.66667C14 2.29848 13.7015 2 13.3333 2Z"
+    stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333">
+  </path>
+  <path
+    d="M13.3333 9.33334L10 9.33334C9.6318 9.33334 9.33333 9.63181 9.33333 10L9.33333 13.3333C9.33333 13.7015 9.6318 14 10 14L13.3333 14C13.7015 14 14 13.7015 14 13.3333L14 10C14 9.63181 13.7015 9.33334 13.3333 9.33334Z"
+    stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/infrastructures_activated.svg b/bigtop-manager-ui/src/assets/images/svg/infrastructures_activated.svg
new file mode 100644
index 0000000..040fb6a
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/infrastructures_activated.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path
+    d="M6 2L2.66667 2C2.29848 2 2 2.29848 2 2.66667L2 6C2 6.3682 2.29848 6.66667 2.66667 6.66667L6 6.66667C6.3682 6.66667 6.66667 6.3682 6.66667 6L6.66667 2.66667C6.66667 2.29848 6.3682 2 6 2Z"
+    stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
+  <path
+    d="M6 9.33334L2.66667 9.33334C2.29848 9.33334 2 9.63181 2 10L2 13.3333C2 13.7015 2.29848 14 2.66667 14L6 14C6.3682 14 6.66667 13.7015 6.66667 13.3333L6.66667 10C6.66667 9.63181 6.3682 9.33334 6 9.33334Z"
+    stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round">
+  </path>
+  <path
+    d="M13.3333 2L9.99998 2C9.63178 2 9.33331 2.29848 9.33331 2.66667L9.33331 6C9.33331 6.3682 9.63178 6.66667 9.99998 6.66667L13.3333 6.66667C13.7015 6.66667 14 6.3682 14 6L14 2.66667C14 2.29848 13.7015 2 13.3333 2Z"
+    stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333">
+  </path>
+  <path
+    d="M13.3333 9.33334L9.99998 9.33334C9.63178 9.33334 9.33331 9.63181 9.33331 10L9.33331 13.3333C9.33331 13.7015 9.63178 14 9.99998 14L13.3333 14C13.7015 14 14 13.7015 14 13.3333L14 10C14 9.63181 13.7015 9.33334 13.3333 9.33334Z"
+    stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/language.svg b/bigtop-manager-ui/src/assets/images/svg/language.svg
new file mode 100644
index 0000000..12a0068
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/language.svg
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20"
+  viewBox="0 0 20 20" fill="none">
+  <path stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round" stroke-linecap="round"
+    d="M11.7857 15.4167L16.5477 15.4167M17.5 17.5L16.5477 15.4167L17.5 17.5ZM10.8334 17.5L11.7857 15.4167L10.8334 17.5ZM11.7857 15.4167L14.1667 10L16.5477 15.4167L11.7857 15.4167Z">
+  </path>
+  <path stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round" stroke-linecap="round"
+    d="M6.66663 2.5L7.08329 3.75">
+  </path>
+  <path stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round" stroke-linecap="round"
+    d="M2.5 4.58334L11.6667 4.58334">
+  </path>
+  <path stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round" stroke-linecap="round"
+    d="M4.16663 6.66666C4.16663 6.66666 4.91225 9.27537 6.77629 10.7246C8.64029 12.1739 11.6666 13.3333 11.6666 13.3333">
+  </path>
+  <path stroke="rgba(255, 255, 255, 1)" stroke-width="1.6666666666666667" stroke-linejoin="round" stroke-linecap="round"
+    d="M10 4.58334C10 4.58334 9.25438 8.00725 7.39033 9.90942C5.52633 11.8116 2.5 13.3333 2.5 13.3333">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/model.svg b/bigtop-manager-ui/src/assets/images/svg/model.svg
new file mode 100644
index 0000000..85dc0a5
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/model.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path
+    d="M5.16667 3.00004L2.33334 4.66671L2.33334 8.00004L2.33334 11.3334L5.16667 13L8 14.6667L10.8334 13L13.6667 11.3334L13.6667 8.00004L13.6667 4.66671L10.8334 3.00004L8 1.33337L5.16667 3.00004Z"
+    stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round">
+  </path>
+  <path stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M8 1.33337L8 8.00004">
+  </path>
+  <path stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M13.6667 11.3333L8 8">
+  </path>
+  <path stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M2.33334 11.3333L8 8">
+  </path>
+  <path stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M8 14.6667L8 11.3334">
+  </path>
+  <path stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M13.6667 4.66663L11 6.33329">
+  </path>
+  <path stroke="rgba(51, 51, 51, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M2.33334 4.66663L5 6.33329">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/model_activated.svg b/bigtop-manager-ui/src/assets/images/svg/model_activated.svg
new file mode 100644
index 0000000..fee86d7
--- /dev/null
+++ b/bigtop-manager-ui/src/assets/images/svg/model_activated.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path
+    d="M5.16668 3.00004L2.33334 4.66671L2.33334 8.00004L2.33334 11.3334L5.16668 13L8.00001 14.6667L10.8334 13L13.6667 11.3334L13.6667 8.00004L13.6667 4.66671L10.8334 3.00004L8.00001 1.33337L5.16668 3.00004Z"
+    stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round">
+  </path>
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M8 1.33337L8 8.00004">
+  </path>
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M13.6667 11.3333L8 8">
+  </path>
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M2.33334 11.3333L8.00001 8">
+  </path>
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M8 14.6667L8 11.3334">
+  </path>
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M13.6667 4.66663L11 6.33329">
+  </path>
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M2.33334 4.66663L5.00001 6.33329">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/plus.svg b/bigtop-manager-ui/src/assets/images/svg/plus.svg
index c5a659b..1b1561e 100644
--- a/bigtop-manager-ui/src/assets/images/svg/plus.svg
+++ b/bigtop-manager-ui/src/assets/images/svg/plus.svg
@@ -1,4 +1,4 @@
-<?xml version="1.0" standalone="no"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,13 +17,12 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg t="1722394248439" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1160"
-  xmlns:xlink="http://www.w3.org/1999/xlink" width="1em" height="1em">
-  <path
-    d="M512 853.333333c-25.6 0-42.666667-17.066667-42.666667-42.666666V213.333333c0-25.6 17.066667-42.666667 42.666667-42.666666s42.666667 17.066667 42.666667 42.666666v597.333334c0 25.6-17.066667 42.666667-42.666667 42.666666z"
-    p-id="1161"></path>
-  <path
-    d="M810.666667 554.666667H213.333333c-25.6 0-42.666667-17.066667-42.666666-42.666667s17.066667-42.666667 42.666666-42.666667h597.333334c25.6 0 42.666667 17.066667 42.666666 42.666667s-17.066667 42.666667-42.666666 42.666667z"
-    p-id="1162"></path>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"
+  viewBox="0 0 16 16" fill="none">
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M8.02017 3.33334L8.00797 12.6667">
+  </path>
+  <path stroke="rgba(22, 119, 255, 1)" stroke-width="1.3333333333333333" stroke-linejoin="round" stroke-linecap="round"
+    d="M3.33333 8L12.6667 8">
+  </path>
 </svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/restart.svg b/bigtop-manager-ui/src/assets/images/svg/restart.svg
deleted file mode 100644
index bfc4bea..0000000
--- a/bigtop-manager-ui/src/assets/images/svg/restart.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg t="1722394200089" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1652"
-  xmlns:xlink="http://www.w3.org/1999/xlink" width="1em" height="1em">
-  <path
-    d="M512 213.333333V42.666667L298.666667 256l213.333333 213.333333V298.666667c141.226667 0 256 114.773333 256 256s-114.773333 256-256 256-256-114.773333-256-256H170.666667c0 188.586667 152.746667 341.333333 341.333333 341.333333s341.333333-152.746667 341.333333-341.333333-152.746667-341.333333-341.333333-341.333334z"
-    fill="#333333" p-id="1653"></path>
-</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/robot.svg b/bigtop-manager-ui/src/assets/images/svg/robot.svg
deleted file mode 100644
index bb7b0e9..0000000
--- a/bigtop-manager-ui/src/assets/images/svg/robot.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
-  <rect x="9" y="18" width="30" height="24" rx="2" fill="none" stroke="#333" stroke-width="2" />
-  <circle cx="17" cy="26" r="2" fill="#333" />
-  <circle cx="31" cy="26" r="2" fill="#333" />
-  <path
-    d="M20 32C18.8954 32 18 32.8954 18 34C18 35.1046 18.8954 36 20 36V32ZM28 36C29.1046 36 30 35.1046 30 34C30 32.8954 29.1046 32 28 32V36ZM20 36H28V32H20V36Z"
-    fill="#333" />
-  <path d="M24 10V18" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-  <path d="M4 26V34" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-  <path d="M44 26V34" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-  <circle cx="24" cy="8" r="2" stroke="#333" stroke-width="4" />
-</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/square-filled.svg b/bigtop-manager-ui/src/assets/images/svg/square-filled.svg
deleted file mode 100644
index 197f3b4..0000000
--- a/bigtop-manager-ui/src/assets/images/svg/square-filled.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 1024 1024">
-  <path fill="currentColor"
-    d="M252.068571 906.496h520.283429c89.581714 0 134.144-44.562286 134.144-132.845714V250.331429c0-88.283429-44.562286-132.845714-134.144-132.845715H252.068571c-89.142857 0-134.582857 44.141714-134.582857 132.845715V773.668571c0 88.704 45.44 132.845714 134.582857 132.845715z" />
-</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/start.svg b/bigtop-manager-ui/src/assets/images/svg/start.svg
deleted file mode 100644
index 360c7ff..0000000
--- a/bigtop-manager-ui/src/assets/images/svg/start.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg t="1722396617369" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1344"
-  xmlns:xlink="http://www.w3.org/1999/xlink" width="1em" height="1em">
-  <path
-    d="M810.4 465.8 253.6 134.4c-6.8-4-13.8-6.4-21.8-6.4-21.8 0-39.6 18-39.6 40L192 168l0 688 0.2 0c0 22 17.8 40 39.6 40 8.2 0 15-2.8 22.4-6.8l556.2-331c13.2-11 21.6-27.6 21.6-46.2C832 493.4 823.6 477 810.4 465.8z"
-    p-id="1345"></path>
-</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/assets/images/svg/stop.svg b/bigtop-manager-ui/src/assets/images/svg/stop.svg
deleted file mode 100644
index 734b035..0000000
--- a/bigtop-manager-ui/src/assets/images/svg/stop.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg t="1722394157011" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1130"
-  xmlns:xlink="http://www.w3.org/1999/xlink" width="1em" height="1em">
-  <path
-    d="M256 192h512c35.392 0 64 28.608 64 64v512c0 35.392-28.608 64-64 64H256c-35.392 0-64-28.608-64-64V256c0-35.392 28.608-64 64-64z"
-    fill="#333333" p-id="1131"></path>
-</svg>
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/components/alert-info/index.vue b/bigtop-manager-ui/src/components/alert-info/index.vue
deleted file mode 100644
index 093bf30..0000000
--- a/bigtop-manager-ui/src/components/alert-info/index.vue
+++ /dev/null
@@ -1,143 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { BellOutlined } from '@ant-design/icons-vue'
-  import { computed, ref } from 'vue'
-  import dayjs from 'dayjs'
-  import customParseFormat from 'dayjs/plugin/customParseFormat'
-  const visible = ref(false)
-  const overlayInnerStyle = {
-    padding: '12px 0',
-    width: '400px'
-  }
-
-  // now Date
-  const getAlertTrigger = computed(() => {
-    dayjs.extend(customParseFormat)
-    return dayjs(new Date())
-  })
-</script>
-
-<template>
-  <a-popover
-    v-model:open="visible"
-    placement="bottomRight"
-    trigger="click"
-    :arrow-point-at-center="true"
-    :auto-adjust-overflow="true"
-    :overlay-inner-style="overlayInnerStyle"
-  >
-    <template #title>
-      <div class="alert-title">{{ $t('common.notification') }}</div>
-    </template>
-    <template #content>
-      <ul class="alert-list">
-        <li v-for="idx in 100" :key="idx">
-          <dot-state
-            width="10"
-            height="10"
-            style="margin-right: 10px; line-height: 28px"
-            color="#f5222d"
-          />
-          <div>
-            <div class="alert-list-ctx">
-              <div>DataNode Process</div>
-              <p>
-                Ulimit for open files (-n)is 1048576 which is higher orequal
-                than critical value of 800000
-              </p>
-            </div>
-            <div class="alert-list-state">{{ getAlertTrigger }}</div>
-          </div>
-        </li>
-      </ul>
-      <footer>
-        <a>{{ $t('common.view_all') }}</a>
-      </footer>
-    </template>
-    <div class="alert">
-      <a-badge size="small" color="red" count="100">
-        <bell-outlined />
-      </a-badge>
-    </div>
-  </a-popover>
-</template>
-
-<style lang="scss" scoped>
-  .alert {
-    height: 36px;
-    width: 36px;
-    font-size: 16px;
-    cursor: pointer;
-    border-radius: 50%;
-    @include flexbox($justify: center, $align: center);
-
-    &:hover {
-      background-color: var(--hover-color);
-    }
-  }
-  .alert-title {
-    font-size: 16px;
-    color: #333333;
-    font-weight: normal;
-    padding-left: 10px;
-  }
-  .alert-list {
-    padding: 0;
-    list-style: none;
-    max-height: 400px;
-    overflow-y: auto;
-    margin-bottom: 0;
-
-    li {
-      padding: 10px;
-      cursor: pointer;
-      @include flexbox($justify: center);
-      &:hover {
-        background-color: var(--hover-color);
-      }
-
-      &:not(:last-child) {
-        border-bottom: 1px solid #eeeeee;
-      }
-    }
-
-    &-ctx {
-      div {
-        font-weight: 700;
-        color: #333333;
-        font-size: 16px;
-      }
-      p {
-        color: #666666;
-      }
-    }
-    &-state {
-      text-align: end;
-      color: #999999;
-      font-size: 14px;
-    }
-  }
-  footer {
-    border-top: 1px solid #eeeeee;
-    text-align: end;
-    padding: 10px 28px 0 10px;
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/cluster-create/choose-stack.vue b/bigtop-manager-ui/src/components/cluster-create/choose-stack.vue
deleted file mode 100644
index 11aee37..0000000
--- a/bigtop-manager-ui/src/components/cluster-create/choose-stack.vue
+++ /dev/null
@@ -1,122 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { ref, onMounted, watch } from 'vue'
-  import { useStackStore } from '@/store/stack'
-  import { storeToRefs } from 'pinia'
-  import { useI18n } from 'vue-i18n'
-  import { ServiceVO } from '@/api/service/types.ts'
-
-  const clusterInfo = defineModel<any>('clusterInfo')
-
-  const { t } = useI18n()
-  const stackStore = useStackStore()
-
-  const selectedOption = ref<string[]>([])
-  const serviceData = ref<ServiceVO[]>([])
-  const { stackOptions, stackServices } = storeToRefs(stackStore)
-
-  watch(selectedOption, (val) => {
-    clusterInfo.value.clusterCommand.stackName = val[0]
-    clusterInfo.value.clusterCommand.stackVersion = val[1]
-    clusterInfo.value.clusterCommand.fullStackName = val[0] + '-' + val[1]
-
-    serviceData.value =
-      stackServices.value[clusterInfo.value.clusterCommand.fullStackName]
-  })
-
-  const serviceColumns = [
-    {
-      title: t('common.name'),
-      dataIndex: 'displayName',
-      align: 'center',
-      width: 150
-    },
-    {
-      title: t('common.version'),
-      dataIndex: 'serviceVersion',
-      align: 'center',
-      width: 150
-    },
-    {
-      title: t('common.desc'),
-      dataIndex: 'serviceDesc',
-      align: 'center'
-    }
-  ]
-
-  onMounted(async () => {
-    if (clusterInfo.value.clusterCommand.fullStackName) {
-      selectedOption.value = [
-        clusterInfo.value.clusterCommand.stackName,
-        clusterInfo.value.clusterCommand.stackVersion
-      ]
-    } else {
-      selectedOption.value = [
-        `${stackOptions.value?.[0]?.value}`,
-        `${stackOptions.value?.[0]?.children?.[0]?.value}`
-      ]
-    }
-  })
-
-  const onNextStep = async () => {
-    return Promise.resolve(true)
-  }
-
-  defineExpose({
-    onNextStep
-  })
-</script>
-
-<template>
-  <div class="container">
-    <div class="title">{{ $t('cluster.choose_stack') }}</div>
-    <a-cascader
-      v-model:value="selectedOption"
-      :options="stackOptions"
-      :placeholder="$t('common.select_tips')"
-    />
-    <div class="space" />
-    <a-table
-      :pagination="false"
-      :scroll="{ y: 400 }"
-      :columns="serviceColumns"
-      :data-source="serviceData"
-    />
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: start, $align: center);
-    align-content: center;
-    height: 100%;
-
-    .title {
-      font-size: 1.5rem;
-      line-height: 2rem;
-      margin-bottom: 1rem;
-    }
-
-    .space {
-      margin: 1rem 0;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/cluster-create/finish.vue b/bigtop-manager-ui/src/components/cluster-create/finish.vue
deleted file mode 100644
index 53d6573..0000000
--- a/bigtop-manager-ui/src/components/cluster-create/finish.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { SmileOutlined, FrownOutlined } from '@ant-design/icons-vue'
-
-  const clusterInfo = defineModel<any>('clusterInfo')
-</script>
-
-<template>
-  <div class="container">
-    <a-result
-      v-if="clusterInfo.success"
-      :title="$t('cluster.create_success_title')"
-      :sub-title="$t('cluster.create_success_sub_title')"
-    >
-      <template #icon>
-        <smile-outlined />
-      </template>
-    </a-result>
-    <a-result
-      v-else
-      :title="$t('cluster.create_fail_title')"
-      :sub-title="$t('cluster.create_fail_sub_title')"
-    >
-      <template #icon>
-        <frown-outlined />
-      </template>
-    </a-result>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: center, $align: center);
-    align-content: center;
-    height: 100%;
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/cluster-create/index.vue b/bigtop-manager-ui/src/components/cluster-create/index.vue
deleted file mode 100644
index 6c9e2bd..0000000
--- a/bigtop-manager-ui/src/components/cluster-create/index.vue
+++ /dev/null
@@ -1,242 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { ref, reactive, h, watch, onMounted } from 'vue'
-  import { Modal } from 'ant-design-vue'
-  import { ExclamationCircleFilled } from '@ant-design/icons-vue'
-  import { useI18n } from 'vue-i18n'
-  import { useStackStore } from '@/store/stack'
-  import SetClusterName from './set-cluster-name.vue'
-  import ChooseStack from './choose-stack.vue'
-  import SetRepository from './set-repository.vue'
-  import SetHosts from './set-hosts.vue'
-  import Install from './install.vue'
-  import Finish from './finish.vue'
-  import { useClusterStore } from '@/store/cluster'
-
-  const open = defineModel<boolean>('open')
-  const { t, locale } = useI18n()
-  const stackStore = useStackStore()
-  const clusterStore = useClusterStore()
-
-  const initItems = () => [
-    {
-      disabled: true,
-      status: 'process',
-      title: t('cluster.set_cluster_name'),
-      content: h(SetClusterName)
-    },
-    {
-      disabled: true,
-      status: 'wait',
-      title: t('cluster.choose_stack'),
-      content: h(ChooseStack)
-    },
-    {
-      disabled: true,
-      status: 'wait',
-      title: t('cluster.set_repository'),
-      content: h(SetRepository)
-    },
-    {
-      disabled: true,
-      status: 'wait',
-      title: t('cluster.set_hosts'),
-      content: h(SetHosts)
-    },
-    {
-      disabled: true,
-      status: 'wait',
-      title: t('common.install'),
-      content: h(Install)
-    },
-    {
-      disabled: true,
-      status: 'wait',
-      title: t('common.finish'),
-      content: h(Finish)
-    }
-  ]
-
-  const initClusterInfo = () => {
-    const clusterCommand = {
-      clusterName: '',
-      // 1-Physical Machine 2-Kubernetes
-      // Only support physical machine right now
-      clusterType: 1,
-      stackName: '',
-      stackVersion: '',
-      fullStackName: '',
-      repoInfoList: [],
-      hosts: '', // save hostsMetaStr
-      hostnames: []
-    }
-
-    return {
-      command: 'create',
-      commandLevel: 'cluster',
-      clusterCommand: clusterCommand,
-      // Related job id
-      jobId: 0,
-      // Job Status
-      success: false
-    }
-  }
-
-  const current = ref<number>(0)
-  const items = reactive(initItems())
-  const clusterInfo = reactive(initClusterInfo())
-  const disableButton = ref<boolean>(false)
-  const currentItemRef = ref<any>(null)
-  const loadingNext = ref<boolean>(false)
-  watch(locale, () => {
-    Object.assign(items, initItems())
-  })
-
-  const next = async () => {
-    loadingNext.value = true
-    try {
-      const valid = await currentItemRef.value?.onNextStep()
-      if (valid) {
-        console.log('clusterInfo:', JSON.stringify(clusterInfo))
-        items[current.value].status = 'finish'
-        current.value++
-        items[current.value].status = 'process'
-      }
-    } finally {
-      loadingNext.value = false
-    }
-  }
-
-  const prev = () => {
-    items[current.value].status = 'wait'
-    current.value--
-    items[current.value].status = 'process'
-  }
-
-  const clear = () => {
-    // Reload clusters
-    clusterStore.loadClusters()
-
-    // Clear status
-    current.value = 0
-    open.value = false
-    Object.assign(items, initItems())
-    Object.assign(clusterInfo, initClusterInfo())
-  }
-
-  const cancel = () => {
-    Modal.confirm({
-      title: t('common.exit'),
-      icon: h(ExclamationCircleFilled),
-      content: t('common.exit_confirm'),
-      onOk() {
-        clear()
-      }
-    })
-  }
-
-  onMounted(async () => {
-    await stackStore.initStacks()
-  })
-</script>
-
-<template>
-  <a-modal
-    :open="open"
-    width="95%"
-    centered
-    destroy-on-close
-    :mask-closable="false"
-    :keyboard="false"
-    @update:open="cancel"
-  >
-    <template #footer>
-      <a-button
-        v-if="current > 0"
-        class="footer-btn"
-        type="primary"
-        :disabled="disableButton"
-        @click="prev"
-      >
-        {{ $t('common.prev') }}
-      </a-button>
-      <a-button
-        v-if="current < items.length - 1"
-        class="footer-btn"
-        type="primary"
-        :loading="loadingNext"
-        :disabled="disableButton"
-        @click="next"
-      >
-        {{ $t('common.next') }}
-      </a-button>
-      <a-button
-        v-if="current === items.length - 1"
-        class="footer-btn"
-        type="primary"
-        @click="() => clear()"
-      >
-        {{ $t('common.done') }}
-      </a-button>
-    </template>
-    <div class="container">
-      <a-steps
-        v-model:current="current"
-        class="step"
-        direction="vertical"
-        size="small"
-        :items="items"
-      />
-      <div class="content">
-        <component
-          :is="items[current].content"
-          ref="currentItemRef"
-          v-model:clusterInfo="clusterInfo"
-          v-model:disableButton="disableButton"
-        />
-      </div>
-    </div>
-  </a-modal>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: row, $justify: center, $align: center);
-
-    .step {
-      width: 15%;
-      height: 35rem;
-    }
-
-    .content {
-      margin-top: 1rem;
-      padding-left: 1rem;
-      height: 35rem;
-      width: 85%;
-      text-align: center;
-      border-left: 1px solid #d9d9d9;
-    }
-  }
-
-  .footer-btn {
-    width: 8.333333%;
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/cluster-create/install.vue b/bigtop-manager-ui/src/components/cluster-create/install.vue
deleted file mode 100644
index 6f31ebe..0000000
--- a/bigtop-manager-ui/src/components/cluster-create/install.vue
+++ /dev/null
@@ -1,154 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { useI18n } from 'vue-i18n'
-  import { getJob } from '@/api/job'
-  import { JOB_SCHEDULE_INTERVAL } from '@/utils/constant.ts'
-  import { useIntervalFn } from '@vueuse/core'
-  import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue'
-  import { useClusterStore } from '@/store/cluster'
-  import { storeToRefs } from 'pinia'
-  import CustomProgress from '@/components/job-info/custom-progress.vue'
-  import Job from '@/components/job-info/job.vue'
-  import { JobVO, StageVO } from '@/api/job/types'
-
-  const clusterInfo = defineModel<any>('clusterInfo')
-  const disableButton = defineModel<boolean>('disableButton')
-
-  const clusterStore = useClusterStore()
-  const { clusterId } = storeToRefs(clusterStore)
-
-  const { t } = useI18n()
-  const loading = ref(true)
-  const jobWindowOpened = ref(false)
-  const jobState = ref<string>('')
-  const jobs = ref<JobVO[]>([])
-  const currStage = ref<StageVO>()
-  const installData = reactive([])
-
-  const installColumns = [
-    {
-      title: t('common.stage'),
-      dataIndex: 'name',
-      align: 'center'
-    },
-    {
-      title: t('common.progress'),
-      dataIndex: 'state',
-      align: 'center'
-    }
-  ]
-
-  const initData = async () => {
-    const res = await getJob(clusterInfo.value.jobId, clusterId.value)
-    // const res: any = await getFetch()
-    jobs.value = [res] as any
-    // console.log(res)
-    jobState.value = res.state
-
-    if (!['Pending', 'Processing'].includes(jobState.value)) {
-      disableButton.value = false
-      clusterInfo.value.success = jobState.value === 'Successful'
-    }
-    return res.stages.sort((a: StageVO, b: StageVO) => a.order - b.order)
-  }
-
-  const clickStage = (record: StageVO) => {
-    jobWindowOpened.value = true
-    currStage.value = record
-  }
-
-  onBeforeMount(async () => {
-    disableButton.value = true
-    const { pause } = useIntervalFn(
-      async () => {
-        Object.assign(installData, await initData())
-        loading.value = false
-        if (!['Pending', 'Processing'].includes(jobState.value)) {
-          pause()
-        }
-      },
-      JOB_SCHEDULE_INTERVAL,
-      { immediateCallback: true }
-    )
-  })
-
-  onBeforeUnmount(() => {
-    disableButton.value = false
-  })
-
-  const onNextStep = async () => {
-    return Promise.resolve(true)
-  }
-
-  defineExpose({
-    onNextStep
-  })
-</script>
-
-<template>
-  <div class="container">
-    <div class="title">{{ $t('common.install') }}</div>
-    <a-table
-      :pagination="false"
-      :scroll="{ y: 400 }"
-      :columns="installColumns"
-      :data-source="installData"
-      :loading="loading"
-    >
-      <template #bodyCell="{ column, text, record }">
-        <template v-if="column.dataIndex === 'name'">
-          <a @click="clickStage(record)">
-            {{ text }}
-          </a>
-        </template>
-        <template v-if="column.dataIndex === 'state'">
-          <custom-progress
-            :key="record.id"
-            :state="text"
-            :progress-data="record.tasks"
-          />
-        </template>
-      </template>
-    </a-table>
-    <job
-      v-model:visible="jobWindowOpened"
-      :outer-data="{ meta: jobs, currItem: currStage }"
-    />
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: start, $align: center);
-    align-content: center;
-    height: 100%;
-
-    .title {
-      font-size: 1.5rem;
-      line-height: 2rem;
-      margin-bottom: 1rem;
-
-      .progress {
-        width: 80%;
-      }
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/cluster-create/set-cluster-name.vue b/bigtop-manager-ui/src/components/cluster-create/set-cluster-name.vue
deleted file mode 100644
index d17f402..0000000
--- a/bigtop-manager-ui/src/components/cluster-create/set-cluster-name.vue
+++ /dev/null
@@ -1,80 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { ref } from 'vue'
-  import { RocketOutlined } from '@ant-design/icons-vue'
-
-  const clusterInfo = defineModel<any>('clusterInfo')
-
-  const formRef = ref<any>(null)
-
-  const onNextStep = async () => {
-    try {
-      await formRef.value?.validate()
-      return Promise.resolve(true)
-    } catch (e) {
-      return Promise.resolve(false)
-    }
-  }
-
-  defineExpose({
-    onNextStep
-  })
-</script>
-
-<template>
-  <div class="container">
-    <a-result
-      :title="$t('cluster.set_cluster_name_title')"
-      :sub-title="$t('cluster.set_cluster_name_sub_title')"
-    >
-      <template #icon>
-        <rocket-outlined />
-      </template>
-      <template #extra>
-        <a-form ref="formRef" :model="clusterInfo.clusterCommand">
-          <a-form-item
-            name="clusterName"
-            :rules="[
-              {
-                required: true,
-                message: $t('cluster.set_cluster_name_valid')
-              }
-            ]"
-          >
-            <a-input
-              v-model:value="clusterInfo.clusterCommand.clusterName"
-              allow-clear
-              :placeholder="$t('cluster.set_cluster_name_input')"
-            />
-          </a-form-item>
-        </a-form>
-      </template>
-    </a-result>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: center, $align: center);
-    align-content: center;
-    height: 100%;
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/cluster-create/set-hosts.vue b/bigtop-manager-ui/src/components/cluster-create/set-hosts.vue
deleted file mode 100644
index 2842238..0000000
--- a/bigtop-manager-ui/src/components/cluster-create/set-hosts.vue
+++ /dev/null
@@ -1,174 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { ref, h } from 'vue'
-  import { execCommand } from '@/api/command'
-  import { parseHostNamesAsPatternExpression } from '@/utils/array'
-  import type { FormInstance } from 'ant-design-vue'
-  import { Modal } from 'ant-design-vue'
-  import { useI18n } from 'vue-i18n'
-  import { CheckCircleOutlined } from '@ant-design/icons-vue'
-
-  const { t } = useI18n()
-  const clusterInfo = defineModel<any>('clusterInfo')
-  const formRef = ref<FormInstance>()
-  const { clusterCommand } = clusterInfo.value
-
-  const onNextStep = async () => {
-    // clusterInfo.value.clusterCommand.hostnames = hosts.value
-    //   .split('\n')
-    //   .filter((item) => item !== '')
-    try {
-      const checkValidate = await formRef.value?.validate()
-      if (checkValidate) {
-        const confirmStatus = await showHosts()
-        if (confirmStatus) {
-          const res = await execCommand(clusterInfo.value)
-          clusterInfo.value.jobId = res.id
-          return Promise.resolve(true)
-        }
-      } else {
-        return Promise.resolve(false)
-      }
-    } catch (e) {
-      console.log(e)
-      return Promise.resolve(false)
-    }
-  }
-
-  const createHostNameEls = (list: string[]) => {
-    const elStyles = {
-      contentStyle: {
-        marginInlineStart: '2.125rem',
-        width: '100%',
-        maxHeight: '31.25rem',
-        overflow: 'auto'
-      },
-      itemStyle: { margin: '0.625rem' },
-      iconWrpStyle: {
-        fontSize: '1.375rem',
-        fontWeight: 600,
-        color: 'green',
-        marginInlineEnd: '0.75rem'
-      },
-      titleStyle: {
-        fontSize: '1rem',
-        fontWeight: 600
-      },
-      redfIconStyle: {
-        display: 'flex',
-        alignItems: 'center'
-      }
-    }
-    const items = list.map((item: string, idx: number) => {
-      return h('li', { key: idx, style: elStyles.itemStyle }, item)
-    })
-
-    const iconWrpStyle = h(
-      'span',
-      {
-        style: elStyles.iconWrpStyle
-      },
-      [h(CheckCircleOutlined)]
-    )
-
-    const replaceTitle = h(
-      'span',
-      { style: elStyles.titleStyle },
-      `${t('cluster.show_hosts_resolved')}`
-    )
-
-    const reDefineIcon = h('div', { style: elStyles.redfIconStyle }, [
-      iconWrpStyle,
-      replaceTitle
-    ])
-
-    const box = h(
-      'div',
-      {
-        style: elStyles.contentStyle
-      },
-      items
-    )
-
-    return { box, reDefineIcon }
-  }
-
-  const showHosts = (): Promise<boolean> => {
-    const hostList = parseHostNamesAsPatternExpression(clusterCommand.hosts)
-    const { box: content, reDefineIcon: icon } = createHostNameEls(hostList)
-    return new Promise((resolve) => {
-      Modal.confirm({
-        title: '',
-        icon,
-        centered: true,
-        width: '31.25rem',
-        content,
-        onOk() {
-          clusterCommand.hostnames = hostList
-          resolve(true)
-        },
-        onCancel() {
-          resolve(false)
-          Modal.destroyAll()
-        }
-      })
-    })
-  }
-
-  defineExpose({
-    onNextStep
-  })
-</script>
-
-<template>
-  <div class="container">
-    <div class="title">{{ $t('cluster.set_hosts') }}</div>
-    <a-form ref="formRef" :style="{ width: '100%' }" :model="clusterCommand">
-      <a-form-item
-        name="hosts"
-        :rules="[
-          {
-            required: true,
-            message: `${$t('cluster.set_hosts_valid')}`
-          }
-        ]"
-      >
-        <a-textarea
-          v-model:value="clusterCommand.hosts"
-          :rows="18"
-          :placeholder="$t('cluster.set_hosts_placeholder')"
-        />
-      </a-form-item>
-    </a-form>
-  </div>
-</template>
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: start, $align: center);
-    height: 100%;
-
-    .title {
-      font-size: 1.5rem;
-      line-height: 2rem;
-      margin-bottom: 1rem;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/cluster-create/set-repository.vue b/bigtop-manager-ui/src/components/cluster-create/set-repository.vue
deleted file mode 100644
index 873c673..0000000
--- a/bigtop-manager-ui/src/components/cluster-create/set-repository.vue
+++ /dev/null
@@ -1,173 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { reactive, UnwrapRef } from 'vue'
-  import { CheckOutlined, EditOutlined } from '@ant-design/icons-vue'
-  import { useI18n } from 'vue-i18n'
-  import { useStackStore } from '@/store/stack'
-  import { storeToRefs } from 'pinia'
-  import _ from 'lodash'
-  import { RepoVO } from '@/api/repo/types.ts'
-
-  const clusterInfo = defineModel<any>('clusterInfo')
-
-  const { t } = useI18n()
-  const stackStore = useStackStore()
-
-  const editableData: UnwrapRef<Record<number, RepoVO>> = reactive({})
-  const { stackRepos } = storeToRefs(stackStore)
-
-  const repositoryData: RepoVO[] = _.cloneDeep(
-    stackRepos.value[clusterInfo.value.clusterCommand.fullStackName]
-  )
-
-  const repositoryColumns = [
-    {
-      title: t('common.os'),
-      dataIndex: 'os',
-      align: 'center',
-      width: 150
-    },
-    {
-      title: t('common.arch'),
-      dataIndex: 'arch',
-      align: 'center',
-      width: 150
-    },
-    {
-      title: t('common.base_url'),
-      dataIndex: 'baseUrl',
-      align: 'center',
-      ellipsis: true
-    }
-  ]
-
-  const edit = (index: number) => {
-    editableData[index] = _.cloneDeep(repositoryData[index])
-  }
-
-  const save = (index: number) => {
-    Object.assign(repositoryData[index], editableData[index])
-
-    delete editableData[index]
-  }
-
-  const onNextStep = async () => {
-    Object.assign(clusterInfo.value.clusterCommand.repoInfoList, repositoryData)
-
-    return Promise.resolve(true)
-  }
-
-  defineExpose({
-    onNextStep
-  })
-</script>
-
-<template>
-  <div class="container">
-    <div class="title">{{ $t('cluster.set_repository') }}</div>
-    <a-table
-      :pagination="false"
-      :scroll="{ y: 400 }"
-      :columns="repositoryColumns"
-      :data-source="repositoryData"
-    >
-      <template #bodyCell="{ text, index, column }">
-        <template v-if="column.dataIndex === 'baseUrl'">
-          <div class="editable-cell">
-            <div v-if="editableData[index]" class="editable-cell-input-wrapper">
-              <a-input
-                v-model:value="editableData[index].baseUrl"
-                @press-enter="save(index)"
-              />
-              <check-outlined
-                class="editable-cell-icon-check"
-                @click="save(index)"
-              />
-            </div>
-            <div v-else class="editable-cell-text-wrapper">
-              {{ text || ' ' }}
-              <edit-outlined class="editable-cell-icon" @click="edit(index)" />
-            </div>
-          </div>
-        </template>
-      </template>
-    </a-table>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: start, $align: center);
-    align-content: center;
-    height: 100%;
-
-    .title {
-      font-size: 1.5rem;
-      line-height: 2rem;
-      margin-bottom: 1rem;
-    }
-
-    .editable-cell {
-      position: relative;
-
-      .editable-cell-input-wrapper {
-        @include flexbox($justify: center, $align: center);
-        padding-right: 24px;
-
-        .editable-cell-icon-check {
-          position: absolute;
-          line-height: 28px;
-          right: 0;
-          width: 20px;
-          cursor: pointer;
-
-          &:hover {
-            color: #108ee9;
-          }
-        }
-      }
-
-      .editable-cell-text-wrapper {
-        @include flexbox($justify: center, $align: center);
-        padding: 5px 24px 5px 5px;
-
-        .editable-cell-icon {
-          display: none;
-          position: absolute;
-          margin-top: 4px;
-          right: 0;
-          width: 20px;
-          cursor: pointer;
-
-          &:hover {
-            color: #108ee9;
-          }
-        }
-      }
-
-      &:hover {
-        .editable-cell-icon {
-          display: inline-block;
-        }
-      }
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/cluster-info/index.vue b/bigtop-manager-ui/src/components/cluster-info/index.vue
deleted file mode 100644
index d35026c..0000000
--- a/bigtop-manager-ui/src/components/cluster-info/index.vue
+++ /dev/null
@@ -1,68 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { ref } from 'vue'
-  import { useClusterStore } from '@/store/cluster'
-  import { storeToRefs } from 'pinia'
-  import ClusterCreate from '@/components/cluster-create/index.vue'
-
-  const clusterStore = useClusterStore()
-  const { selectedCluster } = storeToRefs(clusterStore)
-
-  const createWindowOpened = ref(false)
-</script>
-
-<template>
-  <a-dropdown placement="bottom">
-    <div class="icon">
-      <div class="name">{{ selectedCluster?.clusterName }}</div>
-    </div>
-    <template #overlay>
-      <a-menu>
-        <a-menu-item key="switch">
-          {{ $t('cluster.switch') }}
-        </a-menu-item>
-        <a-menu-item key="create" @click="() => (createWindowOpened = true)">
-          {{ $t('cluster.create') }}
-        </a-menu-item>
-      </a-menu>
-    </template>
-  </a-dropdown>
-
-  <cluster-create v-model:open="createWindowOpened" />
-</template>
-
-<style lang="scss" scoped>
-  .icon {
-    @include flexbox($justify: center, $align: center);
-    padding: 0 0.5rem;
-    border-radius: 6px;
-    cursor: pointer;
-    height: 36px;
-
-    &:hover {
-      background-color: var(--hover-color);
-    }
-
-    .name {
-      font-size: 14px;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/common/dot-state/index.vue b/bigtop-manager-ui/src/components/common/dot-state/index.vue
deleted file mode 100644
index f0f6ae7..0000000
--- a/bigtop-manager-ui/src/components/common/dot-state/index.vue
+++ /dev/null
@@ -1,77 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<template>
-  <div class="dot-state" :style="config"><slot></slot></div>
-</template>
-
-<script lang="ts" setup>
-  import { computed } from 'vue'
-  interface Dot {
-    width?: string | number
-    height?: string | number
-    color?: string
-  }
-
-  const props = withDefaults(defineProps<Dot>(), {
-    width: '16px',
-    height: '16px',
-    color: '#f5222d'
-  })
-
-  const checkProps = (target: string | number): string => {
-    if (typeof target === 'number') {
-      return `${target}px`
-    } else {
-      const int = parseInt(target as string)
-      if (isNaN(int)) {
-        throw new Error('value is not NaN')
-      } else {
-        return `${int}px`
-      }
-    }
-  }
-
-  const config = computed(() => {
-    const width = checkProps(props.width)
-    const height = checkProps(props.width)
-    return {
-      '--state-w': width,
-      '--state-h': height,
-      '--state-color': props.color
-    }
-  })
-</script>
-
-<style lang="scss" scoped>
-  @mixin dot($width, $height, $color) {
-    width: $width;
-    height: $height;
-    background: $color;
-    border-radius: 50%;
-  }
-  .dot-state {
-    &::before {
-      content: '';
-      margin: 0 0.375rem 0 0;
-      display: inline-block;
-      @include dot(var(--state-w), var(--state-h), var(--state-color));
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/common/index.ts b/bigtop-manager-ui/src/components/common/index.ts
index d0b6fcc..faa746b 100644
--- a/bigtop-manager-ui/src/components/common/index.ts
+++ b/bigtop-manager-ui/src/components/common/index.ts
@@ -19,12 +19,10 @@
 
 import type { App } from 'vue'
 import SvgIcon from './svg-icon/index.vue'
-import DotState from './dot-state/index.vue'
 import MarkView from './markdown-view/index.vue'
 
 const comments = {
   SvgIcon,
-  DotState,
   MarkView
 }
 
diff --git a/bigtop-manager-ui/src/components/common/svg-icon/index.vue b/bigtop-manager-ui/src/components/common/svg-icon/index.vue
index e0710e1..c18cc3f 100644
--- a/bigtop-manager-ui/src/components/common/svg-icon/index.vue
+++ b/bigtop-manager-ui/src/components/common/svg-icon/index.vue
@@ -24,26 +24,18 @@
     prefix?: string
     name: string
     color?: string
-    className?: string
   }
 
   const props = withDefaults(defineProps<SvgIconProps>(), {
     prefix: 'icon',
-    color: '#000',
-    className: ''
+    color: '#000'
   })
 
   const symbolId = computed(() => `#${props.prefix}-${props.name}`)
-  const svgClass = computed(() => {
-    if (props.className) {
-      return `svg-icon ${props.className}`
-    }
-    return 'svg-icon'
-  })
 </script>
 
 <template>
-  <svg :class="svgClass" aria-hidden="true">
+  <svg class="svg-icon" aria-hidden="true">
     <use :xlink:href="symbolId" :fill="color" />
   </svg>
 </template>
diff --git a/bigtop-manager-ui/src/components/dashboard/index.vue b/bigtop-manager-ui/src/components/dashboard/index.vue
deleted file mode 100644
index cd440c2..0000000
--- a/bigtop-manager-ui/src/components/dashboard/index.vue
+++ /dev/null
@@ -1,325 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { onMounted, onBeforeUnmount, ref } from 'vue'
-  import * as echarts from 'echarts'
-  import { useHostStore } from '@/store/host'
-  import { storeToRefs } from 'pinia'
-  import {
-    CheckCircleTwoTone,
-    CloseCircleTwoTone,
-    MinusCircleTwoTone,
-    DoubleRightOutlined
-  } from '@ant-design/icons-vue'
-  import { RouterLink } from 'vue-router'
-
-  const hostStore = useHostStore()
-  const { hosts, loading } = storeToRefs(hostStore)
-
-  const resourceChartRef = ref<any>(null)
-  const diskChartRef = ref<any>(null)
-
-  const hostColumns = [
-    {
-      title: 'hosts.hostname',
-      dataIndex: 'hostname',
-      align: 'center'
-    },
-    {
-      title: 'hosts.cluster_name',
-      dataIndex: 'clusterName',
-      align: 'center'
-    },
-    {
-      title: 'common.os',
-      dataIndex: 'os',
-      align: 'center'
-    },
-    {
-      title: 'common.arch',
-      dataIndex: 'arch',
-      align: 'center'
-    },
-    {
-      title: 'hosts.ipv4',
-      dataIndex: 'ipv4',
-      align: 'center'
-    },
-    {
-      title: 'hosts.cores',
-      dataIndex: 'availableProcessors',
-      align: 'center'
-    },
-    {
-      title: 'hosts.ram',
-      dataIndex: 'totalMemorySize',
-      align: 'center'
-    },
-    {
-      title: 'hosts.disk',
-      dataIndex: 'totalDisk',
-      align: 'center'
-    },
-    {
-      title: 'common.status',
-      dataIndex: 'state',
-      align: 'center'
-    }
-  ]
-
-  const renderResourceChart = () => {
-    let option = {
-      title: {
-        text: 'Resource'
-      },
-      legend: {
-        data: ['Core Usage(%)', 'Memory Usage(%)']
-      },
-      grid: {
-        left: '60px',
-        width: '75%'
-      },
-      xAxis: {
-        type: 'category',
-        data: ['10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00']
-      },
-      yAxis: {
-        type: 'value',
-        scale: true,
-        name: 'Percentage',
-        axisLabel: {
-          formatter: '{value} %'
-        }
-      },
-      series: [
-        {
-          name: 'Core Usage(%)',
-          data: [10, 10, 90, 30, 10, 90, 90],
-          type: 'line',
-          smooth: true
-        },
-        {
-          name: 'Memory Usage(%)',
-          data: [22, 19, 88, 66, 5, 90, 75],
-          type: 'line',
-          smooth: true
-        }
-      ],
-      tooltip: {
-        show: true,
-        trigger: 'axis',
-        axisPointer: {
-          type: 'cross',
-          axis: 'auto'
-        },
-        showContent: true
-      }
-    }
-
-    const chart = echarts.init(resourceChartRef.value)
-    chart.setOption(option)
-  }
-
-  const renderDiskChart = () => {
-    let option = {
-      title: {
-        text: 'Disk'
-      },
-      legend: {
-        data: ['Disk Usage(%)', 'Disk Increment(MB)']
-      },
-      grid: {
-        left: '60px',
-        width: '75%'
-      },
-      xAxis: {
-        type: 'category',
-        data: [
-          '2023/08/13',
-          '2023/08/14',
-          '2023/08/15',
-          '2023/08/16',
-          '2023/08/17',
-          '2023/08/18',
-          '2023/08/19'
-        ]
-      },
-      yAxis: [
-        {
-          type: 'value',
-          scale: true,
-          name: 'Increment',
-          min: 0,
-          max: 1000,
-          interval: 100,
-          axisLabel: {
-            formatter: '{value} MB'
-          }
-        },
-        {
-          type: 'value',
-          scale: true,
-          name: 'Percentage',
-          max: 100,
-          min: 0,
-          interval: 10,
-          axisLabel: {
-            formatter: '{value} %'
-          }
-        }
-      ],
-      series: [
-        {
-          name: 'Disk Increment(MB)',
-          data: [100, 800, 500, 233, 420, 155, 333],
-          type: 'bar',
-          yAxisIndex: 0
-        },
-        {
-          name: 'Disk Usage(%)',
-          data: [20, 35, 40, 65, 75, 90, 97],
-          type: 'line',
-          smooth: true,
-          yAxisIndex: 1
-        }
-      ],
-      tooltip: {
-        show: true,
-        trigger: 'axis',
-        axisPointer: {
-          type: 'cross',
-          axis: 'auto'
-        },
-        showContent: true
-      }
-    }
-
-    const chart = echarts.init(diskChartRef.value)
-    chart.setOption(option)
-  }
-
-  onMounted(async () => {
-    renderResourceChart()
-    renderDiskChart()
-
-    hostStore.resumeIntervalFn()
-  })
-
-  onBeforeUnmount(() => {
-    hostStore.pauseIntervalFn()
-  })
-</script>
-
-<template>
-  <a-watermark content="This is fake data">
-    <div class="container">
-      <div class="statistics">
-        <a-card class="card">
-          <a-statistic title="Hosts" value="4" />
-          <div class="card-desc">Health: 4</div>
-        </a-card>
-        <a-card class="card">
-          <a-statistic title="Cores" value="12 / 16" />
-          <div class="card-desc">75%</div>
-        </a-card>
-        <a-card class="card">
-          <a-statistic title="Memory" value="123 / 256 G" />
-          <div class="card-desc">48.05%</div>
-        </a-card>
-        <a-card class="card">
-          <a-statistic title="Disks" value="2 / 5 T" />
-          <div class="card-desc">40%</div>
-        </a-card>
-      </div>
-      <a-divider dashed />
-      <div class="charts">
-        <div ref="resourceChartRef" class="chart" />
-        <div ref="diskChartRef" class="chart" />
-      </div>
-      <a-divider dashed />
-
-      <div class="host-link">
-        <router-link to="/hosts">
-          {{ $t('common.view_all') }} <double-right-outlined />
-        </router-link>
-      </div>
-
-      <a-table
-        :columns="hostColumns"
-        :data-source="hosts.length > 5 ? hosts.slice(0, 5) : hosts"
-        :loading="loading"
-        :pagination="false"
-      >
-        <template #headerCell="{ column }">
-          <span>{{ $t(column.title) }}</span>
-        </template>
-        <template #bodyCell="{ column, text }">
-          <template v-if="column.dataIndex === 'state'">
-            <check-circle-two-tone
-              v-if="text === 'INSTALLED'"
-              two-tone-color="#52c41a"
-            />
-            <minus-circle-two-tone
-              v-else-if="text === 'MAINTAINED'"
-              two-tone-color="orange"
-            />
-            <close-circle-two-tone v-else two-tone-color="red" />
-          </template>
-        </template>
-      </a-table>
-    </div>
-  </a-watermark>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    min-height: 540px;
-
-    .statistics {
-      @include flexbox($justify: space-between, $align: center);
-
-      .card {
-        width: 20%;
-        text-align: center;
-
-        .card-desc {
-          font-size: 0.75rem;
-          line-height: 1rem;
-          color: rgb(156 163 175);
-          margin-top: 0.25rem;
-        }
-      }
-    }
-
-    .charts {
-      @include flexbox($justify: space-between, $align: center);
-
-      .chart {
-        width: 45%;
-        height: 24rem;
-      }
-    }
-
-    .host-link {
-      @include flexbox($direction: column, $align: end);
-      margin-bottom: 1.5rem;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/dashboard/tips.vue b/bigtop-manager-ui/src/components/dashboard/tips.vue
deleted file mode 100644
index 5d67ba7..0000000
--- a/bigtop-manager-ui/src/components/dashboard/tips.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { ref } from 'vue'
-  import ClusterCreate from '@/components/cluster-create/index.vue'
-
-  const open = ref(false)
-</script>
-
-<template>
-  <div class="tour">
-    <a-result
-      :title="$t('cluster.not_exist_title')"
-      :sub-title="$t('cluster.not_exist_sub_title')"
-    >
-      <template #extra>
-        <a-button type="primary" size="large" @click="() => (open = true)">
-          {{ $t('cluster.create') }}
-        </a-button>
-        <cluster-create v-model:open="open" />
-      </template>
-    </a-result>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .tour {
-    @include flexbox($direction: column, $justify: center, $align: center);
-    align-content: center;
-    min-height: 540px;
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/job-info/custom-progress.vue b/bigtop-manager-ui/src/components/job-info/custom-progress.vue
deleted file mode 100644
index dba159a..0000000
--- a/bigtop-manager-ui/src/components/job-info/custom-progress.vue
+++ /dev/null
@@ -1,103 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script lang="ts" setup>
-  import { computed } from 'vue'
-  import { State } from '@/enums/state.ts'
-  import {
-    MinusCircleFilled as Canceled,
-    CheckCircleFilled as Successful,
-    CloseCircleFilled as Failed
-  } from '@ant-design/icons-vue'
-
-  interface ProgressItem {
-    state: keyof typeof State
-    [property: string]: any
-  }
-
-  interface ProgressProps {
-    state: keyof typeof State
-    progressData: ProgressItem[]
-  }
-
-  const props = withDefaults(defineProps<ProgressProps>(), {})
-
-  const progressConfig = computed(() => {
-    if (props.state === 'Pending') {
-      return {
-        progress: 0,
-        status: 'normal'
-      }
-    } else if (props.state === 'Successful') {
-      return {
-        progress: 100,
-        status: 'success',
-        icon: Successful
-      }
-    } else if (props.state === 'Processing') {
-      const proportion =
-        props.progressData.filter((v: ProgressItem) => v.state === 'Successful')
-          .length + 1
-      return {
-        progress: Math.round((proportion / props.progressData.length) * 100),
-        status: 'active'
-      }
-    } else if (props.state === 'Canceled') {
-      return {
-        progress: 100,
-        status: 'normal',
-        icon: Canceled
-      }
-    } else if (props.state === 'Failed') {
-      return {
-        progress: 100,
-        status: 'exception',
-        icon: Failed
-      }
-    } else {
-      return {
-        progress: 0,
-        status: 'status'
-      }
-    }
-  })
-</script>
-
-<template>
-  <div>
-    <a-progress
-      :percent="progressConfig.progress"
-      :status="progressConfig.status"
-      :stroke-color="State[props.state]"
-    >
-      <template #format="percent">
-        <span v-if="['Processing', 'Pending'].includes(props.state)">
-          {{ percent }} %
-        </span>
-        <component
-          :is="progressConfig.icon"
-          v-else-if="progressConfig.icon"
-          :style="{ color: State[props.state] }"
-        />
-      </template>
-    </a-progress>
-  </div>
-</template>
-
-<style lang="scss" scoped></style>
diff --git a/bigtop-manager-ui/src/components/job-info/index.vue b/bigtop-manager-ui/src/components/job-info/index.vue
deleted file mode 100644
index 1d902ee..0000000
--- a/bigtop-manager-ui/src/components/job-info/index.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { SettingOutlined } from '@ant-design/icons-vue'
-  import Job from './job.vue'
-  import { ref } from 'vue'
-
-  const jobWindowOpened = ref(false)
-  const processJobNum = ref(0)
-
-  const handleJobOpen = () => {
-    jobWindowOpened.value = true
-  }
-</script>
-
-<template>
-  <div class="icon" @click="handleJobOpen">
-    <a-badge size="small" color="blue" :count="processJobNum">
-      <setting-outlined />
-    </a-badge>
-  </div>
-  <job v-model:visible="jobWindowOpened" />
-</template>
-
-<style lang="scss" scoped>
-  .icon {
-    @include flexbox($justify: center, $align: center);
-    font-size: 16px;
-    cursor: pointer;
-    border-radius: 50%;
-    height: 36px;
-    width: 36px;
-
-    &:hover {
-      background-color: var(--hover-color);
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/job-info/job.vue b/bigtop-manager-ui/src/components/job-info/job.vue
deleted file mode 100644
index a008bfc..0000000
--- a/bigtop-manager-ui/src/components/job-info/job.vue
+++ /dev/null
@@ -1,326 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { ref, watch, computed, toRefs, nextTick, watchEffect } from 'vue'
-  import { useClusterStore } from '@/store/cluster/index.ts'
-  import { storeToRefs } from 'pinia'
-  import { JobVO, StageVO, TaskVO, OuterData } from '@/api/job/types.ts'
-  import { getJobs } from '@/api/job/index.ts'
-  import { Pausable, useIntervalFn } from '@vueuse/core'
-  import { MONITOR_SCHEDULE_INTERVAL } from '@/utils/constant.ts'
-  import CustomProgress from './custom-progress.vue'
-  import Stage from './stage.vue'
-  import Task from './task.vue'
-  import TaskLog from './task-log.vue'
-  import useBaseTable from '@/composables/use-base-table'
-  import type { TableColumnType, TablePaginationConfig } from 'ant-design-vue'
-
-  const columns: TableColumnType[] = [
-    {
-      title: 'common.name',
-      dataIndex: 'name',
-      align: 'center'
-    },
-    {
-      title: 'common.status',
-      dataIndex: 'state',
-      align: 'center'
-    },
-    {
-      title: 'common.create_time',
-      dataIndex: 'createTime',
-      align: 'center'
-    },
-    {
-      title: 'common.update_time',
-      dataIndex: 'updateTime',
-      align: 'center'
-    }
-  ]
-
-  const clusterStore = useClusterStore()
-  const { clusterId } = storeToRefs(clusterStore)
-
-  interface Props {
-    visible: boolean
-    outerData?: OuterData
-  }
-
-  const props = withDefaults(defineProps<Props>(), {
-    visible: false,
-    outerData: undefined
-  })
-
-  const { visible, outerData } = toRefs(props)
-
-  const emits = defineEmits(['update:visible', 'closed'])
-
-  const showLogAwaitMsg = ref(false)
-  const isComplete = ref(false)
-  const stages = ref<StageVO[]>([])
-  const tasks = ref<TaskVO[]>([])
-  const breadcrumbs = ref<any[]>([{ name: 'Job Info' }])
-  const currTaskInfo = ref<TaskVO>()
-  const intervalId = ref<Pausable | undefined>()
-  const logRef = ref<InstanceType<typeof TaskLog> | null>(null)
-  const currPage = ref<string[]>([
-    'isJobTable',
-    'isStageTable',
-    'isTaskTable',
-    'isTaskLogs'
-  ])
-
-  const {
-    loading,
-    columnsProp,
-    dataSource: jobs,
-    paginationProps,
-    onChange,
-    resetState
-  } = useBaseTable<JobVO>({ columns })
-
-  const getCurrPage = computed(() => {
-    return currPage.value[breadcrumbs.value.length - 1]
-  })
-
-  watch(visible, (val) => {
-    if (!val) return
-    resetState()
-    loading.value = true
-    checkDataOrigin(outerData.value ? true : false)
-  })
-
-  watchEffect(() => {
-    if (!outerData.value) return
-    jobs.value = outerData.value.meta as any
-  })
-
-  watchEffect(() => {
-    if (!jobs.value) return
-    const id = breadcrumbs.value[breadcrumbs.value.length - 1]?.id
-    id &&
-      (stages.value = jobs.value.find((v: JobVO) => v.id == id)?.stages || [])
-  })
-
-  const checkDataOrigin = (isOuter = false) => {
-    if (isOuter) {
-      const { meta, currItem } = outerData.value as OuterData
-      jobs.value = meta
-      clickJob(meta[0])
-      clickStage(currItem as StageVO)
-      loading.value = false
-      return
-    }
-    initInterval()
-  }
-
-  const initInterval = () => {
-    if (intervalId.value) {
-      intervalId.value?.resume()
-      return
-    }
-    intervalId.value = useIntervalFn(getJobsList, MONITOR_SCHEDULE_INTERVAL, {
-      immediate: true,
-      immediateCallback: true
-    })
-  }
-
-  const getJobsList = async () => {
-    try {
-      const { current, pageSize } = paginationProps.value
-      const { content, total } = await getJobs(clusterId.value, {
-        pageNum: current as number,
-        pageSize: pageSize as number,
-        sort: 'desc'
-      })
-      jobs.value = content.map((v) => ({ ...v }))
-      paginationProps.value.total = total
-      loading.value = false
-    } catch (error) {
-      console.log('error :>> ', error)
-    } finally {
-      loading.value = false
-    }
-  }
-
-  const clickTask = async (record: TaskVO) => {
-    breadcrumbs.value.push(record)
-    currTaskInfo.value = record
-    await nextTick()
-    logRef.value?.getLogInfo(record.id)
-  }
-
-  const clickJob = (record: JobVO) => {
-    stages.value = record.stages
-    breadcrumbs.value.push(record)
-  }
-
-  const clickStage = (record: StageVO) => {
-    tasks.value = record.tasks
-    breadcrumbs.value.push(record)
-  }
-
-  const clickBreadCrumbs = (idx: number) => {
-    const len = breadcrumbs.value.length
-    breadcrumbs.value.splice(idx + 1, len)
-  }
-
-  const handleClose = () => {
-    intervalId.value?.pause()
-    breadcrumbs.value = [{ name: 'Job Info' }]
-    resetState()
-    emits('update:visible', false)
-  }
-
-  const setShowLogAwaitMsg = (status: boolean) => {
-    showLogAwaitMsg.value = status
-  }
-
-  const onLogComplete = (status: boolean) => {
-    isComplete.value = status
-  }
-
-  const onTableChange = (pagination: TablePaginationConfig) => {
-    onChange(pagination)
-    loading.value = true
-    getJobsList()
-  }
-</script>
-
-<template>
-  <a-modal :open="props.visible" width="95%" @cancel="handleClose">
-    <template #footer>
-      <div :class="{ 'footer-btns': showLogAwaitMsg }">
-        <div
-          v-if="showLogAwaitMsg"
-          class="logs-wait-msg"
-          :class="{ 'loading-dot': !isComplete }"
-        >
-          {{
-            isComplete
-              ? $t('job.log_complete_message')
-              : $t('job.log_await_message')
-          }}
-        </div>
-        <a-button key="back" type="primary" @click="handleClose">
-          {{ $t('common.confirm') }}
-        </a-button>
-      </div>
-    </template>
-
-    <div class="breadcrumb">
-      <a-breadcrumb>
-        <a-breadcrumb-item
-          v-for="(item, idx) in breadcrumbs"
-          :key="idx"
-          @click="clickBreadCrumbs(idx)"
-        >
-          <a href="#">{{ item.name }}</a>
-        </a-breadcrumb-item>
-      </a-breadcrumb>
-    </div>
-    <a-table
-      v-show="getCurrPage == 'isJobTable'"
-      :scroll="{ y: 400 }"
-      :loading="loading"
-      :data-source="jobs"
-      :columns="columnsProp"
-      :pagination="paginationProps"
-      destroy-on-close
-      @change="onTableChange"
-    >
-      <template #headerCell="{ column }">
-        <span>{{ $t(column.title) }}</span>
-      </template>
-      <template #bodyCell="{ column, text, record }">
-        <template v-if="column.dataIndex === 'name'">
-          <a @click="clickJob(record)">
-            {{ text }}
-          </a>
-        </template>
-        <template v-if="column.dataIndex === 'state'">
-          <custom-progress
-            :key="record.id"
-            :state="text"
-            :progress-data="record.stages"
-          />
-        </template>
-      </template>
-    </a-table>
-    <template v-if="getCurrPage == 'isStageTable'">
-      <stage :columns="columns" :stages="stages" @click-stage="clickStage" />
-    </template>
-    <template v-if="getCurrPage == 'isTaskTable'">
-      <task :columns="columns" :tasks="tasks" @click-task="clickTask" />
-    </template>
-    <template v-if="getCurrPage == 'isTaskLogs'">
-      <task-log
-        ref="logRef"
-        @vue:before-unmount="setShowLogAwaitMsg"
-        @on-log-receive="setShowLogAwaitMsg"
-        @on-log-complete="onLogComplete"
-      />
-    </template>
-  </a-modal>
-</template>
-
-<style lang="scss" scoped>
-  .footer-btns {
-    @include flexbox($justify: space-between, $wrap: wrap, $align: center);
-  }
-
-  .logs-wait-msg {
-    margin: 0;
-    padding: 0;
-  }
-
-  .loading-dot {
-    &::after {
-      content: '';
-      animation: wait 5s 0s infinite;
-    }
-  }
-
-  @keyframes wait {
-    16% {
-      content: '.';
-    }
-    32% {
-      content: '. .';
-    }
-    48% {
-      content: '. . .';
-    }
-    64% {
-      content: '. . . .';
-    }
-    80% {
-      content: '. . . . .';
-    }
-    96% {
-      content: '. . . . . .';
-    }
-  }
-  .breadcrumb {
-    :deep(.ant-breadcrumb) {
-      margin-bottom: 16px !important;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/job-info/stage.vue b/bigtop-manager-ui/src/components/job-info/stage.vue
deleted file mode 100644
index a4a50f4..0000000
--- a/bigtop-manager-ui/src/components/job-info/stage.vue
+++ /dev/null
@@ -1,82 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script lang="ts" setup>
-  import { StageVO } from '@/api/job/types.ts'
-  import { watchEffect } from 'vue'
-  import CustomProgress from './custom-progress.vue'
-  import useBaseTable from '@/composables/use-base-table'
-  import type { TableColumnType } from 'ant-design-vue'
-
-  interface StageProps {
-    stages: StageVO[]
-    columns: TableColumnType[]
-  }
-
-  const props = defineProps<StageProps>()
-  const baseTable = useBaseTable<StageVO>({
-    columns: props.columns,
-    rows: props.stages
-  })
-  const { dataSource, columnsProp, loading, paginationProps, onChange } =
-    baseTable
-
-  watchEffect(() => {
-    dataSource.value = props.stages
-    loading.value = false
-  })
-
-  const emits = defineEmits(['clickStage'])
-  const clickStage = (record: StageVO) => {
-    emits('clickStage', record)
-  }
-</script>
-
-<template>
-  <div class="stage-info">
-    <a-table
-      :scroll="{ y: 500 }"
-      :loading="loading"
-      :columns="columnsProp"
-      :data-source="dataSource"
-      :pagination="paginationProps"
-      @change="onChange"
-    >
-      <template #headerCell="{ column }">
-        <span>{{ $t(column.title) }}</span>
-      </template>
-      <template #bodyCell="{ column, text, record }">
-        <template v-if="column.dataIndex === 'name'">
-          <a @click="clickStage(record)">
-            {{ text }}
-          </a>
-        </template>
-        <template v-if="column.dataIndex === 'state'">
-          <custom-progress
-            :key="record.id"
-            :state="text"
-            :progress-data="record.tasks"
-          />
-        </template>
-      </template>
-    </a-table>
-  </div>
-</template>
-
-<style lang="scss" scoped></style>
diff --git a/bigtop-manager-ui/src/components/job-info/task-log.vue b/bigtop-manager-ui/src/components/job-info/task-log.vue
deleted file mode 100644
index d41e122..0000000
--- a/bigtop-manager-ui/src/components/job-info/task-log.vue
+++ /dev/null
@@ -1,155 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { useI18n } from 'vue-i18n'
-  import { copyText, scrollToBottom } from '@/utils/tools'
-  import { message } from 'ant-design-vue'
-  import { ref, watch, onBeforeUnmount } from 'vue'
-  import { CopyOutlined } from '@ant-design/icons-vue'
-  import { AxiosProgressEvent, Canceler } from 'axios'
-  import { getLogs } from '@/api/sse'
-  import { storeToRefs } from 'pinia'
-  import { useClusterStore } from '@/store/cluster'
-
-  const { t } = useI18n()
-  const clusterStore = useClusterStore()
-  const { clusterId } = storeToRefs(clusterStore)
-  const logsInfoRef = ref<HTMLElement | null>(null)
-  const logText = ref<string | null>(null)
-  const logMeta = ref<string>('')
-  const canceler = ref<Canceler>()
-
-  const emit = defineEmits(['onLogReceive', 'onLogComplete'])
-
-  watch(logMeta, (val) => {
-    logText.value = val
-      .split('\n\n')
-      .map((s) => {
-        return s.substring(5)
-      })
-      .join('\n')
-  })
-
-  const getLogInfo = async (id: number) => {
-    const { cancel, promise } = getLogs(clusterId.value, id, onLogReceive)
-    canceler.value = cancel
-    promise.then(onLogComplete)
-    emit('onLogReceive', true)
-  }
-
-  const onLogReceive = ({ event }: AxiosProgressEvent) => {
-    logMeta.value = event.target.responseText
-    scrollToBottom(logsInfoRef.value)
-  }
-
-  const onLogComplete = (res: string | undefined) => {
-    cancelSseConnect()
-    emit('onLogComplete', res != undefined)
-  }
-
-  const cancelSseConnect = () => {
-    if (!canceler.value) {
-      return
-    }
-    canceler.value()
-  }
-
-  const copyLogTextContent = (text: string | null) => {
-    if (!text) {
-      return
-    }
-    copyText(text)
-      .then(() => {
-        message.success(`${t('common.copy_success')}`)
-      })
-      .catch((err: Error) => {
-        message.error(`${t('common.copy_fail')}`)
-        console.log('err :>> ', err)
-      })
-  }
-
-  onBeforeUnmount(() => {
-    cancelSseConnect()
-    emit('onLogReceive', false)
-    emit('onLogComplete', false)
-  })
-
-  defineExpose({
-    getLogInfo
-  })
-</script>
-
-<template>
-  <div class="logs">
-    <div class="logs_header">
-      <span>Task Logs</span>
-      <div class="logs_header-ops">
-        <a-button type="link" size="small" @click="copyLogTextContent(logText)">
-          <template #icon>
-            <copy-outlined />
-          </template>
-          <span class="copy-button">{{ $t('common.copy') }}</span>
-        </a-button>
-      </div>
-    </div>
-    <div ref="logsInfoRef" class="logs_info">
-      <div id="logs">
-        <pre>{{ logText }}</pre>
-      </div>
-    </div>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .logs {
-    height: 50vh;
-    @include flexbox($direction: column);
-    &_header {
-      font-size: 16px;
-      font-weight: 600;
-      margin: 0 0 10px 0;
-      @include flexbox($justify: space-between);
-
-      .copy-button {
-        margin-left: 3px;
-      }
-    }
-    &_info {
-      height: 100%;
-      overflow: auto;
-      scroll-behavior: smooth;
-      background-color: #f5f5f5;
-      border-radius: 4px;
-      position: relative;
-      & > div {
-        height: 100%;
-        margin: 0;
-        padding: 16px 14px;
-        box-sizing: border-box;
-        border-color: #eee;
-        box-sizing: border-box;
-        pre {
-          line-height: 20px;
-          color: #444;
-        }
-      }
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/job-info/task.vue b/bigtop-manager-ui/src/components/job-info/task.vue
deleted file mode 100644
index e4483ba..0000000
--- a/bigtop-manager-ui/src/components/job-info/task.vue
+++ /dev/null
@@ -1,91 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { TaskVO } from '@/api/job/types.ts'
-  import { State } from '@/enums/state'
-  import useBaseTable from '@/composables/use-base-table'
-  import type { TableColumnType } from 'ant-design-vue'
-
-  import {
-    CheckCircleTwoTone,
-    MinusCircleTwoTone,
-    CloseCircleTwoTone,
-    LoadingOutlined
-  } from '@ant-design/icons-vue'
-
-  interface TaskProps {
-    tasks: TaskVO[]
-    columns: TableColumnType[]
-  }
-
-  const props = defineProps<TaskProps>()
-  const baseTable = useBaseTable<TaskVO>({
-    columns: props.columns,
-    rows: props.tasks
-  })
-  const { dataSource, columnsProp, loading, paginationProps, onChange } =
-    baseTable
-
-  const emits = defineEmits(['clickTask'])
-  const clickTask = (record: TaskVO) => {
-    emits('clickTask', record)
-  }
-</script>
-
-<template>
-  <div class="task-info">
-    <a-table
-      :scroll="{ y: 500 }"
-      :loading="loading"
-      :columns="columnsProp"
-      :data-source="dataSource"
-      :pagination="paginationProps"
-      @change="onChange"
-    >
-      <template #headerCell="{ column }">
-        <span>{{ $t(column.title) }}</span>
-      </template>
-      <template #bodyCell="{ column, text, record }">
-        <template v-if="column.dataIndex === 'name'">
-          <a @click="clickTask(record)">
-            {{ text }}
-          </a>
-        </template>
-        <template v-if="column.dataIndex === 'state'">
-          <check-circle-two-tone
-            v-if="text === 'Successful'"
-            :two-tone-color="State[text as keyof typeof State]"
-          />
-          <close-circle-two-tone
-            v-else-if="text === 'Failed'"
-            :two-tone-color="State[text as keyof typeof State]"
-          />
-          <minus-circle-two-tone
-            v-else-if="text === 'Canceled'"
-            :two-tone-color="State[text as keyof typeof State]"
-          />
-          <loading-outlined v-else />
-        </template>
-      </template>
-    </a-table>
-  </div>
-</template>
-
-<style scoped></style>
diff --git a/bigtop-manager-ui/src/components/select-lang/index.vue b/bigtop-manager-ui/src/components/select-lang/index.vue
index f426cd9..6bc84cc 100644
--- a/bigtop-manager-ui/src/components/select-lang/index.vue
+++ b/bigtop-manager-ui/src/components/select-lang/index.vue
@@ -32,8 +32,8 @@
 
 <template>
   <a-dropdown placement="bottom">
-    <div class="icon">
-      <svg-icon name="carbon-language" style="width: 1em; height: 1em" />
+    <div class="header-item">
+      <svg-icon name="language" />
     </div>
     <template #overlay>
       <a-menu :selected-keys="[locale]" @click="handleClick">
@@ -55,16 +55,13 @@
 </template>
 
 <style lang="scss" scoped>
-  .icon {
-    @include flexbox($justify: center, $align: center);
-    font-size: 16px;
-    cursor: pointer;
-    border-radius: 50%;
-    height: 36px;
-    width: 36px;
-
+  .header-item {
+    :deep(.svg-icon) {
+      width: 20px;
+      height: 20px;
+    }
     &:hover {
-      background-color: var(--hover-color);
+      background-color: $color-primary;
     }
   }
 </style>
diff --git a/bigtop-manager-ui/src/components/service-add/assign-components.vue b/bigtop-manager-ui/src/components/service-add/assign-components.vue
deleted file mode 100644
index 27dd993..0000000
--- a/bigtop-manager-ui/src/components/service-add/assign-components.vue
+++ /dev/null
@@ -1,207 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { computed, onMounted, ref } from 'vue'
-  import { DEFAULT_PAGE_SIZE } from '@/utils/constant.ts'
-  import { useHostStore } from '@/store/host'
-  import { useComponentStore } from '@/store/component'
-  import { storeToRefs } from 'pinia'
-  import { useStackStore } from '@/store/stack'
-  import _ from 'lodash'
-  import { ComponentVO, ServiceComponentVO } from '@/api/component/types.ts'
-  import { arrayEquals } from '@/utils/array.ts'
-
-  const serviceInfo = defineModel<any>('serviceInfo')
-
-  const hostStore = useHostStore()
-  const stackStore = useStackStore()
-  const componentStore = useComponentStore()
-  const { hosts, loading } = storeToRefs(hostStore)
-  const { currentStack, stackComponents } = storeToRefs(stackStore)
-  const { hostComponents } = storeToRefs(componentStore)
-  const pageSize = ref<number>(DEFAULT_PAGE_SIZE)
-
-  const serviceNameToDisplayName = _.fromPairs(
-    currentStack.value.services.map((v) => [v.serviceName, v.displayName])
-  )
-
-  const hostnames = computed(() => hosts.value.map((v) => v.hostname))
-
-  const columns = computed(() => {
-    const services = serviceInfo.value.serviceCommands.map((item: any) => {
-      return {
-        title: serviceNameToDisplayName[item.serviceName],
-        align: 'center',
-        children: stackComponents.value
-          .filter(
-            (component: ServiceComponentVO) =>
-              component.serviceName === item.serviceName
-          )
-          .flatMap((component: ServiceComponentVO) => component.components)
-          .map((component: ComponentVO) => {
-            return {
-              title: component.displayName,
-              dataIndex: component.componentName,
-              align: 'center',
-              width: 180
-            }
-          })
-      }
-    })
-
-    return [
-      {
-        title: 'hosts.host',
-        dataIndex: 'host',
-        align: 'center',
-        fixed: true,
-        width: 200
-      },
-      ...services
-    ]
-  })
-
-  const data = computed(() => hosts.value.map((v) => ({ host: v.hostname })))
-  const pagination = computed(() => {
-    return {
-      pageSize: pageSize.value,
-      showSizeChanger: true,
-      onShowSizeChange: (_current: number, size: number) => {
-        pageSize.value = size
-      }
-    }
-  })
-
-  const checkedComponents = computed(() => {
-    return serviceInfo.value.serviceCommands
-      .flatMap((item: any) => item.componentHosts)
-      .reduce((acc: any, item: any) => {
-        acc[item.componentName] = item.hostnames
-        return acc
-      }, {})
-  })
-
-  const disabledComponents = _.uniq(
-    hostComponents.value.map((item) => item.componentName)
-  )
-
-  const checkComponent = (record: any, column: any) => {
-    const host = record.host
-    const componentName = column.dataIndex
-
-    serviceInfo.value.serviceCommands.forEach((serviceCommand: any) => {
-      serviceCommand.componentHosts.forEach((componentHost: any) => {
-        if (componentHost.componentName === componentName) {
-          if (componentHost.hostnames.includes(host)) {
-            _.remove(componentHost.hostnames, (item: any) => item === host)
-          } else {
-            componentHost.hostnames.push(host)
-          }
-        }
-      })
-    })
-  }
-
-  const checkGroup = (column: any) => {
-    const componentName = column.dataIndex
-    serviceInfo.value.serviceCommands.forEach((serviceCommand: any) => {
-      serviceCommand.componentHosts.forEach((componentHost: any) => {
-        if (componentHost.componentName === componentName) {
-          if (componentHost.hostnames.length > 0) {
-            componentHost.hostnames = []
-          } else {
-            componentHost.hostnames = _.cloneDeep(hostnames.value)
-          }
-        }
-      })
-    })
-  }
-
-  onMounted(() => {
-    hostStore.refreshHosts()
-  })
-
-  const onNextStep = async () => {
-    return Promise.resolve(true)
-  }
-
-  defineExpose({
-    onNextStep
-  })
-</script>
-
-<template>
-  <div class="container">
-    <div class="title">{{ $t('service.assign_components') }}</div>
-    <a-table
-      :loading="loading"
-      :columns="columns"
-      :data-source="data"
-      :scroll="{ x: 'max-content', y: 330 }"
-      :pagination="pagination"
-    >
-      <template #headerCell="{ column }">
-        <span v-if="column.dataIndex === 'host'">{{ $t(column.title) }}</span>
-        <template v-if="column.dataIndex !== 'host' && !column.children">
-          <a-checkbox
-            :disabled="disabledComponents.includes(column.dataIndex)"
-            :indeterminate="
-              !arrayEquals(checkedComponents[column.dataIndex], hostnames) &&
-              checkedComponents[column.dataIndex].length > 0
-            "
-            :checked="
-              arrayEquals(checkedComponents[column.dataIndex], hostnames)
-            "
-            @click="checkGroup(column)"
-          >
-            {{ column.title }}
-          </a-checkbox>
-        </template>
-      </template>
-
-      <template #bodyCell="{ record, column }">
-        <template v-if="column.dataIndex !== 'host'">
-          <a-checkbox
-            :checked="checkedComponents[column.dataIndex].includes(record.host)"
-            :disabled="disabledComponents.includes(column.dataIndex)"
-            @click="checkComponent(record, column)"
-          />
-        </template>
-      </template>
-    </a-table>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox(
-      $direction: column,
-      $justify: space-between,
-      $align: center
-    );
-    align-content: center;
-
-    .title {
-      font-size: 1.5rem;
-      line-height: 2rem;
-      margin-bottom: 1rem;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/service-add/choose-services.vue b/bigtop-manager-ui/src/components/service-add/choose-services.vue
deleted file mode 100644
index 3426c74..0000000
--- a/bigtop-manager-ui/src/components/service-add/choose-services.vue
+++ /dev/null
@@ -1,167 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { storeToRefs } from 'pinia'
-  import { TableProps } from 'ant-design-vue'
-  import { useServiceStore } from '@/store/service'
-  import { MergedServiceVO } from '@/store/service/types.ts'
-  import { onMounted } from 'vue'
-  import { ServiceVO } from '@/api/service/types.ts'
-  import { useStackStore } from '@/store/stack'
-  import { ComponentVO, ServiceComponentVO } from '@/api/component/types.ts'
-  import { ServiceConfigVO, TypeConfigVO } from '@/api/config/types.ts'
-  import _ from 'lodash'
-
-  const serviceInfo = defineModel<any>('serviceInfo')
-  const disableButton = defineModel<boolean>('disableButton')
-
-  const stackStore = useStackStore()
-  const serviceStore = useServiceStore()
-  const { stackComponents, stackConfigs } = storeToRefs(stackStore)
-  const { installedServices, mergedServices } = storeToRefs(serviceStore)
-
-  const defaultSelected = serviceInfo.value.serviceCommands.map(
-    (item: any) => item.serviceName
-  )
-
-  const installedServiceNames = installedServices.value.map(
-    (item: ServiceVO) => item.serviceName
-  )
-
-  const serviceColumns = [
-    {
-      title: 'service.service',
-      dataIndex: 'displayName',
-      align: 'center',
-      width: 150
-    },
-    {
-      title: 'common.version',
-      dataIndex: 'serviceVersion',
-      align: 'center',
-      width: 150
-    },
-    {
-      title: 'common.desc',
-      dataIndex: 'serviceDesc',
-      align: 'center'
-    }
-  ]
-
-  const newServiceCommand = (serviceName: string) => {
-    const componentHosts = stackComponents.value
-      .filter((item: ServiceComponentVO) => item.serviceName === serviceName)
-      .flatMap((item: ServiceComponentVO) => item.components)
-      .map((item: ComponentVO) => ({
-        componentName: item.componentName,
-        hostnames: []
-      }))
-
-    const configs = stackConfigs.value
-      .filter((item: ServiceConfigVO) => item.serviceName === serviceName)
-      .flatMap((item: ServiceConfigVO) => item.configs)
-      .map((item: TypeConfigVO) => ({
-        typeName: item.typeName,
-        properties: item.properties
-      }))
-
-    return {
-      serviceName: serviceName,
-      installed: false,
-      componentHosts: componentHosts,
-      configs: configs
-    }
-  }
-
-  const rowSelection: TableProps['rowSelection'] = {
-    defaultSelectedRowKeys: defaultSelected,
-    onChange: (v: (string | number)[]) => {
-      const existingServices = serviceInfo.value.serviceCommands.map(
-        (item: any) => item.serviceName
-      )
-
-      if (v.length > existingServices.length) {
-        // select a new service
-        v.map((item: string | number) => {
-          if (!existingServices.includes(item)) {
-            serviceInfo.value.serviceCommands.push(
-              newServiceCommand(item as string)
-            )
-          }
-        })
-      } else {
-        // unselect a service
-        _.remove(
-          serviceInfo.value.serviceCommands,
-          (item: any) => !v.includes(item.serviceName)
-        )
-      }
-
-      disableButton.value = _.isEqual(v, installedServiceNames)
-    },
-    getCheckboxProps: (record: MergedServiceVO) => ({
-      disabled: record.installed
-    })
-  }
-
-  onMounted(async () => {
-    disableButton.value = _.isEqual(defaultSelected, installedServiceNames)
-  })
-
-  const onNextStep = async () => {
-    return Promise.resolve(true)
-  }
-
-  defineExpose({
-    onNextStep
-  })
-</script>
-
-<template>
-  <div class="container">
-    <div class="title">{{ $t('service.choose_services') }}</div>
-    <a-table
-      row-key="serviceName"
-      :columns="serviceColumns"
-      :data-source="mergedServices"
-      :row-selection="rowSelection"
-      :pagination="false"
-      :scroll="{ y: 400 }"
-    >
-      <template #headerCell="{ column }">
-        <span>{{ $t(column.title) }}</span>
-      </template>
-    </a-table>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: start, $align: center);
-    align-content: center;
-    height: 100%;
-
-    .title {
-      font-size: 1.5rem;
-      line-height: 2rem;
-      margin-bottom: 1rem;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/service-add/configure-services.vue b/bigtop-manager-ui/src/components/service-add/configure-services.vue
deleted file mode 100644
index 7a0982f..0000000
--- a/bigtop-manager-ui/src/components/service-add/configure-services.vue
+++ /dev/null
@@ -1,157 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { computed, ref } from 'vue'
-  import { storeToRefs } from 'pinia'
-  import { useStackStore } from '@/store/stack'
-  import { execCommand } from '@/api/command'
-  import _ from 'lodash'
-
-  const serviceInfo = defineModel<any>('serviceInfo')
-
-  const stackStore = useStackStore()
-  const { currentStack } = storeToRefs(stackStore)
-
-  const activeServiceTab = ref(serviceInfo.value.serviceCommands[0].serviceName)
-
-  const serviceNameToDisplayName = _.fromPairs(
-    currentStack.value.services.map((v) => [v.serviceName, v.displayName])
-  )
-
-  const services = computed(() => {
-    return serviceInfo.value.serviceCommands.map((item: any) => {
-      return item.serviceName
-    })
-  })
-
-  const configs = computed(() => {
-    return serviceInfo.value.serviceCommands
-      .map((item: any) => {
-        return { [item.serviceName]: item.configs }
-      })
-      .reduce((acc: any, curr: any) => {
-        return { ...acc, ...curr }
-      }, {})
-  })
-
-  const activeConfigTab = ref(configs.value[activeServiceTab.value][0].typeName)
-
-  const onNextStep = async () => {
-    try {
-      const res = await execCommand(serviceInfo.value)
-      serviceInfo.value.jobId = res.id
-    } catch (e) {
-      console.log(e)
-      return Promise.resolve(false)
-    }
-
-    return Promise.resolve(true)
-  }
-
-  defineExpose({
-    onNextStep
-  })
-</script>
-
-<template>
-  <div class="container">
-    <div class="title">{{ $t('service.configure_services') }}</div>
-    <a-tabs
-      v-model:activeKey="activeServiceTab"
-      class="content"
-      @change="(key: string) => (activeConfigTab = configs[key][0].typeName)"
-    >
-      <a-tab-pane
-        v-for="service in services"
-        :key="service"
-        :tab="serviceNameToDisplayName[service]"
-      >
-        <a-collapse v-model:activeKey="activeConfigTab" ghost>
-          <a-collapse-panel
-            v-for="config in configs[activeServiceTab]"
-            :key="config.typeName"
-            class="panel"
-            :header="config.typeName"
-          >
-            <div
-              v-for="property in config.properties"
-              :key="property.name"
-              class="config-item"
-            >
-              <div class="config-item-key">
-                {{ property.displayName ?? property.name }}
-              </div>
-              <a-tooltip class="config-item-value">
-                <template #title>
-                  {{ property.desc }}
-                </template>
-                <a-textarea
-                  v-if="property.attrs && property.attrs.type === 'longtext'"
-                  v-model:value="property.value"
-                  :rows="10"
-                />
-                <a-input v-else v-model:value="property.value" />
-              </a-tooltip>
-            </div>
-          </a-collapse-panel>
-        </a-collapse>
-      </a-tab-pane>
-    </a-tabs>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: start, $align: center);
-    align-content: center;
-    height: 100%;
-
-    .title {
-      font-size: 1.5rem;
-      line-height: 2rem;
-      margin-bottom: 1rem;
-    }
-
-    .content {
-      width: 100%;
-      height: 100%;
-      overflow-y: auto;
-
-      .panel {
-        text-align: start;
-
-        .config-item {
-          @include flexbox($justify: start, $align: center);
-          margin-bottom: 1rem;
-
-          .config-item-key {
-            width: 20%;
-            text-align: start;
-            margin-left: 2rem;
-          }
-
-          .config-item-value {
-            width: 75%;
-          }
-        }
-      }
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/service-add/finish.vue b/bigtop-manager-ui/src/components/service-add/finish.vue
deleted file mode 100644
index 1083874..0000000
--- a/bigtop-manager-ui/src/components/service-add/finish.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { SmileOutlined, FrownOutlined } from '@ant-design/icons-vue'
-
-  const serviceInfo = defineModel<any>('serviceInfo')
-</script>
-
-<template>
-  <div class="container">
-    <a-result
-      v-if="serviceInfo.success"
-      :title="$t('cluster.create_success_title')"
-      :sub-title="$t('cluster.create_success_sub_title')"
-    >
-      <template #icon>
-        <smile-outlined />
-      </template>
-    </a-result>
-    <a-result
-      v-else
-      :title="$t('cluster.create_fail_title')"
-      :sub-title="$t('cluster.create_fail_sub_title')"
-    >
-      <template #icon>
-        <frown-outlined />
-      </template>
-    </a-result>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: center, $align: center);
-    align-content: center;
-    height: 100%;
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/service-add/index.vue b/bigtop-manager-ui/src/components/service-add/index.vue
deleted file mode 100644
index 9862d77..0000000
--- a/bigtop-manager-ui/src/components/service-add/index.vue
+++ /dev/null
@@ -1,282 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { ref, h, watch, reactive, onUnmounted, onMounted } from 'vue'
-  import { Modal } from 'ant-design-vue'
-  import { ExclamationCircleFilled } from '@ant-design/icons-vue'
-  import { useI18n } from 'vue-i18n'
-  import ChooseServices from '@/components/service-add/choose-services.vue'
-  import AssignComponents from '@/components/service-add/assign-components.vue'
-  import ConfigureServices from '@/components/service-add/configure-services.vue'
-  import Install from '@/components/service-add/install.vue'
-  import Finish from '@/components/service-add/finish.vue'
-  import { useClusterStore } from '@/store/cluster'
-  import { storeToRefs } from 'pinia'
-  import { useServiceStore } from '@/store/service'
-  import { useComponentStore } from '@/store/component'
-  import { useConfigStore } from '@/store/config'
-  import { HostComponentVO } from '@/api/component/types.ts'
-  import { TypeConfigVO, ServiceConfigVO } from '@/api/config/types.ts'
-
-  const open = defineModel<boolean>('open')
-
-  const { t, locale } = useI18n()
-
-  const clusterStore = useClusterStore()
-  const serviceStore = useServiceStore()
-  const componentStore = useComponentStore()
-  const configStore = useConfigStore()
-  const { clusterId } = storeToRefs(clusterStore)
-  const { installedServices } = storeToRefs(serviceStore)
-  const { hostComponents } = storeToRefs(componentStore)
-  const { latestConfigs } = storeToRefs(configStore)
-
-  const initItems = () => [
-    {
-      disabled: true,
-      status: 'process',
-      title: t('service.choose_services'),
-      content: h(ChooseServices)
-    },
-    {
-      disabled: true,
-      status: 'wait',
-      title: t('service.assign_components'),
-      content: h(AssignComponents)
-    },
-    {
-      disabled: true,
-      status: 'wait',
-      title: t('service.configure_services'),
-      content: h(ConfigureServices)
-    },
-    {
-      disabled: true,
-      status: 'wait',
-      title: t('common.install'),
-      content: h(Install)
-    },
-    {
-      disabled: true,
-      status: 'wait',
-      title: t('common.finish'),
-      content: h(Finish)
-    }
-  ]
-
-  const initServiceInfo = async () => {
-    await serviceStore.loadServices()
-    await componentStore.loadHostComponents()
-    await configStore.loadLatestConfigs()
-
-    const serviceCommands = installedServices.value.map((item: any) => {
-      const serviceName = item.serviceName
-      const componentHosts: any[] = hostComponents.value
-        .filter((hc: HostComponentVO) => hc.serviceName === serviceName)
-        .reduce((acc: any[], hc: HostComponentVO) => {
-          const existingComponent = acc.find(
-            (comp) => comp.componentName === hc.componentName
-          )
-
-          if (existingComponent) {
-            existingComponent.hostnames.push(hc.hostname)
-          } else {
-            acc.push({
-              componentName: hc.componentName,
-              hostnames: [hc.hostname]
-            })
-          }
-
-          return acc
-        }, [])
-
-      const configs = latestConfigs.value
-        .filter((sc: ServiceConfigVO) => sc.serviceName === serviceName)
-        .flatMap((sc: ServiceConfigVO) => sc.configs)
-        .map((cd: TypeConfigVO) => ({
-          typeName: cd.typeName,
-          properties: cd.properties
-        }))
-
-      return {
-        serviceName: serviceName,
-        installed: true,
-        componentHosts: componentHosts,
-        configs: configs
-      }
-    })
-
-    return {
-      command: 'install',
-      commandLevel: 'service',
-      clusterId: clusterId.value,
-      serviceCommands: serviceCommands,
-      // Related job id
-      jobId: 0,
-      // Job Status
-      success: false
-    }
-  }
-
-  const current = ref<number>(0)
-  const items = reactive(initItems())
-  const serviceInfo = reactive(await initServiceInfo())
-  const disableButton = ref<boolean>(false)
-  const currentItemRef = ref<any>(null)
-  const loadingNext = ref<boolean>(false)
-  watch(locale, () => {
-    Object.assign(items, initItems())
-  })
-
-  watch(clusterId, () => {
-    serviceInfo.clusterId = clusterId.value
-  })
-
-  const next = async () => {
-    loadingNext.value = true
-    try {
-      const valid = await currentItemRef.value?.onNextStep()
-      if (valid) {
-        console.log('serviceInfo:', JSON.stringify(serviceInfo))
-        items[current.value].status = 'finish'
-        current.value++
-        items[current.value].status = 'process'
-      }
-    } finally {
-      loadingNext.value = false
-    }
-  }
-
-  const prev = () => {
-    items[current.value].status = 'wait'
-    current.value--
-    items[current.value].status = 'process'
-  }
-
-  const clear = async () => {
-    // Clear status
-    current.value = 0
-    open.value = false
-    Object.assign(items, initItems())
-    Object.assign(serviceInfo, await initServiceInfo())
-  }
-
-  const cancel = () => {
-    Modal.confirm({
-      title: t('common.exit'),
-      icon: h(ExclamationCircleFilled),
-      content: t('common.exit_confirm'),
-      onOk() {
-        clear()
-      }
-    })
-  }
-
-  onMounted(() => {
-    componentStore.resumeIntervalFn()
-  })
-
-  onUnmounted(() => {
-    componentStore.pauseIntervalFn()
-  })
-</script>
-
-<template>
-  <a-modal
-    :open="open"
-    width="95%"
-    centered
-    destroy-on-close
-    :mask-closable="false"
-    :keyboard="false"
-    @update:open="cancel"
-  >
-    <template #footer>
-      <a-button
-        v-if="current > 0"
-        class="footer-btn"
-        type="primary"
-        :disabled="disableButton"
-        @click="prev"
-      >
-        {{ $t('common.prev') }}
-      </a-button>
-      <a-button
-        v-if="current < items.length - 1"
-        class="footer-btn"
-        type="primary"
-        :loading="loadingNext"
-        :disabled="disableButton"
-        @click="next"
-      >
-        {{ $t('common.next') }}
-      </a-button>
-      <a-button
-        v-if="current === items.length - 1"
-        class="footer-btn"
-        type="primary"
-        @click="() => clear()"
-      >
-        {{ $t('common.done') }}
-      </a-button>
-    </template>
-    <div class="container">
-      <a-steps
-        v-model:current="current"
-        class="step"
-        direction="vertical"
-        size="small"
-        :items="items"
-      />
-      <div class="content">
-        <component
-          :is="items[current].content"
-          ref="currentItemRef"
-          v-model:serviceInfo="serviceInfo"
-          v-model:disableButton="disableButton"
-        />
-      </div>
-    </div>
-  </a-modal>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: row, $justify: center, $align: center);
-
-    .step {
-      width: 15%;
-      height: 35rem;
-    }
-
-    .content {
-      margin-top: 1rem;
-      padding-left: 1rem;
-      height: 35rem;
-      width: 85%;
-      text-align: center;
-      border-left: 1px solid #d9d9d9;
-    }
-  }
-
-  .footer-btn {
-    width: 8.333333%;
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/service-add/install.vue b/bigtop-manager-ui/src/components/service-add/install.vue
deleted file mode 100644
index 0a3eb53..0000000
--- a/bigtop-manager-ui/src/components/service-add/install.vue
+++ /dev/null
@@ -1,190 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { useI18n } from 'vue-i18n'
-  import { getJob, retryJob } from '@/api/job'
-  import { JOB_SCHEDULE_INTERVAL } from '@/utils/constant.ts'
-  import { useIntervalFn } from '@vueuse/core'
-  import { computed, onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue'
-  import { useClusterStore } from '@/store/cluster'
-  import { storeToRefs } from 'pinia'
-  import { JobVO, StageVO } from '@/api/job/types'
-  import CustomProgress from '@/components/job-info/custom-progress.vue'
-  import Job from '@/components/job-info/job.vue'
-  import { RedoOutlined } from '@ant-design/icons-vue'
-
-  const serviceInfo = defineModel<any>('serviceInfo')
-  const disableButton = defineModel<boolean>('disableButton')
-
-  const clusterStore = useClusterStore()
-  const { clusterId } = storeToRefs(clusterStore)
-
-  const { t } = useI18n()
-  const loading = ref(true)
-  const jobWindowOpened = ref(false)
-  const jobState = ref<string>('')
-  const jobs = ref<JobVO[]>([])
-  const currStage = ref<StageVO>()
-  const installData = reactive([])
-
-  const canRetry = computed(() => {
-    return jobState.value === 'Failed'
-  })
-
-  const installColumns = [
-    {
-      title: t('common.stage'),
-      dataIndex: 'name',
-      align: 'center'
-    },
-    {
-      title: t('common.progress'),
-      dataIndex: 'state',
-      align: 'center'
-    }
-  ]
-
-  const doRetry = async () => {
-    await retryJob(serviceInfo.value.jobId, clusterId.value)
-
-    const { pause } = useIntervalFn(
-      async () => {
-        Object.assign(installData, await initData())
-        loading.value = false
-        if (!['Pending', 'Processing'].includes(jobState.value)) {
-          pause()
-        }
-      },
-      JOB_SCHEDULE_INTERVAL,
-      { immediateCallback: true }
-    )
-  }
-
-  const initData = async () => {
-    const res = await getJob(serviceInfo.value.jobId, clusterId.value)
-    jobs.value = [res] as any
-    console.log(res)
-    jobState.value = res.state
-
-    if (jobState.value !== 'Pending' && jobState.value !== 'Processing') {
-      disableButton.value = false
-      serviceInfo.value.success = jobState.value === 'Successful'
-    }
-    return res.stages.sort((a: StageVO, b: StageVO) => a.order - b.order)
-  }
-
-  const clickStage = (record: StageVO) => {
-    jobWindowOpened.value = true
-    currStage.value = record
-  }
-
-  onBeforeMount(async () => {
-    disableButton.value = true
-
-    const { pause } = useIntervalFn(
-      async () => {
-        Object.assign(installData, await initData())
-        loading.value = false
-        if (!['Pending', 'Processing'].includes(jobState.value)) {
-          pause()
-        }
-      },
-      JOB_SCHEDULE_INTERVAL,
-      { immediateCallback: true }
-    )
-  })
-
-  onBeforeUnmount(() => {
-    disableButton.value = false
-  })
-
-  const onNextStep = async () => {
-    return Promise.resolve(true)
-  }
-
-  defineExpose({
-    onNextStep
-  })
-</script>
-
-<template>
-  <div class="container">
-    <div class="title">{{ $t('common.install') }}</div>
-    <div class="retry">
-      <a-button type="link" size="small" :disabled="!canRetry" @click="doRetry">
-        <template #icon>
-          <redo-outlined />
-        </template>
-        <span class="retry-button">{{ $t('common.retry') }}</span>
-      </a-button>
-    </div>
-    <a-table
-      :pagination="false"
-      :scroll="{ y: 400 }"
-      :columns="installColumns"
-      :data-source="installData"
-      :loading="loading"
-    >
-      <template #bodyCell="{ column, text, record }">
-        <template v-if="column.dataIndex === 'name'">
-          <a @click="clickStage(record)">
-            {{ text }}
-          </a>
-        </template>
-        <template v-if="column.dataIndex === 'state'">
-          <custom-progress
-            :key="record.id"
-            :state="text"
-            :progress-data="record.tasks"
-          />
-        </template>
-      </template>
-    </a-table>
-    <job
-      v-model:visible="jobWindowOpened"
-      :outer-data="{ meta: jobs, currItem: currStage }"
-    />
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    @include flexbox($direction: column, $justify: start, $align: center);
-    align-content: center;
-    height: 100%;
-
-    .title {
-      font-size: 1.5rem;
-      line-height: 2rem;
-      margin-bottom: 1rem;
-    }
-
-    .retry {
-      justify-content: end;
-      @include flexbox($direction: row, $justify: end, $align: center);
-      margin: 0 1rem 1rem 0;
-      width: 100%;
-
-      .retry-button {
-        margin-left: 3px;
-      }
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/components/service/service-dropdown.vue b/bigtop-manager-ui/src/components/service/service-dropdown.vue
deleted file mode 100644
index 1a3a0c6..0000000
--- a/bigtop-manager-ui/src/components/service/service-dropdown.vue
+++ /dev/null
@@ -1,142 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { useI18n } from 'vue-i18n'
-  import { storeToRefs } from 'pinia'
-  import { ref, createVNode } from 'vue'
-  import { type MenuProps, Modal } from 'ant-design-vue'
-  import { QuestionCircleOutlined } from '@ant-design/icons-vue'
-
-  import { useClusterStore } from '@/store/cluster'
-  import { useServiceStore } from '@/store/service'
-
-  import { type ServiceVO } from '@/api/service/types.ts'
-  import { execCommand } from '@/api/command'
-
-  import ServiceAdd from '@/components/service-add/index.vue'
-  import Job from '@/components/job-info/job.vue'
-
-  interface Menu {
-    key: string
-    action: string
-    dicText: string
-  }
-
-  const menuOps: Menu[] = [
-    {
-      key: '1',
-      action: 'start',
-      dicText: 'service.start_all'
-    },
-    {
-      key: '2',
-      action: 'stop',
-      dicText: 'service.stop_all'
-    },
-    {
-      key: '3',
-      action: 'restart',
-      dicText: 'service.restart_all'
-    }
-  ]
-
-  const { t } = useI18n()
-  const clusterStore = useClusterStore()
-  const serviceStore = useServiceStore()
-  const { clusterId } = storeToRefs(clusterStore)
-  const { installedServices } = storeToRefs(serviceStore)
-  const menuClicked = ref<Menu>()
-  const addWindowOpened = ref(false)
-  const jobWindowOpened = ref(false)
-
-  const handleMenuClick: MenuProps['onClick'] = (e) => {
-    if (e.key === '4') {
-      addWindowOpened.value = true
-      return
-    }
-    const menu = menuOps.find((menu) => menu.key == e.key)
-    const text = `${menu?.dicText}_services`
-    menuClicked.value = menu
-    Modal.confirm({
-      title: t('common.confirm'),
-      icon: createVNode(QuestionCircleOutlined),
-      content: t(text),
-      centered: true,
-      okText: t('common.confirm'),
-      cancelText: t('common.cancel'),
-      onOk: onOk
-    })
-  }
-
-  const onOk = async () => {
-    try {
-      if (!menuClicked.value) {
-        return
-      }
-      await execCommand({
-        command: menuClicked.value.action,
-        clusterId: clusterId.value,
-        commandLevel: 'service',
-        serviceCommands: getServiceCommands()
-      })
-      jobWindowOpened.value = true
-    } catch (error) {
-      console.log('error :>> ', error)
-    }
-  }
-
-  const getServiceCommands = () => {
-    return installedServices.value.map((service: ServiceVO) => {
-      return {
-        serviceName: service?.serviceName
-      }
-    })
-  }
-</script>
-
-<template>
-  <a-dropdown trigger="click" @click.stop>
-    <a class="dropdown-text">···</a>
-    <template #overlay>
-      <a-menu @click="handleMenuClick">
-        <a-menu-item v-for="menu in menuOps" :key="menu.key">
-          <svg-icon :name="menu.action" />
-          <span>{{ $t(menu.dicText) }}</span>
-        </a-menu-item>
-        <a-menu-divider />
-        <a-menu-item key="4">
-          <svg-icon name="plus" />
-          <span> {{ $t('service.add') }}</span>
-        </a-menu-item>
-      </a-menu>
-    </template>
-  </a-dropdown>
-  <job v-model:visible="jobWindowOpened" />
-  <suspense>
-    <service-add v-model:open="addWindowOpened" />
-  </suspense>
-</template>
-
-<style scoped lang="scss">
-  .dropdown-text {
-    font-size: 24px;
-    color: white;
-  }
-</style>
diff --git a/bigtop-manager-ui/src/assets/images/svg/send.svg b/bigtop-manager-ui/src/components/theme-switch/index.vue
similarity index 69%
rename from bigtop-manager-ui/src/assets/images/svg/send.svg
rename to bigtop-manager-ui/src/components/theme-switch/index.vue
index 62ce314..155fa49 100644
--- a/bigtop-manager-ui/src/assets/images/svg/send.svg
+++ b/bigtop-manager-ui/src/components/theme-switch/index.vue
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,7 +16,17 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="20" height="20" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
-  <path d="M43 5L29.7 43L22.1 25.9L5 18.3L43 5Z" stroke="#fff" stroke-width="4" stroke-linejoin="round" />
-  <path d="M43.0001 5L22.1001 25.9" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-</svg>
\ No newline at end of file
+
+<script setup lang="ts">
+  import { useTheme } from '@/store/theme'
+  const themeStore = useTheme()
+</script>
+
+<template>
+  <div>
+    <a-button @click="themeStore.toggleTheme('default')">Default</a-button>
+    <a-button @click="themeStore.toggleTheme('dark')">Dark</a-button>
+  </div>
+</template>
+
+<style lang="scss" scoped></style>
diff --git a/bigtop-manager-ui/src/components/user-avatar/index.vue b/bigtop-manager-ui/src/components/user-avatar/index.vue
index 2d17fc2..31488ce 100644
--- a/bigtop-manager-ui/src/components/user-avatar/index.vue
+++ b/bigtop-manager-ui/src/components/user-avatar/index.vue
@@ -50,9 +50,9 @@
 
 <template>
   <a-dropdown placement="bottom">
-    <div class="icon">
-      <user-outlined />
-      <div class="name">{{ userVO?.nickname }}</div>
+    <div class="header-item">
+      <svg-icon name="avatar" />
+      <span class="name">{{ userVO?.nickname }}</span>
     </div>
     <template #overlay>
       <a-menu>
@@ -85,22 +85,7 @@
 </template>
 
 <style lang="scss" scoped>
-  .icon {
-    @include flexbox($justify: center, $align: center);
-    font-size: 16px;
-    padding: 0 0.5rem;
-    border-radius: 6px;
-    cursor: pointer;
-    height: 36px;
-
-    &:hover {
-      background-color: var(--hover-color);
-    }
-
-    .name {
-      font-size: 14px;
-      margin-left: 0.5rem;
-      line-height: 36px;
-    }
+  .name {
+    color: $color-white;
   }
 </style>
diff --git a/bigtop-manager-ui/src/layouts/content.vue b/bigtop-manager-ui/src/layouts/content.vue
deleted file mode 100644
index 1093d18..0000000
--- a/bigtop-manager-ui/src/layouts/content.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { HomeOutlined } from '@ant-design/icons-vue'
-  import Chatbot from '@/components/chatbot/chatbot.vue'
-</script>
-
-<template>
-  <a-layout-content class="container">
-    <a-breadcrumb class="breadcrumb">
-      <a-breadcrumb-item>
-        <home-outlined />
-      </a-breadcrumb-item>
-      <a-breadcrumb-item
-        v-for="(item, index) in $route.path.substring(1).split('/')"
-        :key="index"
-      >
-        {{ item }}
-      </a-breadcrumb-item>
-    </a-breadcrumb>
-    <div class="content">
-      <router-view />
-    </div>
-    <chatbot />
-  </a-layout-content>
-</template>
-
-<style scoped lang="scss">
-  .container {
-    margin: 0 1rem;
-    min-height: auto;
-
-    .breadcrumb {
-      margin: 1rem 0;
-    }
-
-    .content {
-      padding: 1rem;
-      border-radius: 0.5rem;
-      background: #fff;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/assets/images/svg/left.svg b/bigtop-manager-ui/src/layouts/default.vue
similarity index 75%
copy from bigtop-manager-ui/src/assets/images/svg/left.svg
copy to bigtop-manager-ui/src/layouts/default.vue
index 01ee633..1f109f2 100644
--- a/bigtop-manager-ui/src/assets/images/svg/left.svg
+++ b/bigtop-manager-ui/src/layouts/default.vue
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
-  <!--
+<!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
   ~ distributed with this work for additional information
@@ -17,7 +16,11 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
-  xmlns="http://www.w3.org/2000/svg">
-  <path d="M31 36L19 24L31 12" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-</svg>
\ No newline at end of file
+
+<script setup lang="ts"></script>
+
+<template>
+  <div>default content</div>
+</template>
+
+<style scoped lang="scss"></style>
diff --git a/bigtop-manager-ui/src/layouts/footer.vue b/bigtop-manager-ui/src/layouts/footer.vue
index c6a6952..8e36ae1 100644
--- a/bigtop-manager-ui/src/layouts/footer.vue
+++ b/bigtop-manager-ui/src/layouts/footer.vue
@@ -17,14 +17,18 @@
   ~ under the License.
 -->
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+  import dayjs from 'dayjs'
+</script>
 
 <template>
   <a-layout-footer>
     <div class="copyright">
-      Copyright ©2011–2023
-      <a href="https://www.apache.org">The Apache Software Foundation</a>. All
-      rights reserved.
+      {{ `Copyright ©2011-${dayjs().year()}` }}
+      <a href="https://www.apache.org" target="_blank">
+        The Apache Software Foundation
+      </a>
+      . All rights reserved.
     </div>
   </a-layout-footer>
 </template>
diff --git a/bigtop-manager-ui/src/layouts/header.vue b/bigtop-manager-ui/src/layouts/header.vue
index 85969ec..cf22580 100644
--- a/bigtop-manager-ui/src/layouts/header.vue
+++ b/bigtop-manager-ui/src/layouts/header.vue
@@ -18,58 +18,90 @@
 -->
 
 <script setup lang="ts">
-  import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons-vue'
-  import ClusterInfo from '@/components/cluster-info/index.vue'
-  import JobInfo from '@/components/job-info/index.vue'
-  import AlertInfo from '@/components/alert-info/index.vue'
+  import { ref, toRefs } from 'vue'
   import SelectLang from '@/components/select-lang/index.vue'
   import UserAvatar from '@/components/user-avatar/index.vue'
-  import { useUIStore } from '@/store/ui'
-  import { storeToRefs } from 'pinia'
-  import { useClusterStore } from '@/store/cluster'
+  import { RouteRecordRaw } from 'vue-router'
 
-  const uiStore = useUIStore()
-  const clusterStore = useClusterStore()
-  const { siderCollapsed } = storeToRefs(uiStore)
-  const { clusters } = storeToRefs(clusterStore)
+  interface Props {
+    headerSelectedKey: string
+    headerMenus: RouteRecordRaw[]
+  }
+
+  const props = withDefaults(defineProps<Props>(), {
+    headerSelectedKey: '',
+    headerMenus: () => []
+  })
+
+  const { headerSelectedKey, headerMenus } = toRefs(props)
+  const githubUrl = import.meta.env.VITE_GITHUB_URL
+  const spaceSize = ref(16)
+  const emits = defineEmits(['onHeaderClick'])
+  const onHeaderClick = ({ key }: any) => {
+    emits('onHeaderClick', key)
+  }
 </script>
 
 <template>
   <a-layout-header class="header">
-    <div class="header-left">
-      <menu-unfold-outlined
-        v-if="siderCollapsed"
-        @click="uiStore.changeCollapsed"
-      />
-      <menu-fold-outlined v-else @click="uiStore.changeCollapsed" />
+    <h1 class="header-left common-layout">
+      <svg-icon name="big-manager-logo" />
+    </h1>
+    <div class="header-menu">
+      <a-menu
+        :selected-keys="[headerSelectedKey]"
+        theme="dark"
+        mode="horizontal"
+        @select="onHeaderClick"
+      >
+        <a-menu-item v-for="route of headerMenus" :key="route.path">
+          {{ $t(route.meta?.title || '') }}
+        </a-menu-item>
+      </a-menu>
     </div>
-    <div class="header-right">
-      <template v-if="clusters.length > 0">
-        <cluster-info />
-        <job-info />
-        <alert-info />
-      </template>
-      <select-lang />
-      <user-avatar />
+    <div class="header-right common-layout">
+      <a-space :size="spaceSize">
+        <user-avatar />
+        <div class="header-item">
+          <svg-icon name="communication" />
+        </div>
+        <select-lang />
+        <div class="header-item">
+          <a :href="githubUrl" target="_blank">
+            <svg-icon name="github" />
+          </a>
+        </div>
+        <div class="header-item">
+          <svg-icon name="book" />
+        </div>
+      </a-space>
     </div>
   </a-layout-header>
 </template>
 
 <style scoped lang="scss">
+  .common-layout {
+    @include flexbox($justify: center, $align: center);
+    height: 100%;
+  }
   .header {
     @include flexbox($justify: space-between, $align: center);
-    background: #fff;
-    padding: 0 1rem;
-    height: 48px;
-
+    padding-inline: 0 16px;
+    height: $layout-header-height;
+    .header-menu {
+      flex: 1;
+    }
     .header-left {
-      font-size: 16px;
-      cursor: pointer;
-      transition: color 0.3s;
+      width: $layout-sider-width;
+      margin: 0;
+      :deep(.svg-icon) {
+        width: 180px;
+        height: 30px;
+      }
     }
 
-    .header-right {
-      @include flexbox($justify: end, $align: center);
+    nav {
+      color: $color-white;
     }
   }
 </style>
diff --git a/bigtop-manager-ui/src/layouts/index.vue b/bigtop-manager-ui/src/layouts/index.vue
index 1005fa0..f0df7bd 100644
--- a/bigtop-manager-ui/src/layouts/index.vue
+++ b/bigtop-manager-ui/src/layouts/index.vue
@@ -18,52 +18,68 @@
 -->
 
 <script setup lang="ts">
-  import { onMounted, onUnmounted } from 'vue'
+  import { onMounted } from 'vue'
   import LayoutFooter from '@/layouts/footer.vue'
-  import LayoutContent from '@/layouts/content.vue'
   import LayoutHeader from '@/layouts/header.vue'
   import LayoutSider from '@/layouts/sider.vue'
   import { useUserStore } from '@/store/user'
   import { useClusterStore } from '@/store/cluster'
-  import { useServiceStore } from '@/store/service'
-  import { useComponentStore } from '@/store/component'
-  import { useConfigStore } from '@/store/config'
+  import { useMenuStore } from '@/store/menu/index'
+  import { storeToRefs } from 'pinia'
 
   const userStore = useUserStore()
+  const menuStore = useMenuStore()
   const clusterStore = useClusterStore()
-  const serviceStore = useServiceStore()
-  const componentStore = useComponentStore()
-  const configStore = useConfigStore()
+  const { headerSelectedKey, headerMenus, siderMenuSelectedKey, siderMenus } =
+    storeToRefs(menuStore)
 
-  onMounted(() => {
+  onMounted(async () => {
     userStore.getUserInfo()
-    clusterStore.loadClusters()
-    serviceStore.loadServices()
-    componentStore.resumeIntervalFn()
-    configStore.loadLatestConfigs()
-  })
-
-  onUnmounted(() => {
-    componentStore.pauseIntervalFn()
+    await clusterStore.loadClusters()
+    menuStore.setBaseRoutesMap()
   })
 </script>
 
 <template>
   <a-layout class="layout">
-    <layout-sider />
-    <a-layout class="layout-inner">
-      <layout-header />
-      <layout-content />
-      <layout-footer />
+    <layout-header
+      :header-selected-key="headerSelectedKey"
+      :header-menus="headerMenus"
+      @on-header-click="menuStore.onHeaderClick"
+    />
+    <a-layout>
+      <layout-sider
+        :sider-menu-selected-key="siderMenuSelectedKey"
+        :sider-menus="siderMenus"
+        @on-sider-click="menuStore.onSiderClick"
+      />
+      <a-layout class="layout-inner">
+        <router-view v-slot="{ Component }">
+          <transition name="fade" mode="out-in">
+            <component :is="Component" />
+          </transition>
+        </router-view>
+        <layout-footer />
+      </a-layout>
     </a-layout>
   </a-layout>
 </template>
 
-<style scoped lang="scss">
+<style lang="scss" scoped>
   .layout {
-    min-height: 100vh;
+    height: 100vh;
     &-inner {
+      padding: $space-lg $space-md;
       overflow: auto;
     }
   }
+
+  .fade-enter-active,
+  .fade-leave-active {
+    transition: opacity 0.4s;
+  }
+  .fade-enter,
+  .fade-leave-to {
+    opacity: 0;
+  }
 </style>
diff --git a/bigtop-manager-ui/src/layouts/sider.vue b/bigtop-manager-ui/src/layouts/sider.vue
index 67b338a..b6e1bcd 100644
--- a/bigtop-manager-ui/src/layouts/sider.vue
+++ b/bigtop-manager-ui/src/layouts/sider.vue
@@ -18,124 +18,130 @@
 -->
 
 <script setup lang="ts">
-  import { computed, onMounted, ref, watch } from 'vue'
-  import { useUIStore } from '@/store/ui'
-  import { useUserStore } from '@/store/user'
-  import { storeToRefs } from 'pinia'
-  import { RouterLink, useRouter } from 'vue-router'
-  import ServiceDropdown from '@/components/service/service-dropdown.vue'
+  import { toRefs } from 'vue'
+  import { useRouter, useRoute } from 'vue-router'
+  import { SPECIAL_ROUTE_NAME } from '@/store/menu/index'
+  import { useMenuStore, type MenuItem } from '@/store/menu'
 
-  const uiStore = useUIStore()
-  const userStore = useUserStore()
-  const router = useRouter()
-
-  const { siderCollapsed } = storeToRefs(uiStore)
-  const { menuItems } = storeToRefs(userStore)
+  interface Props {
+    siderMenuSelectedKey: string
+    siderMenus: MenuItem[]
+  }
 
-  const selectedKeys = ref<string[]>([])
-  const openKeys = ref<string[]>([])
+  const props = withDefaults(defineProps<Props>(), {
+    siderMenuSelectedKey: '',
+    siderMenus: () => []
+  })
 
-  const siderMenu = computed(() =>
-    menuItems.value
-      .filter((menuItem) => !menuItem.hidden)
-      .sort((pre, next) => (pre.priority ?? 0) - (next.priority ?? 0))
-  )
+  const { siderMenuSelectedKey, siderMenus } = toRefs(props)
+  const router = useRouter()
+  const route = useRoute()
+  const menuStore = useMenuStore()
+  const emits = defineEmits(['onSiderClick'])
 
-  const updateSideBar = () => {
-    const splitPath = router.currentRoute.value.path.split('/')
-    const selectedKey = splitPath[splitPath.length - 1]
-    selectedKeys.value = [selectedKey]
-    if (splitPath.length > 2) {
-      openKeys.value = [splitPath[1]]
+  const toggleActivatedIcon = (menuItem: MenuItem) => {
+    const matchStr = '/:cluster/:id'
+    const { key, icon } = menuItem
+    const routePath = route.matched.at(-1)?.path
+    if (routePath?.includes(matchStr)) {
+      return key === routePath.replace(matchStr, '')
+        ? `${icon}_activated`
+        : icon
     } else {
-      openKeys.value = []
+      return key === siderMenuSelectedKey.value ? `${icon}_activated` : icon
     }
   }
 
-  watch(router.currentRoute, () => {
-    updateSideBar()
-  })
+  const addCluster = () => {
+    router.push({ name: 'ClusterCreate' })
+  }
 
-  onMounted(async () => {
-    updateSideBar()
-  })
+  const onSiderClick = ({ key }: any) => {
+    emits('onSiderClick', key)
+  }
 </script>
 
 <template>
-  <a-layout-sider v-model:collapsed="siderCollapsed" class="sider" width="235">
-    <div class="header">
-      <img class="header-logo" src="@/assets/logo.svg" alt="logo" />
-      <div v-if="!siderCollapsed" class="header-title">Bigtop Manager</div>
-    </div>
+  <a-layout-sider class="sider">
     <a-menu
-      v-model:selectedKeys="selectedKeys"
-      v-model:open-keys="openKeys"
-      theme="dark"
+      :selected-keys="[siderMenuSelectedKey]"
       mode="inline"
+      @select="onSiderClick"
     >
-      <template v-for="item in siderMenu">
-        <template v-if="item.children">
-          <a-sub-menu :key="item.key">
-            <template #title>
-              <div v-if="item.title === 'Services'" class="menu-title-flex">
-                <span>
-                  <component :is="() => item.icon" />
-                  <span>
-                    {{ item.title }}
-                  </span>
-                </span>
-                <service-dropdown />
-              </div>
-              <span v-else>
-                <component :is="() => item.icon" />
-                <span>
-                  {{ item.title }}
-                </span>
-              </span>
-            </template>
-            <a-menu-item v-for="subItem in item.children" :key="subItem.key">
-              <component :is="() => subItem.icon" />
-              <span>
-                <router-link :to="subItem.to">{{ subItem.title }}</router-link>
-              </span>
-            </a-menu-item>
-          </a-sub-menu>
-        </template>
+      <template v-for="menuItem in siderMenus" :key="menuItem.key">
+        <a-sub-menu
+          v-if="menuItem.children && menuItem.name === SPECIAL_ROUTE_NAME"
+          :key="menuItem.key"
+        >
+          <template #icon>
+            <svg-icon :name="toggleActivatedIcon(menuItem)" />
+          </template>
+          <template #title>
+            <span>{{ $t(menuItem.label) }}</span>
+          </template>
+          <a-menu-item v-for="child in menuItem.children" :key="child.key">
+            <span style="margin: 0 6px">{{ child.icon }}</span>
+            <span>{{ child.label }}</span>
+          </a-menu-item>
+        </a-sub-menu>
         <template v-else>
-          <a-menu-item :key="item.key">
-            <component :is="() => item.icon" />
-            <span>
-              <router-link :to="item.to">{{ item.title }}</router-link>
-            </span>
+          <a-menu-item :key="menuItem.key">
+            <template #icon>
+              <svg-icon :name="toggleActivatedIcon(menuItem)" />
+            </template>
+            <span>{{ $t(menuItem.label) }}</span>
           </a-menu-item>
         </template>
       </template>
     </a-menu>
+    <div v-show="menuStore.isClusterCreateVisible">
+      <a-divider />
+      <div class="create-option">
+        <a-button type="primary" ghost @click="addCluster">
+          <svg-icon name="plus" />
+          <label>{{ $t('menu.create') }}</label>
+        </a-button>
+      </div>
+    </div>
   </a-layout-sider>
 </template>
 
 <style scoped lang="scss">
+  @mixin reset-sider-menu {
+    width: 100%;
+    border-radius: 0;
+    padding: 0 0 0 14px !important;
+    margin: 4px 0 0 0 !important;
+  }
   .sider {
-    .header {
-      @include flexbox($justify: center, $align: center);
-      height: 32px;
-      margin: 1rem;
+    width: $layout-header-height;
+    background: $layout-sider-bg-color;
+    overflow: auto;
 
-      .header-logo {
-        height: 32px;
-        width: 32px;
-      }
+    :deep(.ant-menu-submenu-title) {
+      @include reset-sider-menu();
+    }
 
-      .header-title {
-        color: #ccc;
-        font-weight: bold;
-        font-size: 16px;
-        margin-left: 1rem;
-      }
+    :deep(.ant-menu-item) {
+      @include reset-sider-menu();
     }
 
-    .menu-title-flex {
-      @include flexbox($justify: space-between, $align: center);
+    :deep(.ant-menu-item-selected) {
+      border-right: 2px solid $color-primary;
+    }
+
+    .create-option {
+      width: 100%;
+      display: flex;
+      justify-content: center;
+      padding-bottom: $space-lg;
+      button {
+        width: 160px;
+        @include flexbox($align: center);
+        label {
+          margin-left: 10px;
+        }
+      }
     }
   }
 </style>
diff --git a/bigtop-manager-ui/src/locales/en_US/ai.ts b/bigtop-manager-ui/src/locales/en_US/ai.ts
deleted file mode 100644
index 6a13d96..0000000
--- a/bigtop-manager-ui/src/locales/en_US/ai.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export default {
-  empty_message: 'Message cannot be empty',
-  select_authorized_platform: 'Please select the following authorized platform',
-  no_authorized_platform: 'No authorized platforms',
-  or_you_can: 'Or you can',
-  authorize_new_platform: 'Authorize New Platform',
-  select_platform_to_authorize: 'Select platform to authorize',
-  authorizing_platform:
-    ' You are authorizing {0} platform, please fill in the following information',
-  select_thread_to_chat: 'Please select the thread to enter chat',
-  select_model: 'Please select the model you want to use',
-  create_new_thread: 'Create New Thread',
-  thread_name: 'Thread {0}'
-}
diff --git a/bigtop-manager-ui/src/locales/en_US/cluster.ts b/bigtop-manager-ui/src/locales/en_US/cluster.ts
deleted file mode 100644
index 5385486..0000000
--- a/bigtop-manager-ui/src/locales/en_US/cluster.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export default {
-  switch: 'Switch Cluster',
-  create: 'Create Cluster',
-  set_cluster_name: 'Set Cluster Name',
-  set_cluster_name_title: "Let's get started!",
-  set_cluster_name_sub_title: 'Please follow the steps to create your cluster.',
-  set_cluster_name_input: 'Input your cluster name',
-  set_cluster_name_valid: 'Cluster name is required',
-  choose_stack: 'Choose Stack',
-  set_repository: 'Set Repository',
-  set_hosts: 'Set Hosts',
-  set_hosts_placeholder: 'Enter a list of hosts, one per line.',
-  set_hosts_valid: 'Input at least one host name.',
-  show_hosts_resolved: 'Hostnames after resolved',
-  not_exist_title: 'Cluster not exist',
-  not_exist_sub_title: 'Cluster not exist, please create one first.',
-  create_success_title: 'Congratulations!',
-  create_success_sub_title: 'Cluster created successfully, please enjoy it.',
-  create_fail_title: 'Oh no!',
-  create_fail_sub_title: 'Cluster created failed, please retry it.'
-}
diff --git a/bigtop-manager-ui/src/locales/en_US/hosts.ts b/bigtop-manager-ui/src/locales/en_US/hosts.ts
deleted file mode 100644
index 7c00362..0000000
--- a/bigtop-manager-ui/src/locales/en_US/hosts.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export default {
-  host: 'Host',
-  host_selected: 'Selected {0} hosts',
-  host_restart: 'Restart Hosts',
-  host_stop: 'Stop Hosts',
-  add: 'Add Host',
-  hostname: 'Hostname',
-  cluster_name: 'Cluster Name',
-  ipv4: 'IPv4',
-  cores: 'CPU Cores',
-  ram: 'RAM',
-  disk: 'Disk'
-}
diff --git a/bigtop-manager-ui/src/locales/en_US/index.ts b/bigtop-manager-ui/src/locales/en_US/index.ts
index b367ad1..a15d017 100644
--- a/bigtop-manager-ui/src/locales/en_US/index.ts
+++ b/bigtop-manager-ui/src/locales/en_US/index.ts
@@ -18,21 +18,13 @@
  */
 
 import common from '@/locales/en_US/common.ts'
+import menu from '@/locales/en_US/menu.ts'
 import login from '@/locales/en_US/login'
 import user from '@/locales/en_US/user.ts'
-import cluster from '@/locales/en_US/cluster.ts'
-import hosts from '@/locales/en_US/hosts.ts'
-import service from '@/locales/en_US/service.ts'
-import job from '@/locales/en_US/job.ts'
-import ai from '@/locales/en_US/ai.ts'
 
 export default {
   common,
+  menu,
   login,
-  user,
-  cluster,
-  hosts,
-  service,
-  job,
-  ai
+  user
 }
diff --git a/bigtop-manager-ui/src/locales/en_US/job.ts b/bigtop-manager-ui/src/locales/en_US/menu.ts
similarity index 83%
rename from bigtop-manager-ui/src/locales/en_US/job.ts
rename to bigtop-manager-ui/src/locales/en_US/menu.ts
index 52b7e99..192158c 100644
--- a/bigtop-manager-ui/src/locales/en_US/job.ts
+++ b/bigtop-manager-ui/src/locales/en_US/menu.ts
@@ -18,6 +18,11 @@
  */
 
 export default {
-  log_await_message: 'Waiting for more logs',
-  log_complete_message: 'Done!'
+  cluster: 'Cluster',
+  infra: 'Infrastructure',
+  component: 'Component',
+  host: 'Host',
+  create: 'Create Cluster',
+  system: 'System',
+  llm_config: 'LLM Config'
 }
diff --git a/bigtop-manager-ui/src/locales/en_US/service.ts b/bigtop-manager-ui/src/locales/en_US/service.ts
deleted file mode 100644
index 010138d..0000000
--- a/bigtop-manager-ui/src/locales/en_US/service.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export default {
-  start_all: 'Start All',
-  stop_all: 'Stop All',
-  restart_all: 'Restart All',
-  start_service: 'Start Service',
-  stop_service: 'Stop Service',
-  restart_service: 'Restart Service',
-  start_all_services: 'Are you sure you want to start all services?',
-  stop_all_services: 'Are you sure you want to stop all services?',
-  restart_all_services: 'Are you sure you want to restart all services?',
-  start_service_warn: 'Are you sure you want to start {0} service?',
-  stop_service_warn: 'Are you sure you want to stop {0} service?',
-  restart_service_warn: 'Are you sure you want to restart {0} service?',
-  add: 'Add service',
-  service: 'Service',
-  service_name: 'Service Name',
-  service_selected: 'Selected {0} Services',
-  service_account: 'Service Account',
-  service_user: 'Service User',
-  service_group: 'Service Group',
-  choose_services: 'Choose Services',
-  assign_components: 'Assign Components',
-  configure_services: 'Configure Services',
-  add_success_title: 'Congratulations!',
-  add_success_sub_title: 'Service added successfully, please enjoy it.',
-  add_fail_title: 'Oh no!',
-  add_fail_sub_title: 'Service added failed, please retry it.',
-  summary: 'Summary',
-  config: 'Config',
-  components: 'Components',
-  quick_links: 'Quick Links',
-  no_link: 'No Link'
-}
diff --git a/bigtop-manager-ui/src/locales/zh_CN/ai.ts b/bigtop-manager-ui/src/locales/zh_CN/ai.ts
deleted file mode 100644
index 551f465..0000000
--- a/bigtop-manager-ui/src/locales/zh_CN/ai.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export default {
-  empty_message: '消息内容不能为空',
-  select_authorized_platform: '请选择下列已授权的平台',
-  no_authorized_platform: '暂无授权平台',
-  or_you_can: '或者你可以',
-  authorize_new_platform: '授权新平台',
-  select_platform_to_authorize: '请选择下列要授权的平台',
-  authorizing_platform: '您正在授权 {0} 平台, 请填写下列信息',
-  select_thread_to_chat: '请选择下面的线程进入聊天',
-  select_model: '请选择您要使用的模型',
-  create_new_thread: '创建新线程',
-  thread_name: '线程 {0}'
-}
diff --git a/bigtop-manager-ui/src/locales/zh_CN/cluster.ts b/bigtop-manager-ui/src/locales/zh_CN/cluster.ts
deleted file mode 100644
index b9f39d7..0000000
--- a/bigtop-manager-ui/src/locales/zh_CN/cluster.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export default {
-  switch: '切换集群',
-  create: '创建集群',
-  set_cluster_name: '设置集群名称',
-  set_cluster_name_title: '让我们来开始吧',
-  set_cluster_name_sub_title: '请跟随后续步骤来创建你的集群',
-  set_cluster_name_input: '输入你的集群名',
-  set_cluster_name_valid: '集群名不能为空',
-  choose_stack: '选择组件栈',
-  set_repository: '设置源',
-  set_hosts: '设置节点',
-  set_hosts_placeholder: '请输入主机名,每行一个。',
-  set_hosts_valid: '主机名不能为空。',
-  show_hosts_resolved: '解析后的主机名列表',
-  not_exist_title: '集群不存在',
-  not_exist_sub_title: '集群不存在,请先创建',
-  create_success_title: '创建成功',
-  create_success_sub_title: '集群已创建成功,快点开始使用吧',
-  create_fail_title: '创建失败',
-  create_fail_sub_title: '集群创建失败,请重试'
-}
diff --git a/bigtop-manager-ui/src/locales/zh_CN/hosts.ts b/bigtop-manager-ui/src/locales/zh_CN/hosts.ts
deleted file mode 100644
index a4f190c..0000000
--- a/bigtop-manager-ui/src/locales/zh_CN/hosts.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export default {
-  host: '主机',
-  host_selected: '已选择 {0} 台主机',
-  host_restart: '重启主机',
-  host_stop: '停止主机',
-  add: '增加主机',
-  hostname: '主机名称',
-  cluster_name: '集群名称',
-  ipv4: 'IP 地址',
-  cores: 'CPU 核数',
-  ram: '内存',
-  disk: '磁盘'
-}
diff --git a/bigtop-manager-ui/src/locales/zh_CN/index.ts b/bigtop-manager-ui/src/locales/zh_CN/index.ts
index fe7d911..2b441ce 100644
--- a/bigtop-manager-ui/src/locales/zh_CN/index.ts
+++ b/bigtop-manager-ui/src/locales/zh_CN/index.ts
@@ -18,21 +18,13 @@
  */
 
 import common from '@/locales/zh_CN/common.ts'
+import menu from '@/locales/zh_CN/menu.ts'
 import login from '@/locales/zh_CN/login'
 import user from '@/locales/zh_CN/user.ts'
-import cluster from '@/locales/zh_CN/cluster.ts'
-import hosts from '@/locales/zh_CN/hosts.ts'
-import service from '@/locales/zh_CN/service.ts'
-import job from '@/locales/zh_CN/job.ts'
-import ai from '@/locales/zh_CN/ai.ts'
 
 export default {
   common,
+  menu,
   login,
-  user,
-  cluster,
-  hosts,
-  service,
-  job,
-  ai
+  user
 }
diff --git a/bigtop-manager-ui/src/locales/zh_CN/job.ts b/bigtop-manager-ui/src/locales/zh_CN/menu.ts
similarity index 81%
rename from bigtop-manager-ui/src/locales/zh_CN/job.ts
rename to bigtop-manager-ui/src/locales/zh_CN/menu.ts
index 9dff298..170f822 100644
--- a/bigtop-manager-ui/src/locales/zh_CN/job.ts
+++ b/bigtop-manager-ui/src/locales/zh_CN/menu.ts
@@ -18,6 +18,11 @@
  */
 
 export default {
-  log_await_message: '获取日志中 ',
-  log_complete_message: '完成 !'
+  cluster: '集群管理',
+  infra: '基础服务',
+  component: '组件信息',
+  host: '主机管理',
+  create: '添加集群',
+  system: '系统管理',
+  llm_config: '大模型配置'
 }
diff --git a/bigtop-manager-ui/src/locales/zh_CN/service.ts b/bigtop-manager-ui/src/locales/zh_CN/service.ts
deleted file mode 100644
index c69dc7e..0000000
--- a/bigtop-manager-ui/src/locales/zh_CN/service.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export default {
-  start_all: '启动所有',
-  stop_all: '停止所有',
-  restart_all: '重启所有',
-  start_service: '启动服务',
-  stop_service: '停止服务',
-  restart_service: '重启服务',
-  start_all_services: '是否确认启动所有服务?',
-  stop_all_services: '是否确认停止所有服务?',
-  restart_all_services: '是否确认重启所有服务?',
-  start_service_warn: '是否确认启动 {0} ?',
-  stop_service_warn: '是否确认停止 {0} ?',
-  restart_service_warn: '是否确认重启 {0}?',
-  add: '新增服务',
-  service: '服务',
-  service_name: '服务名称',
-  service_selected: '已选择 {0} 个服务',
-  service_account: '服务账号',
-  service_user: '服务所属用户',
-  service_group: '服务所属用户组',
-  choose_services: '选择服务',
-  assign_components: '分配组件',
-  configure_services: '配置服务',
-  create_success_title: '新增成功',
-  create_success_sub_title: '组件新增成功,快点开始使用吧',
-  create_fail_title: '新增失败',
-  create_fail_sub_title: '组件新增失败,请重试',
-  summary: '总览',
-  config: '配置',
-  components: '组件',
-  quick_links: '快速链接',
-  no_link: '无'
-}
diff --git a/bigtop-manager-ui/src/main.ts b/bigtop-manager-ui/src/main.ts
index 6539e20..f3534cb 100644
--- a/bigtop-manager-ui/src/main.ts
+++ b/bigtop-manager-ui/src/main.ts
@@ -20,10 +20,6 @@
 import { createApp } from 'vue'
 import App from './App.vue'
 import plugins from '@/plugins'
-
-import '@/styles/main.css'
-import '@/styles/scrollbar.scss'
-import '@/styles/marked.scss'
 import 'ant-design-vue/dist/reset.css'
 import 'virtual:svg-icons-register'
 
diff --git a/bigtop-manager-ui/src/assets/images/svg/user.svg b/bigtop-manager-ui/src/pages/cluster-mange/cluster/create.vue
similarity index 65%
rename from bigtop-manager-ui/src/assets/images/svg/user.svg
rename to bigtop-manager-ui/src/pages/cluster-mange/cluster/create.vue
index 8bb9e8f..a1f074d 100644
--- a/bigtop-manager-ui/src/assets/images/svg/user.svg
+++ b/bigtop-manager-ui/src/pages/cluster-mange/cluster/create.vue
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,9 +16,26 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
-  <circle cx="24" cy="12" r="8" fill="none" stroke="#333" stroke-width="2" stroke-linecap="round"
-    stroke-linejoin="round" />
-  <path d="M42 44C42 34.0589 33.9411 26 24 26C14.0589 26 6 34.0589 6 44" stroke="#333" stroke-width="2"
-    stroke-linecap="round" stroke-linejoin="round" />
-</svg>
\ No newline at end of file
+
+<script setup lang="ts">
+  import { useMenuStore } from '@/store/menu'
+  const menuStore = useMenuStore()
+
+  const onSave = () => {
+    menuStore.updateSiderMenu()
+  }
+
+  const onDel = () => {
+    menuStore.updateSiderMenu(true)
+  }
+</script>
+
+<template>
+  <div>
+    <div> create & del</div>
+    <a-button @click="onSave">create</a-button>
+    <a-button @click="onDel">delete</a-button>
+  </div>
+</template>
+
+<style scoped></style>
diff --git a/bigtop-manager-ui/src/assets/images/svg/send-disabled.svg b/bigtop-manager-ui/src/pages/cluster-mange/cluster/detail.vue
similarity index 69%
rename from bigtop-manager-ui/src/assets/images/svg/send-disabled.svg
rename to bigtop-manager-ui/src/pages/cluster-mange/cluster/detail.vue
index 51b2a88..d761267 100644
--- a/bigtop-manager-ui/src/assets/images/svg/send-disabled.svg
+++ b/bigtop-manager-ui/src/pages/cluster-mange/cluster/detail.vue
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,7 +16,11 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="20" height="20" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
-  <path d="M43 5L29.7 43L22.1 25.9L5 18.3L43 5Z" stroke="#a5a2a2" stroke-width="4" stroke-linejoin="round" />
-  <path d="M43.0001 5L22.1001 25.9" stroke="#a5a2a2" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-</svg>
\ No newline at end of file
+
+<script setup lang="ts"></script>
+
+<template>
+  <div>detail </div>
+</template>
+
+<style scoped></style>
diff --git a/bigtop-manager-ui/src/assets/images/svg/left.svg b/bigtop-manager-ui/src/pages/cluster-mange/cluster/index.vue
similarity index 75%
copy from bigtop-manager-ui/src/assets/images/svg/left.svg
copy to bigtop-manager-ui/src/pages/cluster-mange/cluster/index.vue
index 01ee633..d78ec09 100644
--- a/bigtop-manager-ui/src/assets/images/svg/left.svg
+++ b/bigtop-manager-ui/src/pages/cluster-mange/cluster/index.vue
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
-  <!--
+<!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
   ~ distributed with this work for additional information
@@ -17,7 +16,13 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
-  xmlns="http://www.w3.org/2000/svg">
-  <path d="M31 36L19 24L31 12" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-</svg>
\ No newline at end of file
+
+<script setup lang="ts"></script>
+
+<template>
+  <div>
+    <a-card>{{ $route.params }}</a-card>
+  </div>
+</template>
+
+<style scoped></style>
diff --git a/bigtop-manager-ui/src/assets/images/svg/left.svg b/bigtop-manager-ui/src/pages/cluster-mange/components/index.vue
similarity index 75%
copy from bigtop-manager-ui/src/assets/images/svg/left.svg
copy to bigtop-manager-ui/src/pages/cluster-mange/components/index.vue
index 01ee633..4782fe8 100644
--- a/bigtop-manager-ui/src/assets/images/svg/left.svg
+++ b/bigtop-manager-ui/src/pages/cluster-mange/components/index.vue
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
-  <!--
+<!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
   ~ distributed with this work for additional information
@@ -17,7 +16,11 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
-  xmlns="http://www.w3.org/2000/svg">
-  <path d="M31 36L19 24L31 12" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-</svg>
\ No newline at end of file
+
+<script setup lang="ts"></script>
+
+<template>
+  <div> components</div>
+</template>
+
+<style scoped></style>
diff --git a/bigtop-manager-ui/src/assets/images/svg/left.svg b/bigtop-manager-ui/src/pages/cluster-mange/hosts/create.vue
similarity index 75%
copy from bigtop-manager-ui/src/assets/images/svg/left.svg
copy to bigtop-manager-ui/src/pages/cluster-mange/hosts/create.vue
index 01ee633..c4e8318 100644
--- a/bigtop-manager-ui/src/assets/images/svg/left.svg
+++ b/bigtop-manager-ui/src/pages/cluster-mange/hosts/create.vue
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
-  <!--
+<!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
   ~ distributed with this work for additional information
@@ -17,7 +16,11 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
-  xmlns="http://www.w3.org/2000/svg">
-  <path d="M31 36L19 24L31 12" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-</svg>
\ No newline at end of file
+
+<script setup lang="ts"></script>
+
+<template>
+  <div>host create </div>
+</template>
+
+<style scoped></style>
diff --git a/bigtop-manager-ui/src/pages/dashboard/index.vue b/bigtop-manager-ui/src/pages/cluster-mange/hosts/index.vue
similarity index 72%
rename from bigtop-manager-ui/src/pages/dashboard/index.vue
rename to bigtop-manager-ui/src/pages/cluster-mange/hosts/index.vue
index e65565a..8150b62 100644
--- a/bigtop-manager-ui/src/pages/dashboard/index.vue
+++ b/bigtop-manager-ui/src/pages/cluster-mange/hosts/index.vue
@@ -18,18 +18,18 @@
 -->
 
 <script setup lang="ts">
-  import { useClusterStore } from '@/store/cluster'
-  import { storeToRefs } from 'pinia'
-  import Dashboard from '@/components/dashboard/index.vue'
-  import Tips from '@/components/dashboard/tips.vue'
-
-  const clusterStore = useClusterStore()
-  const { selectedCluster } = storeToRefs(clusterStore)
+  import { useRouter } from 'vue-router'
+  const router = useRouter()
+  const addHost = () => {
+    router.push({ name: 'HostCreate' })
+  }
 </script>
 
 <template>
-  <dashboard v-if="selectedCluster" />
-  <tips v-else />
+  <div>
+    <a-button @click="addHost">create host</a-button>
+    <div>host list</div>
+  </div>
 </template>
 
 <style scoped lang="scss"></style>
diff --git a/bigtop-manager-ui/src/assets/images/svg/left.svg b/bigtop-manager-ui/src/pages/cluster-mange/infrastructures/index.vue
similarity index 75%
copy from bigtop-manager-ui/src/assets/images/svg/left.svg
copy to bigtop-manager-ui/src/pages/cluster-mange/infrastructures/index.vue
index 01ee633..dea9aa3 100644
--- a/bigtop-manager-ui/src/assets/images/svg/left.svg
+++ b/bigtop-manager-ui/src/pages/cluster-mange/infrastructures/index.vue
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
-  <!--
+<!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
   ~ distributed with this work for additional information
@@ -17,7 +16,11 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
-  xmlns="http://www.w3.org/2000/svg">
-  <path d="M31 36L19 24L31 12" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-</svg>
\ No newline at end of file
+
+<script setup lang="ts"></script>
+
+<template>
+  <div> infra list</div>
+</template>
+
+<style scoped></style>
diff --git a/bigtop-manager-ui/src/pages/cluster/account/index.vue b/bigtop-manager-ui/src/pages/cluster/account/index.vue
deleted file mode 100644
index 475e180..0000000
--- a/bigtop-manager-ui/src/pages/cluster/account/index.vue
+++ /dev/null
@@ -1,71 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { storeToRefs } from 'pinia'
-  import { useServiceStore } from '@/store/service'
-
-  const serviceStore = useServiceStore()
-  const { installedServices, loadingServices } = storeToRefs(serviceStore)
-
-  const serviceColumns = [
-    {
-      title: 'service.service_name',
-      dataIndex: 'displayName',
-      align: 'center'
-    },
-    {
-      title: 'service.service_user',
-      dataIndex: 'serviceUser',
-      align: 'center'
-    },
-    {
-      title: 'service.service_group',
-      dataIndex: 'serviceGroup',
-      align: 'center'
-    }
-  ]
-</script>
-
-<template>
-  <div>
-    <a-page-header
-      class="account-page-header"
-      :title="$t('service.service_account')"
-    >
-    </a-page-header>
-    <br />
-    <a-table
-      :data-source="installedServices"
-      :columns="serviceColumns"
-      :loading="loadingServices"
-      :pagination="false"
-    >
-      <template #headerCell="{ column }">
-        <span>{{ $t(column.title) }}</span>
-      </template>
-    </a-table>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .account-page-header {
-    border: 1px solid rgb(235, 237, 240);
-  }
-</style>
diff --git a/bigtop-manager-ui/src/pages/cluster/stack/index.vue b/bigtop-manager-ui/src/pages/cluster/stack/index.vue
deleted file mode 100644
index abf2363..0000000
--- a/bigtop-manager-ui/src/pages/cluster/stack/index.vue
+++ /dev/null
@@ -1,104 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { ref } from 'vue'
-  import { storeToRefs } from 'pinia'
-  import { CheckCircleTwoTone, CloseCircleTwoTone } from '@ant-design/icons-vue'
-  import ClusterCreate from '@/components/cluster-create/index.vue'
-  import { useServiceStore } from '@/store/service'
-
-  const serviceStore = useServiceStore()
-  const { mergedServices, loadingServices } = storeToRefs(serviceStore)
-
-  const createWindowOpened = ref(false)
-
-  const serviceColumns = [
-    {
-      title: 'service.service_name',
-      dataIndex: 'displayName',
-      align: 'center'
-    },
-    {
-      title: 'common.version',
-      dataIndex: 'serviceVersion',
-      align: 'center'
-    },
-    {
-      title: 'common.status',
-      dataIndex: 'state',
-      align: 'center'
-    },
-    {
-      title: 'common.desc',
-      dataIndex: 'serviceDesc',
-      align: 'center'
-    }
-  ]
-</script>
-
-<template>
-  <div>
-    <a-page-header class="host-page-header" :title="$t('common.stack')">
-      <template #extra>
-        <a-button type="primary" @click="createWindowOpened = true">
-          {{ $t('service.add') }}
-        </a-button>
-      </template>
-    </a-page-header>
-    <br />
-
-    <a-table
-      :columns="serviceColumns"
-      :loading="loadingServices"
-      :data-source="mergedServices"
-      :pagination="false"
-    >
-      <template #headerCell="{ column }">
-        <span>{{ $t(column.title) }}</span>
-      </template>
-      <template #bodyCell="{ column, text, record }">
-        <template v-if="column.dataIndex === 'state'">
-          <CheckCircleTwoTone
-            v-if="record.installed"
-            two-tone-color="#52c41a"
-          />
-          <CloseCircleTwoTone v-else two-tone-color="red" />
-        </template>
-        <template v-if="column.dataIndex === 'displayName' && record.installed">
-          <router-link :to="'/services/' + record.serviceName.toLowerCase()">
-            {{ text }}
-          </router-link>
-        </template>
-      </template>
-    </a-table>
-  </div>
-
-  <cluster-create v-model:open="createWindowOpened" />
-</template>
-
-<style scoped lang="scss">
-  .host-page-header {
-    border: 1px solid rgb(235, 237, 240);
-
-    .host-selected-span {
-      margin-left: 8px;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/pages/hosts/index.vue b/bigtop-manager-ui/src/pages/hosts/index.vue
deleted file mode 100644
index afb0691..0000000
--- a/bigtop-manager-ui/src/pages/hosts/index.vue
+++ /dev/null
@@ -1,194 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
-  import { message } from 'ant-design-vue'
-  import { storeToRefs } from 'pinia'
-  import {
-    CaretRightFilled,
-    CheckCircleTwoTone,
-    CloseCircleTwoTone,
-    MinusCircleTwoTone,
-    StopFilled
-  } from '@ant-design/icons-vue'
-  import { useHostStore } from '@/store/host'
-  import { DEFAULT_PAGE_SIZE } from '@/utils/constant.ts'
-  import { CommonState, CurrState } from '@/enums/state'
-
-  const hostStore = useHostStore()
-  const { hosts, loading } = storeToRefs(hostStore)
-  const currentPage = ref<number>(1)
-  const pagination = computed(() => ({
-    total: hosts.value.length,
-    current: currentPage.value,
-    pageSize: DEFAULT_PAGE_SIZE
-  }))
-
-  const selectedRowKeys = ref<string[]>([])
-
-  const hostColumns = [
-    {
-      title: 'hosts.hostname',
-      dataIndex: 'hostname',
-      align: 'center'
-    },
-    {
-      title: 'hosts.cluster_name',
-      dataIndex: 'clusterName',
-      align: 'center'
-    },
-    {
-      title: 'common.os',
-      dataIndex: 'os',
-      align: 'center'
-    },
-    {
-      title: 'common.arch',
-      dataIndex: 'arch',
-      align: 'center'
-    },
-    {
-      title: 'hosts.ipv4',
-      dataIndex: 'ipv4',
-      align: 'center'
-    },
-    {
-      title: 'hosts.cores',
-      dataIndex: 'availableProcessors',
-      align: 'center'
-    },
-    {
-      title: 'hosts.ram',
-      dataIndex: 'totalMemorySize',
-      align: 'center'
-    },
-    {
-      title: 'hosts.disk',
-      dataIndex: 'totalDisk',
-      align: 'center'
-    },
-    {
-      title: 'common.status',
-      dataIndex: 'state',
-      align: 'center'
-    }
-  ]
-
-  const stateColor = (type: keyof typeof CurrState) => {
-    if ([0, 1].includes(CurrState[type])) {
-      return CommonState['normal']
-    } else if (CurrState[type] === 2) {
-      return CommonState['maintained']
-    }
-    return CommonState['abnormal']
-  }
-
-  const displayKeys = (selectedRowKeys: string[]) => {
-    message.info('This is a normal message' + selectedRowKeys)
-  }
-
-  onMounted(async () => {
-    hostStore.resumeIntervalFn()
-  })
-
-  onBeforeUnmount(() => {
-    hostStore.pauseIntervalFn()
-  })
-</script>
-
-<template>
-  <div>
-    <a-page-header class="host-page-header" :title="$t('common.host')">
-      <template #extra>
-        <span class="host-selected-span">
-          <template v-if="selectedRowKeys.length > 0">
-            {{ $t('hosts.host_selected', [selectedRowKeys.length]) }}
-          </template>
-        </span>
-
-        <a-button type="primary" @click="displayKeys(selectedRowKeys)">
-          {{ $t('hosts.add') }}
-        </a-button>
-
-        <a-dropdown :trigger="['click']">
-          <template #overlay>
-            <a-menu>
-              <a-menu-item @click="displayKeys(selectedRowKeys)">
-                <caret-right-filled />
-                {{ $t('hosts.host_restart') }}
-              </a-menu-item>
-              <a-menu-item @click="displayKeys(selectedRowKeys)">
-                <stop-filled />
-                {{ $t('hosts.host_stop') }}
-              </a-menu-item>
-            </a-menu>
-          </template>
-          <a-button type="primary" :disabled="selectedRowKeys.length === 0">
-            {{ $t('common.action') }}
-          </a-button>
-        </a-dropdown>
-      </template>
-    </a-page-header>
-    <br />
-
-    <a-table
-      :row-key="hostColumns[0].dataIndex"
-      :columns="hostColumns"
-      :data-source="hosts"
-      :loading="loading"
-      :pagination="pagination"
-      :row-selection="{
-        selectedRowKeys,
-        onChange: (value: string[]) => (selectedRowKeys = value)
-      }"
-      @change="(v: any) => (currentPage = v.current)"
-    >
-      <template #headerCell="{ column }">
-        <span>{{ $t(column.title) }}</span>
-      </template>
-      <template #bodyCell="{ column, text }">
-        <template v-if="column.dataIndex === 'state'">
-          <check-circle-two-tone
-            v-if="text === 'Started'"
-            :two-tone-color="stateColor(text)"
-          />
-          <minus-circle-two-tone
-            v-else-if="text === 'Maintained'"
-            :two-tone-color="stateColor(text)"
-          />
-          <close-circle-two-tone v-else :two-tone-color="stateColor(text)" />
-        </template>
-        <template v-if="column.dataIndex === 'hostname'">
-          <router-link to="/dashboard"> {{ text }} </router-link>
-        </template>
-      </template>
-    </a-table>
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .host-page-header {
-    border: 1px solid rgb(235, 237, 240);
-
-    .host-selected-span {
-      margin-left: 8px;
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/pages/login/index.vue b/bigtop-manager-ui/src/pages/login/index.vue
index c5f5477..1c291c4 100644
--- a/bigtop-manager-ui/src/pages/login/index.vue
+++ b/bigtop-manager-ui/src/pages/login/index.vue
@@ -54,7 +54,7 @@
       }
 
       message.success(i18n.t('login.login_success'))
-      await router.push('/dashboard')
+      await router.push('/')
     } catch (e) {
       console.warn(e)
     } finally {
diff --git a/bigtop-manager-ui/src/pages/service/index.vue b/bigtop-manager-ui/src/pages/service/index.vue
deleted file mode 100644
index 4115852..0000000
--- a/bigtop-manager-ui/src/pages/service/index.vue
+++ /dev/null
@@ -1,498 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
--->
-
-<script setup lang="ts">
-  import { storeToRefs } from 'pinia'
-  import { useRoute } from 'vue-router'
-  import {
-    computed,
-    onMounted,
-    ref,
-    watch,
-    createVNode,
-    onUnmounted
-  } from 'vue'
-
-  import { useI18n } from 'vue-i18n'
-  import { CommonState, CurrState } from '@/enums/state'
-  import { type SelectProps, type MenuProps, Modal } from 'ant-design-vue'
-  import { DownOutlined, QuestionCircleOutlined } from '@ant-design/icons-vue'
-
-  import { useConfigStore } from '@/store/config'
-  import { useComponentStore } from '@/store/component'
-  import { useServiceStore } from '@/store/service'
-  import { useClusterStore } from '@/store/cluster'
-
-  import type { ServiceVO } from '@/api/service/types.ts'
-  import { ServiceConfigVO, TypeConfigVO } from '@/api/config/types.ts'
-  import { HostComponentVO } from '@/api/component/types.ts'
-  import { execCommand } from '@/api/command'
-
-  import Job from '@/components/job-info/job.vue'
-
-  interface Menu {
-    key: string
-    action: string
-    dicText: string
-  }
-
-  const menuOps: Menu[] = [
-    {
-      key: '1',
-      action: 'start',
-      dicText: 'service.start_service'
-    },
-    {
-      key: '2',
-      action: 'stop',
-      dicText: 'service.stop_service'
-    },
-    {
-      key: '3',
-      action: 'restart',
-      dicText: 'service.restart_service'
-    }
-  ]
-
-  const { t } = useI18n()
-  const route = useRoute()
-  const configStore = useConfigStore()
-  const componentStore = useComponentStore()
-  const serviceStore = useServiceStore()
-  const clusterStore = useClusterStore()
-
-  const { allConfigs } = storeToRefs(configStore)
-  const { hostComponents } = storeToRefs(componentStore)
-  const { installedServices } = storeToRefs(serviceStore)
-  const { clusterId } = storeToRefs(clusterStore)
-
-  const serviceConfigDesc = ref<SelectProps['options']>([])
-  const activeSelect = ref()
-  const currentConfigs = ref<TypeConfigVO[]>([])
-  const currentHostComponent = ref<HostComponentVO[]>([])
-  const serviceName = ref<string>(route.params.serviceName as string)
-  const currentConfigVersion = ref<number>()
-  const initConfigVersion = ref<number>()
-  const showConfigTip = ref<boolean>(false)
-  const activeConfig = ref()
-  const menuClicked = ref<Menu>()
-  const jobWindowOpened = ref(false)
-
-  const selectedService = computed(() => {
-    return installedServices.value.filter(
-      (service: ServiceVO) => service.serviceName === serviceName.value
-    )[0]
-  })
-
-  watch(hostComponents, (newVal) => {
-    currentHostComponent.value = newVal.filter(
-      (hc: HostComponentVO) => hc.serviceName === serviceName.value
-    )
-  })
-
-  watch(currentConfigs, (newVal) => {
-    activeConfig.value = newVal.length > 0 ? newVal[0].typeName : null
-  })
-
-  watch(allConfigs, (newVal) => {
-    allConfigs.value = newVal
-    loadCurrentConfigs()
-  })
-
-  watch(
-    () => route.params,
-    (params) => {
-      serviceName.value = params.serviceName as string
-      initServiceMeta()
-      componentStore.resumeIntervalFn()
-    }
-  )
-
-  const loadCurrentConfigs = () => {
-    serviceConfigDesc.value = allConfigs.value.reduce(
-      (pre, sc: ServiceConfigVO) => {
-        if (sc.serviceName === serviceName.value) {
-          pre?.push({
-            value: sc.version,
-            label: `Version: ${sc.version}`,
-            title: `${sc.configDesc}
-                  \n${sc.createTime}`
-          })
-        }
-        return pre
-      },
-      [] as SelectProps['options']
-    )
-    currentConfigVersion.value = serviceConfigDesc.value?.[0].value as number
-    currentConfigs.value = allConfigs.value.reduce(
-      (pre, sc: ServiceConfigVO) => {
-        if (
-          sc.serviceName === serviceName.value &&
-          currentConfigVersion.value === sc.version
-        ) {
-          const typeConfigs = sc.configs.map(({ typeName, properties }) => ({
-            typeName,
-            properties
-          }))
-          pre.push(...typeConfigs)
-        }
-        return pre
-      },
-      [] as TypeConfigVO[]
-    )
-  }
-
-  const handleChange: SelectProps['onChange'] = (value) => {
-    if (typeof value === 'object' && 'key' in value) {
-      currentConfigVersion.value = Number(value.key)
-    }
-    showConfigTip.value = currentConfigVersion.value !== initConfigVersion.value
-    loadCurrentConfigs()
-  }
-
-  const handleMenuClick: MenuProps['onClick'] = (e) => {
-    const menu = menuOps.find((menu) => menu.key == e.key)
-    const text = `${menu?.dicText}_warn`
-    menuClicked.value = menu
-    Modal.confirm({
-      title: t('common.confirm'),
-      icon: createVNode(QuestionCircleOutlined),
-      content: t(text, [selectedService.value.displayName]),
-      centered: true,
-      okText: t('common.confirm'),
-      cancelText: t('common.cancel'),
-      onOk: onOk
-    })
-  }
-
-  const onOk = async () => {
-    try {
-      if (!menuClicked.value) {
-        return
-      }
-      await execCommand({
-        command: menuClicked.value.action,
-        clusterId: clusterId.value,
-        commandLevel: 'service',
-        serviceCommands: [
-          {
-            serviceName: serviceName.value
-          }
-        ]
-      })
-      jobWindowOpened.value = true
-    } catch (error) {
-      console.log('error :>> ', error)
-    }
-  }
-
-  const initServiceMeta = async () => {
-    await configStore.loadAllConfigs()
-    showConfigTip.value = false
-    activeSelect.value = serviceConfigDesc.value?.[0]
-    currentConfigVersion.value = serviceConfigDesc.value?.[0].value as number
-    initConfigVersion.value = serviceConfigDesc.value?.[0].value as number
-  }
-
-  const stateColor = (type: keyof typeof CurrState) => {
-    if ([0, 1].includes(CurrState[type])) {
-      return CommonState['normal']
-    } else if (CurrState[type] === 2) {
-      return CommonState['maintained']
-    }
-    return CommonState['abnormal']
-  }
-
-  onMounted(() => {
-    initServiceMeta()
-    componentStore.resumeIntervalFn()
-  })
-
-  onUnmounted(() => {
-    componentStore.pauseIntervalFn()
-  })
-</script>
-
-<template>
-  <div>
-    <a-tabs>
-      <template #rightExtra>
-        <a-dropdown :trigger="['click']" placement="bottomRight">
-          <template #overlay>
-            <a-menu @click="handleMenuClick">
-              <a-menu-item v-for="item in menuOps" :key="item.key">
-                <svg-icon :name="item.action" />
-                <span>{{ $t(item.dicText) }}</span>
-              </a-menu-item>
-            </a-menu>
-          </template>
-          <a-button type="primary">
-            {{ $t('common.action') }}
-            <down-outlined />
-          </a-button>
-        </a-dropdown>
-      </template>
-      <a-tab-pane key="summary">
-        <template #tab>{{ $t('service.summary') }}</template>
-        <a-layout-content class="summary-layout">
-          <div class="left-section">
-            <h2>{{ $t('service.components') }}</h2>
-            <div v-if="currentHostComponent.length > 0" class="summary-ctx">
-              <template
-                v-for="item in currentHostComponent"
-                :key="`${item.id}`"
-              >
-                <div class="card">
-                  <div class="service-name">
-                    <router-link :to="'/services/' + serviceName">
-                      {{ item.displayName }}
-                    </router-link>
-                    <a-tag
-                      :bordered="false"
-                      style="color: rgb(145 134 134 / 90%)"
-                    >
-                      {{ item.category }}
-                    </a-tag>
-                  </div>
-                  <div class="comp-info">
-                    <div class="host-name">{{ item.hostname }}</div>
-                  </div>
-                  <footer>
-                    <div class="comp-state">
-                      <dot-state
-                        :color="stateColor(item.state)"
-                        class="dot-rest"
-                      >
-                        <span class="comp-state-text">{{ item.state }}</span>
-                      </dot-state>
-                    </div>
-                  </footer>
-                </div>
-              </template>
-            </div>
-          </div>
-          <div class="right-section">
-            <h2>{{ $t('service.quick_links') }}</h2>
-            <ul
-              v-if="
-                selectedService.quickLinks &&
-                selectedService.quickLinks.length > 0
-              "
-            >
-              <li v-for="link in selectedService.quickLinks" :key="link.url">
-                <a :href="link.url" target="_blank">{{ link.displayName }}</a>
-              </li>
-            </ul>
-            <div v-else class="no-link-text">{{ $t('service.no_link') }}</div>
-          </div>
-        </a-layout-content>
-      </a-tab-pane>
-
-      <a-tab-pane key="config" force-render>
-        <template #tab>{{ $t('service.config') }}</template>
-        <a-space>
-          <a-select
-            v-model:value="activeSelect"
-            label-in-value
-            :options="serviceConfigDesc"
-            @change="handleChange"
-          ></a-select>
-          <template v-if="showConfigTip">
-            <a-button type="primary">Not Current Config</a-button></template
-          >
-        </a-space>
-
-        <a-divider />
-        <a-collapse v-model:active-key="activeConfig" ghost accordion>
-          <a-collapse-panel
-            v-for="config in currentConfigs"
-            :key="config.typeName"
-            class="panel"
-            :header="config.typeName"
-          >
-            <div
-              v-for="property in config.properties"
-              :key="property.name"
-              class="config-item"
-            >
-              <div class="config-item-key">
-                {{ property.displayName ?? property.name }}
-              </div>
-              <a-tooltip class="config-item-value">
-                <template #title>
-                  {{ property.desc }}
-                </template>
-                <a-textarea
-                  v-if="property.attrs && property.attrs.type === 'longtext'"
-                  v-model:value="property.value"
-                  :rows="10"
-                />
-                <a-input v-else v-model:value="property.value" />
-              </a-tooltip>
-            </div>
-          </a-collapse-panel>
-        </a-collapse>
-      </a-tab-pane>
-    </a-tabs>
-    <job v-model:visible="jobWindowOpened" />
-  </div>
-</template>
-
-<style scoped lang="scss">
-  .dot-rest {
-    @include flexbox($justify: center, $align: center);
-  }
-
-  .summary-layout {
-    display: flex;
-
-    .left-section {
-      width: 82%;
-
-      .a-card {
-        background-color: rgb(128, 171, 209);
-      }
-
-      border-right: 2px solid #eee;
-    }
-
-    .right-section {
-      width: 18%;
-      min-width: 13rem;
-      height: 100%;
-      padding: 0 1rem;
-      box-sizing: border-box;
-      min-height: 33.75rem;
-
-      .no-link-text {
-        color: #999999;
-        padding: 0.25rem;
-      }
-
-      ul {
-        list-style: none;
-        margin: 0;
-        padding: 0;
-
-        li {
-          a {
-            display: flex;
-            padding: 0.25rem;
-          }
-        }
-      }
-    }
-
-    .summary-ctx {
-      @include flexbox($wrap: wrap);
-      box-sizing: border-box;
-
-      .card {
-        margin: 0.75rem;
-        padding: 0.75rem;
-        border-radius: 0.5rem;
-        position: relative;
-        flex: 0 1 calc((100% / 3) - 1.5rem);
-        min-width: calc((100% / 3) - 1.5rem);
-        box-shadow: 0 0 2px rgba(0, 0, 0, 0.1);
-        overflow: auto;
-
-        &:hover {
-          box-shadow: 0 0 6px rgba(0, 0, 0, 0.16);
-          transform: scale(1.002);
-          transition: all 0.3s;
-        }
-
-        .service-name {
-          font-size: 1.06rem;
-          font-weight: 600;
-          margin-bottom: 0.375rem;
-          @include flexbox($justify: space-between, $align: center);
-        }
-
-        .comp-info {
-          @include flexbox($justify: center);
-          margin-bottom: 1.25rem;
-
-          .host-name {
-            width: 80%;
-            font-size: 0.8rem;
-            color: #797878d0;
-            font-weight: 500;
-            flex: 1;
-          }
-        }
-
-        footer {
-          @include flexbox($justify: space-between, $align: center);
-          .comp-state {
-            font-size: 1rem;
-            align-items: flex-end;
-
-            &-text {
-              color: #888;
-            }
-          }
-        }
-      }
-    }
-  }
-
-  .container {
-    @include flexbox(
-      $direction: column,
-      $justify: space-between,
-      $align: center
-    );
-    align-content: center;
-    height: 100%;
-
-    .title {
-      font-size: 1.5rem;
-      line-height: 2rem;
-      margin-bottom: 1rem;
-    }
-
-    .content {
-      width: 100%;
-      height: 100%;
-      margin-top: 1rem;
-      overflow-y: auto;
-
-      .panel {
-        text-align: start;
-
-        .config-item {
-          @include flexbox($justify: start, $align: center);
-          margin-bottom: 1rem;
-
-          .config-item-key {
-            width: 20%;
-            text-align: start;
-            margin-left: 2rem;
-          }
-
-          .config-item-value {
-            width: 75%;
-          }
-        }
-      }
-    }
-  }
-</style>
diff --git a/bigtop-manager-ui/src/assets/images/svg/left.svg b/bigtop-manager-ui/src/pages/system-mange/model/index.vue
similarity index 75%
rename from bigtop-manager-ui/src/assets/images/svg/left.svg
rename to bigtop-manager-ui/src/pages/system-mange/model/index.vue
index 01ee633..787cb03 100644
--- a/bigtop-manager-ui/src/assets/images/svg/left.svg
+++ b/bigtop-manager-ui/src/pages/system-mange/model/index.vue
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
-  <!--
+<!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
   ~ distributed with this work for additional information
@@ -17,7 +16,11 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
 -->
-<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
-  xmlns="http://www.w3.org/2000/svg">
-  <path d="M31 36L19 24L31 12" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
-</svg>
\ No newline at end of file
+
+<script setup lang="ts"></script>
+
+<template>
+  <div>model list</div>
+</template>
+
+<style scoped></style>
diff --git a/bigtop-manager-ui/src/router/guard.ts b/bigtop-manager-ui/src/router/guard.ts
index dc95599..6063981 100644
--- a/bigtop-manager-ui/src/router/guard.ts
+++ b/bigtop-manager-ui/src/router/guard.ts
@@ -18,31 +18,10 @@
  */
 
 import type { Router } from 'vue-router'
-import type { ServiceVO } from '@/api/service/types.ts'
-import { storeToRefs } from 'pinia'
-import { useServiceStore } from '@/store/service'
-import { useClusterStore } from '@/store/cluster'
-function setCommonGuard(router: Router) {
-  router.beforeEach(async (to) => {
-    if (to.name === 'services') {
-      const clusterStore = useClusterStore()
-      const serviceStore = useServiceStore()
-      const { clusterId } = storeToRefs(clusterStore)
-      const { installedServices } = storeToRefs(serviceStore)
-
-      if (clusterId.value === 0) {
-        await clusterStore.loadClusters()
-        await serviceStore.loadServices()
-      }
 
-      const installedServiceNames = installedServices.value.map(
-        (service: ServiceVO) => service.serviceName
-      )
-
-      if (!installedServiceNames.includes(to.params.serviceName as string)) {
-        return '/404'
-      }
-    }
+function setCommonGuard(router: Router) {
+  router.beforeEach(async (_to, _from, next) => {
+    next()
   })
 }
 
diff --git a/bigtop-manager-ui/src/router/routes/index.ts b/bigtop-manager-ui/src/router/routes/index.ts
index 23e4d8d..86d5908 100644
--- a/bigtop-manager-ui/src/router/routes/index.ts
+++ b/bigtop-manager-ui/src/router/routes/index.ts
@@ -28,13 +28,15 @@ export const dynamicRoutes: RouteRecordRaw[] =
   mergeRouteModules(dynamicRoutesFiles)
 
 const routes: RouteRecordRaw[] = [
-  { path: '/login', component: () => import('@/pages/login/index.vue') },
+  {
+    path: '/login',
+    component: () => import('@/pages/login/index.vue')
+  },
   {
     path: '/',
-    redirect: '/dashboard',
-    component: () => import('@/layouts/index.vue'),
-    children: [...dynamicRoutes]
+    redirect: '/cluster-mange/'
   },
+  ...dynamicRoutes,
   {
     path: '/:pathMatch(.*)',
     component: () => import('@/pages/error/404.vue')
diff --git a/bigtop-manager-ui/src/router/routes/modules/clusters.ts b/bigtop-manager-ui/src/router/routes/modules/clusters.ts
index c1afab5..4830126 100644
--- a/bigtop-manager-ui/src/router/routes/modules/clusters.ts
+++ b/bigtop-manager-ui/src/router/routes/modules/clusters.ts
@@ -18,36 +18,99 @@
  */
 
 import { RouteRecordRaw } from 'vue-router'
-import {
-  SettingOutlined,
-  BarsOutlined,
-  UserOutlined
-} from '@ant-design/icons-vue'
-import { h } from 'vue'
+import pageView from '@/layouts/index.vue'
 
 const routes: RouteRecordRaw[] = [
   {
-    path: '/cluster/',
+    path: '/cluster-mange',
+    component: pageView,
+    redirect: '/cluster-mange/clusters',
     meta: {
-      title: 'Cluster',
-      icon: h(SettingOutlined)
+      title: 'menu.cluster'
     },
     children: [
       {
-        path: 'stack',
-        component: () => import('@/pages/cluster/stack/index.vue'),
+        name: 'Default',
+        path: 'default',
+        component: () => import('@/layouts/default.vue'),
         meta: {
-          title: 'Stack',
-          icon: h(BarsOutlined)
+          hidden: true
         }
       },
       {
-        path: 'account',
-        component: () => import('@/pages/cluster/account/index.vue'),
+        name: 'Clusters',
+        path: 'clusters',
+        redirect: '',
         meta: {
-          title: 'Account',
-          icon: h(UserOutlined)
+          icon: 'clusters',
+          title: 'menu.cluster'
+        },
+        children: [
+          {
+            name: 'ClusterDetail',
+            path: ':cluster/:id',
+            component: () => import('@/pages/cluster-mange/cluster/index.vue'),
+            meta: {
+              hidden: true
+            }
+          },
+          {
+            name: 'ClusterCreate',
+            path: 'create',
+            component: () => import('@/pages/cluster-mange/cluster/create.vue'),
+            meta: {
+              hidden: true
+            }
+          }
+        ]
+      },
+      {
+        name: 'Infrastructures',
+        path: 'infrastructures',
+        component: () =>
+          import('@/pages/cluster-mange/infrastructures/index.vue'),
+        meta: {
+          icon: 'infrastructures',
+          title: 'menu.infra'
+        }
+      },
+      {
+        name: 'Components',
+        path: 'components',
+        component: () => import('@/pages/cluster-mange/components/index.vue'),
+        meta: {
+          icon: 'components',
+          title: 'menu.component'
         }
+      },
+      {
+        name: 'Hosts',
+        path: 'hosts',
+        redirect: '/cluster-mange/hosts/list',
+        meta: {
+          icon: 'hosts',
+          title: 'menu.host'
+        },
+        children: [
+          {
+            name: 'List',
+            path: 'list',
+            component: () => import('@/pages/cluster-mange/hosts/index.vue'),
+            meta: {
+              hidden: true,
+              activeMenu: '/cluster-mange/hosts'
+            }
+          },
+          {
+            name: 'HostCreate',
+            path: 'addhost',
+            component: () => import('@/pages/cluster-mange/hosts/create.vue'),
+            meta: {
+              hidden: true,
+              activeMenu: '/cluster-mange/hosts'
+            }
+          }
+        ]
       }
     ]
   }
diff --git a/bigtop-manager-ui/src/router/routes/modules/dashboard.ts b/bigtop-manager-ui/src/router/routes/modules/dashboard.ts
deleted file mode 100644
index d3bf5f4..0000000
--- a/bigtop-manager-ui/src/router/routes/modules/dashboard.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { RouteRecordRaw } from 'vue-router'
-import { PieChartOutlined } from '@ant-design/icons-vue'
-import { h } from 'vue'
-
-const routes: RouteRecordRaw[] = [
-  {
-    path: '/dashboard',
-    component: () => import('@/pages/dashboard/index.vue'),
-    meta: {
-      title: 'Dashboard',
-      icon: h(PieChartOutlined)
-    }
-  }
-]
-
-export { routes }
diff --git a/bigtop-manager-ui/src/router/routes/modules/hosts.ts b/bigtop-manager-ui/src/router/routes/modules/hosts.ts
deleted file mode 100644
index ec8771e..0000000
--- a/bigtop-manager-ui/src/router/routes/modules/hosts.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { RouteRecordRaw } from 'vue-router'
-import { DesktopOutlined } from '@ant-design/icons-vue'
-import { h } from 'vue'
-
-const routes: RouteRecordRaw[] = [
-  {
-    path: '/hosts',
-    component: () => import('@/pages/hosts/index.vue'),
-    meta: {
-      title: 'Hosts',
-      icon: h(DesktopOutlined)
-    }
-  }
-]
-
-export { routes }
diff --git a/bigtop-manager-ui/src/router/routes/modules/services.ts b/bigtop-manager-ui/src/router/routes/modules/system.ts
similarity index 69%
rename from bigtop-manager-ui/src/router/routes/modules/services.ts
rename to bigtop-manager-ui/src/router/routes/modules/system.ts
index 9bcb738..849dc35 100644
--- a/bigtop-manager-ui/src/router/routes/modules/services.ts
+++ b/bigtop-manager-ui/src/router/routes/modules/system.ts
@@ -18,18 +18,27 @@
  */
 
 import { RouteRecordRaw } from 'vue-router'
-import { AppstoreOutlined } from '@ant-design/icons-vue'
-import { h } from 'vue'
+import pageView from '@/layouts/index.vue'
 
 const routes: RouteRecordRaw[] = [
   {
-    name: 'services',
-    path: '/services/:serviceName',
-    component: () => import('@/pages/service/index.vue'),
+    path: '/system-mange/',
+    component: pageView,
+    redirect: '/system-mange/model',
     meta: {
-      title: 'Services',
-      icon: h(AppstoreOutlined)
-    }
+      title: 'menu.system'
+    },
+    children: [
+      {
+        name: 'Model',
+        path: 'model',
+        component: () => import('@/pages/system-mange/model/index.vue'),
+        meta: {
+          icon: 'model',
+          title: 'menu.llm_config'
+        }
+      }
+    ]
   }
 ]
 
diff --git a/bigtop-manager-ui/src/router/routes/modules/user.ts b/bigtop-manager-ui/src/router/routes/modules/user.ts
index 9d0f95c..1e23e62 100644
--- a/bigtop-manager-ui/src/router/routes/modules/user.ts
+++ b/bigtop-manager-ui/src/router/routes/modules/user.ts
@@ -18,19 +18,14 @@
  */
 
 import { RouteRecordRaw } from 'vue-router'
-import {
-  SettingOutlined,
-  UserOutlined,
-  ProfileOutlined
-} from '@ant-design/icons-vue'
-import { h } from 'vue'
+import pageView from '@/layouts/index.vue'
 
 const routes: RouteRecordRaw[] = [
   {
     path: '/user/',
+    redirect: '/user/profile',
+    component: pageView,
     meta: {
-      title: 'user',
-      icon: h(UserOutlined),
       hidden: true
     },
     children: [
@@ -38,16 +33,14 @@ const routes: RouteRecordRaw[] = [
         path: 'profile',
         component: () => import('@/pages/user/profile/index.vue'),
         meta: {
-          title: 'Profile',
-          icon: h(ProfileOutlined)
+          title: 'Profile'
         }
       },
       {
         path: 'settings',
         component: () => import('@/pages/user/settings/index.vue'),
         meta: {
-          title: 'Settings',
-          icon: h(SettingOutlined)
+          title: 'Settings'
         }
       }
     ]
diff --git a/bigtop-manager-ui/src/store/cluster/index.ts b/bigtop-manager-ui/src/store/cluster/index.ts
index 51a37ef..afde4fa 100644
--- a/bigtop-manager-ui/src/store/cluster/index.ts
+++ b/bigtop-manager-ui/src/store/cluster/index.ts
@@ -20,30 +20,64 @@
 import { defineStore } from 'pinia'
 import { ClusterVO } from '@/api/cluster/types.ts'
 import { ref } from 'vue'
-import { getClusters } from '@/api/cluster'
+// import { getClusters } from '@/api/cluster'
 
 export const useClusterStore = defineStore(
   'cluster',
   () => {
     const clusters = ref<ClusterVO[]>([])
-    const selectedCluster = ref<ClusterVO | undefined>()
-    const clusterId = ref<number>(0)
+    const count = ref(0)
 
-    const loadClusters = async () => {
-      clusters.value = await getClusters()
-      if (clusters.value.length > 0) {
-        selectedCluster.value = clusters.value.filter(
-          (cluster) => cluster.selected
-        )[0]
-        clusterId.value = selectedCluster.value?.id
+    const generateRandomDataArray = () => {
+      const dataArray = []
+      for (let i = 0; i < count.value; i++) {
+        dataArray.push({
+          id: i,
+          clusterName: `Cluster-${i}`,
+          clusterType: Math.floor(Math.random() * 10),
+          stackName: `Stack-${i}`,
+          stackVersion: `Version-${i}`,
+          selected: Math.random() < 0.5
+        })
+      }
+      return dataArray
+    }
+
+    const addCluster = async () => {
+      count.value = count.value + 1
+      await loadClusters()
+    }
+
+    const delCluster = async () => {
+      if (count.value < 0) {
+        count.value = 0
+        return
       }
+      count.value = count.value - 1
+      await loadClusters()
+    }
 
-      console.log('clusters.value: ', clusters.value)
-      console.log('selectedCluster.value: ', selectedCluster.value)
-      console.log('clusterId.value: ', clusterId.value)
+    const loadClusters = async () => {
+      // clusters.value = await getClusters()
+      clusters.value = (await new Promise((resolve) => {
+        setTimeout(() => {
+          resolve(generateRandomDataArray())
+        }, 1000)
+      })) as ClusterVO[]
     }
 
-    return { loadClusters, clusters, selectedCluster, clusterId }
+    return {
+      clusters,
+      count,
+      addCluster,
+      delCluster,
+      loadClusters
+    }
   },
-  { persist: false }
+  {
+    persist: {
+      storage: sessionStorage,
+      paths: ['clusters', 'count']
+    }
+  }
 )
diff --git a/bigtop-manager-ui/src/store/component/index.ts b/bigtop-manager-ui/src/store/component/index.ts
deleted file mode 100644
index c301f17..0000000
--- a/bigtop-manager-ui/src/store/component/index.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { defineStore, storeToRefs } from 'pinia'
-import { ref, shallowRef, watch } from 'vue'
-import { useClusterStore } from '@/store/cluster'
-import { HostComponentVO } from '@/api/component/types.ts'
-import { getHostComponents } from '@/api/component'
-import { Pausable, useIntervalFn } from '@vueuse/core'
-import { MONITOR_SCHEDULE_INTERVAL } from '@/utils/constant.ts'
-
-export const useComponentStore = defineStore(
-  'component',
-  () => {
-    const clusterStore = useClusterStore()
-    const { clusterId } = storeToRefs(clusterStore)
-    const hostComponents = shallowRef<HostComponentVO[]>([])
-    const intervalFn = ref<Pausable | undefined>()
-
-    watch(clusterId, async () => {
-      await loadHostComponents()
-    })
-
-    const loadHostComponents = async () => {
-      hostComponents.value = await getHostComponents(clusterId.value)
-    }
-
-    intervalFn.value = useIntervalFn(
-      async () => {
-        await loadHostComponents()
-      },
-      MONITOR_SCHEDULE_INTERVAL,
-      { immediate: false, immediateCallback: true }
-    )
-
-    const resumeIntervalFn = () => intervalFn.value?.resume()
-    const pauseIntervalFn = () => intervalFn.value?.pause()
-
-    return {
-      hostComponents,
-      loadHostComponents,
-      resumeIntervalFn,
-      pauseIntervalFn
-    }
-  },
-  { persist: false }
-)
diff --git a/bigtop-manager-ui/src/store/config/index.ts b/bigtop-manager-ui/src/store/config/index.ts
deleted file mode 100644
index 81ef990..0000000
--- a/bigtop-manager-ui/src/store/config/index.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { defineStore, storeToRefs } from 'pinia'
-import { shallowRef, watch } from 'vue'
-import { useClusterStore } from '@/store/cluster'
-import { ServiceConfigVO } from '@/api/config/types.ts'
-import { getAllConfigs, getLatestConfigs } from '@/api/config'
-
-export const useConfigStore = defineStore(
-  'config',
-  () => {
-    const clusterStore = useClusterStore()
-    const { clusterId } = storeToRefs(clusterStore)
-    const latestConfigs = shallowRef<ServiceConfigVO[]>([])
-    const allConfigs = shallowRef<ServiceConfigVO[]>([])
-
-    watch(clusterId, async () => {
-      await loadLatestConfigs()
-    })
-
-    const loadLatestConfigs = async () => {
-      if (clusterId.value !== 0) {
-        latestConfigs.value = await getLatestConfigs(clusterId.value)
-      }
-    }
-
-    watch(clusterId, async () => {
-      await loadAllConfigs()
-    })
-
-    const loadAllConfigs = async () => {
-      allConfigs.value = await getAllConfigs(clusterId.value)
-    }
-
-    return { latestConfigs, loadLatestConfigs, allConfigs, loadAllConfigs }
-  },
-  { persist: false }
-)
diff --git a/bigtop-manager-ui/src/store/host/index.ts b/bigtop-manager-ui/src/store/host/index.ts
deleted file mode 100644
index 458bee0..0000000
--- a/bigtop-manager-ui/src/store/host/index.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { defineStore, storeToRefs } from 'pinia'
-import { ref, watch } from 'vue'
-import { HostVO } from '@/api/hosts/types.ts'
-import { getHosts } from '@/api/hosts'
-import { formatFromByte } from '@/utils/storage.ts'
-import { useClusterStore } from '@/store/cluster'
-import { MONITOR_SCHEDULE_INTERVAL } from '@/utils/constant.ts'
-import { useIntervalFn, Pausable } from '@vueuse/core'
-
-export const useHostStore = defineStore(
-  'host',
-  () => {
-    const clusterStore = useClusterStore()
-
-    const { clusterId } = storeToRefs(clusterStore)
-    const hosts = ref<HostVO[]>([])
-    const loading = ref<boolean>(true)
-    const intervalFn = ref<Pausable | undefined>()
-
-    watch(clusterId, async () => {
-      await refreshHosts()
-    })
-
-    const refreshHosts = async () => {
-      if (clusterId.value !== 0) {
-        const res = await getHosts(clusterId.value)
-        hosts.value = res.map((v: HostVO) => {
-          v.totalMemorySize = formatFromByte(parseInt(v.totalMemorySize))
-          v.freeMemorySize = formatFromByte(parseInt(v.freeMemorySize))
-          v.freeDisk = formatFromByte(parseInt(v.freeDisk))
-          v.totalDisk = formatFromByte(parseInt(v.totalDisk))
-
-          return v
-        })
-
-        if (loading.value) {
-          loading.value = false
-        }
-      }
-    }
-
-    intervalFn.value = useIntervalFn(
-      async () => {
-        await refreshHosts()
-      },
-      MONITOR_SCHEDULE_INTERVAL,
-      { immediate: false, immediateCallback: true }
-    )
-
-    const resumeIntervalFn = () => intervalFn.value?.resume()
-    const pauseIntervalFn = () => intervalFn.value?.pause()
-
-    return { hosts, loading, refreshHosts, resumeIntervalFn, pauseIntervalFn }
-  },
-  { persist: false }
-)
diff --git a/bigtop-manager-ui/src/store/job/index.ts b/bigtop-manager-ui/src/store/job/index.ts
deleted file mode 100644
index 39d68f5..0000000
--- a/bigtop-manager-ui/src/store/job/index.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { defineStore, storeToRefs } from 'pinia'
-import { computed, ref, shallowRef, watch } from 'vue'
-import { useClusterStore } from '@/store/cluster'
-import { JobVO } from '@/api/job/types.ts'
-import { getJobs } from '@/api/job'
-import { Pausable, useIntervalFn } from '@vueuse/core'
-import { MONITOR_SCHEDULE_INTERVAL } from '@/utils/constant.ts'
-
-export const useJobStore = defineStore(
-  'job',
-  () => {
-    const clusterStore = useClusterStore()
-    const { clusterId } = storeToRefs(clusterStore)
-    const jobs = shallowRef<JobVO[]>([])
-    const loadingJobs = ref<boolean>(true)
-    const intervalFn = ref<Pausable | undefined>()
-
-    const processJobNum = computed(() => {
-      return jobs.value.filter(
-        (job: JobVO) => job.state === 'Processing' || job.state === 'Pending'
-      ).length
-    })
-
-    const loadJobs = async () => {
-      const { content } = await getJobs(clusterId.value, {
-        pageNum: 1,
-        pageSize: 10
-      })
-      jobs.value = content
-    }
-
-    watch(clusterId, async () => {
-      if (clusterId.value != 0) {
-        loadingJobs.value = true
-        await loadJobs()
-      }
-    })
-
-    intervalFn.value = useIntervalFn(
-      async () => {
-        await loadJobs()
-      },
-      MONITOR_SCHEDULE_INTERVAL,
-      { immediate: false, immediateCallback: true }
-    )
-    const resumeIntervalFn = () => intervalFn.value?.resume()
-    const pauseIntervalFn = () => intervalFn.value?.pause()
-
-    return {
-      jobs,
-      processJobNum,
-      loadingJobs,
-      loadJobs,
-      resumeIntervalFn,
-      pauseIntervalFn
-    }
-  },
-  { persist: false }
-)
diff --git a/bigtop-manager-ui/src/store/menu/index.ts b/bigtop-manager-ui/src/store/menu/index.ts
new file mode 100644
index 0000000..d83f56b
--- /dev/null
+++ b/bigtop-manager-ui/src/store/menu/index.ts
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { computed, ref, watchEffect } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { dynamicRoutes as dr } from '@/router/routes/index'
+import { defineStore, storeToRefs } from 'pinia'
+import { useClusterStore } from '@/store/cluster/index'
+import lodash from 'lodash'
+
+export const SPECIAL_ROUTE_NAME = 'Clusters'
+export const SPECIAL_ROUTE_PATH = '/cluster-mange/clusters'
+
+export interface MenuItem {
+  icon: string
+  key: string
+  label: string
+  title: string
+  name?: string
+  activeMenu?: string
+  children?: MenuItem[]
+}
+
+export const useMenuStore = defineStore(
+  'menu',
+  () => {
+    const router = useRouter()
+    const route = useRoute()
+    const clusterStore = useClusterStore()
+    const { clusters } = storeToRefs(clusterStore)
+
+    const baseRoutesMap = ref<Map<string, MenuItem[]>>(new Map())
+    const headerMenus = ref(dr.filter((v) => v.meta?.title && !v.meta.hidden))
+    const headerSelectedKey = ref(headerMenus.value[0].path)
+
+    const hasCluster = computed(() => clusters.value.length > 0)
+    const isClusterCreateVisible = computed(() =>
+      SPECIAL_ROUTE_PATH.includes(route.matched[0].path)
+    )
+    const siderMenus = computed((): MenuItem[] => {
+      const siderMenuTemplate = baseRoutesMap.value.get(headerSelectedKey.value)
+      const formatSider = lodash.cloneDeep([...(siderMenuTemplate || [])])
+      if (formatSider) {
+        return hasCluster.value
+          ? addSiderItemByClusters(formatSider as MenuItem[])
+          : formatSider
+      }
+      return []
+    })
+
+    const siderMenuSelectedKey = ref(findActivePath(siderMenus.value[0]))
+
+    watchEffect(() => {
+      // resolve highlight menu
+      const activeMenu = route.meta.activeMenu || route.path
+      headerSelectedKey.value = route.matched[0].path
+      if (route.name == SPECIAL_ROUTE_NAME) {
+        if (hasCluster.value) {
+          siderMenuSelectedKey.value = findActivePath(siderMenus.value[0])
+          siderMenuSelectedKey.value && router.push(siderMenuSelectedKey.value)
+        } else {
+          siderMenuSelectedKey.value = ''
+          router.replace({ name: 'Default' })
+        }
+      } else {
+        siderMenuSelectedKey.value = activeMenu
+      }
+    })
+
+    function addSiderItemByClusters(formatSider: MenuItem[]) {
+      return formatSider.map((item) => {
+        if (item.name == SPECIAL_ROUTE_NAME) {
+          item.children = clusters.value.map((v) => {
+            return {
+              icon: '',
+              key: `${item.key}/${v.clusterName}/${v.id}`,
+              label: v.clusterName,
+              title: v.clusterName,
+              activeMenu: item.key
+            }
+          })
+        }
+        return item
+      })
+    }
+
+    function formatRouteToMenu(tree: any[], upPath = ''): MenuItem[] {
+      return tree
+        .filter(({ meta }) => !meta?.hidden)
+        .map(({ path, name, meta, children }) => {
+          const fullPath = `${upPath}${path}`
+          return {
+            icon: meta.icon,
+            key: fullPath,
+            label: meta.title || '',
+            title: meta.title || '',
+            name: name || '',
+            children:
+              children && children.length > 0
+                ? formatRouteToMenu(children, fullPath)
+                : []
+          }
+        })
+    }
+
+    function setBaseRoutesMap() {
+      dr.forEach((route) => {
+        if (!route.meta?.hidden) {
+          const exist = baseRoutesMap.value.get(route.path) || []
+          baseRoutesMap.value.set(route.path, [
+            ...exist,
+            ...formatRouteToMenu(route.children || [], route.path)
+          ])
+        }
+      })
+    }
+
+    function findActivePath(menu: MenuItem): string {
+      return menu?.children && menu?.children.length > 0
+        ? findActivePath(menu.children[0])
+        : menu?.key
+    }
+
+    function onHeaderClick(key: string) {
+      headerSelectedKey.value = key
+      if (!hasCluster.value && route.name == SPECIAL_ROUTE_NAME) {
+        return
+      }
+      siderMenuSelectedKey.value = findActivePath(siderMenus.value[0])
+      router.push(siderMenuSelectedKey.value)
+    }
+
+    function onSiderClick(key: string) {
+      siderMenuSelectedKey.value = key
+      router.push(key)
+    }
+
+    async function updateSiderMenu(isDelete = false) {
+      isDelete
+        ? await clusterStore.delCluster()
+        : await clusterStore.addCluster()
+      siderMenuSelectedKey.value =
+        siderMenus.value[0].children?.at(-1)?.key || SPECIAL_ROUTE_PATH
+      router.push(siderMenuSelectedKey.value)
+    }
+
+    return {
+      headerMenus,
+      siderMenus,
+      headerSelectedKey,
+      siderMenuSelectedKey,
+      setBaseRoutesMap,
+      onHeaderClick,
+      onSiderClick,
+      updateSiderMenu,
+      isClusterCreateVisible
+    }
+  },
+  {
+    persist: false
+  }
+)
diff --git a/bigtop-manager-ui/src/store/service/index.ts b/bigtop-manager-ui/src/store/service/index.ts
deleted file mode 100644
index 8440cb7..0000000
--- a/bigtop-manager-ui/src/store/service/index.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { defineStore, storeToRefs } from 'pinia'
-import { computed, ref, watch } from 'vue'
-import { ServiceVO } from '@/api/service/types.ts'
-import { useClusterStore } from '@/store/cluster'
-import { getService } from '@/api/service'
-import { MergedServiceVO } from '@/store/service/types.ts'
-import { useStackStore } from '@/store/stack'
-
-export const useServiceStore = defineStore(
-  'service',
-  () => {
-    const clusterStore = useClusterStore()
-    const stackStore = useStackStore()
-    const { clusterId } = storeToRefs(clusterStore)
-    const { currentStack } = storeToRefs(stackStore)
-
-    const installedServices = ref<ServiceVO[]>([])
-    const loadingServices = ref<boolean>(true)
-    const mergedServices = computed(() => {
-      const mergedServices: MergedServiceVO[] = []
-      const installedServiceNames: string[] = []
-      installedServices.value.forEach((service) => {
-        mergedServices.push({
-          installed: true,
-          ...service
-        })
-
-        installedServiceNames.push(service.serviceName)
-      })
-
-      currentStack.value?.services.forEach((service) => {
-        if (!installedServiceNames.includes(service.serviceName)) {
-          mergedServices.push({
-            installed: false,
-            ...service
-          })
-        }
-      })
-
-      return mergedServices
-    })
-
-    const loadServices = async () => {
-      if (clusterId.value != 0) {
-        installedServices.value = await getService(clusterId.value)
-        loadingServices.value = false
-      }
-    }
-
-    watch(clusterId, async () => {
-      if (clusterId.value != 0) {
-        loadingServices.value = true
-        await loadServices()
-      }
-    })
-
-    return {
-      installedServices,
-      loadingServices,
-      mergedServices,
-      loadServices
-    }
-  },
-  { persist: false }
-)
diff --git a/bigtop-manager-ui/src/store/service/types.ts b/bigtop-manager-ui/src/store/service/types.ts
deleted file mode 100644
index 0b53944..0000000
--- a/bigtop-manager-ui/src/store/service/types.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { ServiceVO } from '@/api/service/types.ts'
-
-export type MergedServiceVO = ServiceVO & {
-  installed: boolean
-}
diff --git a/bigtop-manager-ui/src/store/stack/index.ts b/bigtop-manager-ui/src/store/stack/index.ts
deleted file mode 100644
index e969843..0000000
--- a/bigtop-manager-ui/src/store/stack/index.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { defineStore, storeToRefs } from 'pinia'
-import { getStackComponents, getStackConfigs, getStacks } from '@/api/stack'
-import { computed, shallowReactive, shallowRef, watch } from 'vue'
-import { StackInfo, StackOptionProps } from '@/store/stack/types.ts'
-import { useClusterStore } from '@/store/cluster'
-import { StackVO } from '@/api/stack/types.ts'
-import { ServiceConfigVO } from '@/api/config/types.ts'
-import { ServiceComponentVO } from '@/api/component/types.ts'
-import { RepoVO } from '@/api/repo/types.ts'
-import { ServiceVO } from '@/api/service/types.ts'
-
-export const useStackStore = defineStore(
-  'stack',
-  () => {
-    const clusterStore = useClusterStore()
-    const { clusterId, selectedCluster } = storeToRefs(clusterStore)
-    const stackOptions = shallowRef<StackOptionProps[]>([])
-    const stackServices = shallowReactive<Record<string, ServiceVO[]>>({})
-    const stackRepos = shallowReactive<Record<string, RepoVO[]>>({})
-    const stackComponents = shallowRef<ServiceComponentVO[]>([])
-    const stackConfigs = shallowRef<ServiceConfigVO[]>([])
-    const initialized = shallowRef(false)
-
-    const currentStack = computed<StackInfo>(() => {
-      const cluster = selectedCluster.value
-      const name = [cluster?.stackName, cluster?.stackVersion].join('-')
-      const services = stackServices[name]
-
-      return {
-        name: name,
-        services: services ? services : []
-      }
-    })
-
-    watch(clusterId, async () => {
-      const stackName = selectedCluster.value?.stackName as string
-      const stackVersion = selectedCluster.value?.stackVersion as string
-
-      stackComponents.value = await getStackComponents(stackName, stackVersion)
-      stackConfigs.value = await getStackConfigs(stackName, stackVersion)
-    })
-
-    const initStacks = async () => {
-      if (!initialized.value) {
-        const stackVOList: StackVO[] = await getStacks()
-        const stacks: StackOptionProps[] = []
-        stackVOList.forEach((stackVO) => {
-          const fullStackName = stackVO.stackName + '-' + stackVO.stackVersion
-          stackServices[fullStackName] = stackVO.services
-          stackRepos[fullStackName] = stackVO.repos
-
-          const props: StackOptionProps = {
-            label: stackVO.stackVersion,
-            value: stackVO.stackVersion
-          }
-
-          const existStackVO = stacks.find(
-            (stack) => stack.label === stackVO.stackName
-          )
-
-          if (!existStackVO) {
-            stacks.unshift({
-              label: stackVO.stackName,
-              value: stackVO.stackName,
-              children: [props]
-            })
-          } else {
-            existStackVO.children?.unshift(props)
-          }
-        })
-
-        stackOptions.value = stacks
-        initialized.value = true
-      }
-
-      return Promise.resolve()
-    }
-
-    return {
-      stackOptions,
-      stackServices,
-      stackRepos,
-      stackComponents,
-      stackConfigs,
-      currentStack,
-      initStacks
-    }
-  },
-  { persist: false }
-)
diff --git a/bigtop-manager-ui/src/store/stack/types.ts b/bigtop-manager-ui/src/store/stack/types.ts
deleted file mode 100644
index 906f35d..0000000
--- a/bigtop-manager-ui/src/store/stack/types.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { ServiceVO } from '@/api/service/types.ts'
-
-export type StackOptionProps = {
-  label: string
-  value: string
-  children?: StackOptionProps[]
-}
-
-export type StackInfo = {
-  name: string
-  services: ServiceVO[]
-}
diff --git a/bigtop-manager-ui/src/store/theme/index.ts b/bigtop-manager-ui/src/store/theme/index.ts
new file mode 100644
index 0000000..b52ca72
--- /dev/null
+++ b/bigtop-manager-ui/src/store/theme/index.ts
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { defineStore } from 'pinia'
+import { computed, ref, watch } from 'vue'
+import { theme as antdTheme } from 'ant-design-vue'
+import { GlobalToken } from 'ant-design-vue/es/theme'
+
+const themeMap = {
+  default: {
+    algorithm: antdTheme.defaultAlgorithm
+  },
+  dark: {
+    algorithm: antdTheme.darkAlgorithm
+  }
+}
+
+type ThemeMode = keyof typeof themeMap
+
+export const useTheme = defineStore(
+  'theme',
+  () => {
+    const { useToken } = antdTheme
+    const { token } = useToken()
+    const themeMode = ref<ThemeMode>('default')
+    const themeConfig = computed(() => themeMap[themeMode.value])
+
+    // change of theme token is async
+    watch(token, (newToken) => {
+      injectCssVariablesIntoHead(generateCssVariables(newToken))
+    })
+
+    const toggleTheme = (currTheme: ThemeMode) => {
+      themeMode.value = currTheme
+    }
+
+    const generateCssVariables = (token: GlobalToken) => {
+      const variables = Object.keys(token).map((key) => {
+        const cssVarName = `--${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`
+        return `${cssVarName}: ${token[key as keyof typeof token]};`
+      })
+      return `:root {\n${variables.join('\n')}\n}`
+    }
+
+    // inject style variables in token into style tag
+    const injectCssVariablesIntoHead = (cssVariables: string) => {
+      let styleElement = document.getElementById('theme-variables')
+      if (styleElement) {
+        document.head.removeChild(styleElement)
+      }
+      styleElement = document.createElement('style')
+      styleElement.id = 'theme-variables'
+      document.head.appendChild(styleElement)
+      styleElement.innerHTML = cssVariables
+    }
+
+    const initTheme = () => {
+      injectCssVariablesIntoHead(generateCssVariables(token.value))
+    }
+
+    return {
+      themeMode,
+      themeConfig,
+      initTheme,
+      toggleTheme,
+      generateCssVariables,
+      injectCssVariablesIntoHead
+    }
+  },
+  { persist: true }
+)
diff --git a/bigtop-manager-ui/src/store/user/index.ts b/bigtop-manager-ui/src/store/user/index.ts
index 3f7d60f..29ef16b 100644
--- a/bigtop-manager-ui/src/store/user/index.ts
+++ b/bigtop-manager-ui/src/store/user/index.ts
@@ -17,82 +17,16 @@
  * under the License.
  */
 
-import { defineStore, storeToRefs } from 'pinia'
+import { defineStore } from 'pinia'
 import { getCurrentUser, updateUser } from '@/api/user'
-import { computed, h, shallowRef } from 'vue'
+import { shallowRef } from 'vue'
 import { UserReq, UserVO } from '@/api/user/types.ts'
-import { MenuItem } from '@/store/user/types.ts'
-import { routes as initialRoutes } from '@/router/routes/modules/dashboard.ts'
-import { dynamicRoutes as layoutRoutes } from '@/router/routes/index'
-import { useClusterStore } from '@/store/cluster'
-import { RouteRecordRaw } from 'vue-router'
-import { useServiceStore } from '@/store/service'
-import SvgIcon from '@/components/common/svg-icon/index.vue'
-import { routePriorityMap } from '@/utils/router-util'
 
 export const useUserStore = defineStore(
   'user',
   () => {
     const userVO = shallowRef<UserVO>()
 
-    const clusterStore = useClusterStore()
-    const serviceStore = useServiceStore()
-    const { selectedCluster } = storeToRefs(clusterStore)
-    const { installedServices } = storeToRefs(serviceStore)
-
-    const initMenu = (routes: RouteRecordRaw[]) => {
-      const items: MenuItem[] = []
-      routes.forEach((route) => {
-        const menuItem: MenuItem = {
-          key: route.meta?.title?.toLowerCase(),
-          to: route.path,
-          title: route.meta?.title,
-          icon: route.meta?.icon,
-          hidden: Boolean(route.meta?.hidden),
-          priority: routePriorityMap[`${route.meta?.title}`] || 0
-        }
-
-        if (route.meta?.title === 'Services') {
-          menuItem.children = []
-          installedServices.value.forEach((service) => {
-            const color = service.isHealthy ? '#52c41a' : '#f5222d'
-            menuItem.children?.push({
-              key: service.serviceName,
-              to: '/services/' + service.serviceName,
-              title: service.displayName,
-              icon: h(SvgIcon, {
-                name: 'circle-filled',
-                style: `font-size: 8px; color: ${color}; vertical-align:inherit`
-              })
-            })
-          })
-        } else if (route.children !== undefined) {
-          menuItem.children = []
-          route.children.forEach((child) => {
-            menuItem.children?.push({
-              key: child.meta?.title?.toLowerCase(),
-              to: route.path + child.path,
-              title: child.meta?.title,
-              icon: child.meta?.icon
-            })
-          })
-        } else {
-        }
-
-        items.push(menuItem)
-      })
-
-      return items
-    }
-
-    const menuItems = computed(() => {
-      if (selectedCluster.value) {
-        return initMenu(layoutRoutes)
-      } else {
-        return initMenu(initialRoutes)
-      }
-    })
-
     const getUserInfo = async () => {
       userVO.value = await getCurrentUser()
     }
@@ -110,7 +44,6 @@ export const useUserStore = defineStore(
 
     return {
       userVO,
-      menuItems,
       getUserInfo,
       updateUserInfo,
       logout
diff --git a/bigtop-manager-ui/src/store/user/types.ts b/bigtop-manager-ui/src/store/user/types.ts
deleted file mode 100644
index d79d071..0000000
--- a/bigtop-manager-ui/src/store/user/types.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { VNode } from 'vue'
-
-type MenuItem = {
-  key?: string
-  to: string
-  title?: string
-  icon?: VNode
-  children?: MenuItem[]
-  hidden?: boolean
-  priority?: number
-}
-
-export type { MenuItem }
diff --git a/bigtop-manager-ui/src/styles/ant-design-vue.scss b/bigtop-manager-ui/src/styles/ant-design-vue.scss
new file mode 100644
index 0000000..520b154
--- /dev/null
+++ b/bigtop-manager-ui/src/styles/ant-design-vue.scss
@@ -0,0 +1,383 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+$blue: var(--blue);
+$purple: var(--purple);
+$cyan: var(--cyan);
+$green: var(--green);
+$magenta: var(--magenta);
+$pink: var(--pink);
+$red: var(--red);
+$orange: var(--orange);
+$yellow: var(--yellow);
+$volcano: var(--volcano);
+$geekblue: var(--geekblue);
+$gold: var(--gold);
+$lime: var(--lime);
+$color-primary: var(--color-primary);
+$color-success: var(--color-success);
+$color-warning: var(--color-warning);
+$color-error: var(--color-error);
+$color-info: var(--color-info);
+$color-text-base: var(--color-text-base);
+$color-bg-base: var(--color-bg-base);
+$font-family: var(--font-family);
+$font-size: var(--font-size);
+$line-width: var(--line-width);
+$line-type: var(--line-type);
+$motion-unit: var(--motion-unit);
+$motion-base: var(--motion-base);
+$motion-ease-out-circ: var(--motion-ease-out-circ);
+$motion-ease-in-out-circ: var(--motion-ease-in-out-circ);
+$motion-ease-out: var(--motion-ease-out);
+$motion-ease-in-out: var(--motion-ease-in-out);
+$motion-ease-out-back: var(--motion-ease-out-back);
+$motion-ease-in-back: var(--motion-ease-in-back);
+$motion-ease-in-quint: var(--motion-ease-in-quint);
+$motion-ease-out-quint: var(--motion-ease-out-quint);
+$border-radius: var(--border-radius);
+$size-unit: var(--size-unit);
+$size-step: var(--size-step);
+$size-popup-arrow: var(--size-popup-arrow);
+$control-height: var(--control-height);
+$z-index-base: var(--z-index-base);
+$z-index-popup-base: var(--z-index-popup-base);
+$opacity-image: var(--opacity-image);
+$wireframe: var(--wireframe);
+$blue-1: var(--blue-1);
+$blue-2: var(--blue-2);
+$blue-3: var(--blue-3);
+$blue-4: var(--blue-4);
+$blue-5: var(--blue-5);
+$blue-6: var(--blue-6);
+$blue-7: var(--blue-7);
+$blue-8: var(--blue-8);
+$blue-9: var(--blue-9);
+$blue-10: var(--blue-10);
+$purple-1: var(--purple-1);
+$purple-2: var(--purple-2);
+$purple-3: var(--purple-3);
+$purple-4: var(--purple-4);
+$purple-5: var(--purple-5);
+$purple-6: var(--purple-6);
+$purple-7: var(--purple-7);
+$purple-8: var(--purple-8);
+$purple-9: var(--purple-9);
+$purple-10: var(--purple-10);
+$cyan-1: var(--cyan-1);
+$cyan-2: var(--cyan-2);
+$cyan-3: var(--cyan-3);
+$cyan-4: var(--cyan-4);
+$cyan-5: var(--cyan-5);
+$cyan-6: var(--cyan-6);
+$cyan-7: var(--cyan-7);
+$cyan-8: var(--cyan-8);
+$cyan-9: var(--cyan-9);
+$cyan-10: var(--cyan-10);
+$green-1: var(--green-1);
+$green-2: var(--green-2);
+$green-3: var(--green-3);
+$green-4: var(--green-4);
+$green-5: var(--green-5);
+$green-6: var(--green-6);
+$green-7: var(--green-7);
+$green-8: var(--green-8);
+$green-9: var(--green-9);
+$green-10: var(--green-10);
+$magenta-1: var(--magenta-1);
+$magenta-2: var(--magenta-2);
+$magenta-3: var(--magenta-3);
+$magenta-4: var(--magenta-4);
+$magenta-5: var(--magenta-5);
+$magenta-6: var(--magenta-6);
+$magenta-7: var(--magenta-7);
+$magenta-8: var(--magenta-8);
+$magenta-9: var(--magenta-9);
+$magenta-10: var(--magenta-10);
+$pink-1: var(--pink-1);
+$pink-2: var(--pink-2);
+$pink-3: var(--pink-3);
+$pink-4: var(--pink-4);
+$pink-5: var(--pink-5);
+$pink-6: var(--pink-6);
+$pink-7: var(--pink-7);
+$pink-8: var(--pink-8);
+$pink-9: var(--pink-9);
+$pink-10: var(--pink-10);
+$red-1: var(--red-1);
+$red-2: var(--red-2);
+$red-3: var(--red-3);
+$red-4: var(--red-4);
+$red-5: var(--red-5);
+$red-6: var(--red-6);
+$red-7: var(--red-7);
+$red-8: var(--red-8);
+$red-9: var(--red-9);
+$red-10: var(--red-10);
+$orange-1: var(--orange-1);
+$orange-2: var(--orange-2);
+$orange-3: var(--orange-3);
+$orange-4: var(--orange-4);
+$orange-5: var(--orange-5);
+$orange-6: var(--orange-6);
+$orange-7: var(--orange-7);
+$orange-8: var(--orange-8);
+$orange-9: var(--orange-9);
+$orange-10: var(--orange-10);
+$yellow-1: var(--yellow-1);
+$yellow-2: var(--yellow-2);
+$yellow-3: var(--yellow-3);
+$yellow-4: var(--yellow-4);
+$yellow-5: var(--yellow-5);
+$yellow-6: var(--yellow-6);
+$yellow-7: var(--yellow-7);
+$yellow-8: var(--yellow-8);
+$yellow-9: var(--yellow-9);
+$yellow-10: var(--yellow-10);
+$volcano-1: var(--volcano-1);
+$volcano-2: var(--volcano-2);
+$volcano-3: var(--volcano-3);
+$volcano-4: var(--volcano-4);
+$volcano-5: var(--volcano-5);
+$volcano-6: var(--volcano-6);
+$volcano-7: var(--volcano-7);
+$volcano-8: var(--volcano-8);
+$volcano-9: var(--volcano-9);
+$volcano-10: var(--volcano-10);
+$geekblue-1: var(--geekblue-1);
+$geekblue-2: var(--geekblue-2);
+$geekblue-3: var(--geekblue-3);
+$geekblue-4: var(--geekblue-4);
+$geekblue-5: var(--geekblue-5);
+$geekblue-6: var(--geekblue-6);
+$geekblue-7: var(--geekblue-7);
+$geekblue-8: var(--geekblue-8);
+$geekblue-9: var(--geekblue-9);
+$geekblue-10: var(--geekblue-10);
+$gold-1: var(--gold-1);
+$gold-2: var(--gold-2);
+$gold-3: var(--gold-3);
+$gold-4: var(--gold-4);
+$gold-5: var(--gold-5);
+$gold-6: var(--gold-6);
+$gold-7: var(--gold-7);
+$gold-8: var(--gold-8);
+$gold-9: var(--gold-9);
+$gold-10: var(--gold-10);
+$lime-1: var(--lime-1);
+$lime-2: var(--lime-2);
+$lime-3: var(--lime-3);
+$lime-4: var(--lime-4);
+$lime-5: var(--lime-5);
+$lime-6: var(--lime-6);
+$lime-7: var(--lime-7);
+$lime-8: var(--lime-8);
+$lime-9: var(--lime-9);
+$lime-10: var(--lime-10);
+$color-text: var(--color-text);
+$color-text-secondary: var(--color-text-secondary);
+$color-text-tertiary: var(--color-text-tertiary);
+$color-text-quaternary: var(--color-text-quaternary);
+$color-fill: var(--color-fill);
+$color-fill-secondary: var(--color-fill-secondary);
+$color-fill-tertiary: var(--color-fill-tertiary);
+$color-fill-quaternary: var(--color-fill-quaternary);
+$color-bg-layout: var(--color-bg-layout);
+$color-bg-container: var(--color-bg-container);
+$color-bg-elevated: var(--color-bg-elevated);
+$color-bg-spotlight: var(--color-bg-spotlight);
+$color-border: var(--color-border);
+$color-border-secondary: var(--color-border-secondary);
+$color-primary-bg: var(--color-primary-bg);
+$color-primary-bg-hover: var(--color-primary-bg-hover);
+$color-primary-border: var(--color-primary-border);
+$color-primary-border-hover: var(--color-primary-border-hover);
+$color-primary-hover: var(--color-primary-hover);
+$color-primary-active: var(--color-primary-active);
+$color-primary-text-hover: var(--color-primary-text-hover);
+$color-primary-text: var(--color-primary-text);
+$color-primary-text-active: var(--color-primary-text-active);
+$color-success-bg: var(--color-success-bg);
+$color-success-bg-hover: var(--color-success-bg-hover);
+$color-success-border: var(--color-success-border);
+$color-success-border-hover: var(--color-success-border-hover);
+$color-success-hover: var(--color-success-hover);
+$color-success-active: var(--color-success-active);
+$color-success-text-hover: var(--color-success-text-hover);
+$color-success-text: var(--color-success-text);
+$color-success-text-active: var(--color-success-text-active);
+$color-error-bg: var(--color-error-bg);
+$color-error-bg-hover: var(--color-error-bg-hover);
+$color-error-border: var(--color-error-border);
+$color-error-border-hover: var(--color-error-border-hover);
+$color-error-hover: var(--color-error-hover);
+$color-error-active: var(--color-error-active);
+$color-error-text-hover: var(--color-error-text-hover);
+$color-error-text: var(--color-error-text);
+$color-error-text-active: var(--color-error-text-active);
+$color-warning-bg: var(--color-warning-bg);
+$color-warning-bg-hover: var(--color-warning-bg-hover);
+$color-warning-border: var(--color-warning-border);
+$color-warning-border-hover: var(--color-warning-border-hover);
+$color-warning-hover: var(--color-warning-hover);
+$color-warning-active: var(--color-warning-active);
+$color-warning-text-hover: var(--color-warning-text-hover);
+$color-warning-text: var(--color-warning-text);
+$color-warning-text-active: var(--color-warning-text-active);
+$color-info-bg: var(--color-info-bg);
+$color-info-bg-hover: var(--color-info-bg-hover);
+$color-info-border: var(--color-info-border);
+$color-info-border-hover: var(--color-info-border-hover);
+$color-info-hover: var(--color-info-hover);
+$color-info-active: var(--color-info-active);
+$color-info-text-hover: var(--color-info-text-hover);
+$color-info-text: var(--color-info-text);
+$color-info-text-active: var(--color-info-text-active);
+$color-bg-mask: var(--color-bg-mask);
+$color-white: var(--color-white);
+$font-size-s-m: var(--font-size-s-m);
+$font-size-l-g: var(--font-size-l-g);
+$font-size-x-l: var(--font-size-x-l);
+$font-size-heading1: var(--font-size-heading1);
+$font-size-heading2: var(--font-size-heading2);
+$font-size-heading3: var(--font-size-heading3);
+$font-size-heading4: var(--font-size-heading4);
+$font-size-heading5: var(--font-size-heading5);
+$line-height: var(--line-height);
+$line-height-l-g: var(--line-height-l-g);
+$line-height-s-m: var(--line-height-s-m);
+$line-height-heading1: var(--line-height-heading1);
+$line-height-heading2: var(--line-height-heading2);
+$line-height-heading3: var(--line-height-heading3);
+$line-height-heading4: var(--line-height-heading4);
+$line-height-heading5: var(--line-height-heading5);
+$size-x-x-l: var(--size-x-x-l);
+$size-x-l: var(--size-x-l);
+$size-l-g: var(--size-l-g);
+$size-m-d: var(--size-m-d);
+$size-m-s: var(--size-m-s);
+$size: var(--size);
+$size-s-m: var(--size-s-m);
+$size-x-s: var(--size-x-s);
+$size-x-x-s: var(--size-x-x-s);
+$control-height-s-m: var(--control-height-s-m);
+$control-height-x-s: var(--control-height-x-s);
+$control-height-l-g: var(--control-height-l-g);
+$motion-duration-fast: var(--motion-duration-fast);
+$motion-duration-mid: var(--motion-duration-mid);
+$motion-duration-slow: var(--motion-duration-slow);
+$line-width-bold: var(--line-width-bold);
+$border-radius-x-s: var(--border-radius-x-s);
+$border-radius-s-m: var(--border-radius-s-m);
+$border-radius-l-g: var(--border-radius-l-g);
+$border-radius-outer: var(--border-radius-outer);
+$color-link: var(--color-link);
+$color-link-hover: var(--color-link-hover);
+$color-link-active: var(--color-link-active);
+$color-fill-content: var(--color-fill-content);
+$color-fill-content-hover: var(--color-fill-content-hover);
+$color-fill-alter: var(--color-fill-alter);
+$color-bg-container-disabled: var(--color-bg-container-disabled);
+$color-border-bg: var(--color-border-bg);
+$color-split: var(--color-split);
+$color-text-placeholder: var(--color-text-placeholder);
+$color-text-disabled: var(--color-text-disabled);
+$color-text-heading: var(--color-text-heading);
+$color-text-label: var(--color-text-label);
+$color-text-description: var(--color-text-description);
+$color-text-light-solid: var(--color-text-light-solid);
+$color-highlight: var(--color-highlight);
+$color-bg-text-hover: var(--color-bg-text-hover);
+$color-bg-text-active: var(--color-bg-text-active);
+$color-icon: var(--color-icon);
+$color-icon-hover: var(--color-icon-hover);
+$color-error-outline: var(--color-error-outline);
+$color-warning-outline: var(--color-warning-outline);
+$font-size-icon: var(--font-size-icon);
+$control-outline-width: var(--control-outline-width);
+$control-interactive-size: var(--control-interactive-size);
+$control-item-bg-hover: var(--control-item-bg-hover);
+$control-item-bg-active: var(--control-item-bg-active);
+$control-item-bg-active-hover: var(--control-item-bg-active-hover);
+$control-item-bg-active-disabled: var(--control-item-bg-active-disabled);
+$control-tmp-outline: var(--control-tmp-outline);
+$control-outline: var(--control-outline);
+$font-weight-strong: var(--font-weight-strong);
+$opacity-loading: var(--opacity-loading);
+$link-decoration: var(--link-decoration);
+$link-hover-decoration: var(--link-hover-decoration);
+$link-focus-decoration: var(--link-focus-decoration);
+$control-padding-horizontal: var(--control-padding-horizontal);
+$control-padding-horizontal-s-m: var(--control-padding-horizontal-s-m);
+$padding-x-x-s: var(--padding-x-x-s);
+$padding-x-s: var(--padding-x-s);
+$padding-s-m: var(--padding-s-m);
+$padding: var(--padding);
+$padding-m-d: var(--padding-m-d);
+$padding-l-g: var(--padding-l-g);
+$padding-x-l: var(--padding-x-l);
+$padding-content-horizontal-l-g: var(--padding-content-horizontal-l-g);
+$padding-content-vertical-l-g: var(--padding-content-vertical-l-g);
+$padding-content-horizontal: var(--padding-content-horizontal);
+$padding-content-vertical: var(--padding-content-vertical);
+$padding-content-horizontal-s-m: var(--padding-content-horizontal-s-m);
+$padding-content-vertical-s-m: var(--padding-content-vertical-s-m);
+$margin-x-x-s: var(--margin-x-x-s);
+$margin-x-s: var(--margin-x-s);
+$margin-s-m: var(--margin-s-m);
+$margin: var(--margin);
+$margin-m-d: var(--margin-m-d);
+$margin-l-g: var(--margin-l-g);
+$margin-x-l: var(--margin-x-l);
+$margin-x-x-l: var(--margin-x-x-l);
+$box-shadow: var(--box-shadow);
+$box-shadow-secondary: var(--box-shadow-secondary);
+$box-shadow-tertiary: var(--box-shadow-tertiary);
+$screen-x-s: var(--screen-x-s);
+$screen-x-s-min: var(--screen-x-s-min);
+$screen-x-s-max: var(--screen-x-s-max);
+$screen-s-m: var(--screen-s-m);
+$screen-s-m-min: var(--screen-s-m-min);
+$screen-s-m-max: var(--screen-s-m-max);
+$screen-m-d: var(--screen-m-d);
+$screen-m-d-min: var(--screen-m-d-min);
+$screen-m-d-max: var(--screen-m-d-max);
+$screen-l-g: var(--screen-l-g);
+$screen-l-g-min: var(--screen-l-g-min);
+$screen-l-g-max: var(--screen-l-g-max);
+$screen-x-l: var(--screen-x-l);
+$screen-x-l-min: var(--screen-x-l-min);
+$screen-x-l-max: var(--screen-x-l-max);
+$screen-x-x-l: var(--screen-x-x-l);
+$screen-x-x-l-min: var(--screen-x-x-l-min);
+$screen-x-x-l-max: var(--screen-x-x-l-max);
+$screen-x-x-x-l: var(--screen-x-x-x-l);
+$screen-x-x-x-l-min: var(--screen-x-x-x-l-min);
+$box-shadow-popover-arrow: var(--box-shadow-popover-arrow);
+$box-shadow-card: var(--box-shadow-card);
+$box-shadow-drawer-right: var(--box-shadow-drawer-right);
+$box-shadow-drawer-left: var(--box-shadow-drawer-left);
+$box-shadow-drawer-up: var(--box-shadow-drawer-up);
+$box-shadow-drawer-down: var(--box-shadow-drawer-down);
+$box-shadow-tabs-overflow-left: var(--box-shadow-tabs-overflow-left);
+$box-shadow-tabs-overflow-right: var(--box-shadow-tabs-overflow-right);
+$box-shadow-tabs-overflow-top: var(--box-shadow-tabs-overflow-top);
+$box-shadow-tabs-overflow-bottom: var(--box-shadow-tabs-overflow-bottom);
+$_token-key: var(--_token-key);
+$_hash-id: var(--_hash-id);
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/styles/common/index.scss b/bigtop-manager-ui/src/styles/common/index.scss
deleted file mode 100644
index 2edafe0..0000000
--- a/bigtop-manager-ui/src/styles/common/index.scss
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-@import './variables.scss';
-@import './mixins.scss';
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/styles/common/variables.scss b/bigtop-manager-ui/src/styles/common/variables.scss
deleted file mode 100644
index 61f5439..0000000
--- a/bigtop-manager-ui/src/styles/common/variables.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/styles/main.css b/bigtop-manager-ui/src/styles/index.scss
similarity index 70%
rename from bigtop-manager-ui/src/styles/main.css
rename to bigtop-manager-ui/src/styles/index.scss
index addd8b5..3744349 100644
--- a/bigtop-manager-ui/src/styles/main.css
+++ b/bigtop-manager-ui/src/styles/index.scss
@@ -17,34 +17,9 @@
  * under the License.
  */
 
-* {
-  outline: 0;
-}
-
-html {
-  --text-color: rgba(0, 0, 0, 0.85);
-  --text-color-desc: rgba(0, 0, 0, 0.45);
-  --bg-color: #fff;
-  --hover-color: rgba(0, 0, 0, 0.05);
-  --bg-color-container: #f0f2f5;
-  --c-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
-}
-
-.m-0 {
-  margin: 0;
-}
-
-.p-0 {
-  padding: 0;
-}
-
-.hidden {
-  display: none;
-}
-
-.ant-table-body {
-  overflow-y: auto !important;
-}
+@import './variables.scss';
+@import './marked.scss';
+@import './scrollbar.scss';
 
 #app {
   width: 100%;
@@ -54,3 +29,21 @@ html {
   bottom: 0;
   left: 0;
 }
+
+.header-item {
+  height: $layout-header-height;
+  border-radius: 0;
+  box-sizing: border-box;
+  padding: 0 16px;
+  cursor: pointer;
+  @include flexbox($justify: center, $align: center);
+
+  &:hover {
+    background-color: var(--color-primary);
+  }
+
+  :deep(.svg-icon) {
+    width: 20px;
+    height: 20px;
+  }
+}
\ No newline at end of file
diff --git a/bigtop-manager-ui/src/styles/common/mixins.scss b/bigtop-manager-ui/src/styles/variables.scss
similarity index 84%
rename from bigtop-manager-ui/src/styles/common/mixins.scss
rename to bigtop-manager-ui/src/styles/variables.scss
index 6bf0486..c553fc5 100644
--- a/bigtop-manager-ui/src/styles/common/mixins.scss
+++ b/bigtop-manager-ui/src/styles/variables.scss
@@ -17,6 +17,16 @@
  * under the License.
  */
 
+@import './ant-design-vue.scss';
+// margin
+$space-lg: 24px;
+$space-md: 16px;
+$space-sm: 8px;
+
+$layout-header-height: 64px;
+$layout-sider-width: 200px;
+$layout-sider-bg-color: #fff;
+
 @mixin flexbox($direction: null, $wrap: null, $justify: null, $align: null) {
   display: flex;
   flex-direction: $direction;
diff --git a/bigtop-manager-ui/src/types/route.d.ts b/bigtop-manager-ui/src/types/route.d.ts
index 1cbcb95..b8d38a7 100644
--- a/bigtop-manager-ui/src/types/route.d.ts
+++ b/bigtop-manager-ui/src/types/route.d.ts
@@ -18,13 +18,15 @@
  */
 
 import 'vue-router'
-import { VNode } from 'vue'
 
 declare module 'vue-router' {
   interface RouteMeta {
     title?: string
-    icon?: VNode
+    icon?: string
     hidden?: boolean
-    priority?: number
+    alwaysShow?: boolean
+    belong?: string
+    noCache?: boolean
+    activeMenu?: string
   }
 }
diff --git a/bigtop-manager-ui/src/utils/router-util.ts b/bigtop-manager-ui/src/utils/router-util.ts
index 7e89af8..3cd9a60 100644
--- a/bigtop-manager-ui/src/utils/router-util.ts
+++ b/bigtop-manager-ui/src/utils/router-util.ts
@@ -22,14 +22,6 @@ interface RouteModuleType {
   routes: RouteRecordRaw[]
 }
 
-type RoutePriorityMap = { [key: string]: number }
-export const routePriorityMap: RoutePriorityMap = {
-  Dashboard: 1,
-  Hosts: 2,
-  Services: 3,
-  Cluster: 4
-}
-
 export function mergeRouteModules(
   routeModules: Record<string, unknown>
 ): RouteRecordRaw[] {
@@ -39,5 +31,30 @@ export function mergeRouteModules(
     mergedRoutes.push(...moduleRoutes)
   }
 
-  return mergedRoutes
+  return getMergeRoutes(mergedRoutes)
+}
+
+function getMergeRoutes<T extends RouteRecordRaw>(routes: T[]): T[] {
+  const mergedMap = new Map()
+  routes.forEach((route: T) => {
+    const firstLevelPath = route.path.split('/')[1]
+    if (!mergedMap.has(firstLevelPath)) {
+      mergedMap.set(firstLevelPath, {
+        path: `/${firstLevelPath}/`,
+        component: route.component,
+        meta: route.meta,
+        children: [],
+        redirect: route.redirect || undefined
+      })
+    }
+    if (route.children) {
+      const existingRoute = mergedMap.get(firstLevelPath)
+      route.children.forEach((child) => {
+        if (!existingRoute.children.some((c: T) => c.path === child.path)) {
+          existingRoute.children.push(child)
+        }
+      })
+    }
+  })
+  return Array.from(mergedMap.values())
 }
diff --git a/bigtop-manager-ui/tests/__components__/svg-icon.test.ts b/bigtop-manager-ui/tests/__components__/svg-icon.test.ts
index d7857c1..69fc791 100644
--- a/bigtop-manager-ui/tests/__components__/svg-icon.test.ts
+++ b/bigtop-manager-ui/tests/__components__/svg-icon.test.ts
@@ -38,12 +38,10 @@ describe('SvgIcon', () => {
       props: {
         name: 'home',
         prefix: 'vietest',
-        color: 'yellow',
-        className: 'home'
+        color: 'yellow'
       }
     })
     expect(wrapper.find('use').attributes()['href']).toBe('#vietest-home')
     expect(wrapper.find('use').attributes().fill).toBe('yellow')
-    expect(wrapper.find('svg').classes()).toEqual(['svg-icon', 'home'])
   })
 })
diff --git a/bigtop-manager-ui/vite.config.ts b/bigtop-manager-ui/vite.config.ts
index 50a2b2a..4fd219e 100644
--- a/bigtop-manager-ui/vite.config.ts
+++ b/bigtop-manager-ui/vite.config.ts
@@ -47,7 +47,7 @@ export default defineConfig(({ mode }) => {
     css: {
       preprocessorOptions: {
         scss: {
-          additionalData: '@import "@/styles/common/index.scss";'
+          additionalData: '@import "@/styles/index.scss";'
         }
       }
     },