diff --git a/README.md b/README.md
index 33895ab..32dfb20 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-# Vue 3 + TypeScript + Vite
+# GERP
+
+An ERP backend built using Vue, TypeScript, and Vite, handed over for use in the SAAS scenarios under GVSDS.
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/router/index.ts b/src/router/index.ts
new file mode 100644
index 0000000..d874fa0
--- /dev/null
+++ b/src/router/index.ts
@@ -0,0 +1,79 @@
+import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
+import { useUserStore } from '@/stores/user'
+
+/** 静态路由(无需权限) */
+export const staticRoutes: RouteRecordRaw[] = [
+ {
+ path: '/login',
+ name: 'Login',
+ component: () => import('@/views/Login.vue'),
+ meta: { title: '登录', requiresAuth: false, layout: 'blank' },
+ },
+ {
+ path: '/',
+ component: () => import('@/layouts/DefaultLayout.vue'),
+ redirect: '/dashboard',
+ children: [
+ {
+ path: 'dashboard',
+ name: 'Dashboard',
+ component: () => import('@/views/Dashboard.vue'),
+ meta: { title: '仪表盘', icon: 'Odometer', requiresAuth: true },
+ },
+ {
+ path: 'profile',
+ name: 'Profile',
+ component: () => import('@/views/Profile.vue'),
+ meta: { title: '个人中心', icon: 'User', requiresAuth: true },
+ },
+ ],
+ },
+ {
+ path: '/:pathMatch(.*)*',
+ name: 'NotFound',
+ component: () => import('@/views/NotFound.vue'),
+ meta: { title: '页面不存在', requiresAuth: false, layout: 'blank' },
+ },
+]
+
+/** 动态路由(从后端菜单加载后注入) */
+export const dynamicRoutes: RouteRecordRaw[] = []
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes: staticRoutes,
+ scrollBehavior(_to, _from, savedPosition) {
+ return savedPosition || { top: 0 }
+ },
+})
+
+/** 全局前置守卫:登录态校验、动态路由注入 */
+router.beforeEach(async (to, _from, next) => {
+ // 设置页面标题
+ document.title = (to.meta.title as string) || 'GERP 管理系统'
+
+ const userStore = useUserStore()
+
+ // 不需要登录的页面直接放行
+ if (to.meta.requiresAuth === false) {
+ next()
+ return
+ }
+
+ // 已登录但未加载用户信息:尝试加载
+ if (!userStore.isLoggedIn) {
+ try {
+ await userStore.fetchUserInfo()
+ await userStore.fetchMenus()
+ // TODO: 注入动态路由后 next({ ...to, replace: true })
+ } catch {
+ // 加载失败:跳转登录
+ next({ name: 'Login', query: { redirect: to.fullPath } })
+ return
+ }
+ }
+
+ next()
+})
+
+export default router
diff --git a/src/stores/app.ts b/src/stores/app.ts
new file mode 100644
index 0000000..ee6f4d0
--- /dev/null
+++ b/src/stores/app.ts
@@ -0,0 +1,45 @@
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+
+/** 应用状态:侧边栏折叠、主题、语言等全局 UI 状态 */
+export const useAppStore = defineStore('app', () => {
+ /** 侧边栏是否折叠 */
+ const sidebarCollapsed = ref(false)
+ /** 当前主题:light / dark */
+ const theme = ref<'light' | 'dark'>('light')
+ /** 当前语言 */
+ const locale = ref<'zh-CN' | 'en-US'>('zh-CN')
+
+ /** 切换侧边栏 */
+ function toggleSidebar(): void {
+ sidebarCollapsed.value = !sidebarCollapsed.value
+ }
+
+ /** 设置主题 */
+ function setTheme(value: 'light' | 'dark'): void {
+ theme.value = value
+ document.documentElement.classList.toggle('dark', value === 'dark')
+ localStorage.setItem('gerp-theme', value)
+ }
+
+ /** 初始化主题(从 localStorage 恢复) */
+ function initTheme(): void {
+ const saved = localStorage.getItem('gerp-theme') as 'light' | 'dark' | null
+ if (saved) setTheme(saved)
+ }
+
+ /** 切换主题 */
+ function toggleTheme(): void {
+ setTheme(theme.value === 'light' ? 'dark' : 'light')
+ }
+
+ return {
+ sidebarCollapsed,
+ theme,
+ locale,
+ toggleSidebar,
+ setTheme,
+ initTheme,
+ toggleTheme,
+ }
+})
diff --git a/src/stores/user.ts b/src/stores/user.ts
new file mode 100644
index 0000000..ff824d2
--- /dev/null
+++ b/src/stores/user.ts
@@ -0,0 +1,110 @@
+import { defineStore } from 'pinia'
+import { ref, computed } from 'vue'
+import type { UserInfo, MenuItem } from '@/types/api'
+import { getCurrentUser, getUserRoles, login as apiLogin, logout as apiLogout, type LoginParams } from '@/api/auth'
+import { getMenuList } from '@/api/menu'
+
+/** 用户状态管理:当前登录用户、角色、菜单、权限 */
+export const useUserStore = defineStore('user', () => {
+ // === 状态 ===
+ const userInfo = ref(null)
+ const roles = ref([])
+ const menus = ref