diff --git a/src/composables/index.ts b/src/composables/index.ts index 5086761..c894854 100644 --- a/src/composables/index.ts +++ b/src/composables/index.ts @@ -1,5 +1,6 @@ export { useAdminFiles } from './useAdminFiles' export { useAdminLogin } from './useAdminLogin' +export { useAdminSession } from './useAdminSession' export { useAppShell } from './useAppShell' export { useDashboardStats } from './useDashboardStats' export { useInjectedDarkMode } from './useInjectedDarkMode' diff --git a/src/composables/useAdminLogin.ts b/src/composables/useAdminLogin.ts index 7c81627..ce6a219 100644 --- a/src/composables/useAdminLogin.ts +++ b/src/composables/useAdminLogin.ts @@ -35,7 +35,13 @@ export function useAdminLogin() { return false } - adminStore.setToken(response.detail.token) + adminStore.login({ + id: response.detail.id || 'admin', + username: response.detail.username || 'admin', + token: response.detail.token, + token_type: response.detail.token_type, + expires_at: response.detail.expires_at + }) return true } catch (error: unknown) { alertStore.showAlert(getErrorMessage(error, '登录失败'), 'error') diff --git a/src/composables/useAdminSession.ts b/src/composables/useAdminSession.ts new file mode 100644 index 0000000..9333146 --- /dev/null +++ b/src/composables/useAdminSession.ts @@ -0,0 +1,35 @@ +import { AuthService } from '@/services' +import { useAdminStore } from '@/stores/adminStore' + +export function useAdminSession() { + const adminStore = useAdminStore() + + const verifySession = async () => { + if (!adminStore.hasToken) return false + + try { + const response = await AuthService.verifyToken() + if (response.code === 200 && response.detail?.token) { + adminStore.login(response.detail) + return true + } + } catch { + adminStore.logout() + } + + return false + } + + const logout = async () => { + try { + await AuthService.logout() + } finally { + adminStore.logout() + } + } + + return { + verifySession, + logout + } +} diff --git a/src/layout/AdminLayout/AdminLayout.vue b/src/layout/AdminLayout/AdminLayout.vue index 6eb588f..24c3a7d 100644 --- a/src/layout/AdminLayout/AdminLayout.vue +++ b/src/layout/AdminLayout/AdminLayout.vue @@ -120,7 +120,7 @@ import { import { RouterLink, useRoute, useRouter } from 'vue-router' import { useI18n } from 'vue-i18n' import { ROUTE_NAMES, ROUTES } from '@/constants' -import { useAdminStore } from '@/stores/adminStore' +import { useAdminSession } from '@/composables' interface MenuItem { id: string @@ -133,7 +133,7 @@ const router = useRouter() const route = useRoute() const { t } = useI18n() const isDarkMode = inject('isDarkMode') -const adminStore = useAdminStore() +const { verifySession, logout } = useAdminSession() const menuItems: MenuItem[] = [ { id: ROUTE_NAMES.DASHBOARD, @@ -172,6 +172,11 @@ const handleResize = () => { onMounted(() => { handleResize() window.addEventListener('resize', handleResize) + void verifySession().then((isValid) => { + if (!isValid) { + void router.push(ROUTES.LOGIN) + } + }) }) onUnmounted(() => { @@ -179,9 +184,9 @@ onUnmounted(() => { }) // 登出处理 -const handleLogout = () => { - adminStore.logout() - router.push(ROUTES.LOGIN) +const handleLogout = async () => { + await logout() + await router.push(ROUTES.LOGIN) } diff --git a/src/services/config.ts b/src/services/config.ts index 9d60b75..0f183bf 100644 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -1,13 +1,39 @@ import api from './client' import type { ApiResponse, ConfigState } from '@/types' +type PublicConfigEnvelope = { + config?: Partial + meta?: unknown +} + +const isPublicConfigEnvelope = ( + detail: ConfigState | PublicConfigEnvelope | null | undefined +): detail is PublicConfigEnvelope => { + return !!detail && typeof detail === 'object' && 'config' in detail +} + export class ConfigService { static async getConfig(): Promise> { return api.get('/admin/config/get') } static async getUserConfig(): Promise> { - return api.post('/') + try { + const response = (await api.get('/api/v1/config')) as ApiResponse< + ConfigState | PublicConfigEnvelope + > + + if (isPublicConfigEnvelope(response.detail) && response.detail.config) { + return { + ...response, + detail: response.detail.config as ConfigState + } + } + + return response as ApiResponse + } catch { + return api.post('/') + } } static async updateConfig(config: Partial): Promise { diff --git a/src/types/api.ts b/src/types/api.ts index 3ae1779..ebb6f43 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -1,6 +1,7 @@ export interface ApiResponse { code: number message?: string + msg?: string detail?: T } diff --git a/src/types/auth.ts b/src/types/auth.ts index 8558757..800740b 100644 --- a/src/types/auth.ts +++ b/src/types/auth.ts @@ -2,4 +2,6 @@ export interface AdminUser { id: string username: string token: string + token_type?: string + expires_at?: number }