feat: Multi-user system with PostgreSQL - WIP temporary save

This commit is contained in:
TIANHE
2026-01-14 05:29:55 +08:00
parent 996e3b38fe
commit 61a5e5e6aa
68 changed files with 91057 additions and 1920 deletions
+6 -6
View File
@@ -4,13 +4,13 @@ import Vuex from 'vuex'
import app from './modules/app'
import user from './modules/user'
// default router permission control
// 默认路由模式为静态路由 (router.config.js)
import permission from './modules/static-router'
// dynamic router permission control
// 动态路由模式(支持基于角色的菜单过滤)
import permission from './modules/async-router'
// dynamic router permission control (Experimental)
// 态路由模式(api请求后端生成
// import permission from './modules/async-router'
// static router permission control (NO filtering)
// 态路由模式(不过滤菜单,已弃用
// import permission from './modules/static-router'
import getters from './getters'
@@ -13,10 +13,15 @@ const permission = {
SET_ROUTERS: (state, routers) => {
state.addRouters = routers
state.routers = constantRouterMap.concat(routers)
},
// Reset routers to force regeneration (used on login/logout)
RESET_ROUTERS: (state) => {
state.addRouters = []
state.routers = constantRouterMap
}
},
actions: {
GenerateRoutes ({ commit }, data) {
GenerateRoutes ({ commit, rootState }, data) {
return new Promise((resolve, reject) => {
const { token } = data
generatorDynamicRouter(token).then(routers => {
@@ -26,6 +31,10 @@ const permission = {
reject(e)
})
})
},
// Reset routes action
ResetRoutes ({ commit }) {
commit('RESET_ROUTERS')
}
}
}
+27 -6
View File
@@ -30,7 +30,11 @@ function getStoredToken () {
}
const initialInfo = getStoredInfo()
const initialRoles = getStoredRoles()
// If is_demo is missing (legacy cache), force roles to empty to trigger GetInfo in permission.js
let initialRoles = getStoredRoles()
if (initialInfo && typeof initialInfo.is_demo === 'undefined') {
initialRoles = []
}
const initialToken = getStoredToken() || ''
const initialName = initialInfo.nickname || initialInfo.username || ''
const initialAvatar = initialInfo.avatar || ''
@@ -66,7 +70,7 @@ const user = {
actions: {
// 登录
Login ({ commit }, userInfo) {
Login ({ commit, dispatch }, userInfo) {
return new Promise((resolve, reject) => {
login(userInfo).then(response => {
// 适配 Python 后端响应格式
@@ -86,11 +90,23 @@ const user = {
commit('SET_NAME', { name: name, welcome: welcome() })
commit('SET_AVATAR', info.avatar || '/avatar2.jpg')
// 设置默认角色,防止路由鉴权失败
const roles = [{ id: 'admin', permissionList: ['dashboard', 'exception', 'account'] }]
// 从服务器返回的角色信息设置角色
let roles = [DEFAULT_ROLE]
if (info.role) {
// role: { id: 'admin', permissions: [...] }
const roleId = info.role.id || info.role
const permissions = info.role.permissions || []
roles = [{
id: roleId,
permissionList: permissions.length > 0 ? permissions : ['dashboard']
}]
}
commit('SET_ROLES', roles)
storage.set(USER_ROLES, roles, expiresAt)
// 重置路由,强制重新生成(根据新用户的角色)
dispatch('ResetRoutes')
resolve(response)
} else {
reject(new Error((response && response.msg) || 'Login failed'))
@@ -279,7 +295,8 @@ const user = {
GetInfo ({ commit, state }) {
return new Promise((resolve, reject) => {
// 用户信息已经在登录时保存到 store 中,直接返回
if (state.info && Object.keys(state.info).length > 0) {
// 增加 check: 必须包含 is_demo 字段,否则视为过期缓存,强制刷新
if (state.info && Object.keys(state.info).length > 0 && typeof state.info.is_demo !== 'undefined') {
// 补全 Roles
const info = state.info
if (info.role) {
@@ -379,7 +396,7 @@ const user = {
},
// 登出
Logout ({ commit, state }) {
Logout ({ commit, state, dispatch }) {
return new Promise((resolve) => {
// 兼容旧登出与新后端登出
const req = typeof apiLogout === 'function' ? apiLogout() : logout(state.token)
@@ -392,12 +409,16 @@ const user = {
storage.remove(ACCESS_TOKEN)
storage.remove(USER_INFO)
storage.remove(USER_ROLES)
// 重置路由
dispatch('ResetRoutes')
resolve()
}).catch(() => {
// 登出失败时也继续执行,确保清理本地状态
storage.remove(ACCESS_TOKEN)
storage.remove(USER_INFO)
storage.remove(USER_ROLES)
// 重置路由
dispatch('ResetRoutes')
resolve()
}).finally(() => {
})