import config from '../config.js' const BASE_URL = config.API_BASE_URL var _dedupMap = {} var DEDUP_WINDOW_MS = 3000 function _makeDedupKey(method, url, body) { var bodyStr = '' try { bodyStr = JSON.stringify(body || {}) } catch (e) { bodyStr = '' } return method + '|' + url + '|' + bodyStr } function _tryDedup(method, fullUrl, body) { var key = _makeDedupKey(method, fullUrl, body) var cached = _dedupMap[key] if (cached && Date.now() - cached.ts < DEDUP_WINDOW_MS) { return cached.promise } return null } function _registerDedup(method, fullUrl, body, promise) { var key = _makeDedupKey(method, fullUrl, body) _dedupMap[key] = { promise: promise, ts: Date.now() } var _cleanup = function() { setTimeout(function() { if (_dedupMap[key] && _dedupMap[key].promise === promise) { delete _dedupMap[key] } }, DEDUP_WINDOW_MS) } promise.then(_cleanup, _cleanup) } function _clearDedup() { _dedupMap = {} } export { _clearDedup as clearApiDedup } function request(url, method = 'POST', data = {}, options = {}) { var fullUrl = BASE_URL + url const token = uni.getStorageSync('token') var key = _makeDedupKey(method, fullUrl, data) if (!options._skipDedup) { var cached = _tryDedup(method, fullUrl, data) if (cached) { return cached } } var _promise = new Promise((resolve, reject) => { uni.request({ url: fullUrl, method: method, data: data, header: { 'Content-Type': 'application/json', 'Authorization': token ? 'Bearer ' + token : '' }, success: function(res) { if (res.statusCode === 401) { uni.login({ provider: 'weixin', success: function(loginRes) { if (loginRes && loginRes.code) { silentLogin(loginRes.code).then(function(sr) { if (sr && sr.data && sr.data.token) { uni.setStorageSync('token', sr.data.token) uni.setStorageSync('openid', sr.data.openid) resolve(sr.data) } else { uni.showToast({ title: '登录已过期,请重新进入', icon: 'none' }) reject(res.data) } }) } } }) return } if (res.data && res.data.code === 200) { resolve(res.data) } else { var msg = res.data && res.data.message ? res.data.message : '请求失败' uni.showToast({ title: msg, icon: 'none' }) reject(res.data) } }, fail: function(err) { console.error('[API] 网络错误 ' + method + ' ' + fullUrl, err) uni.showToast({ title: '网络请求失败', icon: 'none' }) reject(err) } }) }) if (!options._skipDedup) { _registerDedup(method, fullUrl, data, _promise) } return _promise } // ===== 认证 ===== export const silentLogin = (code, options) => { return request('/api/auth/silent-login', 'POST', { code }, options || {}) } export const wechatLogin = (code, userInfo) => { return request('/api/auth/wechat-login', 'POST', { code, nickname: userInfo.nickname, avatar: userInfo.avatar }) } export const getUserInfo = () => { return request('/api/user/info', 'POST', {}) } // ===== 减脂专题 API ===== // 体重 export const getWeightList = (memberId, startDate, endDate) => { var data = {} if (memberId) data.memberId = memberId if (startDate) data.startDate = startDate if (endDate) data.endDate = endDate return request('/api/fatloss/weight/list', 'POST', data) } export const createWeightRecord = (data) => { return request('/api/fatloss/weight/create', 'POST', data) } export const updateWeightRecord = (data) => { return request('/api/fatloss/weight/update', 'POST', data) } export const deleteWeightRecord = (id) => { return request('/api/fatloss/weight/delete', 'POST', { id: id }) } // 饮食 export const getDietList = (memberId, startDate, endDate) => { var data = {} if (memberId) data.memberId = memberId if (startDate) data.startDate = startDate if (endDate) data.endDate = endDate return request('/api/fatloss/diet/list', 'POST', data) } export const createDietRecord = (data) => { return request('/api/fatloss/diet/create', 'POST', data) } export const deleteDietRecord = (id) => { return request('/api/fatloss/diet/delete', 'POST', { id: id }) } export const getCaloriesSummary = (date) => { var data = {} if (date) data.date = date return request('/api/fatloss/diet/calories-summary', 'POST', data) } // 运动 export const getExerciseList = (memberId, startDate, endDate) => { var data = {} if (memberId) data.memberId = memberId if (startDate) data.startDate = startDate if (endDate) data.endDate = endDate return request('/api/fatloss/exercise/list', 'POST', data) } export const createExerciseRecord = (data) => { return request('/api/fatloss/exercise/create', 'POST', data) } export const deleteExerciseRecord = (id) => { return request('/api/fatloss/exercise/delete', 'POST', { id: id }) } // 目标 export const getActiveGoal = () => { return request('/api/fatloss/goal/active', 'POST', {}) } export const createGoal = (data) => { return request('/api/fatloss/goal/create', 'POST', data) } export const updateGoal = (data) => { return request('/api/fatloss/goal/update', 'POST', data) } export const completeGoal = (id) => { return request('/api/fatloss/goal/complete', 'POST', { id: id }) } export const abandonGoal = (id) => { return request('/api/fatloss/goal/abandon', 'POST', { id: id }) } // ===== AI 教练(走主系统 AiGateway) ===== export const aiCoachSend = (data) => { return request('/api/ai/health-coach/send', 'POST', data) }