diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue
new file mode 100644
index 0000000..b47f3ac
--- /dev/null
+++ b/src/layouts/MainLayout.vue
@@ -0,0 +1,148 @@
+
+
+
+ 凡荣e链
+
+
+
+ {{ node.name }}
+
+ {{ child.name }}
+
+
+
+ {{ node.name }}
+
+
+
+
+
+
+
+ {{ authStore.userInfo?.realName || authStore.userInfo?.username || '用户' }}
+
+
+
+ 退出登录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/stores/tabs.js b/src/stores/tabs.js
new file mode 100644
index 0000000..6727c65
--- /dev/null
+++ b/src/stores/tabs.js
@@ -0,0 +1,39 @@
+import { defineStore } from 'pinia'
+
+export const useTabsStore = defineStore('tabs', {
+ state: () => ({
+ tabs: [],
+ activeKey: ''
+ }),
+ actions: {
+ openTab(route) {
+ const key = route.path
+ if (!this.tabs.some((t) => t.key === key)) {
+ this.tabs.push({
+ key,
+ title: route.meta?.title || key,
+ path: route.fullPath
+ })
+ }
+ this.activeKey = key
+ },
+ closeTab(key, router, currentPath) {
+ const index = this.tabs.findIndex((t) => t.key === key)
+ if (index === -1) return
+ this.tabs.splice(index, 1)
+ if (key === currentPath) {
+ const next = this.tabs[index] || this.tabs[index - 1]
+ if (next) {
+ this.activeKey = next.key
+ router.push(next.path)
+ } else {
+ router.push('/')
+ }
+ }
+ },
+ reset() {
+ this.tabs = []
+ this.activeKey = ''
+ }
+ }
+})