import { Transaction, Message, BillReminder } from '../types'; // API基础配置 const getApiUrl = (): string => { return process.env.API_URL || 'http://localhost:8000'; }; const getAuthToken = (): string | null => { return localStorage.getItem('auth_token'); }; // 统一响应格式 interface ApiResponse { code: number; msg?: string; message?: string; result?: T; } // 分页响应格式 interface PaginatedResponse { items: T[]; skip: number; total: number; } // 统计数据响应格式 interface TransactionStats { month: string; total_income: number; total_expense: number; balance: number; expense_by_category: Record; income_by_category: Record; daily_expense: Array<{ date: string; amount: number }>; } // 预算响应格式 interface Budget { id: string; user_id?: string; member_id?: string; budgets: Record; month: string; created_at?: string; updated_at?: string; } // 预算执行情况 interface BudgetExecution { month: string; budgets: Record; total_budget: number; total_spent: number; total_remaining: number; is_over_budget: boolean; } // AI设置 interface AISettings { id?: string; user_id?: string; member_id?: string; name: string; persona: string; avatar?: string; created_at?: string; updated_at?: string; } // 通用请求函数 async function request( endpoint: string, options: RequestInit = {} ): Promise { const token = getAuthToken(); const apiUrl = getApiUrl(); const url = `${apiUrl}${endpoint}`; console.log(`请求地址: ${url}`); const defaultHeaders: HeadersInit = { 'Content-Type': 'application/json', }; if (token) { defaultHeaders['Authorization'] = `Bearer ${token}`; } const config: RequestInit = { ...options, headers: { ...defaultHeaders, ...options.headers, }, }; try { const response = await fetch(url, config); const data: ApiResponse = await response.json(); if (!response.ok || (data.code && data.code !== 200)) { const errorMsg = data.msg || data.message || `HTTP error! status: ${response.status}`; throw new Error(errorMsg); } return data.result as T; } catch (error) { console.error('API请求错误:', error); throw error; } } // ==================== 用户认证接口 ==================== /** * 登录或注册 */ export async function loginOrRegister(openid: string, mobile: string): Promise<{ token: string; user: any; }> { const apiUrl = getApiUrl(); console.log(`请求地址: ${apiUrl}/wx/loginOrRegister`); const response = await fetch(`${apiUrl}/wx/loginOrRegister`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ openid, mobile }), }); const data = await response.json(); if (data.code === 200 && data.result?.token) { // 保存token到localStorage localStorage.setItem('auth_token', data.result.token); } return data.result; } /** * 获取用户信息 */ export async function getUserProfile(): Promise { return request('/wx/profile', { method: 'GET', }); } /** * 退出登录 */ export function logout(): void { localStorage.removeItem('auth_token'); } // ==================== 交易记录接口 ==================== /** * 创建交易记录 */ export async function createTransaction(data: { item: string; amount: number; type: 'expense' | 'income'; category: string; date: string; timestamp: number; }): Promise { return request('/bill/transactions/', { method: 'POST', body: JSON.stringify(data), }); } /** * 查询交易记录列表(分页) */ export async function getTransactions(params?: { skip?: number; limit?: number; type?: 'expense' | 'income'; category?: string; start_date?: string; end_date?: string; month?: string; }): Promise> { const queryString = new URLSearchParams( Object.entries(params || {}).reduce((acc, [key, value]) => { if (value !== undefined) { acc[key] = String(value); } return acc; }, {} as Record) ).toString(); return request>( `/bill/transactions/${queryString ? `?${queryString}` : ''}` ); } /** * 获取单个交易记录 */ export async function getTransaction(id: string): Promise { return request(`/bill/transactions/${id}`); } /** * 更新交易记录 */ export async function updateTransaction( id: string, data: Partial<{ item: string; amount: number; type: 'expense' | 'income'; category: string; date: string; timestamp: number; }> ): Promise { return request(`/bill/transactions/${id}`, { method: 'PUT', body: JSON.stringify(data), }); } /** * 删除交易记录 */ export async function deleteTransaction(id: string): Promise { return request(`/bill/transactions/${id}`, { method: 'DELETE', }); } /** * 批量删除交易记录 */ export async function batchDeleteTransactions( transactionIds: string[] ): Promise<{ deleted_count: number }> { return request<{ deleted_count: number }>('/bill/transactions/batch', { method: 'DELETE', body: JSON.stringify({ transaction_ids: transactionIds }), }); } /** * 获取交易统计数据 */ export async function getTransactionStats( month: string ): Promise { return request(`/bill/transactions/stats/summary?month=${month}`); } // ==================== 聊天消息接口 ==================== /** * 创建聊天消息 */ export async function createMessage(data: { role: 'user' | 'assistant'; content: string; timestamp: number; transaction_id?: string; }): Promise { return request('/bill/messages/', { method: 'POST', body: JSON.stringify(data), }); } /** * 查询聊天消息列表 */ export async function getMessages(params?: { skip?: number; limit?: number; role?: 'user' | 'assistant'; start_timestamp?: number; end_timestamp?: number; }): Promise> { const queryString = new URLSearchParams( Object.entries(params || {}).reduce((acc, [key, value]) => { if (value !== undefined) { acc[key] = String(value); } return acc; }, {} as Record) ).toString(); return request>( `/bill/messages/${queryString ? `?${queryString}` : ''}` ); } /** * 获取单个消息 */ export async function getMessage(id: string): Promise { return request(`/bill/messages/${id}`); } /** * 删除消息 */ export async function deleteMessage(id: string): Promise { return request(`/bill/messages/${id}`, { method: 'DELETE', }); } /** * 清空聊天历史 */ export async function clearMessages(): Promise<{ deleted_count: number }> { return request<{ deleted_count: number }>('/bill/messages/clear', { method: 'DELETE', }); } // ==================== 预算管理接口 ==================== /** * 获取月度预算 */ export async function getMonthlyBudget(month: string): Promise { return request(`/bill/budgets/${month}`); } /** * 设置/更新月度预算 */ export async function updateMonthlyBudget( month: string, budgets: Record ): Promise { return request(`/bill/budgets/${month}`, { method: 'PUT', body: JSON.stringify({ budgets }), }); } /** * 获取预算执行情况 */ export async function getBudgetExecution( month: string ): Promise { return request(`/bill/budgets/${month}/execution`); } // ==================== 账单提醒接口 ==================== /** * 创建账单提醒 */ export async function createReminder(data: { title: string; amount?: number; frequency: 'monthly' | 'once'; target_date: string; }): Promise { return request('/bill/reminders/', { method: 'POST', body: JSON.stringify(data), }); } /** * 查询账单提醒列表 */ export async function getReminders(params?: { skip?: number; limit?: number; frequency?: 'monthly' | 'once'; is_completed?: boolean; month?: string; }): Promise> { const queryString = new URLSearchParams( Object.entries(params || {}).reduce((acc, [key, value]) => { if (value !== undefined) { acc[key] = String(value); } return acc; }, {} as Record) ).toString(); return request>( `/bill/reminders/${queryString ? `?${queryString}` : ''}` ); } /** * 获取单个提醒 */ export async function getReminder(id: string): Promise { return request(`/bill/reminders/${id}`); } /** * 更新账单提醒 */ export async function updateReminder( id: string, data: Partial<{ title: string; amount?: number; frequency: 'monthly' | 'once'; target_date: string; }> ): Promise { return request(`/bill/reminders/${id}`, { method: 'PUT', body: JSON.stringify(data), }); } /** * 切换提醒完成状态 */ export async function toggleReminder( id: string ): Promise<{ id: string; is_completed: boolean }> { return request<{ id: string; is_completed: boolean }>( `/bill/reminders/${id}/toggle`, { method: 'PATCH', } ); } /** * 删除账单提醒 */ export async function deleteReminder(id: string): Promise { return request(`/bill/reminders/${id}`, { method: 'DELETE', }); } /** * 获取即将到期的提醒 */ export async function getUpcomingReminders( days: number = 7 ): Promise> { return request>( `/bill/reminders/upcoming?days=${days}` ); } // ==================== AI设置接口 ==================== /** * 获取AI设置 */ export async function getAISettings(): Promise { return request('/h5/ai-settings'); } /** * 更新AI设置 */ export async function updateAISettings(data: { name?: string; persona?: string; avatar?: string; }): Promise { return request('/h5/ai-settings', { method: 'PUT', body: JSON.stringify(data), }); } /** * 重置AI设置为默认 */ export async function resetAISettings(): Promise { return request('/h5/ai-settings/reset', { method: 'POST', }); } // ==================== 用户偏好接口 ==================== interface UserPreferences { id?: string; user_id?: string; custom_preset_name?: string; custom_preset_description?: string; theme_index?: number; created_at?: string; updated_at?: string; } /** * 获取用户偏好 */ export async function getUserPreferences(): Promise { return request('/h5/preferences'); } /** * 更新用户偏好 */ export async function updateUserPreferences( data: Partial ): Promise { return request('/h5/preferences', { method: 'PUT', body: JSON.stringify(data), }); } // ==================== 数据同步接口 ==================== interface SyncData { transactions?: Transaction[]; messages?: Message[]; budgets?: Record; reminders?: BillReminder[]; ai_settings?: AISettings; preferences?: UserPreferences; } /** * 全量数据同步(上传) */ export async function uploadSyncData(data: SyncData): Promise<{ synced_at: string; summary: { transactions_count: number; messages_count: number; reminders_count: number; }; }> { return request('/bill/sync/upload', { method: 'POST', body: JSON.stringify(data), }); } /** * 全量数据同步(下载) */ export async function downloadSyncData(): Promise { return request('/bill/sync/download'); } /** * 增量数据同步 */ export async function incrementalSync(data: { last_sync_at: string; changes: SyncData; }): Promise<{ synced_at: string; server_changes: SyncData; }> { return request('/bill/sync/incremental', { method: 'POST', body: JSON.stringify(data), }); } // ==================== AI处理接口 ==================== interface AIProcessResult { transaction: { item: string; amount: number; type: 'expense' | 'income'; category: string; } | null; reply: string; created_transaction_id?: string; created_message_ids?: string[]; } /** * AI处理用户消息 */ export async function processAIMessage(data: { message: string; image_base64?: string; mime_type?: string; }): Promise { return request('/ai/process', { method: 'POST', body: JSON.stringify(data), }); } /** * AI识别账单图片 */ export async function recognizeReceipt( imageFile: File ): Promise { const formData = new FormData(); formData.append('image', imageFile); // 注意: FormData需要特殊处理,不设置Content-Type让浏览器自动设置 return request('/ai/recognize-receipt', { method: 'POST', body: formData, headers: {}, // 清空默认headers,让fetch自动处理multipart/form-data }); } // ==================== 导出所有API ==================== export default { // 用户认证 loginOrRegister, getUserProfile, logout, // 交易记录 createTransaction, getTransactions, getTransaction, updateTransaction, deleteTransaction, batchDeleteTransactions, getTransactionStats, // 聊天消息 createMessage, getMessages, getMessage, deleteMessage, clearMessages, // 预算管理 getMonthlyBudget, updateMonthlyBudget, getBudgetExecution, // 账单提醒 createReminder, getReminders, getReminder, updateReminder, toggleReminder, deleteReminder, getUpcomingReminders, // AI设置 getAISettings, updateAISettings, resetAISettings, // 用户偏好 getUserPreferences, updateUserPreferences, // 数据同步 uploadSyncData, downloadSyncData, incrementalSync, // AI处理 processAIMessage, recognizeReceipt, };