ddshi 250c05e85e feat: 禅意设计风格重构与体验优化
- LandingPage: 全新水墨晕染算法背景,循环墨迹动画
- 登录/注册页: 禅意黑白极简风格
- HomePage: 三栏布局优化,标题颜色语义化
- 纪念日组件: 分类逻辑优化,颜色语义统一
- 提醒组件: 分组标题颜色优化,逾期提示更醒目
- 修复农历日期边界问题(29/30天月份)
- 添加 lunar-javascript 类型声明
- 清理未使用的导入和代码
2026-02-02 15:26:47 +08:00

143 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { User, Event, Note, EventType } from '../types';
// API Base URL - from environment variable
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000/api';
// Token storage
const TOKEN_KEY = 'qia_token';
const REFRESH_TOKEN_KEY = 'qia_refresh_token';
export const api = {
// Token management
getToken: () => localStorage.getItem(TOKEN_KEY),
getRefreshToken: () => localStorage.getItem(REFRESH_TOKEN_KEY),
setTokens: (token: string, refreshToken: string) => {
localStorage.setItem(TOKEN_KEY, token);
localStorage.setItem(REFRESH_TOKEN_KEY, refreshToken);
},
clearTokens: () => {
localStorage.removeItem(TOKEN_KEY);
localStorage.removeItem(REFRESH_TOKEN_KEY);
},
// Generic request helper
async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const token = api.getToken();
const headers: HeadersInit = {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` }),
...options.headers,
};
const response = await fetch(`${API_URL}${endpoint}`, {
...options,
headers,
credentials: 'include', // 确保跨域请求时发送凭证cookie
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || 'Request failed');
}
return data;
},
// Auth API
auth: {
register: async (email: string, password: string, nickname?: string) => {
return api.request<{ user: User; token: string; refreshToken: string }>(
'/auth/register',
{
method: 'POST',
body: JSON.stringify({ email, password, nickname }),
}
);
},
login: async (email: string, password: string) => {
return api.request<{ user: User; token: string; refreshToken: string }>(
'/auth/login',
{
method: 'POST',
body: JSON.stringify({ email, password }),
}
);
},
logout: async () => {
return api.request('/auth/logout', { method: 'POST' });
},
getCurrentUser: async () => {
return api.request<{ user: User }>('/auth/me');
},
refreshToken: async () => {
const refreshToken = api.getRefreshToken();
if (!refreshToken) throw new Error('No refresh token');
return api.request<{ token: string }>('/auth/refresh', {
method: 'POST',
body: JSON.stringify({ refreshToken }),
});
},
},
// Events API
events: {
list: async (type?: EventType) => {
const query = type ? `?type=${type}` : '';
return api.request<Event[]>(`/events${query}`);
},
getById: async (id: string) => {
return api.request<Event>(`/events/${id}`);
},
create: async (event: Partial<Event>) => {
return api.request<Event>('/events', {
method: 'POST',
body: JSON.stringify(event),
});
},
update: async (id: string, updates: Partial<Event>) => {
return api.request<Event>(`/events/${id}`, {
method: 'PUT',
body: JSON.stringify(updates),
});
},
delete: async (id: string) => {
return api.request(`/events/${id}`, { method: 'DELETE' });
},
},
// Notes API
notes: {
get: async () => {
return api.request<Note>('/notes');
},
update: async (content: string) => {
return api.request<Note>('/notes', {
method: 'PUT',
body: JSON.stringify({ content }),
});
},
},
// AI API
ai: {
parse: async (message: string) => {
return api.request<{ parsed: any; response: string }>('/ai/parse', {
method: 'POST',
body: JSON.stringify({ message }),
});
},
},
};