bdd30f0a88
- deps.py: _create_redis_client 增加同步 ping 校验,Redis 不可达时正确降级为内存模式 - main.py: lifespan 复用 deps 的 UserStore 单例,避免 admin 与 API 请求实例不一致 - 前端: 强制改密弹窗(must_change_password 用户)、兼容新旧登录返回格式、markPasswordChanged - 新增 NAS SSH 部署脚本与批处理测试;gitignore 前端构建产物
88 lines
2.3 KiB
JavaScript
88 lines
2.3 KiB
JavaScript
import { defineStore } from 'pinia'
|
|
|
|
const TOKEN_STORAGE_KEY = 'qmd_token'
|
|
const USER_STORAGE_KEY = 'qmd_user'
|
|
|
|
/**
|
|
* 从 localStorage 读取用户信息
|
|
* @returns {{username:string, role:string, created_at?:string} | null}
|
|
*/
|
|
function loadUserFromStorage() {
|
|
try {
|
|
const raw = localStorage.getItem(USER_STORAGE_KEY)
|
|
if (!raw) return null
|
|
const parsed = JSON.parse(raw)
|
|
if (parsed && typeof parsed === 'object' && parsed.username) {
|
|
return parsed
|
|
}
|
|
return null
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
export const useAuthStore = defineStore('auth', {
|
|
state: () => ({
|
|
token: localStorage.getItem(TOKEN_STORAGE_KEY) || '',
|
|
user: loadUserFromStorage()
|
|
}),
|
|
|
|
getters: {
|
|
isAuthenticated: (state) => Boolean(state.token),
|
|
isAdmin: (state) => state.user?.role === 'admin',
|
|
displayName: (state) => {
|
|
if (!state.user) return ''
|
|
return `${state.user.username} (${state.user.role})`
|
|
}
|
|
},
|
|
|
|
actions: {
|
|
/**
|
|
* 登录成功后保存 token + user
|
|
* 兼容后端两种返回:
|
|
* - 新格式 { token, username, role, must_change_password }
|
|
* - 旧格式 { access_token, user: { username, role, ... } }
|
|
* @param {object} data
|
|
*/
|
|
setAuth(data) {
|
|
const token = data?.access_token ?? data?.token
|
|
const user =
|
|
data?.user ??
|
|
(data
|
|
? {
|
|
username: data.username,
|
|
role: data.role,
|
|
must_change_password: data.must_change_password ?? false
|
|
}
|
|
: null)
|
|
if (!token || !user) return
|
|
this.token = token
|
|
this.user = user
|
|
localStorage.setItem(TOKEN_STORAGE_KEY, token)
|
|
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(user))
|
|
},
|
|
|
|
/** 清除登录态(登出 / 401) */
|
|
clearAuth() {
|
|
this.token = ''
|
|
this.user = null
|
|
localStorage.removeItem(TOKEN_STORAGE_KEY)
|
|
localStorage.removeItem(USER_STORAGE_KEY)
|
|
},
|
|
|
|
/** 改密成功后更新本地用户状态(清除 must_change_password 标记) */
|
|
markPasswordChanged() {
|
|
if (!this.user) return
|
|
this.user = { ...this.user, must_change_password: false }
|
|
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(this.user))
|
|
},
|
|
|
|
/**
|
|
* 登出
|
|
*/
|
|
logout() {
|
|
this.clearAuth()
|
|
}
|
|
}
|
|
})
|