2026-04-01 00:58:42 +08:00
|
|
|
import { defineStore } from "pinia";
|
|
|
|
|
import { computed, ref } from "vue";
|
|
|
|
|
|
|
|
|
|
import type { LoginRequest, UserInfo } from "@geo/shared-types";
|
|
|
|
|
|
|
|
|
|
import { authApi } from "@/lib/api";
|
|
|
|
|
import {
|
|
|
|
|
clearStoredSession,
|
|
|
|
|
readStoredSession,
|
|
|
|
|
setStoredTokens,
|
|
|
|
|
setStoredUser,
|
|
|
|
|
subscribeStoredSession,
|
|
|
|
|
type SessionSnapshot,
|
|
|
|
|
} from "@/lib/session";
|
|
|
|
|
|
|
|
|
|
export const useAuthStore = defineStore("auth", () => {
|
|
|
|
|
const accessToken = ref<string | null>(null);
|
|
|
|
|
const refreshToken = ref<string | null>(null);
|
|
|
|
|
const user = ref<UserInfo | null>(null);
|
|
|
|
|
const initialized = ref(false);
|
|
|
|
|
let unsubscribe: (() => void) | null = null;
|
|
|
|
|
|
|
|
|
|
function sync(snapshot: SessionSnapshot = readStoredSession()): void {
|
|
|
|
|
accessToken.value = snapshot.accessToken;
|
|
|
|
|
refreshToken.value = snapshot.refreshToken;
|
|
|
|
|
user.value = snapshot.user;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function bootstrap(): Promise<void> {
|
|
|
|
|
if (!unsubscribe) {
|
|
|
|
|
unsubscribe = subscribeStoredSession(sync);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sync();
|
|
|
|
|
if (accessToken.value) {
|
|
|
|
|
try {
|
|
|
|
|
const currentUser = await authApi.me();
|
|
|
|
|
setStoredUser(currentUser);
|
|
|
|
|
} catch {
|
|
|
|
|
clearStoredSession();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initialized.value = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function login(payload: LoginRequest): Promise<UserInfo> {
|
|
|
|
|
const response = await authApi.login(payload);
|
|
|
|
|
setStoredTokens({
|
|
|
|
|
accessToken: response.access_token,
|
|
|
|
|
refreshToken: response.refresh_token,
|
|
|
|
|
});
|
|
|
|
|
setStoredUser(response.user);
|
|
|
|
|
return response.user;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function logout(): Promise<void> {
|
|
|
|
|
try {
|
|
|
|
|
if (accessToken.value) {
|
|
|
|
|
await authApi.logout();
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
clearStoredSession();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isAuthenticated = computed(() => Boolean(accessToken.value && user.value));
|
2026-04-17 09:02:39 +08:00
|
|
|
const kolProfile = computed(() => user.value?.kol_profile ?? null);
|
|
|
|
|
const isActiveKol = computed(() => kolProfile.value?.status === "active");
|
2026-04-01 00:58:42 +08:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
accessToken,
|
|
|
|
|
refreshToken,
|
|
|
|
|
user,
|
|
|
|
|
initialized,
|
|
|
|
|
isAuthenticated,
|
2026-04-17 09:02:39 +08:00
|
|
|
kolProfile,
|
|
|
|
|
isActiveKol,
|
2026-04-01 00:58:42 +08:00
|
|
|
bootstrap,
|
|
|
|
|
login,
|
|
|
|
|
logout,
|
|
|
|
|
};
|
|
|
|
|
});
|