Files
xh-medical-sign-web/clinical-web/src/stores/login.ts
T

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,
}
})