const { request, uploadFile, setToken, setRefreshToken } = require('./request.js'); // 登录成功后统一落盘 access + refresh 两个令牌 function saveTokens(data) { setToken(data.token); setRefreshToken(data.refresh_token); return data; } // wx.login 取 code function wxLogin() { return new Promise((resolve, reject) => { wx.login({ success: (r) => (r.code ? resolve(r.code) : reject(new Error('wx.login 未返回 code'))), fail: reject, }); }); } // 登录:优先微信 code2session,失败回退开发态 Mock 登录(后端 dev_login=true) async function login() { try { const code = await wxLogin(); // noAuthRetry:登录接口失败时也会返回 40100,不能再触发「续期→重新登录」,否则会自己套自己 const data = await request({ url: '/api/auth/wechat', method: 'POST', data: { code }, noAuthRetry: true }); return saveTokens(data); } catch (e) { console.warn('[api] 微信登录失败,回退 Mock 登录:', e && e.message); const data = await request({ url: '/api/auth/login', method: 'POST', data: { nickname: '开发用户' }, noAuthRetry: true, }); return saveTokens(data); } } const api = { login, uploadFile, // 用户 getProfile: () => request({ url: '/api/user/profile' }), bindPhone: (code) => request({ url: '/api/user/phone', method: 'POST', data: { code } }), updateProfile: (body) => request({ url: '/api/user/profile', method: 'PUT', data: body }), // 用户 userSummary: () => request({ url: '/api/user/summary' }), // 记录类型(后台可配)。分组好的,前端直接渲染 recordTypes: () => request({ url: '/api/record-types' }), updateDecoration: (body) => request({ url: '/api/user/decoration', method: 'PUT', data: body }), // 宠物 getPets: () => request({ url: '/api/pets' }), homeSummary: (id) => request({ url: `/api/pets/${id}/home-summary` }), getPet: (id) => request({ url: `/api/pets/${id}` }), // 养护方案:可选列表 + 套用到某个月 careTemplates: (species, stage) => request({ url: '/api/care-templates?species=' + species + '&stage=' + encodeURIComponent(stage) }), applyTemplate: (petId, templateID, monthOffset) => request({ url: `/api/pets/${petId}/apply-template`, method: 'POST', data: { template_id: templateID, month_offset: monthOffset || 0 } }), // 生命阶段的划分标准。判定和展示用同一份数据 —— 不另写一份说明文案, // 否则改了阈值忘了改文案,用户看到的依据和实际行为对不上 lifeStages: (species, size) => request({ url: `/api/life-stages?species=${species}&size=${size || ''}` }), petIDCard: (id) => request({ url: `/api/pets/${id}/id-card` }), petStageDrift: (petId) => request({ url: `/api/pets/${petId}/stage-drift` }), // 品种(后台可配),按首字母分组 breeds: (species) => request({ url: '/api/breeds?species=' + species }), createPet: (body) => request({ url: '/api/pets', method: 'POST', data: body }), updatePet: (id, body) => request({ url: `/api/pets/${id}`, method: 'PUT', data: body }), deletePet: (id) => request({ url: `/api/pets/${id}`, method: 'DELETE' }), onboarding: (body) => request({ url: '/api/onboarding', method: 'POST', data: body }), // 记录 getRecords: (id, { type, page, pageSize } = {}) => { const qs = []; if (type) qs.push(`type=${type}`); if (page) qs.push(`page=${page}`); if (pageSize) qs.push(`page_size=${pageSize}`); return request({ url: `/api/pets/${id}/records${qs.length ? '?' + qs.join('&') : ''}` }); }, createRecord: (id, body) => request({ url: `/api/pets/${id}/records`, method: 'POST', data: body }), deleteRecord: (recordId) => request({ url: `/api/records/${recordId}`, method: 'DELETE' }), petInsights: (id) => request({ url: `/api/pets/${id}/insights` }), weightTrend: (id) => request({ url: `/api/pets/${id}/records/weight-trend` }), // 任务 getTasks: (id, date) => request({ url: `/api/pets/${id}/tasks${date ? `?date=${date}` : ''}` }), createTask: (id, body) => request({ url: `/api/pets/${id}/tasks`, method: 'POST', data: body }), updateTask: (taskId, body) => request({ url: `/api/tasks/${taskId}`, method: 'PUT', data: body }), deleteTask: (taskId) => request({ url: `/api/tasks/${taskId}`, method: 'DELETE' }), toggleTask: (taskId) => request({ url: `/api/tasks/${taskId}/toggle`, method: 'POST' }), completeAllTasks: (id) => request({ url: `/api/pets/${id}/tasks/complete-all`, method: 'POST' }), // 计划 getPlan: (id) => request({ url: `/api/pets/${id}/plan` }), planCalendar: (id, month) => request({ url: `/api/pets/${id}/plan/calendar${month ? `?month=${month}` : ''}` }), dayPlan: (id, date) => request({ url: `/api/pets/${id}/day-plan?date=${date}` }), // AI 相关:用户端入口已全部下掉,后端 10 个路由和配额配置都还在。 // 想开回来把这几行解注释、再把入口接上就行,不用重写。 // createAIPlan: (id, input) => request({ url: `/api/pets/${id}/ai-plan`, method: 'POST', data: { input } }), // applyAIPlan: (planId) => request({ url: `/api/ai-plan/${planId}/apply`, method: 'POST' }), // 用户自己管理计划节点 planMonthStatus: (petId) => request({ url: `/api/pets/${petId}/plan/month-status` }), addPlanTask: (petId, body) => request({ url: `/api/pets/${petId}/plan-tasks`, method: 'POST', data: body }), updatePlanTask: (taskId, body) => request({ url: `/api/plan-tasks/${taskId}`, method: 'PUT', data: body }), deletePlanTask: (taskId) => request({ url: `/api/plan-tasks/${taskId}`, method: 'DELETE' }), togglePlanTask: (taskId) => request({ url: `/api/plan-tasks/${taskId}/toggle`, method: 'POST' }), // 提醒 getReminders: (id) => request({ url: `/api/pets/${id}/reminders` }), createReminder: (id, body) => request({ url: `/api/pets/${id}/reminders`, method: 'POST', data: body }), updateReminder: (remId, body) => request({ url: `/api/reminders/${remId}`, method: 'PUT', data: body }), deleteReminder: (remId) => request({ url: `/api/reminders/${remId}`, method: 'DELETE' }), // 报告 weeklyReport: (id) => request({ url: `/api/pets/${id}/report/weekly` }), getBill: (id, period) => request({ url: `/api/pets/${id}/bill?period=${period || 'month'}` }), healthSummary: (id) => request({ url: `/api/pets/${id}/health-summary` }), getPoster: (id) => request({ url: `/api/pets/${id}/poster` }), // 个人主页卡片(「我的」页头部用;社区/关注已下线) userCard: (userId) => request({ url: `/api/users/${userId}/profile` }), // 文章 listArticles: () => request({ url: '/api/articles' }), submitFeedback: (body) => request({ url: '/api/feedback', method: 'POST', data: body }), getArticle: (id) => request({ url: `/api/articles/${id}` }), // Pro getPro: () => request({ url: '/api/pro' }), activatePro: () => request({ url: '/api/pro/activate', method: 'POST' }), // AI // aiMessages: (session, limit) => // request({ url: `/api/ai/messages?session=${session || ''}&limit=${limit || 30}` }), // aiChat: (body) => request({ url: '/api/ai/chat', method: 'POST', data: body }), // assessSymptom: (id, body) => // request({ url: `/api/pets/${id}/ai/assess-symptom`, method: 'POST', data: body }), }; module.exports = api;