feat: 第一阶段基础框架搭建

后端 (Laravel 10 + Sanctum):
- RBAC 四层权限系统 (users→roles→permissions→menus)
- 门店隔离中间件 (BelongsToStore Trait + StoreIsolation Middleware)
- 操作日志中间件 (自动记录写操作)
- 权限检查中间件 (CheckPermission)
- 16张数据库表迁移 (系统基础+RBAC+字典+配置)
- 11个 Eloquent Model
- Auth API (登录/登出/用户信息)
- 系统设置模块 CRUD (门店/部门/职务/用户/角色/菜单/权限/字典/日志)
- 45条 RESTful API 路由
- InitSeeder 初始数据 (超管/角色/76权限/31菜单)

前端 (Vue 3 + Element Plus + Vite):
- Axios 请求封装 + Token 注入
- Pinia 状态管理 (user + permission store)
- 动态路由 (服务端菜单→前端路由自动生成)
- 后台布局 (侧边栏+顶栏+主内容区)
- 登录页 + 仪表盘首页
- 系统设置 7 个 CRUD 页面

技术方案文档 (7卷):
- 技术总览/数据库设计/API规范/RBAC设计/模块详设/小程序设计/部署方案
This commit is contained in:
li
2026-03-13 19:52:09 +08:00
commit 11c177a432
144 changed files with 25209 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
import { createRouter, createWebHistory } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { constantRoutes } from '@/router/routes.js'
NProgress.configure({ showSpinner: false })
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
}
return { top: 0 }
}
})
// Whitelist paths that don't require authentication
const WHITE_LIST = ['/login', '/404']
router.beforeEach(async (to, from, next) => {
NProgress.start()
// Lazily import stores to avoid circular dependency at module init time
const { useUserStore } = await import('@/stores/user.js')
const { usePermissionStore } = await import('@/stores/permission.js')
const userStore = useUserStore()
const permissionStore = usePermissionStore()
const token = userStore.token
if (token) {
if (to.path === '/login') {
// Already logged in — redirect to home
next({ path: '/' })
} else {
// Check if user info has been fetched
if (!userStore.userInfo) {
try {
await userStore.getInfo()
const accessRoutes = permissionStore.generateRoutes(userStore.menus)
accessRoutes.forEach((route) => router.addRoute(route))
// Replace so the new routes are active
next({ ...to, replace: true })
} catch (err) {
// Token invalid — clear and redirect
await userStore.logout()
next(`/login?redirect=${to.path}`)
}
} else {
next()
}
}
} else {
// No token
if (WHITE_LIST.includes(to.path)) {
next()
} else {
next(`/login?redirect=${to.path}`)
}
}
})
router.afterEach(() => {
NProgress.done()
})
export default router