feat: 班级小助手 阶段1-3(monorepo + 后端 REST/Socket.IO + Web 管理端)

This commit is contained in:
LoveChengke committed 2026-09-11 21:57:38 +08:00
commit 84ab49de10
102 files changed
+14751

No files matched your search

+89
View File
@@ -0,0 +1,89 @@
import { computed, ref } from 'vue';
import { defineStore } from 'pinia';
import { STORAGE_KEYS, type LoginRequest, type LoginResponse, type StudentDto } from '@classhelper/shared';
import { authApi } from '@/api';
function readStoredUser(): StudentDto | null {
const raw = localStorage.getItem(STORAGE_KEYS.user);
if (!raw) return null;
try {
return JSON.parse(raw) as StudentDto;
} catch {
return null;
}
}
export const useAuthStore = defineStore('auth', () => {
const token = ref<string | null>(localStorage.getItem(STORAGE_KEYS.token));
const user = ref<StudentDto | null>(readStoredUser());
const loading = ref(false);
const isAuthenticated = computed(() => Boolean(token.value));
const role = computed(() => user.value?.role ?? null);
const isStaff = computed(() => role.value === 'ADMIN' || role.value === 'TEACHER');
const displayName = computed(() => user.value?.name ?? '未登录');
const roleLabel = computed(() => {
if (role.value === 'ADMIN') return '管理员';
if (role.value === 'TEACHER') return '教师';
return '学生';
});
function persist(): void {
if (token.value) localStorage.setItem(STORAGE_KEYS.token, token.value);
else localStorage.removeItem(STORAGE_KEYS.token);
if (user.value) localStorage.setItem(STORAGE_KEYS.user, JSON.stringify(user.value));
else localStorage.removeItem(STORAGE_KEYS.user);
}
function setSession(payload: LoginResponse): void {
token.value = payload.token;
user.value = { ...payload.user } as StudentDto;
persist();
}
async function login(payload: LoginRequest): Promise<void> {
loading.value = true;
try {
setSession(await authApi.login(payload));
} finally {
loading.value = false;
}
}
async function fetchProfile(): Promise<void> {
if (!token.value) return;
user.value = await authApi.me();
persist();
}
async function logout(): Promise<void> {
try {
if (token.value) await authApi.logout();
} catch {
// 退出登录失败不阻塞本地清理
} finally {
clear();
}
}
function clear(): void {
token.value = null;
user.value = null;
persist();
}
return {
token,
user,
loading,
isAuthenticated,
isStaff,
role,
displayName,
roleLabel,
login,
logout,
fetchProfile,
clear,
};
});