06488f0237
功能: - Go后端 (Gin + GORM + PostgreSQL) - UniApp用户端 (iOS/Android/小程序) - DaisyUI5后台管理 - JWT认证 + 微信登录 - 盲选加权算法 - 会员系统 + 优惠券 - 打分评价 + 偏好学习
123 lines
3.8 KiB
JavaScript
123 lines
3.8 KiB
JavaScript
// API 配置
|
|
// 开发环境: 指向本地后端
|
|
// 小程序生产: 指向你的 HTTPS 域名
|
|
|
|
// #ifdef MP-WEIXIN
|
|
// 微信小程序环境 → 生产域名 (替换为你自己的域名)
|
|
const BASE_URL = 'https://api.yourdomain.com/api/v1'
|
|
// #endif
|
|
|
|
// #ifdef H5
|
|
// H5 环境 → 本地或生产
|
|
const BASE_URL = 'http://localhost:8080/api/v1'
|
|
// #endif
|
|
|
|
// #ifndef MP-WEIXIN && !H5
|
|
// 其他平台 (APP等)
|
|
const BASE_URL = 'http://localhost:8080/api/v1'
|
|
// #endif
|
|
|
|
// 请求封装
|
|
function request(url, method = 'GET', data = null) {
|
|
const token = uni.getStorageSync('token')
|
|
return new Promise((resolve, reject) => {
|
|
uni.request({
|
|
url: BASE_URL + url,
|
|
method,
|
|
data,
|
|
header: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': token ? `Bearer ${token}` : ''
|
|
},
|
|
success: (res) => {
|
|
if (res.statusCode === 200 && res.data.code === 2) {
|
|
resolve(res.data.data)
|
|
} else if (res.statusCode === 401) {
|
|
// Token 过期 → 尝试刷新
|
|
refreshAndRetry(url, method, data).then(resolve).catch(reject)
|
|
} else {
|
|
uni.showToast({
|
|
title: res.data.message || '请求失败',
|
|
icon: 'none',
|
|
duration: 1500
|
|
})
|
|
reject(new Error(res.data.message || 'request failed'))
|
|
}
|
|
},
|
|
fail: (err) => {
|
|
uni.showToast({ title: '网络错误', icon: 'none' })
|
|
reject(err)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// Token 刷新后重试
|
|
async function refreshAndRetry(url, method, data) {
|
|
const refreshToken = uni.getStorageSync('refresh_token')
|
|
if (!refreshToken) {
|
|
// 没有 refresh token → 跳转登录
|
|
uni.removeStorageSync('token')
|
|
uni.removeStorageSync('userInfo')
|
|
uni.showToast({ title: '请重新登录', icon: 'none' })
|
|
uni.reLaunch({ url: '/pages/login/login' })
|
|
throw new Error('unauthorized')
|
|
}
|
|
|
|
try {
|
|
const authApi = (await import('@/api/index.js')).authApi
|
|
const res = await authApi.refreshToken({ refresh_token: refreshToken })
|
|
|
|
uni.setStorageSync('token', res.token)
|
|
|
|
// 重试原请求
|
|
return request(url, method, data)
|
|
} catch (e) {
|
|
// 刷新也失败 → 跳转登录
|
|
uni.removeStorageSync('token')
|
|
uni.removeStorageSync('refresh_token')
|
|
uni.removeStorageSync('userInfo')
|
|
uni.reLaunch({ url: '/pages/login/login' })
|
|
throw e
|
|
}
|
|
}
|
|
|
|
// ============== Auth ==============
|
|
export const authApi = {
|
|
register: (data) => request('/auth/register', 'POST', data),
|
|
login: (data) => request('/auth/login', 'POST', data),
|
|
wechatLogin: (data) => request('/auth/wechat/login', 'POST', data),
|
|
refreshToken: (data) => request('/auth/refresh', 'POST', data),
|
|
getProfile: () => request('/user/profile', 'GET'),
|
|
updateProfile: (data) => request('/user/profile', 'PUT', data),
|
|
}
|
|
|
|
// ============== Blind Selection ==============
|
|
export const blindApi = {
|
|
getCategories: () => request('/blind/categories', 'GET'),
|
|
getPool: (params) => request('/blind/pool?' + new URLSearchParams(params).toString(), 'GET'),
|
|
choose: (data) => request('/blind/choose', 'POST', data),
|
|
getResult: (id) => request(`/blind/result/${id}`, 'GET'),
|
|
getHistory: () => request('/blind/history', 'GET'),
|
|
}
|
|
|
|
// ============== Review ==============
|
|
export const reviewApi = {
|
|
submit: (data) => request('/review/submit', 'POST', data),
|
|
getStats: () => request('/review/stats', 'GET'),
|
|
}
|
|
|
|
// ============== Coupon ==============
|
|
export const couponApi = {
|
|
getMyCoupons: () => request('/coupon/list', 'GET'),
|
|
getAvailable: () => request('/coupon/available', 'GET'),
|
|
claim: (data) => request('/coupon/claim', 'POST', data),
|
|
}
|
|
|
|
// ============== Member ==============
|
|
export const memberApi = {
|
|
getStatus: () => request('/member/status', 'GET'),
|
|
getPlans: () => request('/member/plans', 'GET'),
|
|
subscribe: (data) => request('/member/subscribe', 'POST', data),
|
|
}
|