feat: 完成登录session处理

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-04-24 22:22:21 +08:00
parent 5294528148
commit 81965595f0
15 changed files with 804 additions and 240 deletions
+7
View File
@@ -1,6 +1,13 @@
<script setup lang="ts">
import { Toaster } from "vue-sonner";
import { useUserStore } from "~/stores";
import "vue-sonner/style.css";
const userStore = useUserStore();
onMounted(() => {
userStore.getUserInfo();
});
</script>
<template>
+2
View File
@@ -19,6 +19,7 @@ const emit = defineEmits<{
const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const { isOnline, getUserInfoLoading } = storeToRefs(userStore);
const formRef = ref<FormRef>();
const form = reactive<Required<IUserLoginRequest>>({
@@ -99,6 +100,7 @@ defineExpose({
size="large"
type="primary"
:loading="userStore.loginLoading"
:disabled="getUserInfoLoading || isOnline"
>
登录
</el-button>
+2
View File
@@ -26,6 +26,7 @@ const emit = defineEmits<{
const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const { isOnline, getUserInfoLoading } = storeToRefs(userStore);
const formRef = ref<FormRef>();
const form = reactive<RegisterForm>({
@@ -175,6 +176,7 @@ defineExpose({
size="large"
type="primary"
:loading="userStore.registerLoading"
:disabled="getUserInfoLoading || isOnline"
>
注册
</el-button>
+2 -2
View File
@@ -13,8 +13,8 @@ const { isOnline } = storeToRefs(userStore);
const isSignUp = computed(() => route.query._loginAction === "signUp");
onMounted(() => {
if (isOnline.value) {
watch(isOnline, (online) => {
if (online) {
navigateTo("/");
}
});
+7
View File
@@ -3,6 +3,7 @@ import type {
IUserLoginData,
IUserLoginRequest,
IUserLogoutData,
IUserMeData,
IUserRegisterData,
IUserRegisterRequest
} from "#shared/types";
@@ -20,6 +21,12 @@ export class UserService {
);
}
public static UserMe() {
return $fetch<ICommonResponse<IUserMeData>>(`${UserService.basePath}/me`, {
method: "GET"
});
}
public static UserRegister(request: IUserRegisterRequest) {
return $fetch<ICommonResponse<IUserRegisterData>>(
`${UserService.basePath}/register`,
+53 -7
View File
@@ -1,3 +1,4 @@
import { StorageSerializers, useLocalStorage } from "@vueuse/core";
import { toast } from "vue-sonner";
import type {
ICommonResponse,
@@ -9,30 +10,41 @@ import type {
} from "#shared/types";
import { UserService } from "~/services";
const USER_INFO_STORAGE_KEY = "newapi_user_info";
export const useUserStore = defineStore("user", () => {
/** 用户登录状态 */
const isOnline = ref(false);
/** 用户信息 */
const userInfo = ref<IUserLoginData | null>(null);
const userInfo = useLocalStorage<IUserLoginData | null>(
USER_INFO_STORAGE_KEY,
null,
{
serializer: StorageSerializers.object
}
);
/** 登录加载状态 */
const loginLoading = ref(false);
/** 注册加载状态 */
const registerLoading = ref(false);
/** 登出加载状态 */
const logoutLoading = ref(false);
/** 刷新当前用户信息加载状态 */
const getUserInfoLoading = ref(false);
/** 用户登录 */
const login = async (
request: IUserLoginRequest
): Promise<ICommonResponse<IUserLoginData> | null> => {
if (loginLoading.value || isOnline.value) return null;
if (loginLoading.value || isOnline.value || getUserInfoLoading.value)
return null;
loginLoading.value = true;
try {
const res = await UserService.UserLogin(request);
if (res.code === 0) {
if (res.code === 0 && res.data) {
isOnline.value = true;
userInfo.value = res.data;
toast.success(res.msg || "登录成功");
@@ -53,11 +65,40 @@ export const useUserStore = defineStore("user", () => {
}
};
/** 通过 /api/auth/me 恢复刷新后的登录状态 */
const getUserInfo =
async (): Promise<ICommonResponse<IUserLoginData> | null> => {
if (getUserInfoLoading.value) return null;
getUserInfoLoading.value = true;
try {
const res = await UserService.UserMe();
if (res.code === 0 && res.data) {
isOnline.value = true;
userInfo.value = res.data;
} else {
isOnline.value = false;
userInfo.value = null;
}
return res;
} catch {
isOnline.value = false;
userInfo.value = null;
return null;
} finally {
getUserInfoLoading.value = false;
}
};
/** 用户注册 */
const register = async (
request: IUserRegisterRequest
): Promise<ICommonResponse<IUserRegisterData> | null> => {
if (registerLoading.value || isOnline.value) return null;
if (registerLoading.value || isOnline.value || getUserInfoLoading.value)
return null;
registerLoading.value = true;
@@ -79,7 +120,7 @@ export const useUserStore = defineStore("user", () => {
/** 用户登出 */
const logout = async (): Promise<ICommonResponse<IUserLogoutData> | null> => {
if (logoutLoading.value || !isOnline.value) return null;
if (logoutLoading.value || getUserInfoLoading.value) return null;
logoutLoading.value = true;
@@ -87,15 +128,18 @@ export const useUserStore = defineStore("user", () => {
const res = await UserService.UserLogout();
if (res.code === 0) {
isOnline.value = false;
userInfo.value = null;
toast.success(res.msg || "登出成功");
} else {
toast.warning(res.msg || "登出失败");
}
isOnline.value = false;
userInfo.value = null;
return res;
} catch (err) {
isOnline.value = false;
userInfo.value = null;
toast.error(getErrorMessage(err, "登出失败"));
return null;
} finally {
@@ -109,7 +153,9 @@ export const useUserStore = defineStore("user", () => {
loginLoading,
registerLoading,
logoutLoading,
getUserInfoLoading,
login,
getUserInfo,
register,
logout
};