135 lines
3.4 KiB
TypeScript
135 lines
3.4 KiB
TypeScript
import { computed, ref } from 'vue'
|
|
import { defineStore } from 'pinia'
|
|
|
|
import { getCurrentUser, login as loginRequest, logout as logoutRequest } from '@/api/auth'
|
|
import type { AuthenticatedUser, LoginRequest, LoginResponse } from '@/types/auth'
|
|
import { clearAuthStorage, readStoredAuthSession, saveAuthSession } from '@/utils/auth-storage'
|
|
|
|
const dataScopeLabels: Record<AuthenticatedUser['dataScope'], string> = {
|
|
ALL: '全院',
|
|
CAMPUS: '院区',
|
|
DEPARTMENT: '科室',
|
|
READ_ONLY_ALL: '全院只读',
|
|
}
|
|
|
|
function getUserContext(user: AuthenticatedUser | null) {
|
|
return user ? `${dataScopeLabels[user.dataScope]}数据范围` : '医签通用户'
|
|
}
|
|
|
|
export const useLoginStore = defineStore('login', () => {
|
|
const storedSession = readStoredAuthSession()
|
|
const token = ref(storedSession?.token ?? '')
|
|
const expiresAt = ref(storedSession?.expiresAt ?? '')
|
|
const user = ref<AuthenticatedUser | null>(storedSession?.user ?? null)
|
|
const currentUserReady = ref(false)
|
|
let currentUserRequest: Promise<AuthenticatedUser> | null = null
|
|
|
|
const isLoggedIn = computed(() => Boolean(token.value))
|
|
const userName = computed(() => user.value?.displayName || user.value?.username || '医护用户')
|
|
const department = computed(() => getUserContext(user.value))
|
|
|
|
function hasPermission(required: string | string[]) {
|
|
const requiredPermissions = Array.isArray(required) ? required : [required]
|
|
|
|
if (!requiredPermissions.length) {
|
|
return true
|
|
}
|
|
|
|
const permissions = user.value?.permissions ?? []
|
|
return requiredPermissions.every(
|
|
(permission) => permissions.includes(permission) || permissions.includes('*'),
|
|
)
|
|
}
|
|
|
|
function setSession(session: LoginResponse) {
|
|
saveAuthSession(session)
|
|
token.value = session.token
|
|
expiresAt.value = session.expiresAt
|
|
user.value = session.user
|
|
currentUserReady.value = false
|
|
}
|
|
|
|
function setCurrentUser(nextUser: AuthenticatedUser) {
|
|
user.value = nextUser
|
|
|
|
if (token.value) {
|
|
saveAuthSession({
|
|
token: token.value,
|
|
expiresAt: expiresAt.value,
|
|
user: nextUser,
|
|
})
|
|
}
|
|
}
|
|
|
|
function clearSession() {
|
|
clearAuthStorage()
|
|
token.value = ''
|
|
expiresAt.value = ''
|
|
user.value = null
|
|
currentUserReady.value = false
|
|
currentUserRequest = null
|
|
}
|
|
|
|
async function login(payload: LoginRequest) {
|
|
const session = await loginRequest(payload)
|
|
setSession(session)
|
|
return session
|
|
}
|
|
|
|
async function refreshCurrentUser() {
|
|
const currentUser = await getCurrentUser()
|
|
setCurrentUser(currentUser)
|
|
return currentUser
|
|
}
|
|
|
|
async function ensureCurrentUser() {
|
|
if (!token.value) {
|
|
return null
|
|
}
|
|
|
|
if (currentUserReady.value && user.value) {
|
|
return user.value
|
|
}
|
|
|
|
if (!currentUserRequest) {
|
|
currentUserRequest = refreshCurrentUser()
|
|
.then((currentUser) => {
|
|
currentUserReady.value = true
|
|
return currentUser
|
|
})
|
|
.catch((error: unknown) => {
|
|
currentUserReady.value = false
|
|
throw error
|
|
})
|
|
.finally(() => {
|
|
currentUserRequest = null
|
|
})
|
|
}
|
|
|
|
return currentUserRequest
|
|
}
|
|
|
|
async function logout() {
|
|
try {
|
|
await logoutRequest()
|
|
} finally {
|
|
clearSession()
|
|
}
|
|
}
|
|
|
|
return {
|
|
token,
|
|
expiresAt,
|
|
user,
|
|
isLoggedIn,
|
|
userName,
|
|
department,
|
|
login,
|
|
refreshCurrentUser,
|
|
ensureCurrentUser,
|
|
hasPermission,
|
|
logout,
|
|
clearSession,
|
|
}
|
|
})
|