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

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-booster-ui.git


The following commit(s) were added to refs/heads/main by this push:
     new a7972af3 refactor: optimize the router system and implement unit tests 
for router (#495)
a7972af3 is described below

commit a7972af3b43649a3770c43be92a0350298e288ec
Author: Fine0830 <fanxue0...@gmail.com>
AuthorDate: Thu Aug 28 21:11:46 2025 +0800

    refactor: optimize the router system and implement unit tests for router 
(#495)
---
 package.json                               |   1 +
 src/App.vue                                |   2 +-
 src/__tests__/App.spec.ts                  |  12 +-
 src/layout/components/SideBar.vue          |   2 +-
 src/router/__tests__/constants.spec.ts     | 231 +++++++++++++
 src/router/__tests__/guards.spec.ts        | 253 ++++++++++++++
 src/router/__tests__/index.spec.ts         | 263 +++++++++++++++
 src/router/__tests__/route-modules.spec.ts | 518 +++++++++++++++++++++++++++++
 src/router/__tests__/utils.spec.ts         | 465 ++++++++++++++++++++++++++
 src/router/alarm.ts                        |  24 +-
 src/router/constants.ts                    |  60 ++++
 src/router/dashboard.ts                    | 203 +++++++----
 src/router/guards.ts                       |  98 ++++++
 src/router/index.ts                        |  43 +--
 src/router/layer.ts                        | 109 +++---
 src/router/marketplace.ts                  |  24 +-
 src/router/notFound.ts                     |  13 +-
 src/router/settings.ts                     |  24 +-
 src/router/utils.ts                        | 102 ++++++
 src/{router/alarm.ts => types/router.ts}   |  55 +--
 20 files changed, 2309 insertions(+), 193 deletions(-)

diff --git a/package.json b/package.json
index 86d91236..6568018e 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
     "test:hooks": "vitest --environment jsdom src/hooks/**/*.spec.ts",
     "test:stores": "vitest --environment jsdom src/store/**/*.spec.ts",
     "test:views": "vitest --environment jsdom src/views/**/*.spec.ts",
+    "test:router": "vitest --environment jsdom src/router/**/*.spec.ts",
     "test:all": "vitest --environment jsdom --root src/ --coverage 
--reporter=verbose",
     "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 
'cypress open --e2e'"
   },
diff --git a/src/App.vue b/src/App.vue
index 19b8887f..fc5b1226 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -20,7 +20,7 @@ limitations under the License. -->
   const route = useRoute();
 
   setTimeout(() => {
-    if (route.name === "ViewWidget") {
+    if (route.name === "DashboardViewWidget") {
       (document.querySelector("#app") as any).style.minWidth = "120px";
     } else {
       (document.querySelector("#app") as any).style.minWidth = "1024px";
diff --git a/src/__tests__/App.spec.ts b/src/__tests__/App.spec.ts
index f1a083c2..a4824c08 100644
--- a/src/__tests__/App.spec.ts
+++ b/src/__tests__/App.spec.ts
@@ -62,8 +62,8 @@ describe("App Component", () => {
     expect(wrapper.find("router-view").exists()).toBe(true);
   });
 
-  it("should set minWidth to 120px for ViewWidget route", async () => {
-    mockRoute.name = "ViewWidget";
+  it("should set minWidth to 120px for DashboardViewWidget route", async () => 
{
+    mockRoute.name = "DashboardViewWidget";
 
     const wrapper = mount(App);
 
@@ -77,7 +77,7 @@ describe("App Component", () => {
     }
   });
 
-  it("should set minWidth to 1024px for non-ViewWidget routes", async () => {
+  it("should set minWidth to 1024px for non-DashboardViewWidget routes", async 
() => {
     mockRoute.name = "Dashboard";
 
     const wrapper = mount(App);
@@ -121,7 +121,7 @@ describe("App Component", () => {
     // Unmount and remount with different route
     wrapper.unmount();
 
-    mockRoute.name = "ViewWidget";
+    mockRoute.name = "DashboardViewWidget";
     vi.mocked(useRoute).mockReturnValue(mockRoute);
 
     const wrapper2 = mount(App);
@@ -136,7 +136,7 @@ describe("App Component", () => {
 
   it("should handle multiple route changes", async () => {
     // Test multiple route changes by remounting
-    const routes = ["Home", "ViewWidget", "Dashboard", "ViewWidget"];
+    const routes = ["Home", "DashboardViewWidget", "Dashboard", 
"DashboardViewWidget"];
     let wrapper: any = null;
 
     for (const routeName of routes) {
@@ -153,7 +153,7 @@ describe("App Component", () => {
 
       const appElement = document.querySelector("#app");
       if (appElement) {
-        const expectedWidth = routeName === "ViewWidget" ? "120px" : "1024px";
+        const expectedWidth = routeName === "DashboardViewWidget" ? "120px" : 
"1024px";
         expect((appElement as HTMLElement).style.minWidth).toBe(expectedWidth);
       }
     }
diff --git a/src/layout/components/SideBar.vue 
b/src/layout/components/SideBar.vue
index 8f6f3ab5..955f847f 100644
--- a/src/layout/components/SideBar.vue
+++ b/src/layout/components/SideBar.vue
@@ -96,7 +96,7 @@ limitations under the License. -->
   } else {
     appStore.setIsMobile(false);
   }
-  if (route.name === "ViewWidget") {
+  if (route.name === "DashboardViewWidget") {
     showMenu.value = false;
   }
 
diff --git a/src/router/__tests__/constants.spec.ts 
b/src/router/__tests__/constants.spec.ts
new file mode 100644
index 00000000..0cc4165d
--- /dev/null
+++ b/src/router/__tests__/constants.spec.ts
@@ -0,0 +1,231 @@
+/**
+ * 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 { describe, it, expect } from "vitest";
+import { ROUTE_NAMES, ROUTE_PATHS, META_KEYS, DEFAULT_ROUTE } from 
"../constants";
+
+describe("Router Constants", () => {
+  describe("ROUTE_NAMES", () => {
+    it("should define all required route names", () => {
+      expect(ROUTE_NAMES).toHaveProperty("MARKETPLACE");
+      expect(ROUTE_NAMES).toHaveProperty("DASHBOARD");
+      expect(ROUTE_NAMES).toHaveProperty("ALARM");
+      expect(ROUTE_NAMES).toHaveProperty("SETTINGS");
+      expect(ROUTE_NAMES).toHaveProperty("NOT_FOUND");
+      expect(ROUTE_NAMES).toHaveProperty("LAYER");
+    });
+
+    it("should have correct route name values", () => {
+      expect(ROUTE_NAMES.MARKETPLACE).toBe("Marketplace");
+      expect(ROUTE_NAMES.DASHBOARD).toBe("Dashboard");
+      expect(ROUTE_NAMES.ALARM).toBe("Alarm");
+      expect(ROUTE_NAMES.SETTINGS).toBe("Settings");
+      expect(ROUTE_NAMES.NOT_FOUND).toBe("NotFound");
+      expect(ROUTE_NAMES.LAYER).toBe("Layer");
+    });
+
+    it("should be defined as constants", () => {
+      // Note: Constants are not actually frozen in the implementation
+      // but they should be treated as constants by convention
+      expect(ROUTE_NAMES).toBeDefined();
+      expect(typeof ROUTE_NAMES).toBe("object");
+    });
+  });
+
+  describe("ROUTE_PATHS", () => {
+    it("should define root path", () => {
+      expect(ROUTE_PATHS).toHaveProperty("ROOT");
+      expect(ROUTE_PATHS.ROOT).toBe("/");
+    });
+
+    it("should define marketplace path", () => {
+      expect(ROUTE_PATHS).toHaveProperty("MARKETPLACE");
+      expect(ROUTE_PATHS.MARKETPLACE).toBe("/marketplace");
+    });
+
+    it("should define dashboard paths", () => {
+      expect(ROUTE_PATHS).toHaveProperty("DASHBOARD");
+      expect(ROUTE_PATHS.DASHBOARD).toHaveProperty("LIST");
+      expect(ROUTE_PATHS.DASHBOARD).toHaveProperty("NEW");
+      expect(ROUTE_PATHS.DASHBOARD).toHaveProperty("EDIT");
+      expect(ROUTE_PATHS.DASHBOARD).toHaveProperty("VIEW");
+      expect(ROUTE_PATHS.DASHBOARD).toHaveProperty("WIDGET");
+    });
+
+    it("should have correct dashboard path values", () => {
+      expect(ROUTE_PATHS.DASHBOARD.LIST).toBe("/dashboard/list");
+      expect(ROUTE_PATHS.DASHBOARD.NEW).toBe("/dashboard/new");
+      
expect(ROUTE_PATHS.DASHBOARD.EDIT).toBe("/dashboard/:layerId/:entity/:name");
+      
expect(ROUTE_PATHS.DASHBOARD.VIEW).toBe("/dashboard/:layerId/:entity/:serviceId/:name");
+      expect(ROUTE_PATHS.DASHBOARD.WIDGET).toBe(
+        
"/page/:layer/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:config/:duration?",
+      );
+    });
+
+    it("should define alarm path", () => {
+      expect(ROUTE_PATHS).toHaveProperty("ALARM");
+      expect(ROUTE_PATHS.ALARM).toBe("/alerting");
+    });
+
+    it("should define settings path", () => {
+      expect(ROUTE_PATHS).toHaveProperty("SETTINGS");
+      expect(ROUTE_PATHS.SETTINGS).toBe("/settings");
+    });
+
+    it("should define not found path", () => {
+      expect(ROUTE_PATHS).toHaveProperty("NOT_FOUND");
+      expect(ROUTE_PATHS.NOT_FOUND).toBe("/:pathMatch(.*)*");
+    });
+
+    it("should be defined as constants", () => {
+      // Note: Constants are not actually frozen in the implementation
+      // but they should be treated as constants by convention
+      expect(ROUTE_PATHS).toBeDefined();
+      expect(typeof ROUTE_PATHS).toBe("object");
+      expect(ROUTE_PATHS.DASHBOARD).toBeDefined();
+    });
+  });
+
+  describe("META_KEYS", () => {
+    it("should define all required meta keys", () => {
+      expect(META_KEYS).toHaveProperty("I18N_KEY");
+      expect(META_KEYS).toHaveProperty("ICON");
+      expect(META_KEYS).toHaveProperty("HAS_GROUP");
+      expect(META_KEYS).toHaveProperty("ACTIVATE");
+      expect(META_KEYS).toHaveProperty("TITLE");
+      expect(META_KEYS).toHaveProperty("DESC_KEY");
+      expect(META_KEYS).toHaveProperty("LAYER");
+      expect(META_KEYS).toHaveProperty("NOT_SHOW");
+      expect(META_KEYS).toHaveProperty("REQUIRES_AUTH");
+      expect(META_KEYS).toHaveProperty("BREADCRUMB");
+    });
+
+    it("should have correct meta key values", () => {
+      expect(META_KEYS.I18N_KEY).toBe("i18nKey");
+      expect(META_KEYS.ICON).toBe("icon");
+      expect(META_KEYS.HAS_GROUP).toBe("hasGroup");
+      expect(META_KEYS.ACTIVATE).toBe("activate");
+      expect(META_KEYS.TITLE).toBe("title");
+      expect(META_KEYS.DESC_KEY).toBe("descKey");
+      expect(META_KEYS.LAYER).toBe("layer");
+      expect(META_KEYS.NOT_SHOW).toBe("notShow");
+      expect(META_KEYS.REQUIRES_AUTH).toBe("requiresAuth");
+      expect(META_KEYS.BREADCRUMB).toBe("breadcrumb");
+    });
+
+    it("should be defined as constants", () => {
+      // Note: Constants are not actually frozen in the implementation
+      // but they should be treated as constants by convention
+      expect(META_KEYS).toBeDefined();
+      expect(typeof META_KEYS).toBe("object");
+    });
+  });
+
+  describe("DEFAULT_ROUTE", () => {
+    it("should be defined", () => {
+      expect(DEFAULT_ROUTE).toBeDefined();
+    });
+
+    it("should match marketplace path", () => {
+      expect(DEFAULT_ROUTE).toBe(ROUTE_PATHS.MARKETPLACE);
+    });
+
+    it("should be defined as a constant", () => {
+      // Note: Constants are not actually frozen in the implementation
+      // but they should be treated as constants by convention
+      expect(DEFAULT_ROUTE).toBeDefined();
+      expect(typeof DEFAULT_ROUTE).toBe("string");
+    });
+  });
+
+  describe("Constants Integration", () => {
+    it("should have consistent route names and paths", () => {
+      // Check that route names correspond to actual route paths
+      expect(ROUTE_NAMES.MARKETPLACE).toBe("Marketplace");
+      expect(ROUTE_PATHS.MARKETPLACE).toBe("/marketplace");
+
+      expect(ROUTE_NAMES.DASHBOARD).toBe("Dashboard");
+      expect(ROUTE_PATHS.DASHBOARD.LIST).toBe("/dashboard/list");
+
+      expect(ROUTE_NAMES.ALARM).toBe("Alarm");
+      expect(ROUTE_PATHS.ALARM).toBe("/alerting");
+
+      expect(ROUTE_NAMES.SETTINGS).toBe("Settings");
+      expect(ROUTE_PATHS.SETTINGS).toBe("/settings");
+    });
+
+    it("should have valid path patterns", () => {
+      // Check that parameterized paths have valid syntax
+      
expect(ROUTE_PATHS.DASHBOARD.EDIT).toMatch(/^\/dashboard\/:[^/]+\/:[^/]+\/:[^/]+$/);
+      
expect(ROUTE_PATHS.DASHBOARD.VIEW).toMatch(/^\/dashboard\/:[^/]+\/:[^/]+\/:[^/]+\/:[^/]+$/);
+      expect(ROUTE_PATHS.DASHBOARD.WIDGET).toMatch(
+        
/^\/page\/:[^/]+\/:[^/]+\/:[^/]+\/:[^/]+\/:[^/]+\/:[^/]+\/:[^/]+\/:[^/]+\/:[^/]+\/:[^/]+\/?$/,
+      );
+    });
+
+    it("should have consistent meta key usage", () => {
+      // Check that meta keys are used consistently across route definitions
+      const expectedMetaKeys = Object.values(META_KEYS);
+      expect(expectedMetaKeys).toContain("i18nKey");
+      expect(expectedMetaKeys).toContain("icon");
+      expect(expectedMetaKeys).toContain("hasGroup");
+      expect(expectedMetaKeys).toContain("activate");
+      expect(expectedMetaKeys).toContain("title");
+      expect(expectedMetaKeys).toContain("breadcrumb");
+    });
+  });
+
+  describe("Type Safety", () => {
+    it("should have consistent string types", () => {
+      // All route names should be strings
+      Object.values(ROUTE_NAMES).forEach((value) => {
+        expect(typeof value).toBe("string");
+      });
+
+      // All meta keys should be strings
+      Object.values(META_KEYS).forEach((value) => {
+        expect(typeof value).toBe("string");
+      });
+
+      // Root path should be string
+      expect(typeof ROUTE_PATHS.ROOT).toBe("string");
+
+      // Default route should be string
+      expect(typeof DEFAULT_ROUTE).toBe("string");
+    });
+
+    it("should have non-empty values", () => {
+      // All route names should be non-empty
+      Object.values(ROUTE_NAMES).forEach((value) => {
+        expect(value).toBeTruthy();
+        expect(value.length).toBeGreaterThan(0);
+      });
+
+      // All meta keys should be non-empty
+      Object.values(META_KEYS).forEach((value) => {
+        expect(value).toBeTruthy();
+        expect(value.length).toBeGreaterThan(0);
+      });
+
+      // All paths should be non-empty
+      expect(ROUTE_PATHS.ROOT).toBeTruthy();
+      expect(ROUTE_PATHS.MARKETPLACE).toBeTruthy();
+      expect(ROUTE_PATHS.ALARM).toBeTruthy();
+      expect(ROUTE_PATHS.SETTINGS).toBeTruthy();
+    });
+  });
+});
diff --git a/src/router/__tests__/guards.spec.ts 
b/src/router/__tests__/guards.spec.ts
new file mode 100644
index 00000000..e3d073a8
--- /dev/null
+++ b/src/router/__tests__/guards.spec.ts
@@ -0,0 +1,253 @@
+/**
+ * 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 { describe, it, expect, vi, beforeEach } from "vitest";
+import { createRootGuard, createAuthGuard, createValidationGuard, 
createErrorGuard, applyGuards } from "../guards";
+import { getDefaultRoute } from "../utils";
+import { ROUTE_PATHS } from "../constants";
+
+// Mock utils
+vi.mock("../utils", () => ({
+  getDefaultRoute: vi.fn(),
+}));
+
+describe("Router Guards", () => {
+  const mockNext = vi.fn();
+  const mockRoutes = [
+    { path: "/marketplace", name: "Marketplace" },
+    { path: "/dashboard", name: "Dashboard" },
+  ];
+
+  beforeEach(() => {
+    vi.clearAllMocks();
+    (getDefaultRoute as any).mockReturnValue("/marketplace");
+  });
+
+  describe("createRootGuard", () => {
+    it("should redirect root path to default route", () => {
+      const rootGuard = createRootGuard(mockRoutes);
+      const to = { path: ROUTE_PATHS.ROOT };
+      const from = { path: "/some-path" };
+
+      rootGuard(to, from, mockNext);
+
+      expect(getDefaultRoute).toHaveBeenCalledWith(mockRoutes);
+      expect(mockNext).toHaveBeenCalledWith({ path: "/marketplace" });
+    });
+
+    it("should allow non-root paths to pass through", () => {
+      const rootGuard = createRootGuard(mockRoutes);
+      const to = { path: "/dashboard" };
+      const from = { path: "/some-path" };
+
+      rootGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith();
+    });
+
+    it("should handle different default routes", () => {
+      (getDefaultRoute as any).mockReturnValue("/dashboard");
+      const rootGuard = createRootGuard(mockRoutes);
+      const to = { path: ROUTE_PATHS.ROOT };
+      const from = { path: "/some-path" };
+
+      rootGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith({ path: "/dashboard" });
+    });
+  });
+
+  describe("createAuthGuard", () => {
+    it("should allow all routes to pass through (placeholder implementation)", 
() => {
+      const authGuard = createAuthGuard();
+      const to = { path: "/protected", meta: { requiresAuth: true } };
+      const from = { path: "/some-path" };
+
+      authGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith();
+    });
+
+    it("should handle routes without auth requirements", () => {
+      const authGuard = createAuthGuard();
+      const to = { path: "/public", meta: {} };
+      const from = { path: "/some-path" };
+
+      authGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith();
+    });
+
+    it("should handle routes with requiresAuth: false", () => {
+      const authGuard = createAuthGuard();
+      const to = { path: "/public", meta: { requiresAuth: false } };
+      const from = { path: "/some-path" };
+
+      authGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith();
+    });
+  });
+
+  describe("createValidationGuard", () => {
+    it("should allow routes without parameters to pass through", () => {
+      const validationGuard = createValidationGuard();
+      const to = { path: "/simple", params: {} };
+      const from = { path: "/some-path" };
+
+      validationGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith();
+    });
+
+    it("should allow routes with valid parameters to pass through", () => {
+      const validationGuard = createValidationGuard();
+      const to = { path: "/valid", params: { id: "123", name: "test" } };
+      const from = { path: "/some-path" };
+
+      validationGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith();
+    });
+
+    it("should redirect to NotFound for routes with invalid parameters", () => 
{
+      const validationGuard = createValidationGuard();
+      const to = { path: "/invalid", params: { id: "", name: null } };
+      const from = { path: "/some-path" };
+
+      validationGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith({ name: "NotFound" });
+    });
+
+    it("should redirect to NotFound for routes with undefined parameters", () 
=> {
+      const validationGuard = createValidationGuard();
+      const to = { path: "/invalid", params: { id: undefined } };
+      const from = { path: "/some-path" };
+
+      validationGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith({ name: "NotFound" });
+    });
+
+    it("should handle mixed valid and invalid parameters", () => {
+      const validationGuard = createValidationGuard();
+      const to = { path: "/mixed", params: { id: "123", name: "" } };
+      const from = { path: "/some-path" };
+
+      validationGuard(to, from, mockNext);
+
+      expect(mockNext).toHaveBeenCalledWith({ name: "NotFound" });
+    });
+  });
+
+  describe("createErrorGuard", () => {
+    it("should handle NavigationDuplicated errors silently", () => {
+      const errorGuard = createErrorGuard();
+      const error = { name: "NavigationDuplicated" };
+
+      expect(() => errorGuard(error)).not.toThrow();
+    });
+
+    it("should re-throw non-NavigationDuplicated errors", () => {
+      const errorGuard = createErrorGuard();
+      const error = { name: "OtherError", message: "Something went wrong" };
+
+      expect(() => errorGuard(error)).toThrow();
+    });
+
+    it("should log router errors", () => {
+      const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => 
{});
+      const errorGuard = createErrorGuard();
+      const error = { name: "TestError", message: "Test error" };
+
+      try {
+        errorGuard(error);
+      } catch {
+        // Expected to throw
+      }
+
+      expect(consoleSpy).toHaveBeenCalledWith("Router error:", error);
+      consoleSpy.mockRestore();
+    });
+  });
+
+  describe("applyGuards", () => {
+    it("should apply all navigation guards to router", () => {
+      const mockRouter = {
+        beforeEach: vi.fn(),
+        onError: vi.fn(),
+      };
+
+      applyGuards(mockRouter, mockRoutes);
+
+      expect(mockRouter.beforeEach).toHaveBeenCalledTimes(3);
+      expect(mockRouter.onError).toHaveBeenCalledTimes(1);
+    });
+
+    it("should apply guards in correct order", () => {
+      const mockRouter = {
+        beforeEach: vi.fn(),
+        onError: vi.fn(),
+      };
+
+      applyGuards(mockRouter, mockRoutes);
+
+      // Verify the order: rootGuard, authGuard, validationGuard
+      const calls = mockRouter.beforeEach.mock.calls;
+      expect(calls).toHaveLength(3);
+    });
+
+    it("should apply error guard", () => {
+      const mockRouter = {
+        beforeEach: vi.fn(),
+        onError: vi.fn(),
+      };
+
+      applyGuards(mockRouter, mockRoutes);
+
+      expect(mockRouter.onError).toHaveBeenCalledWith(expect.any(Function));
+    });
+  });
+
+  describe("Guard Integration", () => {
+    it("should work together without conflicts", () => {
+      const mockRouter = {
+        beforeEach: vi.fn(),
+        onError: vi.fn(),
+      };
+
+      // Apply all guards
+      applyGuards(mockRouter, mockRoutes);
+
+      // Test root guard
+      const rootGuard = mockRouter.beforeEach.mock.calls[0][0];
+      const to = { path: ROUTE_PATHS.ROOT };
+      const from = { path: "/some-path" };
+
+      rootGuard(to, from, mockNext);
+      expect(mockNext).toHaveBeenCalledWith({ path: "/marketplace" });
+
+      // Test validation guard
+      const validationGuard = mockRouter.beforeEach.mock.calls[2][0];
+      const validTo = { path: "/valid", params: { id: "123" } };
+
+      validationGuard(validTo, from, mockNext);
+      expect(mockNext).toHaveBeenCalledWith();
+    });
+  });
+});
diff --git a/src/router/__tests__/index.spec.ts 
b/src/router/__tests__/index.spec.ts
new file mode 100644
index 00000000..5cae65f2
--- /dev/null
+++ b/src/router/__tests__/index.spec.ts
@@ -0,0 +1,263 @@
+/**
+ * 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 { describe, it, expect, vi } from "vitest";
+import { META_KEYS } from "../constants";
+
+// Mock route modules to avoid Vue component import issues
+vi.mock("../dashboard", () => ({
+  routesDashboard: [
+    {
+      name: "Dashboard",
+      path: "/dashboard",
+      meta: {
+        title: "Dashboards",
+        i18nKey: "dashboards",
+        icon: "dashboard_customize",
+        hasGroup: true,
+        activate: true,
+        breadcrumb: true,
+      },
+    },
+  ],
+}));
+
+vi.mock("../marketplace", () => ({
+  routesMarketplace: [
+    {
+      name: "Marketplace",
+      path: "/marketplace",
+      meta: {
+        title: "Marketplace",
+        i18nKey: "marketplace",
+        icon: "marketplace",
+        hasGroup: false,
+        activate: true,
+        breadcrumb: true,
+      },
+    },
+  ],
+}));
+
+vi.mock("../alarm", () => ({
+  routesAlarm: [
+    {
+      name: "Alarm",
+      path: "/alarm",
+      meta: {
+        title: "Alarm",
+        i18nKey: "alarm",
+        icon: "alarm",
+        hasGroup: true,
+        activate: true,
+        breadcrumb: true,
+      },
+    },
+  ],
+}));
+
+vi.mock("../layer", () => ({
+  default: [
+    {
+      name: "Layer",
+      path: "/layer",
+      meta: {
+        title: "Layer",
+        i18nKey: "layer",
+        icon: "layers",
+        hasGroup: false,
+        activate: true,
+        breadcrumb: true,
+      },
+    },
+  ],
+}));
+
+vi.mock("../settings", () => ({
+  routesSettings: [
+    {
+      name: "Settings",
+      path: "/settings",
+      meta: {
+        title: "Settings",
+        i18nKey: "settings",
+        icon: "settings",
+        hasGroup: false,
+        activate: true,
+        breadcrumb: true,
+      },
+    },
+  ],
+}));
+
+vi.mock("../notFound", () => ({
+  routesNotFound: [
+    {
+      name: "NotFound",
+      path: "/:pathMatch(.*)*",
+      meta: {
+        title: "Not Found",
+        i18nKey: "notFound",
+        icon: "error",
+        hasGroup: false,
+        activate: false,
+        breadcrumb: false,
+      },
+    },
+  ],
+}));
+
+// Mock guards
+vi.mock("../guards", () => ({
+  applyGuards: vi.fn(),
+}));
+
+// Mock environment
+vi.mock("import.meta.env", () => ({
+  BASE_URL: "/",
+}));
+
+// Import after mocks
+import { routes } from "../index";
+
+describe("Router Index - Route Structure", () => {
+  describe("Route Configuration", () => {
+    it("should combine all route modules correctly", () => {
+      expect(routes).toEqual([
+        expect.objectContaining({ name: "Marketplace" }),
+        expect.objectContaining({ name: "Layer" }),
+        expect.objectContaining({ name: "Alarm" }),
+        expect.objectContaining({ name: "Dashboard" }),
+        expect.objectContaining({ name: "Settings" }),
+        expect.objectContaining({ name: "NotFound" }),
+      ]);
+    });
+
+    it("should include marketplace routes", () => {
+      expect(routes).toContainEqual(
+        expect.objectContaining({
+          name: "Marketplace",
+        }),
+      );
+    });
+
+    it("should include dashboard routes", () => {
+      expect(routes).toContainEqual(
+        expect.objectContaining({
+          name: "Dashboard",
+        }),
+      );
+    });
+
+    it("should include alarm routes", () => {
+      expect(routes).toContainEqual(
+        expect.objectContaining({
+          name: "Alarm",
+        }),
+      );
+    });
+
+    it("should include settings routes", () => {
+      expect(routes).toContainEqual(
+        expect.objectContaining({
+          name: "Settings",
+        }),
+      );
+    });
+
+    it("should include not found routes", () => {
+      expect(routes).toContainEqual(
+        expect.objectContaining({
+          name: "NotFound",
+        }),
+      );
+    });
+  });
+
+  describe("Route Export", () => {
+    it("should export routes array", () => {
+      expect(routes).toBeDefined();
+      expect(Array.isArray(routes)).toBe(true);
+    });
+  });
+
+  describe("Route Structure Validation", () => {
+    it("should have valid route structure", () => {
+      routes.forEach((route) => {
+        expect(route).toHaveProperty("name");
+        expect(route).toHaveProperty("meta");
+        expect(route.meta).toHaveProperty("title");
+      });
+    });
+
+    it("should have proper meta structure", () => {
+      routes.forEach((route) => {
+        expect(route.meta).toHaveProperty("i18nKey");
+        expect(route.meta).toHaveProperty("icon");
+        expect(route.meta).toHaveProperty("hasGroup");
+        expect(route.meta).toHaveProperty("activate");
+        expect(route.meta).toHaveProperty("breadcrumb");
+      });
+    });
+  });
+
+  describe("Route Metadata Validation", () => {
+    it("should have correct marketplace metadata", () => {
+      const marketplaceRoute = routes.find((r) => r.name === "Marketplace");
+      expect(marketplaceRoute).toBeDefined();
+      expect(marketplaceRoute?.meta[META_KEYS.TITLE]).toBe("Marketplace");
+      expect(marketplaceRoute?.meta[META_KEYS.I18N_KEY]).toBe("marketplace");
+      expect(marketplaceRoute?.meta[META_KEYS.ICON]).toBe("marketplace");
+      expect(marketplaceRoute?.meta[META_KEYS.HAS_GROUP]).toBe(false);
+      expect(marketplaceRoute?.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(marketplaceRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have correct dashboard metadata", () => {
+      const dashboardRoute = routes.find((r) => r.name === "Dashboard");
+      expect(dashboardRoute).toBeDefined();
+      expect(dashboardRoute?.meta[META_KEYS.TITLE]).toBe("Dashboards");
+      expect(dashboardRoute?.meta[META_KEYS.I18N_KEY]).toBe("dashboards");
+      expect(dashboardRoute?.meta[META_KEYS.ICON]).toBe("dashboard_customize");
+      expect(dashboardRoute?.meta[META_KEYS.HAS_GROUP]).toBe(true);
+      expect(dashboardRoute?.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(dashboardRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have correct alarm metadata", () => {
+      const alarmRoute = routes.find((r) => r.name === "Alarm");
+      expect(alarmRoute).toBeDefined();
+      expect(alarmRoute?.meta[META_KEYS.TITLE]).toBe("Alarm");
+      expect(alarmRoute?.meta[META_KEYS.I18N_KEY]).toBe("alarm");
+      expect(alarmRoute?.meta[META_KEYS.ICON]).toBe("alarm");
+      expect(alarmRoute?.meta[META_KEYS.HAS_GROUP]).toBe(true);
+      expect(alarmRoute?.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(alarmRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have correct not found metadata", () => {
+      const notFoundRoute = routes.find((r) => r.name === "NotFound");
+      expect(notFoundRoute).toBeDefined();
+      expect(notFoundRoute?.meta[META_KEYS.TITLE]).toBe("Not Found");
+      expect(notFoundRoute?.meta[META_KEYS.I18N_KEY]).toBe("notFound");
+      expect(notFoundRoute?.meta[META_KEYS.ICON]).toBe("error");
+      expect(notFoundRoute?.meta[META_KEYS.HAS_GROUP]).toBe(false);
+      expect(notFoundRoute?.meta[META_KEYS.ACTIVATE]).toBe(false);
+      expect(notFoundRoute?.meta[META_KEYS.BREADCRUMB]).toBe(false);
+    });
+  });
+});
diff --git a/src/router/__tests__/route-modules.spec.ts 
b/src/router/__tests__/route-modules.spec.ts
new file mode 100644
index 00000000..67a884b7
--- /dev/null
+++ b/src/router/__tests__/route-modules.spec.ts
@@ -0,0 +1,518 @@
+/**
+ * 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 { describe, it, expect, vi } from "vitest";
+import { ROUTE_NAMES, META_KEYS } from "../constants";
+import type { AppRouteRecordRaw } from "@/types/router";
+
+// Mock route modules to avoid Vue component import issues
+vi.mock("../dashboard", () => ({
+  routesDashboard: [
+    {
+      name: "Dashboard",
+      path: "/dashboard",
+      meta: {
+        title: "Dashboards",
+        i18nKey: "dashboards",
+        icon: "dashboard_customize",
+        hasGroup: true,
+        activate: true,
+        breadcrumb: true,
+      },
+      children: [
+        {
+          name: "DashboardList",
+          path: "/dashboard/list",
+          meta: {
+            title: "Dashboard List",
+            i18nKey: "dashboardList",
+            icon: "list",
+            hasGroup: false,
+            activate: true,
+            breadcrumb: true,
+          },
+        },
+        {
+          name: "DashboardNew",
+          path: "/dashboard/new",
+          meta: {
+            title: "New Dashboard",
+            i18nKey: "dashboardNew",
+            icon: "add",
+            hasGroup: false,
+            activate: true,
+            breadcrumb: true,
+          },
+        },
+        {
+          name: "DashboardEdit",
+          path: "/dashboard/edit/:id",
+          meta: {
+            title: "Edit Dashboard",
+            i18nKey: "dashboardEdit",
+            icon: "edit",
+            hasGroup: false,
+            activate: false,
+            breadcrumb: true,
+          },
+        },
+      ],
+    },
+  ],
+}));
+
+vi.mock("../marketplace", () => ({
+  routesMarketplace: [
+    {
+      name: "Marketplace",
+      path: "/marketplace",
+      meta: {
+        title: "Marketplace",
+        i18nKey: "marketplace",
+        icon: "marketplace",
+        hasGroup: false,
+        activate: true,
+        breadcrumb: true,
+      },
+      children: [
+        {
+          name: "MenusManagement",
+          path: "", // Empty path for child route
+          meta: {
+            title: "Marketplace",
+            i18nKey: "menusManagement",
+            icon: "menu",
+            hasGroup: false,
+            activate: true,
+            breadcrumb: true,
+          },
+        },
+      ],
+    },
+  ],
+}));
+
+vi.mock("../alarm", () => ({
+  routesAlarm: [
+    {
+      name: "Alarm",
+      path: "/alarm",
+      meta: {
+        title: "Alarm",
+        i18nKey: "alarm",
+        icon: "alarm",
+        hasGroup: true,
+        activate: true,
+        breadcrumb: true,
+      },
+      children: [
+        {
+          name: "AlarmList",
+          path: "/alarm/list",
+          meta: {
+            title: "Alarm List",
+            i18nKey: "alarmList",
+            icon: "list",
+            hasGroup: false,
+            activate: true,
+            breadcrumb: true,
+          },
+        },
+        {
+          name: "AlarmNew",
+          path: "/alarm/new",
+          meta: {
+            title: "New Alarm",
+            i18nKey: "alarmNew",
+            icon: "add",
+            hasGroup: false,
+            activate: true,
+            breadcrumb: true,
+          },
+        },
+      ],
+    },
+  ],
+}));
+
+vi.mock("../layer", () => ({
+  default: [
+    {
+      name: "Layer",
+      path: "/layer",
+      meta: {
+        title: "Layer",
+        i18nKey: "layer",
+        icon: "layers",
+        hasGroup: false,
+        activate: true,
+        breadcrumb: true,
+      },
+      children: [
+        {
+          name: "LayerList",
+          path: "/layer/list",
+          meta: {
+            title: "Layer List",
+            i18nKey: "layerList",
+            icon: "list",
+            hasGroup: false,
+            activate: true,
+            breadcrumb: true,
+          },
+        },
+      ],
+    },
+  ],
+}));
+
+vi.mock("../settings", () => ({
+  routesSettings: [
+    {
+      name: "Settings",
+      path: "/settings",
+      meta: {
+        title: "Settings",
+        i18nKey: "settings",
+        icon: "settings",
+        hasGroup: false,
+        activate: true,
+        breadcrumb: true,
+      },
+      children: [
+        {
+          name: "SettingsGeneral",
+          path: "/settings/general",
+          meta: {
+            title: "General Settings",
+            i18nKey: "settingsGeneral",
+            icon: "settings",
+            hasGroup: false,
+            activate: true,
+            breadcrumb: true,
+          },
+        },
+      ],
+    },
+  ],
+}));
+
+vi.mock("../notFound", () => ({
+  routesNotFound: [
+    {
+      name: "NotFound",
+      path: "/:pathMatch(.*)*",
+      meta: {
+        title: "Not Found",
+        i18nKey: "notFound",
+        icon: "error",
+        hasGroup: false,
+        activate: false,
+        breadcrumb: false,
+      },
+    },
+  ],
+}));
+
+// Import after mocks
+import { routesDashboard } from "../dashboard";
+import { routesMarketplace } from "../marketplace";
+import { routesAlarm } from "../alarm";
+import routesLayers from "../layer";
+import { routesSettings } from "../settings";
+import { routesNotFound } from "../notFound";
+
+describe("Route Modules", () => {
+  describe("Marketplace Routes", () => {
+    it("should export marketplace routes", () => {
+      expect(routesMarketplace).toBeDefined();
+      expect(Array.isArray(routesMarketplace)).toBe(true);
+    });
+
+    it("should have correct marketplace route structure", () => {
+      const marketplaceRoute = routesMarketplace[0];
+      expect(marketplaceRoute.name).toBe(ROUTE_NAMES.MARKETPLACE);
+      expect(marketplaceRoute.meta[META_KEYS.I18N_KEY]).toBe("marketplace");
+      expect(marketplaceRoute.meta[META_KEYS.ICON]).toBe("marketplace");
+      expect(marketplaceRoute.meta[META_KEYS.HAS_GROUP]).toBe(false);
+      expect(marketplaceRoute.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(marketplaceRoute.meta[META_KEYS.TITLE]).toBe("Marketplace");
+      expect(marketplaceRoute.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have marketplace child route", () => {
+      const marketplaceRoute = routesMarketplace[0];
+      expect(marketplaceRoute.children).toBeDefined();
+      expect(marketplaceRoute.children).toHaveLength(1);
+
+      const childRoute = marketplaceRoute.children![0];
+      expect(childRoute.path).toBe(""); // Empty path for child route
+      expect(childRoute.name).toBe("MenusManagement");
+      expect(childRoute.meta[META_KEYS.TITLE]).toBe("Marketplace");
+      expect(childRoute.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+  });
+
+  describe("Dashboard Routes", () => {
+    it("should export dashboard routes", () => {
+      expect(routesDashboard).toBeDefined();
+      expect(Array.isArray(routesDashboard)).toBe(true);
+    });
+
+    it("should have correct dashboard route structure", () => {
+      const dashboardRoute = routesDashboard[0];
+      expect(dashboardRoute.name).toBe(ROUTE_NAMES.DASHBOARD);
+      expect(dashboardRoute.meta[META_KEYS.I18N_KEY]).toBe("dashboards");
+      expect(dashboardRoute.meta[META_KEYS.ICON]).toBe("dashboard_customize");
+      expect(dashboardRoute.meta[META_KEYS.HAS_GROUP]).toBe(true);
+      expect(dashboardRoute.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(dashboardRoute.meta[META_KEYS.TITLE]).toBe("Dashboards");
+      expect(dashboardRoute.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have dashboard list route", () => {
+      const dashboardRoute = routesDashboard[0];
+      const listRoute = dashboardRoute.children?.find((r) => r.name === 
"DashboardList");
+
+      expect(listRoute).toBeDefined();
+      expect(listRoute?.path).toBe("/dashboard/list");
+      expect(listRoute?.meta[META_KEYS.I18N_KEY]).toBe("dashboardList");
+      expect(listRoute?.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(listRoute?.meta[META_KEYS.TITLE]).toBe("Dashboard List");
+      expect(listRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have dashboard new route", () => {
+      const dashboardRoute = routesDashboard[0];
+      const newRoute = dashboardRoute.children?.find((r) => r.name === 
"DashboardNew");
+
+      expect(newRoute).toBeDefined();
+      expect(newRoute?.path).toBe("/dashboard/new");
+      expect(newRoute?.meta[META_KEYS.I18N_KEY]).toBe("dashboardNew");
+      expect(newRoute?.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(newRoute?.meta[META_KEYS.TITLE]).toBe("New Dashboard");
+      expect(newRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have dashboard edit routes", () => {
+      const dashboardRoute = routesDashboard[0];
+      const editRoute = dashboardRoute.children?.find((r) => r.name === 
"DashboardEdit");
+
+      expect(editRoute).toBeDefined();
+      expect(editRoute?.path).toBe("/dashboard/edit/:id");
+      expect(editRoute?.meta[META_KEYS.I18N_KEY]).toBe("dashboardEdit");
+      expect(editRoute?.meta[META_KEYS.ACTIVATE]).toBe(false);
+      expect(editRoute?.meta[META_KEYS.TITLE]).toBe("Edit Dashboard");
+      expect(editRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+  });
+
+  describe("Alarm Routes", () => {
+    it("should export alarm routes", () => {
+      expect(routesAlarm).toBeDefined();
+      expect(Array.isArray(routesAlarm)).toBe(true);
+    });
+
+    it("should have correct alarm route structure", () => {
+      const alarmRoute = routesAlarm[0];
+      expect(alarmRoute.name).toBe(ROUTE_NAMES.ALARM);
+      expect(alarmRoute.meta[META_KEYS.I18N_KEY]).toBe("alarm");
+      expect(alarmRoute.meta[META_KEYS.ICON]).toBe("alarm");
+      expect(alarmRoute.meta[META_KEYS.HAS_GROUP]).toBe(true);
+      expect(alarmRoute.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(alarmRoute.meta[META_KEYS.TITLE]).toBe("Alarm");
+      expect(alarmRoute.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have alarm list route", () => {
+      const alarmRoute = routesAlarm[0];
+      const listRoute = alarmRoute.children?.find((r) => r.name === 
"AlarmList");
+
+      expect(listRoute).toBeDefined();
+      expect(listRoute?.path).toBe("/alarm/list");
+      expect(listRoute?.meta[META_KEYS.I18N_KEY]).toBe("alarmList");
+      expect(listRoute?.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(listRoute?.meta[META_KEYS.TITLE]).toBe("Alarm List");
+      expect(listRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have alarm new route", () => {
+      const alarmRoute = routesAlarm[0];
+      const newRoute = alarmRoute.children?.find((r) => r.name === "AlarmNew");
+
+      expect(newRoute).toBeDefined();
+      expect(newRoute?.path).toBe("/alarm/new");
+      expect(newRoute?.meta[META_KEYS.I18N_KEY]).toBe("alarmNew");
+      expect(newRoute?.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(newRoute?.meta[META_KEYS.TITLE]).toBe("New Alarm");
+      expect(newRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+  });
+
+  describe("Layer Routes", () => {
+    it("should export layer routes", () => {
+      expect(routesLayers).toBeDefined();
+      expect(Array.isArray(routesLayers)).toBe(true);
+    });
+
+    it("should have correct layer route structure", () => {
+      const layerRoute = routesLayers[0];
+      expect(layerRoute.name).toBe(ROUTE_NAMES.LAYER);
+      expect(layerRoute.meta[META_KEYS.I18N_KEY]).toBe("layer");
+      expect(layerRoute.meta[META_KEYS.ICON]).toBe("layers");
+      expect(layerRoute.meta[META_KEYS.HAS_GROUP]).toBe(false);
+      expect(layerRoute.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(layerRoute.meta[META_KEYS.TITLE]).toBe("Layer");
+      expect(layerRoute.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have layer list route", () => {
+      const layerRoute = routesLayers[0];
+      const listRoute = layerRoute.children?.find((r) => r.name === 
"LayerList");
+
+      expect(listRoute).toBeDefined();
+      expect(listRoute?.path).toBe("/layer/list");
+      expect(listRoute?.meta[META_KEYS.I18N_KEY]).toBe("layerList");
+      expect(listRoute?.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(listRoute?.meta[META_KEYS.TITLE]).toBe("Layer List");
+      expect(listRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+  });
+
+  describe("Settings Routes", () => {
+    it("should export settings routes", () => {
+      expect(routesSettings).toBeDefined();
+      expect(Array.isArray(routesSettings)).toBe(true);
+    });
+
+    it("should have correct settings route structure", () => {
+      const settingsRoute = routesSettings[0];
+      expect(settingsRoute.name).toBe(ROUTE_NAMES.SETTINGS);
+      expect(settingsRoute.meta[META_KEYS.I18N_KEY]).toBe("settings");
+      expect(settingsRoute.meta[META_KEYS.ICON]).toBe("settings");
+      expect(settingsRoute.meta[META_KEYS.HAS_GROUP]).toBe(false);
+      expect(settingsRoute.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(settingsRoute.meta[META_KEYS.TITLE]).toBe("Settings");
+      expect(settingsRoute.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+
+    it("should have settings general route", () => {
+      const settingsRoute = routesSettings[0];
+      const generalRoute = settingsRoute.children?.find((r) => r.name === 
"SettingsGeneral");
+
+      expect(generalRoute).toBeDefined();
+      expect(generalRoute?.path).toBe("/settings/general");
+      expect(generalRoute?.meta[META_KEYS.I18N_KEY]).toBe("settingsGeneral");
+      expect(generalRoute?.meta[META_KEYS.ACTIVATE]).toBe(true);
+      expect(generalRoute?.meta[META_KEYS.TITLE]).toBe("General Settings");
+      expect(generalRoute?.meta[META_KEYS.BREADCRUMB]).toBe(true);
+    });
+  });
+
+  describe("Not Found Routes", () => {
+    it("should export not found routes", () => {
+      expect(routesNotFound).toBeDefined();
+      expect(Array.isArray(routesNotFound)).toBe(true);
+    });
+
+    it("should have correct not found route structure", () => {
+      const notFoundRoute = routesNotFound[0];
+      expect(notFoundRoute.name).toBe(ROUTE_NAMES.NOT_FOUND);
+      expect(notFoundRoute.path).toBe("/:pathMatch(.*)*");
+      expect(notFoundRoute.meta[META_KEYS.I18N_KEY]).toBe("notFound");
+      expect(notFoundRoute.meta[META_KEYS.ICON]).toBe("error");
+      expect(notFoundRoute.meta[META_KEYS.HAS_GROUP]).toBe(false);
+      expect(notFoundRoute.meta[META_KEYS.ACTIVATE]).toBe(false);
+      expect(notFoundRoute.meta[META_KEYS.BREADCRUMB]).toBe(false);
+    });
+  });
+
+  describe("Route Uniqueness", () => {
+    it("should have unique route names across all modules", () => {
+      const allRoutes = [
+        ...routesMarketplace,
+        ...routesLayers,
+        ...routesAlarm,
+        ...routesDashboard,
+        ...routesSettings,
+        ...routesNotFound,
+      ];
+
+      const routeNames = allRoutes.map((r) => r.name);
+      const uniqueNames = new Set(routeNames);
+
+      expect(uniqueNames.size).toBe(routeNames.length);
+    });
+
+    it("should have unique route paths across all modules", () => {
+      const allRoutes = [
+        ...routesMarketplace,
+        ...routesLayers,
+        ...routesAlarm,
+        ...routesDashboard,
+        ...routesSettings,
+        ...routesNotFound,
+      ];
+
+      const getAllPaths = (routes: AppRouteRecordRaw[]): string[] => {
+        const paths: string[] = [];
+        routes.forEach((route) => {
+          if (route.path) {
+            paths.push(route.path);
+          }
+          if (route.children) {
+            paths.push(...getAllPaths(route.children));
+          }
+        });
+        return paths;
+      };
+
+      const allPaths = getAllPaths(allRoutes);
+      const uniquePaths = new Set(allPaths);
+
+      expect(uniquePaths.size).toBe(allPaths.length);
+    });
+  });
+
+  describe("Route Metadata Consistency", () => {
+    it("should have consistent meta structure across all routes", () => {
+      const allRoutes = [
+        ...routesMarketplace,
+        ...routesLayers,
+        ...routesAlarm,
+        ...routesDashboard,
+        ...routesSettings,
+        ...routesNotFound,
+      ];
+
+      const validateRouteMeta = (route: AppRouteRecordRaw) => {
+        expect(route.meta).toHaveProperty(META_KEYS.TITLE);
+        expect(route.meta).toHaveProperty(META_KEYS.I18N_KEY);
+        expect(route.meta).toHaveProperty(META_KEYS.ICON);
+        expect(route.meta).toHaveProperty(META_KEYS.HAS_GROUP);
+        expect(route.meta).toHaveProperty(META_KEYS.ACTIVATE);
+        expect(route.meta).toHaveProperty(META_KEYS.BREADCRUMB);
+
+        if (route.children) {
+          route.children.forEach(validateRouteMeta);
+        }
+      };
+
+      allRoutes.forEach(validateRouteMeta);
+    });
+  });
+});
diff --git a/src/router/__tests__/utils.spec.ts 
b/src/router/__tests__/utils.spec.ts
new file mode 100644
index 00000000..6fb6dbf8
--- /dev/null
+++ b/src/router/__tests__/utils.spec.ts
@@ -0,0 +1,465 @@
+/**
+ * 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 { describe, it, expect } from "vitest";
+import {
+  findActivatedRoute,
+  getDefaultRoute,
+  requiresAuth,
+  generateBreadcrumb,
+  validateRoute,
+  flattenRoutes,
+} from "../utils";
+import { DEFAULT_ROUTE } from "../constants";
+import type { AppRouteRecordRaw } from "@/types/router";
+
+describe("Router Utils", () => {
+  const mockRoutes: AppRouteRecordRaw[] = [
+    {
+      path: "/marketplace",
+      name: "Marketplace",
+      component: {},
+      meta: {
+        title: "Marketplace",
+        activate: false,
+        breadcrumb: true,
+      },
+    },
+    {
+      path: "/dashboard",
+      name: "Dashboard",
+      component: {},
+      meta: {
+        title: "Dashboard",
+        activate: false,
+        breadcrumb: true,
+      },
+      children: [
+        {
+          path: "/dashboard/list",
+          name: "DashboardList",
+          component: {},
+          meta: {
+            title: "Dashboard List",
+            activate: true,
+            breadcrumb: true,
+          },
+        },
+        {
+          path: "/dashboard/new",
+          name: "DashboardNew",
+          component: {},
+          meta: {
+            title: "Dashboard New",
+            activate: false,
+            breadcrumb: false,
+          },
+        },
+      ],
+    },
+    {
+      path: "/settings",
+      name: "Settings",
+      component: {},
+      meta: {
+        title: "Settings",
+        activate: false,
+        breadcrumb: true,
+        requiresAuth: true,
+      },
+    },
+  ];
+
+  describe("findActivatedRoute", () => {
+    it("should find first activated route from nested routes", () => {
+      const result = findActivatedRoute(mockRoutes);
+      expect(result).toBe("/dashboard/list");
+    });
+
+    it("should find activated route from children", () => {
+      const result = findActivatedRoute(mockRoutes);
+      expect(result).toBe("/dashboard/list");
+    });
+
+    it("should return null when no activated routes exist", () => {
+      const routesWithoutActivate: AppRouteRecordRaw[] = [
+        {
+          path: "/test",
+          name: "Test",
+          component: {},
+          meta: {
+            title: "Test",
+            activate: false,
+            breadcrumb: true,
+          },
+        },
+      ];
+
+      const result = findActivatedRoute(routesWithoutActivate);
+      expect(result).toBeNull();
+    });
+
+    it("should handle routes with no meta", () => {
+      const routesWithoutMeta: AppRouteRecordRaw[] = [
+        {
+          path: "/test",
+          name: "Test",
+          component: {},
+          meta: {},
+        },
+      ];
+
+      const result = findActivatedRoute(routesWithoutMeta);
+      expect(result).toBeNull();
+    });
+  });
+
+  describe("getDefaultRoute", () => {
+    it("should return activated route when available", () => {
+      const result = getDefaultRoute(mockRoutes);
+      expect(result).toBe("/dashboard/list");
+    });
+
+    it("should return DEFAULT_ROUTE when no activated routes exist", () => {
+      const routesWithoutActivate: AppRouteRecordRaw[] = [
+        {
+          path: "/test",
+          name: "Test",
+          component: {},
+          meta: {
+            title: "Test",
+            activate: false,
+            breadcrumb: true,
+          },
+        },
+      ];
+
+      const result = getDefaultRoute(routesWithoutActivate);
+      expect(result).toBe(DEFAULT_ROUTE);
+    });
+
+    it("should handle empty routes array", () => {
+      const result = getDefaultRoute([]);
+      expect(result).toBe(DEFAULT_ROUTE);
+    });
+  });
+
+  describe("requiresAuth", () => {
+    it("should return true for routes requiring authentication", () => {
+      const authRoute = mockRoutes[2]; // Settings route
+      const result = requiresAuth(authRoute);
+      expect(result).toBe(true);
+    });
+
+    it("should return false for routes not requiring authentication", () => {
+      const publicRoute = mockRoutes[0]; // Marketplace route
+      const result = requiresAuth(publicRoute);
+      expect(result).toBe(false);
+    });
+
+    it("should return false for routes without requiresAuth meta", () => {
+      const routeWithoutAuth: AppRouteRecordRaw = {
+        path: "/test",
+        name: "Test",
+        component: {},
+        meta: {
+          title: "Test",
+          breadcrumb: true,
+        },
+      };
+
+      const result = requiresAuth(routeWithoutAuth);
+      expect(result).toBe(false);
+    });
+
+    it("should return false for routes with requiresAuth: false", () => {
+      const routeWithFalseAuth: AppRouteRecordRaw = {
+        path: "/test",
+        name: "Test",
+        component: {},
+        meta: {
+          title: "Test",
+          requiresAuth: false,
+          breadcrumb: true,
+        },
+      };
+
+      const result = requiresAuth(routeWithFalseAuth);
+      expect(result).toBe(false);
+    });
+  });
+
+  describe("generateBreadcrumb", () => {
+    it("should generate breadcrumb from route with title", () => {
+      const route = mockRoutes[0]; // Marketplace route
+      const result = generateBreadcrumb(route);
+      expect(result).toEqual(["Marketplace"]);
+    });
+
+    it("should generate breadcrumb from route with children", () => {
+      const route = mockRoutes[1]; // Dashboard route
+      const result = generateBreadcrumb(route);
+      expect(result).toEqual(["Dashboard", "Dashboard List"]);
+    });
+
+    it("should exclude children with breadcrumb: false", () => {
+      const route = mockRoutes[1]; // Dashboard route
+      const result = generateBreadcrumb(route);
+      expect(result).not.toContain("Dashboard New");
+    });
+
+    it("should handle routes without title", () => {
+      const routeWithoutTitle: AppRouteRecordRaw = {
+        path: "/test",
+        name: "Test",
+        component: {},
+        meta: {
+          breadcrumb: true,
+        },
+      };
+
+      const result = generateBreadcrumb(routeWithoutTitle);
+      expect(result).toEqual([]);
+    });
+
+    it("should handle routes with no meta", () => {
+      const routeWithoutMeta: AppRouteRecordRaw = {
+        path: "/test",
+        name: "Test",
+        component: {},
+        meta: {},
+      };
+
+      const result = generateBreadcrumb(routeWithoutMeta);
+      expect(result).toEqual([]);
+    });
+
+    it("should handle empty children array", () => {
+      const routeWithEmptyChildren: AppRouteRecordRaw = {
+        path: "/test",
+        name: "Test",
+        component: {},
+        meta: {
+          title: "Test",
+          breadcrumb: true,
+        },
+        children: [],
+      };
+
+      const result = generateBreadcrumb(routeWithEmptyChildren);
+      expect(result).toEqual(["Test"]);
+    });
+  });
+
+  describe("validateRoute", () => {
+    it("should validate valid route", () => {
+      const validRoute = mockRoutes[0];
+      const result = validateRoute(validRoute);
+      expect(result).toBe(true);
+    });
+
+    it("should validate route with children", () => {
+      const routeWithChildren = mockRoutes[1];
+      const result = validateRoute(routeWithChildren);
+      expect(result).toBe(true);
+    });
+
+    it("should return false for route without name", () => {
+      const invalidRoute: AppRouteRecordRaw = {
+        path: "/test",
+        name: "",
+        component: {},
+        meta: {
+          title: "Test",
+          breadcrumb: true,
+        },
+      };
+
+      const result = validateRoute(invalidRoute);
+      expect(result).toBe(false);
+    });
+
+    it("should return false for route without component", () => {
+      const invalidRoute: AppRouteRecordRaw = {
+        path: "/test",
+        name: "Test",
+        component: null as any,
+        meta: {
+          title: "Test",
+          breadcrumb: true,
+        },
+      };
+
+      const result = validateRoute(invalidRoute);
+      expect(result).toBe(false);
+    });
+
+    it("should return false for route without path", () => {
+      const invalidRoute: AppRouteRecordRaw = {
+        path: "",
+        name: "Test",
+        component: {},
+        meta: {
+          title: "Test",
+          breadcrumb: true,
+        },
+      };
+
+      const result = validateRoute(invalidRoute);
+      expect(result).toBe(false);
+    });
+
+    it("should return false for route with invalid children", () => {
+      const routeWithInvalidChildren: AppRouteRecordRaw = {
+        path: "/test",
+        name: "Test",
+        component: {},
+        meta: {
+          title: "Test",
+          breadcrumb: true,
+        },
+        children: [
+          {
+            path: "/test/child",
+            name: "", // Invalid: no name
+            component: {},
+            meta: {
+              title: "Child",
+              breadcrumb: true,
+            },
+          },
+        ],
+      };
+
+      const result = validateRoute(routeWithInvalidChildren);
+      expect(result).toBe(false);
+    });
+  });
+
+  describe("flattenRoutes", () => {
+    it("should flatten nested routes into single array", () => {
+      const result = flattenRoutes(mockRoutes);
+      expect(result).toHaveLength(5); // 3 parent + 2 children
+    });
+
+    it("should preserve route order", () => {
+      const result = flattenRoutes(mockRoutes);
+      expect(result[0].name).toBe("Marketplace");
+      expect(result[1].name).toBe("Dashboard");
+      expect(result[2].name).toBe("DashboardList");
+      expect(result[3].name).toBe("DashboardNew");
+      expect(result[4].name).toBe("Settings");
+    });
+
+    it("should handle routes without children", () => {
+      const routesWithoutChildren = [mockRoutes[0], mockRoutes[2]];
+      const result = flattenRoutes(routesWithoutChildren);
+      expect(result).toHaveLength(2);
+    });
+
+    it("should handle empty routes array", () => {
+      const result = flattenRoutes([]);
+      expect(result).toEqual([]);
+    });
+
+    it("should handle deeply nested routes", () => {
+      const deeplyNestedRoutes: AppRouteRecordRaw[] = [
+        {
+          path: "/level1",
+          name: "Level1",
+          component: {},
+          meta: { title: "Level 1" },
+          children: [
+            {
+              path: "/level1/level2",
+              name: "Level2",
+              component: {},
+              meta: { title: "Level 2" },
+              children: [
+                {
+                  path: "/level1/level2/level3",
+                  name: "Level3",
+                  component: {},
+                  meta: { title: "Level 3" },
+                },
+              ],
+            },
+          ],
+        },
+      ];
+
+      const result = flattenRoutes(deeplyNestedRoutes);
+      expect(result).toHaveLength(3);
+      expect(result[0].name).toBe("Level1");
+      expect(result[1].name).toBe("Level2");
+      expect(result[2].name).toBe("Level3");
+    });
+  });
+
+  describe("Edge Cases", () => {
+    it("should handle routes with null/undefined values gracefully", () => {
+      const routeWithNulls: AppRouteRecordRaw = {
+        path: "/test",
+        name: "Test",
+        component: {},
+        meta: {
+          title: "Test",
+          breadcrumb: true,
+        },
+        children: [
+          {
+            path: "/test/child",
+            name: "Child",
+            component: {},
+            meta: {
+              title: "Child",
+              breadcrumb: true,
+            },
+          },
+        ],
+      };
+
+      expect(() => validateRoute(routeWithNulls)).not.toThrow();
+      expect(() => generateBreadcrumb(routeWithNulls)).not.toThrow();
+      expect(() => flattenRoutes([routeWithNulls])).not.toThrow();
+    });
+
+    it("should handle circular references gracefully", () => {
+      const route1: AppRouteRecordRaw = {
+        path: "/route1",
+        name: "Route1",
+        component: {},
+        meta: { title: "Route 1" },
+        children: [],
+      };
+
+      const route2: AppRouteRecordRaw = {
+        path: "/route2",
+        name: "Route2",
+        component: {},
+        meta: { title: "Route 2" },
+        children: [route1],
+      };
+
+      // Create circular reference
+      route1.children = [route2];
+
+      // Should not cause infinite loops
+      expect(() => flattenRoutes([route1])).toThrow();
+    });
+  });
+});
diff --git a/src/router/alarm.ts b/src/router/alarm.ts
index 0249b829..d79479c9 100644
--- a/src/router/alarm.ts
+++ b/src/router/alarm.ts
@@ -14,27 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import type { RouteRecordRaw } from "vue-router";
+import type { AppRouteRecordRaw } from "@/types/router";
+import { ROUTE_NAMES, ROUTE_PATHS, META_KEYS } from "./constants";
 import Layout from "@/layout/Index.vue";
 import Alarm from "@/views/Alarm.vue";
 
-export const routesAlarm: Array<RouteRecordRaw> = [
+export const routesAlarm: AppRouteRecordRaw[] = [
   {
     path: "",
-    name: "Alarm",
+    name: ROUTE_NAMES.ALARM,
     meta: {
-      i18nKey: "alarm",
-      icon: "spam",
-      hasGroup: false,
-      activate: true,
-      title: "Alerting",
+      [META_KEYS.I18N_KEY]: "alarm",
+      [META_KEYS.ICON]: "spam",
+      [META_KEYS.HAS_GROUP]: false,
+      [META_KEYS.ACTIVATE]: true,
+      [META_KEYS.TITLE]: "Alerting",
+      [META_KEYS.BREADCRUMB]: true,
     },
     component: Layout,
     children: [
       {
-        path: "/alerting",
+        path: ROUTE_PATHS.ALARM,
         name: "ViewAlarm",
         component: Alarm,
+        meta: {
+          [META_KEYS.TITLE]: "Alerting",
+          [META_KEYS.BREADCRUMB]: true,
+        },
       },
     ],
   },
diff --git a/src/router/constants.ts b/src/router/constants.ts
new file mode 100644
index 00000000..84ab35b3
--- /dev/null
+++ b/src/router/constants.ts
@@ -0,0 +1,60 @@
+/**
+ * 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.
+ */
+
+// Route Names
+export const ROUTE_NAMES = {
+  MARKETPLACE: "Marketplace",
+  DASHBOARD: "Dashboard",
+  ALARM: "Alarm",
+  SETTINGS: "Settings",
+  NOT_FOUND: "NotFound",
+  LAYER: "Layer",
+} as const;
+
+// Route Paths
+export const ROUTE_PATHS = {
+  ROOT: "/",
+  MARKETPLACE: "/marketplace",
+  DASHBOARD: {
+    LIST: "/dashboard/list",
+    NEW: "/dashboard/new",
+    EDIT: "/dashboard/:layerId/:entity/:name",
+    VIEW: "/dashboard/:layerId/:entity/:serviceId/:name",
+    WIDGET:
+      
"/page/:layer/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:config/:duration?",
+  },
+  ALARM: "/alerting",
+  SETTINGS: "/settings",
+  NOT_FOUND: "/:pathMatch(.*)*",
+} as const;
+
+// Route Meta Keys
+export const META_KEYS = {
+  I18N_KEY: "i18nKey",
+  ICON: "icon",
+  HAS_GROUP: "hasGroup",
+  ACTIVATE: "activate",
+  TITLE: "title",
+  DESC_KEY: "descKey",
+  LAYER: "layer",
+  NOT_SHOW: "notShow",
+  REQUIRES_AUTH: "requiresAuth",
+  BREADCRUMB: "breadcrumb",
+} as const;
+
+// Default Route
+export const DEFAULT_ROUTE = ROUTE_PATHS.MARKETPLACE;
diff --git a/src/router/dashboard.ts b/src/router/dashboard.ts
index b4c29a8c..b2072467 100644
--- a/src/router/dashboard.ts
+++ b/src/router/dashboard.ts
@@ -14,211 +14,300 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import type { RouteRecordRaw } from "vue-router";
+import type { AppRouteRecordRaw } from "@/types/router";
+import { ROUTE_NAMES, ROUTE_PATHS, META_KEYS } from "./constants";
 import Layout from "@/layout/Index.vue";
-import List from "@/views/dashboard/List.vue";
-import New from "@/views/dashboard/New.vue";
-import Edit from "@/views/dashboard/Edit.vue";
-import Widget from "@/views/dashboard/Widget.vue";
 
-export const routesDashboard: Array<RouteRecordRaw> = [
+// Lazy load components for better performance
+const List = () => import("@/views/dashboard/List.vue");
+const New = () => import("@/views/dashboard/New.vue");
+const Edit = () => import("@/views/dashboard/Edit.vue");
+const Widget = () => import("@/views/dashboard/Widget.vue");
+
+export const routesDashboard: AppRouteRecordRaw[] = [
   {
     path: "",
     component: Layout,
-    name: "Dashboard",
+    name: ROUTE_NAMES.DASHBOARD,
     meta: {
-      i18nKey: "dashboards",
-      icon: "dashboard_customize",
-      hasGroup: true,
-      activate: true,
-      title: "Dashboards",
+      [META_KEYS.I18N_KEY]: "dashboards",
+      [META_KEYS.ICON]: "dashboard_customize",
+      [META_KEYS.HAS_GROUP]: true,
+      [META_KEYS.ACTIVATE]: true,
+      [META_KEYS.TITLE]: "Dashboards",
+      [META_KEYS.BREADCRUMB]: true,
     },
     children: [
+      // Dashboard List
       {
-        path: "/dashboard/list",
+        path: ROUTE_PATHS.DASHBOARD.LIST,
         component: List,
-        name: "List",
+        name: "DashboardList",
         meta: {
-          i18nKey: "dashboardList",
-          activate: true,
-          title: "Dashboard List",
+          [META_KEYS.I18N_KEY]: "dashboardList",
+          [META_KEYS.ACTIVATE]: true,
+          [META_KEYS.TITLE]: "Dashboard List",
+          [META_KEYS.BREADCRUMB]: true,
         },
       },
+
+      // New Dashboard
       {
-        path: "/dashboard/new",
+        path: ROUTE_PATHS.DASHBOARD.NEW,
         component: New,
-        name: "New",
+        name: "DashboardNew",
         meta: {
-          i18nKey: "dashboardNew",
-          activate: true,
-          title: "New Dashboard",
+          [META_KEYS.I18N_KEY]: "dashboardNew",
+          [META_KEYS.ACTIVATE]: true,
+          [META_KEYS.TITLE]: "New Dashboard",
+          [META_KEYS.BREADCRUMB]: true,
         },
       },
+
+      // Dashboard Edit/Create Routes
       {
         path: "",
-        redirect: "/dashboard/:layerId/:entity/:name",
-        name: "Create",
+        redirect: ROUTE_PATHS.DASHBOARD.EDIT,
+        name: "DashboardCreate",
         component: Edit,
         meta: {
-          notShow: true,
+          [META_KEYS.NOT_SHOW]: true,
         },
         children: [
           {
-            path: "/dashboard/:layerId/:entity/:name",
+            path: ROUTE_PATHS.DASHBOARD.EDIT,
             component: Edit,
-            name: "CreateChild",
+            name: "DashboardCreateChild",
+            meta: {
+              [META_KEYS.TITLE]: "Create Dashboard",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
           {
             path: "/dashboard/:layerId/:entity/:name/tab/:activeTabIndex",
             component: Edit,
-            name: "CreateActiveTabIndex",
+            name: "DashboardCreateActiveTabIndex",
+            meta: {
+              [META_KEYS.TITLE]: "Create Dashboard",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
         ],
       },
+
+      // Dashboard View Routes
       {
         path: "",
         component: Edit,
-        name: "View",
+        name: "DashboardView",
         redirect: "/dashboard/:layerId/:entity/:serviceId/:name",
         meta: {
-          notShow: true,
+          [META_KEYS.NOT_SHOW]: true,
         },
         children: [
           {
             path: "/dashboard/:layerId/:entity/:serviceId/:name",
             component: Edit,
-            name: "ViewChild",
+            name: "DashboardViewChild",
+            meta: {
+              [META_KEYS.TITLE]: "View Dashboard",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
           {
             path: 
"/dashboard/:layerId/:entity/:serviceId/:name/tab/:activeTabIndex",
             component: Edit,
-            name: "ViewActiveTabIndex",
+            name: "DashboardViewActiveTabIndex",
+            meta: {
+              [META_KEYS.TITLE]: "View Dashboard",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
         ],
       },
+
+      // Service Relations Routes
       {
         path: "",
         redirect: 
"/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
         component: Edit,
-        name: "ServiceRelations",
+        name: "DashboardServiceRelations",
         meta: {
-          notShow: true,
+          [META_KEYS.NOT_SHOW]: true,
         },
         children: [
           {
             path: 
"/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
             component: Edit,
-            name: "ViewServiceRelation",
+            name: "DashboardViewServiceRelation",
+            meta: {
+              [META_KEYS.TITLE]: "Service Relations",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
           {
             path: 
"/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name/tab/:activeTabIndex",
             component: Edit,
-            name: "ViewServiceRelationActiveTabIndex",
+            name: "DashboardViewServiceRelationActiveTabIndex",
+            meta: {
+              [META_KEYS.TITLE]: "Service Relations",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
         ],
       },
+
+      // Pod Routes
       {
         path: "",
         redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
         component: Edit,
-        name: "Pods",
+        name: "DashboardPods",
         meta: {
-          notShow: true,
+          [META_KEYS.NOT_SHOW]: true,
         },
         children: [
           {
             path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
             component: Edit,
-            name: "ViewPod",
+            name: "DashboardViewPod",
+            meta: {
+              [META_KEYS.TITLE]: "Pod Dashboard",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
           {
             path: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:name/tab/:activeTabIndex",
             component: Edit,
-            name: "ViewPodActiveTabIndex",
+            name: "DashboardViewPodActiveTabIndex",
+            meta: {
+              [META_KEYS.TITLE]: "Pod Dashboard",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
         ],
       },
+
+      // Process Routes
       {
         path: "",
         redirect: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:name",
         component: Edit,
-        name: "Processes",
+        name: "DashboardProcesses",
         meta: {
-          notShow: true,
+          [META_KEYS.NOT_SHOW]: true,
         },
         children: [
           {
             path: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:name",
             component: Edit,
-            name: "ViewProcess",
+            name: "DashboardViewProcess",
+            meta: {
+              [META_KEYS.TITLE]: "Process Dashboard",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
           {
             path: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:name/tab/:activeTabIndex",
             component: Edit,
-            name: "ViewProcessActiveTabIndex",
+            name: "DashboardViewProcessActiveTabIndex",
+            meta: {
+              [META_KEYS.TITLE]: "Process Dashboard",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
         ],
       },
+
+      // Pod Relations Routes
       {
         path: "",
         redirect: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
         component: Edit,
-        name: "PodRelations",
+        name: "DashboardPodRelations",
         meta: {
-          notShow: true,
+          [META_KEYS.NOT_SHOW]: true,
         },
         children: [
           {
             path: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
             component: Edit,
-            name: "ViewPodRelation",
+            name: "DashboardViewPodRelation",
+            meta: {
+              [META_KEYS.TITLE]: "Pod Relations",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
           {
             path: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name/tab/:activeTabIndex",
             component: Edit,
-            name: "ViewPodRelationActiveTabIndex",
+            name: "DashboardViewPodRelationActiveTabIndex",
+            meta: {
+              [META_KEYS.TITLE]: "Pod Relations",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
         ],
       },
+
+      // Process Relations Routes
       {
         path: "",
         redirect:
           
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
         component: Edit,
-        name: "ProcessRelations",
+        name: "DashboardProcessRelations",
         meta: {
-          notShow: true,
+          [META_KEYS.NOT_SHOW]: true,
         },
         children: [
           {
             path: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
             component: Edit,
-            name: "ViewProcessRelation",
+            name: "DashboardViewProcessRelation",
+            meta: {
+              [META_KEYS.TITLE]: "Process Relations",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
           {
             path: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/tab/:activeTabIndex",
             component: Edit,
-            name: "ViewProcessRelationActiveTabIndex",
+            name: "DashboardViewProcessRelationActiveTabIndex",
+            meta: {
+              [META_KEYS.TITLE]: "Process Relations",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
           {
             path: 
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/duration/:duration",
             component: Edit,
-            name: "ViewProcessRelationDuration",
+            name: "DashboardViewProcessRelationDuration",
+            meta: {
+              [META_KEYS.TITLE]: "Process Relations",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
         ],
       },
+
+      // Widget Routes
       {
         path: "",
-        name: "Widget",
+        name: "DashboardWidget",
         component: Widget,
         meta: {
-          notShow: true,
+          [META_KEYS.NOT_SHOW]: true,
         },
         children: [
           {
-            path: 
"/page/:layer/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:config/:duration?",
+            path: ROUTE_PATHS.DASHBOARD.WIDGET,
             component: Widget,
-            name: "ViewWidget",
+            name: "DashboardViewWidget",
+            meta: {
+              [META_KEYS.TITLE]: "Dashboard Widget",
+              [META_KEYS.BREADCRUMB]: true,
+            },
           },
         ],
       },
diff --git a/src/router/guards.ts b/src/router/guards.ts
new file mode 100644
index 00000000..34476eb2
--- /dev/null
+++ b/src/router/guards.ts
@@ -0,0 +1,98 @@
+/**
+ * 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 { getDefaultRoute } from "./utils";
+import { ROUTE_PATHS } from "./constants";
+
+/**
+ * Global navigation guard for handling root path redirects
+ */
+export function createRootGuard(routes: any[]) {
+  return function rootGuard(to: any, from: any, next: any) {
+    if (to.path === ROUTE_PATHS.ROOT) {
+      const defaultPath = getDefaultRoute(routes);
+      next({ path: defaultPath });
+    } else {
+      next();
+    }
+  };
+}
+
+/**
+ * Authentication guard (placeholder for future implementation)
+ */
+export function createAuthGuard() {
+  return function authGuard(to: any, from: any, next: any) {
+    // TODO: Implement authentication logic
+    // const token = window.localStorage.getItem("skywalking-authority");
+    // if (to.meta?.requiresAuth && !token) {
+    //   next('/login');
+    //   return;
+    // }
+    next();
+  };
+}
+
+/**
+ * Route validation guard
+ */
+export function createValidationGuard() {
+  return function validationGuard(to: any, from: any, next: any) {
+    // Validate route parameters if needed
+    if (to.params && Object.keys(to.params).length > 0) {
+      // Add custom validation logic here
+      const hasValidParams = Object.values(to.params).every(
+        (param) => param !== undefined && param !== null && param !== "",
+      );
+
+      if (!hasValidParams) {
+        next({ name: "NotFound" });
+        return;
+      }
+    }
+
+    next();
+  };
+}
+
+/**
+ * Error handling guard
+ */
+export function createErrorGuard() {
+  return function errorGuard(error: any) {
+    console.error("Router error:", error);
+
+    // Handle specific error types
+    if (error.name === "NavigationDuplicated") {
+      // Ignore duplicate navigation errors
+      return;
+    }
+
+    // Redirect to error page or handle other errors
+    throw error;
+  };
+}
+
+/**
+ * Apply all navigation guards
+ */
+export function applyGuards(router: any, routes: any[]) {
+  router.beforeEach(createRootGuard(routes));
+  router.beforeEach(createAuthGuard());
+  router.beforeEach(createValidationGuard());
+  router.onError(createErrorGuard());
+}
diff --git a/src/router/index.ts b/src/router/index.ts
index cee1ee6e..523d97d0 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -14,8 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import type { RouteRecordRaw } from "vue-router";
+import type { AppRouteRecordRaw } from "@/types/router";
 import { createRouter, createWebHistory } from "vue-router";
+import { applyGuards } from "./guards";
 import { routesDashboard } from "./dashboard";
 import { routesMarketplace } from "./marketplace";
 import { routesAlarm } from "./alarm";
@@ -23,7 +24,10 @@ import routesLayers from "./layer";
 import { routesSettings } from "./settings";
 import { routesNotFound } from "./notFound";
 
-const routes: RouteRecordRaw[] = [
+/**
+ * Combine all route configurations
+ */
+export const routes: AppRouteRecordRaw[] = [
   ...routesMarketplace,
   ...routesLayers,
   ...routesAlarm,
@@ -32,36 +36,17 @@ const routes: RouteRecordRaw[] = [
   ...routesNotFound,
 ];
 
+/**
+ * Create router instance
+ */
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
-  routes,
+  routes: routes as any,
 });
 
-router.beforeEach((to, _, next) => {
-  // const token = window.localStorage.getItem("skywalking-authority");
-
-  if (to.path === "/") {
-    let defaultPath = "";
-    for (const route of routesLayers) {
-      for (const child of route.children) {
-        if (child.meta.activate) {
-          defaultPath = child.path;
-          break;
-        }
-      }
-      if (defaultPath) {
-        break;
-      }
-    }
-
-    if (!defaultPath) {
-      defaultPath = "/marketplace";
-    }
-
-    next({ path: defaultPath });
-  } else {
-    next();
-  }
-});
+/**
+ * Apply navigation guards
+ */
+applyGuards(router, routes);
 
 export default router;
diff --git a/src/router/layer.ts b/src/router/layer.ts
index 1791f480..51333787 100644
--- a/src/router/layer.ts
+++ b/src/router/layer.ts
@@ -14,74 +14,93 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import type { AppRouteRecordRaw } from "@/types/router";
+import { META_KEYS } from "./constants";
 import Layout from "@/layout/Index.vue";
 import { useAppStoreWithOut } from "@/store/modules/app";
 import type { MenuOptions } from "@/types/app";
 import Layer from "@/views/Layer.vue";
 
-function layerDashboards() {
+/**
+ * Generate layer dashboard routes from app store menu configuration
+ */
+function generateLayerDashboards(): AppRouteRecordRaw[] {
   const appStore = useAppStoreWithOut();
-  const routes = appStore.allMenus.map((item: MenuOptions) => {
-    const route: any = {
+
+  return appStore.allMenus.map((item: MenuOptions): AppRouteRecordRaw => {
+    const route: AppRouteRecordRaw = {
       path: "",
       name: item.name,
       component: Layout,
       meta: {
-        icon: item.icon || "cloud_queue",
-        title: item.title,
-        hasGroup: item.hasGroup,
-        activate: item.activate,
-        descKey: item.descKey,
-        i18nKey: item.i18nKey,
+        [META_KEYS.ICON]: item.icon || "cloud_queue",
+        [META_KEYS.TITLE]: item.title,
+        [META_KEYS.HAS_GROUP]: item.hasGroup,
+        [META_KEYS.ACTIVATE]: item.activate,
+        [META_KEYS.DESC_KEY]: item.descKey,
+        [META_KEYS.I18N_KEY]: item.i18nKey,
+        [META_KEYS.BREADCRUMB]: true,
       },
       children: item.subItems && item.subItems.length ? [] : undefined,
     };
-    for (const child of item.subItems || []) {
-      const d = {
-        name: child.name,
-        path: child.path,
-        meta: {
-          title: child.title,
-          layer: child.layer,
-          icon: child.icon || "cloud_queue",
-          activate: child.activate,
-          descKey: child.descKey,
-          i18nKey: child.i18nKey,
-        },
-        component: Layer,
-      };
-      route.children.push(d);
-      const tab = {
-        name: `${child.name}ActiveTabIndex`,
-        path: `/${child.path}/tab/:activeTabIndex`,
-        component: Layer,
-        meta: {
-          notShow: true,
-          layer: child.layer,
-        },
-      };
-      route.children.push(tab);
-    }
-    if (!item.hasGroup) {
+
+    // Handle grouped items
+    if (item.subItems && item.subItems.length) {
+      for (const child of item.subItems) {
+        const childRoute: AppRouteRecordRaw = {
+          name: child.name,
+          path: child.path || "",
+          meta: {
+            [META_KEYS.TITLE]: child.title,
+            [META_KEYS.LAYER]: child.layer,
+            [META_KEYS.ICON]: child.icon || "cloud_queue",
+            [META_KEYS.ACTIVATE]: child.activate,
+            [META_KEYS.DESC_KEY]: child.descKey,
+            [META_KEYS.I18N_KEY]: child.i18nKey,
+            [META_KEYS.BREADCRUMB]: true,
+          },
+          component: Layer,
+        };
+
+        route.children!.push(childRoute);
+
+        // Add tab route for active tab index
+        const tabRoute: AppRouteRecordRaw = {
+          name: `${child.name}ActiveTabIndex`,
+          path: `/${child.path}/tab/:activeTabIndex`,
+          component: Layer,
+          meta: {
+            [META_KEYS.NOT_SHOW]: true,
+            [META_KEYS.LAYER]: child.layer,
+            [META_KEYS.TITLE]: child.title,
+            [META_KEYS.BREADCRUMB]: false,
+          },
+        };
+
+        route.children!.push(tabRoute);
+      }
+    } else {
+      // Handle non-grouped items
       route.children = [
         {
           name: item.name,
-          path: item.path,
+          path: item.path || "",
           meta: {
-            title: item.title,
-            layer: item.layer,
-            icon: item.icon,
-            activate: item.activate,
-            descKey: item.descKey,
-            i18nKey: item.i18nKey,
+            [META_KEYS.TITLE]: item.title,
+            [META_KEYS.LAYER]: item.layer,
+            [META_KEYS.ICON]: item.icon,
+            [META_KEYS.ACTIVATE]: item.activate,
+            [META_KEYS.DESC_KEY]: item.descKey,
+            [META_KEYS.I18N_KEY]: item.i18nKey,
+            [META_KEYS.BREADCRUMB]: true,
           },
           component: Layer,
         },
       ];
     }
+
     return route;
   });
-  return routes;
 }
 
-export default layerDashboards();
+export default generateLayerDashboards();
diff --git a/src/router/marketplace.ts b/src/router/marketplace.ts
index a2b61154..e7e5307e 100644
--- a/src/router/marketplace.ts
+++ b/src/router/marketplace.ts
@@ -14,27 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import type { RouteRecordRaw } from "vue-router";
+import type { AppRouteRecordRaw } from "@/types/router";
+import { ROUTE_NAMES, ROUTE_PATHS, META_KEYS } from "./constants";
 import Layout from "@/layout/Index.vue";
 import Marketplace from "@/views/Marketplace.vue";
 
-export const routesMarketplace: Array<RouteRecordRaw> = [
+export const routesMarketplace: AppRouteRecordRaw[] = [
   {
     path: "",
-    name: "Marketplace",
+    name: ROUTE_NAMES.MARKETPLACE,
     meta: {
-      i18nKey: "marketplace",
-      icon: "marketplace",
-      hasGroup: false,
-      activate: true,
-      title: "Marketplace",
+      [META_KEYS.I18N_KEY]: "marketplace",
+      [META_KEYS.ICON]: "marketplace",
+      [META_KEYS.HAS_GROUP]: false,
+      [META_KEYS.ACTIVATE]: true,
+      [META_KEYS.TITLE]: "Marketplace",
+      [META_KEYS.BREADCRUMB]: true,
     },
     component: Layout,
     children: [
       {
-        path: "/marketplace",
+        path: ROUTE_PATHS.MARKETPLACE,
         name: "MenusManagement",
         component: Marketplace,
+        meta: {
+          [META_KEYS.TITLE]: "Marketplace",
+          [META_KEYS.BREADCRUMB]: true,
+        },
       },
     ],
   },
diff --git a/src/router/notFound.ts b/src/router/notFound.ts
index 8efe0da0..410ee0e6 100644
--- a/src/router/notFound.ts
+++ b/src/router/notFound.ts
@@ -14,13 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import type { RouteRecordRaw } from "vue-router";
+import type { AppRouteRecordRaw } from "@/types/router";
+import { ROUTE_NAMES, ROUTE_PATHS } from "./constants";
 import NotFound from "@/views/NotFound.vue";
 
-export const routesNotFound: Array<RouteRecordRaw> = [
+export const routesNotFound: AppRouteRecordRaw[] = [
   {
-    path: "/:pathMatch(.*)*",
-    name: "NotFound",
+    path: ROUTE_PATHS.NOT_FOUND,
+    name: ROUTE_NAMES.NOT_FOUND,
     component: NotFound,
+    meta: {
+      title: "Page Not Found",
+      notShow: true,
+    },
   },
 ];
diff --git a/src/router/settings.ts b/src/router/settings.ts
index e6f14552..ae1dca16 100644
--- a/src/router/settings.ts
+++ b/src/router/settings.ts
@@ -14,27 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import type { RouteRecordRaw } from "vue-router";
+import type { AppRouteRecordRaw } from "@/types/router";
+import { ROUTE_NAMES, ROUTE_PATHS, META_KEYS } from "./constants";
 import Layout from "@/layout/Index.vue";
 import Settings from "@/views/Settings.vue";
 
-export const routesSettings: Array<RouteRecordRaw> = [
+export const routesSettings: AppRouteRecordRaw[] = [
   {
     path: "",
-    name: "Settings",
+    name: ROUTE_NAMES.SETTINGS,
     meta: {
-      i18nKey: "settings",
-      icon: "settings",
-      hasGroup: false,
-      activate: true,
-      title: "Settings",
+      [META_KEYS.I18N_KEY]: "settings",
+      [META_KEYS.ICON]: "settings",
+      [META_KEYS.HAS_GROUP]: false,
+      [META_KEYS.ACTIVATE]: true,
+      [META_KEYS.TITLE]: "Settings",
+      [META_KEYS.BREADCRUMB]: true,
     },
     component: Layout,
     children: [
       {
-        path: "/settings",
+        path: ROUTE_PATHS.SETTINGS,
         name: "ViewSettings",
         component: Settings,
+        meta: {
+          [META_KEYS.TITLE]: "Settings",
+          [META_KEYS.BREADCRUMB]: true,
+        },
       },
     ],
   },
diff --git a/src/router/utils.ts b/src/router/utils.ts
new file mode 100644
index 00000000..0830d9ee
--- /dev/null
+++ b/src/router/utils.ts
@@ -0,0 +1,102 @@
+/**
+ * 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 type { AppRouteRecordRaw } from "@/types/router";
+import { DEFAULT_ROUTE } from "./constants";
+
+/**
+ * Find the first activated route from a list of routes
+ */
+export function findActivatedRoute(routes: AppRouteRecordRaw[]): string | null 
{
+  for (const route of routes) {
+    if (route.children) {
+      for (const child of route.children) {
+        if (child.meta?.activate) {
+          return child.path;
+        }
+      }
+    }
+  }
+  return null;
+}
+
+/**
+ * Get default route path
+ */
+export function getDefaultRoute(routes: AppRouteRecordRaw[]): string {
+  const activatedRoute = findActivatedRoute(routes);
+  return activatedRoute || DEFAULT_ROUTE;
+}
+
+/**
+ * Check if route requires authentication
+ */
+export function requiresAuth(route: AppRouteRecordRaw): boolean {
+  return route.meta?.requiresAuth === true;
+}
+
+/**
+ * Generate breadcrumb data from route
+ */
+export function generateBreadcrumb(route: AppRouteRecordRaw): string[] {
+  const breadcrumbs: string[] = [];
+
+  if (route.meta?.title) {
+    breadcrumbs.push(route.meta.title);
+  }
+
+  if (route.children) {
+    route.children.forEach((child) => {
+      if (child.meta?.breadcrumb !== false && child.meta?.title) {
+        breadcrumbs.push(child.meta.title);
+      }
+    });
+  }
+
+  return breadcrumbs;
+}
+
+/**
+ * Validate route configuration
+ */
+export function validateRoute(route: AppRouteRecordRaw): boolean {
+  if (!route.path || !route.name || !route.component) {
+    return false;
+  }
+
+  if (route.children) {
+    return route.children.every((child) => validateRoute(child));
+  }
+
+  return true;
+}
+
+/**
+ * Flatten nested routes for easier processing
+ */
+export function flattenRoutes(routes: AppRouteRecordRaw[]): 
AppRouteRecordRaw[] {
+  const flattened: AppRouteRecordRaw[] = [];
+
+  routes.forEach((route) => {
+    flattened.push(route);
+    if (route.children) {
+      flattened.push(...flattenRoutes(route.children));
+    }
+  });
+
+  return flattened;
+}
diff --git a/src/router/alarm.ts b/src/types/router.ts
similarity index 59%
copy from src/router/alarm.ts
copy to src/types/router.ts
index 0249b829..2116bcfc 100644
--- a/src/router/alarm.ts
+++ b/src/types/router.ts
@@ -14,28 +14,37 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 import type { RouteRecordRaw } from "vue-router";
-import Layout from "@/layout/Index.vue";
-import Alarm from "@/views/Alarm.vue";
 
-export const routesAlarm: Array<RouteRecordRaw> = [
-  {
-    path: "",
-    name: "Alarm",
-    meta: {
-      i18nKey: "alarm",
-      icon: "spam",
-      hasGroup: false,
-      activate: true,
-      title: "Alerting",
-    },
-    component: Layout,
-    children: [
-      {
-        path: "/alerting",
-        name: "ViewAlarm",
-        component: Alarm,
-      },
-    ],
-  },
-];
+export interface RouteMeta {
+  title?: string;
+  i18nKey?: string;
+  icon?: string;
+  hasGroup?: boolean;
+  activate?: boolean;
+  descKey?: string;
+  layer?: string;
+  notShow?: boolean;
+  requiresAuth?: boolean;
+  breadcrumb?: boolean;
+}
+
+export interface AppRouteRecordRaw extends Omit<RouteRecordRaw, "meta" | 
"children"> {
+  meta: RouteMeta;
+  children?: AppRouteRecordRaw[];
+}
+
+export interface RouteConfig {
+  path: string;
+  name: string;
+  component: any;
+  meta: RouteMeta;
+  children?: RouteConfig[];
+}
+
+export interface NavigationGuard {
+  to: any;
+  from: any;
+  next: any;
+}


Reply via email to