moodist/src/stores/auth.ts
zl aa2d0dbb05 feat: 实现完整的用户认证系统
- 添加 SQLite 数据库支持用户存储
- 实现用户注册和登录 API 端点
- 新增独立的认证按钮组件,位于右上角
- 集成 Zustand 状态管理支持持久化登录状态
- 添加密码哈希和验证功能
- 支持登录表单模态框和用户状态显示
- 启用服务端渲染支持 API 路由
2025-11-17 15:55:19 +08:00

177 lines
No EOL
4.2 KiB
TypeScript

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
export interface User {
id: number;
username: string;
created_at: string;
}
interface AuthState {
user: User | null;
isAuthenticated: boolean;
isLoading: boolean;
error: string | null;
}
interface AuthStore extends AuthState {
// Actions
login: (userData: { username: string; password: string }) => Promise<void>;
register: (userData: { username: string; password: string }) => Promise<void>;
logout: () => void;
clearError: () => void;
setLoading: (loading: boolean) => void;
checkAuth: () => Promise<void>;
}
/**
* API 调用辅助函数
*/
const apiCall = async (url: string, data: any) => {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.error || 'API 调用失败');
}
return result;
};
/**
* 用户认证状态管理 Store
*/
export const useAuthStore = create<AuthStore>()(
persist(
(set, get) => ({
// Initial state
user: null,
isAuthenticated: false,
isLoading: false,
error: null,
// Actions
login: async (userData) => {
set({ isLoading: true, error: null });
try {
const result = await apiCall('/api/auth/login', userData);
const user = result.user;
set({
user,
isAuthenticated: true,
isLoading: false,
error: null,
});
console.log('✅ 用户登录成功:', user.username);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : '登录失败';
set({
user: null,
isAuthenticated: false,
isLoading: false,
error: errorMessage,
});
console.error('❌ 登录失败:', error);
throw error;
}
},
register: async (userData) => {
set({ isLoading: true, error: null });
try {
const result = await apiCall('/api/auth/register', userData);
const user = result.user;
set({
user,
isAuthenticated: true,
isLoading: false,
error: null,
});
console.log('✅ 用户注册成功:', user.username);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : '注册失败';
set({
user: null,
isAuthenticated: false,
isLoading: false,
error: errorMessage,
});
console.error('❌ 注册失败:', error);
throw error;
}
},
logout: () => {
set({
user: null,
isAuthenticated: false,
isLoading: false,
error: null,
});
console.log('✅ 用户已登出');
},
clearError: () => {
set({ error: null });
},
setLoading: (loading: boolean) => {
set({ isLoading: loading });
},
checkAuth: async () => {
const { user, isAuthenticated } = get();
// 如果已经有用户信息且已认证,则直接返回
if (user && isAuthenticated) {
return;
}
// 这里可以添加token验证或会话验证逻辑
// 目前简单检查本地存储的用户信息
set({ isLoading: true });
try {
// 如果有用户信息但未认证,可以尝试验证
if (user && !isAuthenticated) {
set({
isAuthenticated: true,
isLoading: false,
error: null,
});
} else {
set({ isLoading: false });
}
} catch (error) {
console.error('❌ 认证检查失败:', error);
set({
user: null,
isAuthenticated: false,
isLoading: false,
error: '认证检查失败',
});
}
},
}),
{
name: 'auth-storage', // localStorage key
partialize: (state) => ({
user: state.user,
isAuthenticated: state.isAuthenticated,
}),
}
)
);