You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by ki...@apache.org on 2021/12/21 12:57:21 UTC

[dolphinscheduler] branch dev updated: [Fix-7525][Feature][UI Next] Provide a common layout for the module of dolphinscheduler-ui-next. (#7526)

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

kirs pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 49662c7  [Fix-7525][Feature][UI Next] Provide a common  layout for the module of dolphinscheduler-ui-next. (#7526)
49662c7 is described below

commit 49662c78650a584eaaab5e67011e57317278a05d
Author: calvin <ji...@163.com>
AuthorDate: Tue Dec 21 20:57:11 2021 +0800

    [Fix-7525][Feature][UI Next] Provide a common  layout for the module of dolphinscheduler-ui-next. (#7526)
    
    * add layout
    
    * add layout
    
    * add layout
    
    * add routes
    
    * add routes
    
    * modify layout
    
    * modify layout
    
    * modify layout
    
    * modify layout
    
    * improve a few issues with code specification
---
 dolphinscheduler-ui-next/package.json              |   9 +
 dolphinscheduler-ui-next/src/App.tsx               |   5 +-
 .../src/assets/images/nav-logo.svg                 |  99 +++++++++
 .../basic/components/header/index.module.scss}     |  70 +++---
 .../src/layouts/basic/components/header/index.tsx  | 106 ++++++++++
 .../components/logo/index.module.scss}             |  32 +--
 .../components/logo/index.tsx}                     |  28 +--
 .../components/sider/index.module.scss}            |  19 +-
 .../src/layouts/basic/components/sider/index.tsx   |  79 +++++++
 .../index.ts => layouts/basic/index.module.scss}   |  72 +++----
 .../src/layouts/basic/index.tsx                    | 234 +++++++++++++++++++++
 .../src/layouts/content/Content.tsx                |  12 +-
 dolphinscheduler-ui-next/src/router/index.ts       |  24 +--
 dolphinscheduler-ui-next/src/router/routes.ts      | 181 ++++++++++++++--
 .../content/Content.tsx => store/route/route.ts}   |  42 ++--
 .../content/Content.tsx => store/route/types.ts}   |  23 +-
 16 files changed, 850 insertions(+), 185 deletions(-)

diff --git a/dolphinscheduler-ui-next/package.json b/dolphinscheduler-ui-next/package.json
index 712e768..1cb7eba 100644
--- a/dolphinscheduler-ui-next/package.json
+++ b/dolphinscheduler-ui-next/package.json
@@ -28,6 +28,15 @@
     "@types/qs": "^6.9.7",
     "@typescript-eslint/eslint-plugin": "^5.6.0",
     "@typescript-eslint/parser": "^5.6.0",
+    "@vicons/antd": "^0.11.0",
+    "@vicons/carbon": "^0.11.0",
+    "@vicons/fa": "^0.11.0",
+    "@vicons/fluent": "^0.11.0",
+    "@vicons/ionicons4": "^0.11.0",
+    "@vicons/ionicons5": "^0.11.0",
+    "@vicons/material": "^0.11.0",
+    "@vicons/tabler": "^0.11.0",
+    "@vicons/utils": "^0.1.4",
     "@vitejs/plugin-vue": "^1.10.2",
     "@vitejs/plugin-vue-jsx": "^1.3.1",
     "dart-sass": "^1.25.0",
diff --git a/dolphinscheduler-ui-next/src/App.tsx b/dolphinscheduler-ui-next/src/App.tsx
index 62ceab3..3b31730 100644
--- a/dolphinscheduler-ui-next/src/App.tsx
+++ b/dolphinscheduler-ui-next/src/App.tsx
@@ -17,17 +17,18 @@
 
 import { defineComponent, computed } from 'vue'
 import { NConfigProvider, darkTheme, GlobalThemeOverrides } from 'naive-ui'
