import Taro from '@tarojs/taro' const BASE_URL = 'http://localhost:8080' type ApiResult = { code: number message: string data: T } type RequestOptions = Omit export async function request(url: string, options: RequestOptions = {}): Promise { const token = Taro.getStorageSync('token') const headers = { 'content-type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), ...(options.header || {}) } const res = await Taro.request>({ url: `${BASE_URL}${url}`, ...options, header: headers }) if (res.data.code !== 0) { throw new Error(res.data.message || '请求失败') } return res.data.data } export const api = { wxLogin: (code: string) => request<{ sessionKey: string; phoneBound: boolean }>('/api/auth/wx-login', { method: 'POST', data: { code } }), sendSms: (phone: string) => request<{ mockCode?: string }>('/api/auth/sms', { method: 'POST', data: { phone } }), bindPhone: (sessionKey: string, phone: string, captcha: string) => request<{ token: string; user: UserProfile }>('/api/auth/bind-phone', { method: 'POST', data: { sessionKey, phone, captcha } }), profile: () => request('/api/user/profile'), updateProfile: (data: Partial) => request('/api/user/profile', { method: 'PUT', data }), exchangeStatus: () => request<{ points: number; available: boolean; message: string }>('/api/points/exchange-status'), agreement: (type: string) => request<{ title: string; body: string }>(`/api/content/agreement/${type}`), follow: () => request>('/api/content/follow'), homeOverview: () => request('/api/home/overview'), tiangong: () => request('/api/tiangong/items'), tiangongDetail: (id: string) => request(`/api/tiangong/items/${id}`), dailyHome: () => request('/api/daily/home'), pinDailyCard: (cardId: string) => request<{ pinnedCardId: string | null }>(`/api/daily/cards/${cardId}/pin`, { method: 'POST' }) } export type ElementScore = { name: string color: string value: number } export type UserProfile = { id: number nickname: string phone?: string gender: string birthday: string birthHour: string province: string city: string district: string points: number remainingEdits: number elementReport: { scores: ElementScore[] favorable: string unfavorable: string dayMaster: string } } export type CalendarDay = { day: number weekName: string label: string } export type LuckyPanel = { title: string value: string accent: string } export type FortuneCard = { id: string title: string category: string categoryIcon: string verdict: string avoid: string summary: string detail: string color: string gradient: string mascot: string } export type LifeTip = { id: string title: string icon: string content: string color: string mark: string } export type DailyHome = { date: string lunarDate: string weekName: string fortuneLevel: string greeting: string dailySummary: string calendarDays: CalendarDay[] luckyPanels: LuckyPanel[] cards: FortuneCard[] lifeTips: LifeTip[] pinnedCardId?: string | null } export type DayFortune = { label: '昨日' | '今日' | '明日' date: string weekName: string lunarDate: string status: string } export type LuckyColor = { name: string value: string } export type DimensionItem = { id: string title: string icon: string headline: string detail: string suitable: boolean } export type HomeOverview = { days: DayFortune[] activeDay: '昨日' | '今日' | '明日' summary: string overallIndex: number luckyColors: LuckyColor[] luckyNumbers: string[] luckyDirection: string luckyHours: Array<{ branch: string; time: string }> dimensions: DimensionItem[] } export type TiangongItem = { id: string name: string imageUrl: string unlocked: boolean } export type TiangongDetail = { id: string name: string title: string imageUrl: string introduction: string blessing: string }