feat :init
This commit is contained in:
489
miniprogram/utils/api.js
Normal file
489
miniprogram/utils/api.js
Normal file
@@ -0,0 +1,489 @@
|
||||
/**
|
||||
* API服务工具
|
||||
* 统一处理网络请求、错误处理、token管理等
|
||||
*/
|
||||
|
||||
const app = getApp();
|
||||
|
||||
// API配置
|
||||
const API_CONFIG = {
|
||||
baseUrl: 'https://api.xiaozhi.com', // 生产环境API地址
|
||||
timeout: 10000,
|
||||
retryCount: 3,
|
||||
retryDelay: 1000
|
||||
};
|
||||
|
||||
// 请求状态码
|
||||
const STATUS_CODE = {
|
||||
SUCCESS: 200,
|
||||
UNAUTHORIZED: 401,
|
||||
FORBIDDEN: 403,
|
||||
NOT_FOUND: 404,
|
||||
SERVER_ERROR: 500,
|
||||
NETWORK_ERROR: -1
|
||||
};
|
||||
|
||||
// 错误消息映射
|
||||
const ERROR_MESSAGES = {
|
||||
[STATUS_CODE.UNAUTHORIZED]: '登录已过期,请重新登录',
|
||||
[STATUS_CODE.FORBIDDEN]: '没有访问权限',
|
||||
[STATUS_CODE.NOT_FOUND]: '请求的资源不存在',
|
||||
[STATUS_CODE.SERVER_ERROR]: '服务器内部错误',
|
||||
[STATUS_CODE.NETWORK_ERROR]: '网络连接失败,请检查网络设置'
|
||||
};
|
||||
|
||||
/**
|
||||
* 基础请求方法
|
||||
* @param {Object} options 请求配置
|
||||
* @returns {Promise} 请求结果
|
||||
*/
|
||||
function request(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const {
|
||||
url,
|
||||
method = 'GET',
|
||||
data = {},
|
||||
header = {},
|
||||
needAuth = true,
|
||||
showLoading = true,
|
||||
loadingText = '加载中...',
|
||||
retryCount = 0
|
||||
} = options;
|
||||
|
||||
// 显示加载提示
|
||||
if (showLoading) {
|
||||
wx.showLoading({
|
||||
title: loadingText,
|
||||
mask: true
|
||||
});
|
||||
}
|
||||
|
||||
// 构建请求头
|
||||
const requestHeader = {
|
||||
'Content-Type': 'application/json',
|
||||
...header
|
||||
};
|
||||
|
||||
// 添加认证token
|
||||
if (needAuth && app.globalData.token) {
|
||||
requestHeader['Authorization'] = `Bearer ${app.globalData.token}`;
|
||||
}
|
||||
|
||||
// 发起请求
|
||||
wx.request({
|
||||
url: `${API_CONFIG.baseUrl}${url}`,
|
||||
method,
|
||||
data,
|
||||
header: requestHeader,
|
||||
timeout: API_CONFIG.timeout,
|
||||
success: (res) => {
|
||||
if (showLoading) {
|
||||
wx.hideLoading();
|
||||
}
|
||||
|
||||
const { statusCode, data: responseData } = res;
|
||||
|
||||
// 请求成功
|
||||
if (statusCode === STATUS_CODE.SUCCESS) {
|
||||
if (responseData.code === 0) {
|
||||
resolve(responseData);
|
||||
} else {
|
||||
// 业务错误
|
||||
handleBusinessError(responseData, reject);
|
||||
}
|
||||
} else {
|
||||
// HTTP错误
|
||||
handleHttpError(statusCode, reject, options, retryCount);
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
if (showLoading) {
|
||||
wx.hideLoading();
|
||||
}
|
||||
|
||||
console.error('Request failed:', error);
|
||||
|
||||
// 网络错误重试
|
||||
if (retryCount < API_CONFIG.retryCount) {
|
||||
setTimeout(() => {
|
||||
request({
|
||||
...options,
|
||||
retryCount: retryCount + 1
|
||||
}).then(resolve).catch(reject);
|
||||
}, API_CONFIG.retryDelay);
|
||||
} else {
|
||||
handleNetworkError(error, reject);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理业务错误
|
||||
* @param {Object} responseData 响应数据
|
||||
* @param {Function} reject 拒绝函数
|
||||
*/
|
||||
function handleBusinessError(responseData, reject) {
|
||||
const { code, message } = responseData;
|
||||
|
||||
// 特殊错误码处理
|
||||
switch (code) {
|
||||
case 401:
|
||||
// token过期,清除登录状态
|
||||
app.clearLoginStatus();
|
||||
wx.showToast({
|
||||
title: '登录已过期',
|
||||
icon: 'none'
|
||||
});
|
||||
// 跳转到登录页
|
||||
wx.navigateTo({
|
||||
url: '/pages/login/login'
|
||||
});
|
||||
break;
|
||||
case 403:
|
||||
wx.showToast({
|
||||
title: '权限不足',
|
||||
icon: 'none'
|
||||
});
|
||||
break;
|
||||
default:
|
||||
wx.showToast({
|
||||
title: message || '操作失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
reject({
|
||||
code,
|
||||
message,
|
||||
type: 'business'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理HTTP错误
|
||||
* @param {Number} statusCode 状态码
|
||||
* @param {Function} reject 拒绝函数
|
||||
* @param {Object} options 请求选项
|
||||
* @param {Number} retryCount 重试次数
|
||||
*/
|
||||
function handleHttpError(statusCode, reject, options, retryCount) {
|
||||
const message = ERROR_MESSAGES[statusCode] || '请求失败';
|
||||
|
||||
// 401错误特殊处理
|
||||
if (statusCode === STATUS_CODE.UNAUTHORIZED) {
|
||||
app.clearLoginStatus();
|
||||
wx.navigateTo({
|
||||
url: '/pages/login/login'
|
||||
});
|
||||
}
|
||||
|
||||
// 5xx错误重试
|
||||
if (statusCode >= 500 && retryCount < API_CONFIG.retryCount) {
|
||||
setTimeout(() => {
|
||||
request({
|
||||
...options,
|
||||
retryCount: retryCount + 1
|
||||
}).then(resolve).catch(reject);
|
||||
}, API_CONFIG.retryDelay);
|
||||
return;
|
||||
}
|
||||
|
||||
wx.showToast({
|
||||
title: message,
|
||||
icon: 'none'
|
||||
});
|
||||
|
||||
reject({
|
||||
code: statusCode,
|
||||
message,
|
||||
type: 'http'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理网络错误
|
||||
* @param {Object} error 错误对象
|
||||
* @param {Function} reject 拒绝函数
|
||||
*/
|
||||
function handleNetworkError(error, reject) {
|
||||
wx.showToast({
|
||||
title: '网络连接失败',
|
||||
icon: 'none'
|
||||
});
|
||||
|
||||
reject({
|
||||
code: STATUS_CODE.NETWORK_ERROR,
|
||||
message: '网络连接失败',
|
||||
type: 'network',
|
||||
error
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* GET请求
|
||||
* @param {String} url 请求地址
|
||||
* @param {Object} params 请求参数
|
||||
* @param {Object} options 其他选项
|
||||
* @returns {Promise} 请求结果
|
||||
*/
|
||||
function get(url, params = {}, options = {}) {
|
||||
const queryString = Object.keys(params)
|
||||
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
||||
.join('&');
|
||||
|
||||
const requestUrl = queryString ? `${url}?${queryString}` : url;
|
||||
|
||||
return request({
|
||||
url: requestUrl,
|
||||
method: 'GET',
|
||||
...options
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* POST请求
|
||||
* @param {String} url 请求地址
|
||||
* @param {Object} data 请求数据
|
||||
* @param {Object} options 其他选项
|
||||
* @returns {Promise} 请求结果
|
||||
*/
|
||||
function post(url, data = {}, options = {}) {
|
||||
return request({
|
||||
url,
|
||||
method: 'POST',
|
||||
data,
|
||||
...options
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT请求
|
||||
* @param {String} url 请求地址
|
||||
* @param {Object} data 请求数据
|
||||
* @param {Object} options 其他选项
|
||||
* @returns {Promise} 请求结果
|
||||
*/
|
||||
function put(url, data = {}, options = {}) {
|
||||
return request({
|
||||
url,
|
||||
method: 'PUT',
|
||||
data,
|
||||
...options
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE请求
|
||||
* @param {String} url 请求地址
|
||||
* @param {Object} options 其他选项
|
||||
* @returns {Promise} 请求结果
|
||||
*/
|
||||
function del(url, options = {}) {
|
||||
return request({
|
||||
url,
|
||||
method: 'DELETE',
|
||||
...options
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param {String} url 上传地址
|
||||
* @param {String} filePath 文件路径
|
||||
* @param {Object} formData 表单数据
|
||||
* @param {Object} options 其他选项
|
||||
* @returns {Promise} 上传结果
|
||||
*/
|
||||
function upload(url, filePath, formData = {}, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const {
|
||||
name = 'file',
|
||||
header = {},
|
||||
needAuth = true,
|
||||
showLoading = true
|
||||
} = options;
|
||||
|
||||
if (showLoading) {
|
||||
wx.showLoading({
|
||||
title: '上传中...',
|
||||
mask: true
|
||||
});
|
||||
}
|
||||
|
||||
// 构建请求头
|
||||
const requestHeader = { ...header };
|
||||
if (needAuth && app.globalData.token) {
|
||||
requestHeader['Authorization'] = `Bearer ${app.globalData.token}`;
|
||||
}
|
||||
|
||||
wx.uploadFile({
|
||||
url: `${API_CONFIG.baseUrl}${url}`,
|
||||
filePath,
|
||||
name,
|
||||
formData,
|
||||
header: requestHeader,
|
||||
success: (res) => {
|
||||
if (showLoading) {
|
||||
wx.hideLoading();
|
||||
}
|
||||
|
||||
try {
|
||||
const data = JSON.parse(res.data);
|
||||
if (data.code === 0) {
|
||||
resolve(data);
|
||||
} else {
|
||||
handleBusinessError(data, reject);
|
||||
}
|
||||
} catch (error) {
|
||||
reject({
|
||||
code: -1,
|
||||
message: '响应数据解析失败',
|
||||
type: 'parse',
|
||||
error
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
if (showLoading) {
|
||||
wx.hideLoading();
|
||||
}
|
||||
handleNetworkError(error, reject);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 会员相关API
|
||||
const memberAPI = {
|
||||
// 获取用户信息
|
||||
getUserInfo() {
|
||||
return get('/api/member/user/info');
|
||||
},
|
||||
|
||||
// 微信登录
|
||||
wxLogin(code) {
|
||||
return post('/api/member/auth/wx-login', { code }, { needAuth: false });
|
||||
},
|
||||
|
||||
// 获取会员信息
|
||||
getMemberInfo() {
|
||||
return get('/api/member/info');
|
||||
},
|
||||
|
||||
// 绑定会员
|
||||
bindMember(memberData) {
|
||||
return post('/api/member/bind', memberData);
|
||||
},
|
||||
|
||||
// 解绑会员
|
||||
unbindMember() {
|
||||
return post('/api/member/unbind');
|
||||
},
|
||||
|
||||
// 获取会员权益
|
||||
getMemberBenefits() {
|
||||
return get('/api/member/benefits');
|
||||
},
|
||||
|
||||
// 验证会员权益
|
||||
verifyBenefit(benefitType) {
|
||||
return post('/api/member/verify-benefit', { benefitType });
|
||||
},
|
||||
|
||||
// 获取会员等级配置
|
||||
getMemberLevels() {
|
||||
return get('/api/member/levels');
|
||||
},
|
||||
|
||||
// 升级会员
|
||||
upgradeMember(targetLevel) {
|
||||
return post('/api/member/upgrade', { targetLevel });
|
||||
},
|
||||
|
||||
// 获取绑定历史
|
||||
getBindHistory(page = 1, size = 10) {
|
||||
return get('/api/member/bind-history', { page, size });
|
||||
},
|
||||
|
||||
// 获取权益使用记录
|
||||
getBenefitUsage(page = 1, size = 10) {
|
||||
return get('/api/member/benefit-usage', { page, size });
|
||||
},
|
||||
|
||||
// 邀请好友
|
||||
inviteFriend(inviteCode) {
|
||||
return post('/api/member/invite', { inviteCode });
|
||||
},
|
||||
|
||||
// 获取邀请记录
|
||||
getInviteHistory(page = 1, size = 10) {
|
||||
return get('/api/member/invite-history', { page, size });
|
||||
}
|
||||
};
|
||||
|
||||
// 支付相关API
|
||||
const paymentAPI = {
|
||||
// 创建支付订单
|
||||
createOrder(orderData) {
|
||||
return post('/api/payment/create-order', orderData);
|
||||
},
|
||||
|
||||
// 查询订单状态
|
||||
queryOrder(orderId) {
|
||||
return get(`/api/payment/order/${orderId}`);
|
||||
},
|
||||
|
||||
// 取消订单
|
||||
cancelOrder(orderId) {
|
||||
return post(`/api/payment/order/${orderId}/cancel`);
|
||||
},
|
||||
|
||||
// 申请退款
|
||||
requestRefund(orderId, refundData) {
|
||||
return post(`/api/payment/order/${orderId}/refund`, refundData);
|
||||
},
|
||||
|
||||
// 查询退款状态
|
||||
queryRefund(refundId) {
|
||||
return get(`/api/payment/refund/${refundId}`);
|
||||
}
|
||||
};
|
||||
|
||||
// 通用API
|
||||
const commonAPI = {
|
||||
// 获取系统配置
|
||||
getSystemConfig() {
|
||||
return get('/api/common/config', {}, { needAuth: false });
|
||||
},
|
||||
|
||||
// 上传图片
|
||||
uploadImage(filePath) {
|
||||
return upload('/api/common/upload/image', filePath);
|
||||
},
|
||||
|
||||
// 发送验证码
|
||||
sendVerifyCode(phone) {
|
||||
return post('/api/common/send-verify-code', { phone }, { needAuth: false });
|
||||
},
|
||||
|
||||
// 验证验证码
|
||||
verifyCode(phone, code) {
|
||||
return post('/api/common/verify-code', { phone, code }, { needAuth: false });
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
request,
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
del: del,
|
||||
upload,
|
||||
memberAPI,
|
||||
paymentAPI,
|
||||
commonAPI,
|
||||
API_CONFIG,
|
||||
STATUS_CODE
|
||||
};
|
||||
Reference in New Issue
Block a user