+import { useAsyncRouteStore } from '@/store/route/route'
 import { useThemeStore } from '@/store/theme/theme'
 import themeList from '@/themes'
 
 const App = defineComponent({
   name: 'App',
   setup() {
+    const asyncRouteStore = useAsyncRouteStore()
     const themeStore = useThemeStore()
     const currentTheme = computed(() =>
       themeStore.darkTheme ? darkTheme : undefined
     )
-
     return {
       currentTheme,
     }
@@ -42,7 +43,7 @@ const App = defineComponent({
       <NConfigProvider
         theme={this.currentTheme}
         themeOverrides={themeOverrides}
-        style={{ width: '100%', height: '100vh' }}
+        style={{ width: '100%', height: '100vh', overflow: 'hidden' }}
       >
         <router-view />
       </NConfigProvider>
diff --git a/dolphinscheduler-ui-next/src/assets/images/nav-logo.svg b/dolphinscheduler-ui-next/src/assets/images/nav-logo.svg
new file mode 100755
index 0000000..6a26786
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/assets/images/nav-logo.svg
@@ -0,0 +1,99 @@
+<!-- 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. -->
+<!--<?xml version="1.0" encoding="utf-8"?>-->
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 180 46" style="enable-background:new 0 0 180 46;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#85CDF0;}
+	.st1{fill:#0097E0;}
+	.st2{fill:#FFFFFF;}
+</style>
+<g>
+	<path class="st0" d="M29.9,25.6H14.5c-2.1,0-3.8,1.8-3.8,3.9c0,0.8,0.2,1.6,0.7,2.2c0.3-0.1,0.6-0.2,0.9-0.3l0,0l0,0
+		c1-0.4,2.1-1.2,2.8-1.8c0.2-0.1,0.3-0.2,0.4-0.3c0.1-0.1,0.2-0.2,0.4-0.3c0.6-0.5,1.4-1.1,2.6-1.3c0.2,0,0.4,0,0.7,0
+		c1,0,1.9,0.3,2.5,0.9c0.2-0.1,0.4-0.2,0.5-0.3c0.3-0.1,0.5-0.3,0.7-0.4s0.5-0.2,0.8-0.2c0.6,0,1.2,0.3,1.5,0.9
+		c0.2,0.4,0.4,1.1-0.2,2.2c-0.1,0.2-0.3,0.4-0.4,0.7c-0.3,0.6-0.7,1.2-1.3,2h6.6c2.1,0,3.8-1.8,3.8-3.9C33.7,27.4,32,25.6,29.9,25.6
+		z"/>
+	<path class="st1" d="M5.7,20.3h1c0.6,0,1-0.4,1-1s-0.4-1-1-1h-1c-2.1,0-3.7-1.7-3.7-3.9c0-2.1,1.6-3.8,3.6-3.9v2.1l2.8-2.9l-2.8-3
+		v1.7c-3,0.2-5.6,2.8-5.6,6C0,17.7,2.5,20.3,5.7,20.3z"/>
+	<path class="st1" d="M38.4,18.6h-1c-0.6,0-1,0.4-1,1s0.4,1,1,1h1c2.1,0,3.7,1.7,3.7,3.9c0,2.1-1.6,3.8-3.6,3.9v-2.1L35.7,29l2.8,3
+		v-1.7c3-0.1,5.5-2.6,5.5-5.9C44.1,21.1,41.6,18.6,38.4,18.6z"/>
+	<path class="st0" d="M29.9,15.3H14.5c-2.1,0-3.8,1.8-3.8,3.9s1.7,3.9,3.8,3.9h15.4c2.1,0,3.8-1.8,3.8-3.9S32,15.3,29.9,15.3z"/>
+	<path class="st0" d="M29.9,5.1H14.5c-2.1,0-3.8,1.8-3.8,3.9l0,0c0,2.2,1.7,3.9,3.8,3.9h15.4c2.1,0,3.8-1.8,3.8-3.9l0,0
+		C33.7,6.8,32,5.1,29.9,5.1z"/>
+	<path class="st1" d="M19.5,39c0.2,1.3-0.4,1-0.9,0.6c-0.3-0.2-1.2-0.7-1.7-1c0.8-0.4,1.5-0.9,2-1.3C19.2,37.8,19.4,38.4,19.5,39z
+		 M18.4,31c-0.1,0-0.2,0.1-0.2,0.2s0.1,0.2,0.2,0.2s0.2-0.1,0.2-0.2S18.5,31,18.4,31z M24.2,30.3c-0.8,1.3-1.8,3.3-4.6,5.9
+		c-0.6,0.6-1.9,1.5-3.2,2.1c-0.4,0.2-1,0.4-1.6,0.6c0.4-0.6,0.6-1.2,0.7-1.8h-0.3c-0.7,2.3-2.4,4.3-4.5,5c-1.3,0.4-1-0.3-0.8-0.9
+		c0.2-0.4,0.7-2.4,0.9-3.4l-0.4-0.1c0,0,0,0.2-0.1,0.4s-0.1,0.5-0.2,0.8c-1.2-0.4-2.4-1-3.3-2.1c-1.3-1.6-1.9-3.1-2.2-5.9
+		c-0.1-0.7-0.8-1.4-1.6-2.3c-1-1.1-1-2.7-0.4-2.9c0.4-0.1,2.5,0.9,3.2,1.4c0.8-0.6,2-1.6,2.4-1.3C8.5,26,8.6,27,7.9,28.5
+		c-1.5,3.1,0.6,4,1.1,4.1c0.9,0.2,2.3,0.3,3.7-0.3c1.3-0.5,2.9-1.8,3.4-2.2c0.7-0.5,1.4-1.2,2.5-1.4c1.3-0.2,2.3,0.2,2.8,1.1
+		c0.6-0.2,1.4-0.8,2-1C23.9,28.5,25,28.9,24.2,30.3z M18.8,31.4c0-0.3-0.2-0.6-0.5-0.6s-0.5,0.3-0.5,0.6S18,32,18.3,32
+		C18.6,31.9,18.8,31.7,18.8,31.4z"/>
+	<g>
+		<path class="st2" d="M49,17.6h4.8c1.6,0,2.9,0.6,3.8,1.8c0.8,1.1,1.2,2.5,1.2,4.2c0,1.3-0.2,2.5-0.7,3.6c-0.8,1.9-2.3,2.8-4.3,2.8
+			H49V17.6z M53.5,28.6c0.5,0,1-0.1,1.3-0.2c0.6-0.2,1.1-0.6,1.5-1.3c0.3-0.5,0.5-1.1,0.7-1.9c0.1-0.5,0.1-0.9,0.1-1.3
+			c0-1.5-0.3-2.7-0.9-3.6c-0.6-0.8-1.5-1.3-2.8-1.3h-2.8v9.5L53.5,28.6L53.5,28.6z"/>
+		<path class="st2" d="M67.3,21.9c0.8,0.8,1.2,1.9,1.2,3.4s-0.3,2.7-1,3.6c-0.7,1-1.7,1.4-3.2,1.4c-1.2,0-2.2-0.4-2.9-1.3
+			c-0.7-0.8-1.1-2-1.1-3.4c0-1.5,0.4-2.7,1.1-3.6c0.7-0.9,1.7-1.4,3-1.4C65.5,20.7,66.5,21.1,67.3,21.9z M66.3,27.9
+			c0.4-0.8,0.5-1.6,0.5-2.5c0-0.8-0.1-1.5-0.4-2.1c-0.4-0.8-1.1-1.2-2.1-1.2c-0.9,0-1.5,0.4-1.9,1.1s-0.6,1.6-0.6,2.6
+			s0.2,1.8,0.6,2.4c0.4,0.6,1,1,1.9,1C65.3,29.1,66,28.7,66.3,27.9z"/>
+		<path class="st2" d="M70.3,17.6h1.5V30h-1.5V17.6z"/>
+		<path class="st2" d="M73.8,21h1.4v1.2c0.3-0.4,0.6-0.7,1-1c0.5-0.3,1.1-0.5,1.8-0.5c1,0,1.8,0.4,2.5,1.2c0.7,0.8,1,1.9,1,3.4
+			c0,2-0.5,3.4-1.5,4.2c-0.6,0.5-1.4,0.8-2.2,0.8c-0.7,0-1.2-0.1-1.7-0.4c-0.3-0.2-0.6-0.5-0.9-0.9v4.6h-1.5L73.8,21L73.8,21z
+			 M79.4,28.1c0.5-0.6,0.7-1.5,0.7-2.7c0-0.7-0.1-1.3-0.3-1.9c-0.4-1-1.1-1.5-2.1-1.5s-1.7,0.5-2.1,1.6c-0.2,0.6-0.3,1.3-0.3,2.1
+			c0,0.7,0.1,1.3,0.3,1.8c0.4,0.9,1.1,1.4,2.1,1.4C78.4,29,78.9,28.7,79.4,28.1z"/>
+		<path class="st2" d="M83.3,17.6h1.5v4.6c0.3-0.5,0.7-0.8,0.9-1c0.5-0.3,1.1-0.5,1.8-0.5c1.3,0,2.1,0.5,2.6,1.4
+			c0.2,0.5,0.4,1.2,0.4,2.1V30H89v-5.7c0-0.7-0.1-1.2-0.2-1.5c-0.3-0.5-0.8-0.7-1.5-0.7c-0.6,0-1.2,0.2-1.7,0.7
+			c-0.5,0.4-0.7,1.3-0.7,2.5V30h-1.5V17.6H83.3z"/>
+		<path class="st2" d="M92.6,17.6h1.5v1.7h-1.5V17.6z M92.6,21h1.5v9h-1.5V21z"/>
+		<path class="st2" d="M96.4,21h1.4v1.3c0.4-0.5,0.9-0.9,1.3-1.1c0.5-0.2,1-0.3,1.5-0.3c1.2,0,2.1,0.4,2.5,1.3
+			c0.2,0.5,0.4,1.2,0.4,2.1V30H102v-5.7c0-0.6-0.1-1-0.2-1.3c-0.3-0.6-0.7-0.8-1.4-0.8c-0.3,0-0.6,0-0.9,0.1
+			c-0.4,0.1-0.8,0.4-1.1,0.7c-0.2,0.3-0.4,0.6-0.5,0.9s-0.1,0.8-0.1,1.4V30h-1.5L96.4,21L96.4,21z"/>
+		<path class="st2" d="M107,26c0,0.7,0.2,1.3,0.5,1.7c0.5,0.8,1.4,1.2,2.8,1.2c0.6,0,1.1-0.1,1.6-0.3c0.9-0.3,1.4-1,1.4-1.9
+			c0-0.7-0.2-1.2-0.6-1.4c-0.4-0.3-1-0.5-1.9-0.7l-1.6-0.4c-1-0.2-1.8-0.5-2.2-0.8c-0.7-0.5-1.1-1.3-1.1-2.3c0-1.1,0.4-2,1.1-2.7
+			s1.8-1.1,3.1-1.1c1.2,0,2.3,0.3,3.1,0.9c0.9,0.6,1.3,1.6,1.3,3H113c-0.1-0.7-0.2-1.2-0.5-1.5c-0.5-0.6-1.3-1-2.4-1
+			c-0.9,0-1.6,0.2-2,0.6s-0.6,0.9-0.6,1.5s0.2,1.1,0.7,1.3c0.3,0.2,1,0.4,2.1,0.7l1.6,0.4c0.8,0.2,1.4,0.5,1.8,0.8
+			c0.7,0.6,1.1,1.4,1.1,2.5c0,1.4-0.5,2.4-1.4,2.9c-0.9,0.6-2,0.9-3.3,0.9c-1.5,0-2.6-0.4-3.4-1.2c-0.8-0.8-1.2-1.8-1.2-3.2h1.5V26z
+			"/>
+		<path class="st2" d="M122.7,21.5c0.6,0.5,1,1.3,1.1,2.6h-1.4c-0.1-0.6-0.3-1-0.6-1.4c-0.3-0.4-0.8-0.6-1.5-0.6
+			c-0.9,0-1.6,0.5-2,1.4c-0.3,0.6-0.4,1.4-0.4,2.3s0.2,1.7,0.6,2.3c0.4,0.6,1,0.9,1.8,0.9c0.6,0,1.1-0.2,1.5-0.6s0.6-0.9,0.7-1.6
+			h1.4c-0.2,1.2-0.6,2.1-1.2,2.6c-0.7,0.6-1.5,0.8-2.5,0.8c-1.1,0-2.1-0.4-2.7-1.3c-0.7-0.9-1-1.9-1-3.2c0-1.6,0.4-2.8,1.1-3.7
+			c0.7-0.9,1.7-1.3,2.9-1.3C121.3,20.7,122.1,21,122.7,21.5z"/>
+		<path class="st2" d="M125.3,17.6h1.5v4.6c0.3-0.5,0.7-0.8,0.9-1c0.5-0.3,1.1-0.5,1.8-0.5c1.3,0,2.1,0.5,2.6,1.4
+			c0.2,0.5,0.4,1.2,0.4,2.1V30H131v-5.7c0-0.7-0.1-1.2-0.2-1.5c-0.3-0.5-0.8-0.7-1.5-0.7c-0.6,0-1.2,0.2-1.7,0.7
+			c-0.5,0.4-0.7,1.3-0.7,2.5V30h-1.5V17.6H125.3z"/>
+		<path class="st2" d="M140,21.2c0.6,0.3,1,0.7,1.3,1.2s0.5,1,0.6,1.6c0.1,0.4,0.1,1.1,0.1,2h-6.4c0,0.9,0.2,1.7,0.6,2.2
+			c0.4,0.6,1,0.8,1.8,0.8s1.4-0.3,1.8-0.8c0.3-0.3,0.4-0.7,0.5-1.1h1.5c0,0.3-0.2,0.7-0.4,1.1s-0.5,0.7-0.7,1
+			c-0.4,0.5-1,0.8-1.7,0.9c-0.4,0.1-0.8,0.1-1.2,0.1c-1.1,0-2-0.4-2.8-1.2c-0.8-0.8-1.1-2-1.1-3.4c0-1.5,0.4-2.6,1.1-3.5
+			c0.8-0.9,1.8-1.4,3-1.4C138.9,20.8,139.5,20.9,140,21.2z M140.6,24.8c-0.1-0.7-0.2-1.2-0.4-1.6c-0.4-0.7-1.1-1.1-2-1.1
+			c-0.7,0-1.2,0.3-1.7,0.8s-0.7,1.1-0.7,1.9C135.8,24.8,140.6,24.8,140.6,24.8z"/>
+		<path class="st2" d="M148.8,21.3c0.3,0.2,0.6,0.5,0.9,0.9v-4.6h1.4V30h-1.3v-1.3c-0.3,0.6-0.7,1-1.2,1.2s-1,0.4-1.6,0.4
+			c-1,0-1.8-0.4-2.5-1.3c-0.7-0.8-1.1-2-1.1-3.4c0-1.3,0.3-2.5,1-3.4c0.7-1,1.6-1.4,2.8-1.4C147.8,20.8,148.3,21,148.8,21.3z
+			 M145.5,28.1c0.4,0.7,1,1,1.9,1c0.7,0,1.2-0.3,1.7-0.9c0.4-0.6,0.7-1.5,0.7-2.6s-0.2-2-0.7-2.5s-1-0.8-1.7-0.8s-1.3,0.3-1.8,0.9
+			s-0.7,1.4-0.7,2.6C144.9,26.6,145.1,27.4,145.5,28.1z"/>
+		<path class="st2" d="M154.8,21v6c0,0.5,0.1,0.8,0.2,1.1c0.3,0.5,0.7,0.8,1.4,0.8c1,0,1.7-0.5,2-1.4c0.2-0.5,0.3-1.2,0.3-2.1V21
+			h1.5v9h-1.4v-1.3c-0.2,0.3-0.4,0.6-0.7,0.9c-0.6,0.5-1.2,0.7-2,0.7c-1.2,0-2.1-0.4-2.5-1.3c-0.2-0.5-0.4-1.1-0.4-1.8V21H154.8z"/>
+		<path class="st2" d="M162.7,17.6h1.5V30h-1.5V17.6z"/>
+		<path class="st2" d="M171.8,21.2c0.6,0.3,1,0.7,1.3,1.2s0.5,1,0.6,1.6c0.1,0.4,0.1,1.1,0.1,2h-6.4c0,0.9,0.2,1.7,0.6,2.2
+			c0.4,0.6,1,0.8,1.8,0.8s1.4-0.3,1.8-0.8c0.3-0.3,0.4-0.7,0.5-1.1h1.5c0,0.3-0.2,0.7-0.4,1.1s-0.5,0.7-0.7,1
+			c-0.4,0.5-1,0.8-1.7,0.9c-0.4,0.1-0.8,0.1-1.2,0.1c-1.1,0-2-0.4-2.8-1.2c-0.8-0.8-1.1-2-1.1-3.4c0-1.5,0.4-2.6,1.1-3.5
+			c0.8-0.9,1.8-1.4,3-1.4C170.6,20.8,171.2,20.9,171.8,21.2z M172.3,24.8c-0.1-0.7-0.2-1.2-0.4-1.6c-0.4-0.7-1.1-1.1-2-1.1
+			c-0.7,0-1.2,0.3-1.7,0.8s-0.7,1.1-0.7,1.9C167.5,24.8,172.3,24.8,172.3,24.8z"/>
+		<path class="st2" d="M175.7,21h1.4v1.6c0.1-0.3,0.4-0.7,0.8-1.1c0.4-0.4,1-0.7,1.5-0.7h0.1c0.1,0,0.2,0,0.3,0v1.6
+			c-0.1,0-0.2,0-0.2,0c-0.1,0-0.2,0-0.2,0c-0.7,0-1.3,0.2-1.7,0.7s-0.6,1.1-0.6,1.7V30h-1.5L175.7,21L175.7,21z"/>
+	</g>
+</g>
+</svg>
diff --git a/dolphinscheduler-ui-next/src/router/index.ts b/dolphinscheduler-ui-next/src/layouts/basic/components/header/index.module.scss
similarity index 52%
copy from dolphinscheduler-ui-next/src/router/index.ts
copy to dolphinscheduler-ui-next/src/layouts/basic/components/header/index.module.scss
index ed70ba8..5778fae 100644
--- a/dolphinscheduler-ui-next/src/router/index.ts
+++ b/dolphinscheduler-ui-next/src/layouts/basic/components/header/index.module.scss
@@ -15,40 +15,38 @@
  * limitations under the License.
  */
 
-import {
-  createRouter,
-  createWebHistory,
-  NavigationGuardNext,
-  RouteLocationNormalized,
-} from 'vue-router'
-import routes from './routes'
-
-// NProgress
-import NProgress from 'nprogress'
-import 'nprogress/nprogress.css'
-
-const router = createRouter({
-  history: createWebHistory(),
-  routes,
-})
-
-/**
- * Routing to intercept
- */
-router.beforeEach(
-  async (
-    to: RouteLocationNormalized,
-    from: RouteLocationNormalized,
-    next: NavigationGuardNext
-  ) => {
-    NProgress.start()
-    next()
-    NProgress.done()
+.header-model {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 60px;
+  box-shadow: rgba(0, 0, 0, 0.3) 0px 3px 5px;
+  position: relative;
+  width: 100%;
+  padding: 0px;
+  margin: 0px;
+  .nav {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    width: inherit;
+    .menu {
+      margin-left: 0px;
+      text-align: center;
+      font-size: 15px;
+      color: rgb(255, 255, 255);
+    }
+    .profile {
+      width: 135px;
+      display: flex;
+      justify-content: space-between;
+      margin-right: 20px;
+      text-align: center;
+      .icon {
+        margin-right: 5px;
+        display: inline-flex;
+        align-items: center;
+      }
+    }
   }
-)
-
-router.afterEach(() => {
-  NProgress.done()
-})
-
-export default router
+}
diff --git a/dolphinscheduler-ui-next/src/layouts/basic/components/header/index.tsx b/dolphinscheduler-ui-next/src/layouts/basic/components/header/index.tsx
new file mode 100644
index 0000000..5d076eb
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/layouts/basic/components/header/index.tsx
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+import { defineComponent, ref } from "vue";
+
+import styles from "./index.module.scss";
+import { NDropdown, NIcon, NLayoutHeader, NMenu } from "naive-ui";
+import { Logo } from "@/layouts/basic/components/logo";
+import { IosArrowDown } from "@vicons/ionicons4";
+import { UserAlt } from "@vicons/fa";
+
+const Header = defineComponent({
+  name: "Header",
+  props: {
+    inverted: {
+      type: Boolean,
+      default: true,
+    },
+    menuOptions: {
+      type: Array,
+      default: [],
+    },
+    languageOptions: {
+      type: Array,
+      default: [],
+    },
+    profileOptions: {
+      type: Array,
+      default: [],
+    },
+    currentMenu: {
+      type: Object,
+    },
+    defaultMenuKey: {
+      type: String,
+    },
+  },
+  setup(props, context) {
+    const currentMenuRef = ref({});
+
+    const handleMenuClick = (key, data) => {
+      currentMenuRef.value = data;
+      context.emit("menuClick", data);
+    };
+
+    return { handleMenuClick };
+  },
+  render() {
+    return (
+      <NLayoutHeader
+        class={styles["header-model"]}
+        inverted={this.inverted}
+        bordered
+      >
+        <Logo />
+        <div class={styles.nav}>
+          <NMenu
+            mode="horizontal"
+            onUpdate:value={this.handleMenuClick}
+            defaultValue={this.defaultMenuKey}
+            class={styles.menu}
+            inverted={this.inverted}
+            options={this.menuOptions}
+          />
+          <div class={styles.profile}>
+            <NDropdown inverted={this.inverted} options={this.languageOptions}>
+              <span>
+                中文
+                <NIcon class={styles.icon}>
+                  <IosArrowDown />
+                </NIcon>
+              </span>
+            </NDropdown>
+            <NDropdown inverted={this.inverted} options={this.profileOptions}>
+              <span>
+                <NIcon class={styles.icon}>
+                  <UserAlt />
+                </NIcon>
+                admin
+                <NIcon class={styles.icon}>
+                  <IosArrowDown />
+                </NIcon>
+              </span>
+            </NDropdown>
+          </div>
+        </div>
+      </NLayoutHeader>
+    );
+  },
+});
+
+export { Header };
diff --git a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx b/dolphinscheduler-ui-next/src/layouts/basic/components/logo/index.module.scss
similarity index 71%
copy from dolphinscheduler-ui-next/src/layouts/content/Content.tsx
copy to dolphinscheduler-ui-next/src/layouts/basic/components/logo/index.module.scss
index 8211f18..d7891cb 100644
--- a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx
+++ b/dolphinscheduler-ui-next/src/layouts/basic/components/logo/index.module.scss
@@ -15,20 +15,22 @@
  * limitations under the License.
  */
 
-import { defineComponent } from 'vue'
-import { NLayout, NLayoutContent } from 'naive-ui'
+.logo {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 64px;
+  line-height: 64px;
+  overflow: hidden;
+  white-space: nowrap;
+  width: 280px;
 
-const Content = defineComponent({
-  name: 'Content',
-  render() {
-    return (
-      <NLayout>
-        <NLayoutContent>
-          <router-view />
-        </NLayoutContent>
-      </NLayout>
-    )
-  },
-})
+  img {
+    width: auto;
+    height: 46px;
+  }
 
-export default Content
+  .title {
+    margin-bottom: 0;
+  }
+}
diff --git a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx b/dolphinscheduler-ui-next/src/layouts/basic/components/logo/index.tsx
similarity index 70%
copy from dolphinscheduler-ui-next/src/layouts/content/Content.tsx
copy to dolphinscheduler-ui-next/src/layouts/basic/components/logo/index.tsx
index 8211f18..bac1fae 100644
--- a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx
+++ b/dolphinscheduler-ui-next/src/layouts/basic/components/logo/index.tsx
@@ -15,20 +15,24 @@
  * limitations under the License.
  */
 
-import { defineComponent } from 'vue'
-import { NLayout, NLayoutContent } from 'naive-ui'
+import { defineComponent, ref } from "vue";
 
-const Content = defineComponent({
-  name: 'Content',
+import styles from "./index.module.scss";
+
+const Logo = defineComponent({
+  name: "Logo",
+  setup() {
+    const invertedRef = ref(true);
+
+    return { invertedRef };
+  },
   render() {
     return (
-      <NLayout>
-        <NLayoutContent>
-          <router-view />
-        </NLayoutContent>
-      </NLayout>
-    )
+      <div class={styles.logo}>
+        <img src="../../../src/assets/images/nav-logo.svg" alt="" />
+      </div>
+    );
   },
-})
+});
 
-export default Content
+export { Logo };
diff --git a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx b/dolphinscheduler-ui-next/src/layouts/basic/components/sider/index.module.scss
similarity index 71%
copy from dolphinscheduler-ui-next/src/layouts/content/Content.tsx
copy to dolphinscheduler-ui-next/src/layouts/basic/components/sider/index.module.scss
index 8211f18..9a5d1a3 100644
--- a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx
+++ b/dolphinscheduler-ui-next/src/layouts/basic/components/sider/index.module.scss
@@ -15,20 +15,5 @@
  * limitations under the License.
  */
 
-import { defineComponent } from 'vue'
-import { NLayout, NLayoutContent } from 'naive-ui'
-
-const Content = defineComponent({
-  name: 'Content',
-  render() {
-    return (
-      <NLayout>
-        <NLayoutContent>
-          <router-view />
-        </NLayoutContent>
-      </NLayout>
-    )
-  },
-})
-
-export default Content
+.sider-model {
+}
diff --git a/dolphinscheduler-ui-next/src/layouts/basic/components/sider/index.tsx b/dolphinscheduler-ui-next/src/layouts/basic/components/sider/index.tsx
new file mode 100644
index 0000000..93dd0a6
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/layouts/basic/components/sider/index.tsx
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+import { defineComponent, ref } from "vue";
+import { NLayoutSider, NMenu } from "naive-ui";
+
+const Sider = defineComponent({
+  name: "Sider",
+  props: {
+    visible: {
+      type: Boolean,
+      default: true,
+    },
+    inverted: {
+      type: Boolean,
+      default: true,
+    },
+    menuOptions: {
+      type: Array,
+      default: [],
+    },
+    currentMenu: {
+      type: Object,
+    },
+    defaultMenuKey: {
+      type: String,
+    },
+  },
+  setup(props) {
+    const currentMenuRef = ref({});
+
+    const handleMenuClick = (key, data) => {
+      currentMenuRef.value = data;
+    };
+
+    return { handleMenuClick };
+  },
+  render() {
+    if (this.visible) {
+      return (
+        <NLayoutSider
+          width={240}
+          collapseMode={"width"}
+          collapsedWidth={64}
+          inverted={this.inverted}
+          nativeScrollbar={false}
+          show-trigger
+          bordered
+        >
+          <NMenu
+            onUpdate:value={this.handleMenuClick}
+            inverted={this.inverted}
+            collapsedWidth={64}
+            collapsedIconSize={22}
+            options={this.menuOptions}
+          />
+        </NLayoutSider>
+      );
+    } else {
+      return "";
+    }
+  },
+});
+
+export { Sider };
diff --git a/dolphinscheduler-ui-next/src/router/index.ts b/dolphinscheduler-ui-next/src/layouts/basic/index.module.scss
similarity index 50%
copy from dolphinscheduler-ui-next/src/router/index.ts
copy to dolphinscheduler-ui-next/src/layouts/basic/index.module.scss
index ed70ba8..e7c0589 100644
--- a/dolphinscheduler-ui-next/src/router/index.ts
+++ b/dolphinscheduler-ui-next/src/layouts/basic/index.module.scss
@@ -15,40 +15,40 @@
  * limitations under the License.
  */
 
-import {
-  createRouter,
-  createWebHistory,
-  NavigationGuardNext,
-  RouteLocationNormalized,
-} from 'vue-router'
-import routes from './routes'
-
-// NProgress
-import NProgress from 'nprogress'
-import 'nprogress/nprogress.css'
-
-const router = createRouter({
-  history: createWebHistory(),
-  routes,
-})
-
-/**
- * Routing to intercept
- */
-router.beforeEach(
-  async (
-    to: RouteLocationNormalized,
-    from: RouteLocationNormalized,
-    next: NavigationGuardNext
-  ) => {
-    NProgress.start()
-    next()
-    NProgress.done()
+.container {
+  .header-model {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 60px;
+    box-shadow: rgba(0, 0, 0, 0.3) 0px 3px 5px;
+    position: relative;
+    width: 100%;
+    padding: 0px;
+    margin: 0px;
+    .nav {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      width: inherit;
+      .menu {
+        margin-left: 0px;
+        text-align: center;
+        font-size: 15px;
+        color: rgb(255, 255, 255);
+      }
+      .profile {
+        width: 135px;
+        display: flex;
+        justify-content: space-between;
+        margin-right: 20px;
+        text-align: center;
+        .icon {
+          margin-right: 5px;
+          display: inline-flex;
+          align-items: center;
+        }
+      }
+    }
   }
-)
-
-router.afterEach(() => {
-  NProgress.done()
-})
-
-export default router
+}
diff --git a/dolphinscheduler-ui-next/src/layouts/basic/index.tsx b/dolphinscheduler-ui-next/src/layouts/basic/index.tsx
new file mode 100644
index 0000000..444835d
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/layouts/basic/index.tsx
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+import { h, defineComponent, ref } from "vue";
+import styles from "./index.module.scss";
+import { useI18n } from "vue-i18n";
+import {
+  PersonCircleOutline,
+  LogOutOutline,
+  FileTrayFullOutline,
+  Server,
+  SettingsOutline,
+} from "@vicons/ionicons5";
+import {
+  HomeOutlined,
+  FolderOutlined,
+  SafetyCertificateOutlined,
+  UserOutlined,
+} from "@vicons/antd";
+import { Database, Notes, Users } from "@vicons/tabler";
+import { MonitorFilled, AcUnitOutlined } from "@vicons/material";
+import { Flow } from "@vicons/carbon";
+import { Header } from "./components/header";
+import { Sider } from "./components/sider";
+import { NLayout, NLayoutContent, NIcon } from "naive-ui";
+
+function renderIcon(icon) {
+  return () => h(NIcon, null, { default: () => h(icon) });
+}
+
+const switchLanguageOptions = [
+  {
+    label: "English",
+    key: "en",
+  },
+  {
+    label: "中文",
+    key: "zh",
+  },
+];
+
+const profileOptions = [
+  {
+    label: "用户信息",
+    key: "profile",
+    icon: renderIcon(PersonCircleOutline),
+  },
+  {
+    label: "退出登录",
+    key: "logout",
+    icon: renderIcon(LogOutOutline),
+  },
+];
+
+const menuOptions = [
+  {
+    label: "首页",
+    key: "home",
+    icon: renderIcon(HomeOutlined),
+  },
+  {
+    label: "项目管理",
+    key: "project",
+    icon: renderIcon(Notes),
+    children: [
+      {
+        label: "项目",
+        key: "projects-list",
+        icon: renderIcon(Notes),
+      },
+      {
+        label: "工作流监控",
+        key: "projects-index",
+        icon: renderIcon(Flow),
+      },
+    ],
+  },
+  {
+    label: "资源中心",
+    key: "resources",
+    icon: renderIcon(FolderOutlined),
+    children: [
+      {
+        label: "文件管理",
+        key: "file",
+        icon: renderIcon(FileTrayFullOutline),
+      },
+      {
+        label: "创建资源",
+        key: "resource-file-create",
+        icon: renderIcon(AcUnitOutlined),
+      },
+    ],
+  },
+  {
+    label: "数据源中心",
+    key: "datasource",
+    icon: renderIcon(Database),
+    children: [
+      {
+        label: "数据源中心",
+        key: "datasource-list",
+        icon: renderIcon(Database),
+      },
+    ],
+  },
+  {
+    label: "监控中心",
+    key: "monitor",
+    icon: renderIcon(MonitorFilled),
+    children: [
+      {
+        key: "servers-master",
+        title: "服务管理-Master",
+        icon: renderIcon(Server),
+      },
+      {
+        key: "servers-worker",
+        title: "服务管理-Worker",
+        icon: renderIcon(SettingsOutline),
+      },
+    ],
+  },
+  {
+    label: "安全中心",
+    key: "security",
+    icon: renderIcon(SafetyCertificateOutlined),
+    children: [
+      {
+        key: "tenement-manage",
+        label: "租户管理",
+        icon: renderIcon(UserOutlined),
+      },
+      {
+        key: "users-manage",
+        label: "用户管理",
+        icon: renderIcon(Users),
+      },
+    ],
+  },
+];
+
+const basic = defineComponent({
+  name: "basic",
+  setup() {
+    const invertedRef = ref(true);
+    const hasSiderRef = ref(false);
+    const defaultMenuKeyRef = ref("home");
+    const currentMenuRef = ref({});
+    const topMenuOptionsRef = ref([]);
+    const sideMenuOptionsRef = ref([]);
+
+    const handleTopMenuClick = (data) => {
+      currentMenuRef.value = data;
+      generateMenus();
+    };
+
+    const handleSideMenuClick = (key, data) => {
+      console.log(data);
+    };
+
+    const generateMenus = () => {
+      topMenuOptionsRef.value = [];
+      sideMenuOptionsRef.value = [];
+      hasSiderRef.value = false;
+      menuOptions.forEach((option) => {
+        topMenuOptionsRef.value.push({
+          label: option.label,
+          key: option.key,
+          icon: option.icon,
+        });
+        if (
+          currentMenuRef.value.key === option.key ||
+          defaultMenuKeyRef.value === option.key
+        ) {
+          if (option.hasOwnProperty("children") && option.children) {
+            sideMenuOptionsRef.value = option.children;
+            hasSiderRef.value = true;
+          }
+        }
+      });
+    };
+    generateMenus();
+    return {
+      topMenuOptionsRef,
+      sideMenuOptionsRef,
+      invertedRef,
+      hasSiderRef,
+      defaultMenuKeyRef,
+      handleTopMenuClick,
+      handleSideMenuClick,
+    };
+  },
+  render() {
+    return (
+      <NLayout class={styles.container}>
+        <Header
+          languageOptions={switchLanguageOptions}
+          profileOptions={profileOptions}
+          menuOptions={this.topMenuOptionsRef}
+          inverted={this.invertedRef}
+          defaultMenuKey={this.defaultMenuKeyRef}
+          onMenuClick={this.handleTopMenuClick}
+        />
+        <NLayout hasSider>
+          <Sider
+            visible={this.hasSiderRef}
+            inverted={this.invertedRef}
+            menuOptions={this.sideMenuOptionsRef}
+          />
+          <NLayoutContent>
+            <router-view />
+          </NLayoutContent>
+        </NLayout>
+      </NLayout>
+    );
+  },
+});
+
+export default basic;
diff --git a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx b/dolphinscheduler-ui-next/src/layouts/content/Content.tsx
index 8211f18..b1daebc 100644
--- a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx
+++ b/dolphinscheduler-ui-next/src/layouts/content/Content.tsx
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-import { defineComponent } from 'vue'
-import { NLayout, NLayoutContent } from 'naive-ui'
+import { defineComponent } from "vue";
+import { NLayout, NLayoutContent } from "naive-ui";
 
 const Content = defineComponent({
-  name: 'Content',
+  name: "Content",
   render() {
     return (
       <NLayout>
@@ -27,8 +27,8 @@ const Content = defineComponent({
           <router-view />
         </NLayoutContent>
       </NLayout>
-    )
+    );
   },
-})
+});
 
-export default Content
+export default Content;
diff --git a/dolphinscheduler-ui-next/src/router/index.ts b/dolphinscheduler-ui-next/src/router/index.ts
index ed70ba8..7aa6948 100644
--- a/dolphinscheduler-ui-next/src/router/index.ts
+++ b/dolphinscheduler-ui-next/src/router/index.ts
@@ -20,17 +20,17 @@ import {
   createWebHistory,
   NavigationGuardNext,
   RouteLocationNormalized,
-} from 'vue-router'
-import routes from './routes'
+} from "vue-router";
+import routes from "./routes";
 
 // NProgress
-import NProgress from 'nprogress'
-import 'nprogress/nprogress.css'
+import NProgress from "nprogress";
+import "nprogress/nprogress.css";
 
 const router = createRouter({
   history: createWebHistory(),
   routes,
-})
+});
 
 /**
  * Routing to intercept
@@ -41,14 +41,14 @@ router.beforeEach(
     from: RouteLocationNormalized,
     next: NavigationGuardNext
   ) => {
-    NProgress.start()
-    next()
-    NProgress.done()
+    NProgress.start();
+    next();
+    NProgress.done();
   }
-)
+);
 
 router.afterEach(() => {
-  NProgress.done()
-})
+  NProgress.done();
+});
 
-export default router
+export default router;
diff --git a/dolphinscheduler-ui-next/src/router/routes.ts b/dolphinscheduler-ui-next/src/router/routes.ts
index 01535f9..a92bb4d 100644
--- a/dolphinscheduler-ui-next/src/router/routes.ts
+++ b/dolphinscheduler-ui-next/src/router/routes.ts
@@ -15,44 +15,189 @@
  * limitations under the License.
  */
 
-import type { RouteRecordRaw } from 'vue-router'
-import type { Component } from 'vue'
-import utils from '@/utils'
+import type { RouteRecordRaw } from "vue-router";
+import type { Component } from "vue";
+import utils from "@/utils";
+import { useI18n } from "vue-i18n";
 
 // All TSX files under the views folder automatically generate mapping relationship
-const modules = import.meta.glob('/src/views/**/**.tsx')
-const components: { [key: string]: Component } = utils.mapping(modules)
+const modules = import.meta.glob("/src/views/**/**.tsx");
+const components: { [key: string]: Component } = utils.mapping(modules);
 
 /**
  * Basic page
  */
 const basePage: RouteRecordRaw[] = [
   {
-    path: '/',
-    redirect: { name: 'home' },
-    component: () => import('@/layouts/content/Content'),
+    path: "/",
+    redirect: { name: "home" },
+    meta: { title: "首页" },
+    component: () => import("@/layouts/basic"),
     children: [
       {
-        path: '/home',
-        name: 'home',
-        component: components['home'],
+        path: "/home",
+        name: "home",
+        component: components["home"],
+        meta: {
+          title: "首页",
+        },
       },
     ],
   },
-]
+];
+
+const projectsPage = [
+  {
+    path: "/projects",
+    name: "projects",
+    redirect: { name: "projects-list" },
+    meta: { title: "项目管理" },
+    component: () => import("@/layouts/basic"),
+    children: [
+      {
+        path: "/projects/list",
+        name: "projects-list",
+        component: components["home"],
+        meta: {
+          title: "项目",
+        },
+      },
+      {
+        path: "/projects/:projectCode/index",
+        name: "projects-index",
+        component: components["home"],
+        meta: {
+          title: "工作流监控",
+        },
+      },
+    ],
+  },
+];
+
+const resourcesPage = [
+  {
+    path: "/resource",
+    name: "resource",
+    redirect: { name: "file" },
+    meta: { title: "资源中心" },
+    component: () => import("@/layouts/basic"),
+    children: [
+      {
+        path: "/resource/file",
+        name: "file",
+        component: components["home"],
+        meta: {
+          title: "文件管理",
+        },
+      },
+      {
+        path: "/resource/file/create",
+        name: "resource-file-create",
+        component: components["home"],
+        meta: {
+          title: "创建资源",
+        },
+      },
+    ],
+  },
+];
+
+const datasourcePage = [
+  {
+    path: "/datasource",
+    name: "datasource",
+    redirect: { name: "datasource-list" },
+    meta: { title: "数据源中心" },
+    component: () => import("@/layouts/basic"),
+    children: [
+      {
+        path: "/datasource/list",
+        name: "datasource-list",
+        component: components["home"],
+        meta: {
+          title: "数据源中心",
+        },
+      },
+    ],
+  },
+];
+
+const monitorPage = [
+  {
+    path: "/monitor",
+    name: "monitor",
+    meta: { title: "monitor" },
+    redirect: { name: "servers-master" },
+    component: () => import("@/layouts/basic"),
+    children: [
+      {
+        path: "/monitor/servers/master",
+        name: "servers-master",
+        component: components["home"],
+        meta: {
+          title: "服务管理-Master",
+        },
+      },
+      {
+        path: "/monitor/servers/worker",
+        name: "servers-worker",
+        component: components["home"],
+        meta: {
+          title: "服务管理-Worker",
+        },
+      },
+    ],
+  },
+];
+
+const securityPage: RouteRecordRaw[] = [
+  {
+    path: "/security",
+    name: "security",
+    meta: { title: "安全中心" },
+    redirect: { name: "tenement-manage" },
+    component: () => import("@/layouts/basicLayout"),
+    children: [
+      {
+        path: "/security/tenant",
+        name: "tenement-manage",
+        component: components["home"],
+        meta: {
+          title: "租户管理",
+        },
+      },
+      {
+        path: "/security/users",
+        name: "users-manage",
+        component: components["home"],
+        meta: {
+          title: "用户管理",
+        },
+      },
+    ],
+  },
+];
 
 /**
  * Login page
  */
 const loginPage: RouteRecordRaw[] = [
   {
-    path: '/login',
-    name: 'login',
-    component: components['login'],
+    path: "/login",
+    name: "login",
+    component: components["login"],
   },
-]
+];
 
-const routes: RouteRecordRaw[] = [...basePage, ...loginPage]
+const routes: RouteRecordRaw[] = [
+  ...basePage,
+  ...loginPage,
+  ...projectsPage,
+  ...resourcesPage,
+  ...datasourcePage,
+  ...monitorPage,
+  ...securityPage,
+];
 
 // 重新组织后导出
-export default routes
+export default routes;
diff --git a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx b/dolphinscheduler-ui-next/src/store/route/route.ts
similarity index 57%
copy from dolphinscheduler-ui-next/src/layouts/content/Content.tsx
copy to dolphinscheduler-ui-next/src/store/route/route.ts
index 8211f18..5ef26a5 100644
--- a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx
+++ b/dolphinscheduler-ui-next/src/store/route/route.ts
@@ -15,20 +15,32 @@
  * limitations under the License.
  */
 
-import { defineComponent } from 'vue'
-import { NLayout, NLayoutContent } from 'naive-ui'
+import { toRaw } from "vue";
+import { defineStore } from "pinia";
+import RouteState from "./types";
+import { RouteRecordRaw } from "vue-router";
 
-const Content = defineComponent({
-  name: 'Content',
-  render() {
-    return (
-      <NLayout>
-        <NLayoutContent>
-          <router-view />
-        </NLayoutContent>
-      </NLayout>
-    )
+export const useAsyncRouteStore = defineStore({
+  id: "route",
+  state: (): RouteState => ({
+    menus: [],
+    routers: [],
+    addRouters: [],
+  }),
+  getters: {
+    getMenus(): RouteRecordRaw[] {
+      return this.menus;
+    },
+    getRouters(): RouteRecordRaw[] {
+      return toRaw(this.addRouters);
+    },
   },
-})
-
-export default Content
+  actions: {
+    setMenus(menus) {
+      this.menus = menus;
+    },
+    async generateRouters(routes) {
+      console.log(routes);
+    },
+  },
+});
diff --git a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx b/dolphinscheduler-ui-next/src/store/route/types.ts
similarity index 71%
copy from dolphinscheduler-ui-next/src/layouts/content/Content.tsx
copy to dolphinscheduler-ui-next/src/store/route/types.ts
index 8211f18..86fbc6a 100644
--- a/dolphinscheduler-ui-next/src/layouts/content/Content.tsx
+++ b/dolphinscheduler-ui-next/src/store/route/types.ts
@@ -14,21 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import { RouteRecordRaw } from "vue-router";
 
-import { defineComponent } from 'vue'
-import { NLayout, NLayoutContent } from 'naive-ui'
+interface RouteState {
+  menus: RouteRecordRaw[];
+  routers: any[];
+  addRouters: any[];
+}
 
-const Content = defineComponent({
-  name: 'Content',
-  render() {
-    return (
-      <NLayout>
-        <NLayoutContent>
-          <router-view />
-        </NLayoutContent>
-      </NLayout>
-    )
-  },
-})
-
-export default Content
+export default RouteState;