miniprogramme/utils/api-client.js
2025-09-12 16:08:17 +08:00

1091 lines
No EOL
30 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// API客户端工具类 - 真实API版本
const config = require('../config/config.js');
class ApiClient {
constructor() {
this.baseUrl = config.api.baseUrl;
this.timeout = config.api.timeout || 15000;
this.token = null;
// 自动从本地存储获取token
try {
const userInfo = wx.getStorageSync('userInfo');
if (userInfo && userInfo.token) {
this.token = userInfo.token;
console.log('API客户端初始化已加载token');
}
} catch (error) {
console.error('初始化时获取token失败:', error);
}
// 请求拦截器
this.requestInterceptors = [];
this.responseInterceptors = [];
console.log('API客户端初始化:', {
baseUrl: this.baseUrl,
timeout: this.timeout,
configLoaded: !!config?.api
});
}
// 设置token
setToken(token) {
this.token = token;
console.log('Token已设置');
}
// 清除token
clearToken() {
this.token = null;
console.log('Token已清除');
}
// 获取token
getToken() {
// 如果没有token尝试从存储中获取
if (!this.token) {
try {
const userInfo = wx.getStorageSync('userInfo');
if (userInfo && userInfo.token) {
this.token = userInfo.token;
console.log('从存储中获取token成功用户customId:', userInfo.user?.customId);
} else {
console.log('存储中没有找到有效的token');
}
} catch (error) {
console.error('从存储获取token失败:', error);
}
}
return this.token;
}
// 获取设备信息
async getDeviceInfo() {
try {
// 使用新的API替代废弃的wx.getSystemInfoSync
const [windowInfo, deviceInfo, appBaseInfo] = await Promise.all([
this.getWindowInfo(),
this.getDeviceInfo_new(),
this.getAppBaseInfo()
]);
const systemInfo = { ...windowInfo, ...deviceInfo, ...appBaseInfo };
return {
deviceId: deviceInfo.deviceId || systemInfo.deviceId || 'unknown',
deviceModel: deviceInfo.model || systemInfo.model || 'unknown',
deviceType: 'miniprogram', // 标识为小程序
appVersion: config?.appVersion || '1.0.0',
platform: deviceInfo.platform || systemInfo.platform || 'unknown',
system: deviceInfo.system || systemInfo.system || 'unknown'
};
} catch (error) {
console.error('获取设备信息失败,使用兜底方案:', error);
// 兜底使用旧API
try {
const systemInfo = wx.getSystemInfoSync();
return {
deviceId: systemInfo.deviceId || 'unknown',
deviceModel: systemInfo.model || 'unknown',
deviceType: 'miniprogram',
appVersion: config?.appVersion || '1.0.0',
platform: systemInfo.platform || 'unknown',
system: systemInfo.system || 'unknown'
};
} catch (fallbackError) {
console.error('兜底方案也失败:', fallbackError);
return {
deviceId: 'unknown',
deviceModel: 'unknown',
deviceType: 'miniprogram',
appVersion: config?.appVersion || '1.0.0',
platform: 'unknown',
system: 'unknown'
};
}
}
}
// 获取窗口信息
getWindowInfo() {
return new Promise((resolve) => {
try {
const windowInfo = wx.getWindowInfo();
resolve(windowInfo);
} catch (error) {
resolve({});
}
});
}
// 获取设备信息新API
getDeviceInfo_new() {
return new Promise((resolve) => {
try {
const deviceInfo = wx.getDeviceInfo();
resolve(deviceInfo);
} catch (error) {
resolve({});
}
});
}
// 获取应用基础信息
getAppBaseInfo() {
return new Promise((resolve) => {
try {
const appBaseInfo = wx.getAppBaseInfo();
resolve(appBaseInfo);
} catch (error) {
resolve({});
}
});
}
// 编码查询参数
encodeParams(params) {
if (!params) return '';
return Object.keys(params)
.filter(key => params[key] !== null && params[key] !== undefined)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
.join('&');
}
// 通用请求方法
async request(method, url, data = null, options = {}) {
const token = this.getToken();
const fullUrl = url.startsWith('http') ? url : `${this.baseUrl}${url}`;
console.log('发起API请求:', {
method,
url: fullUrl,
hasToken: !!token,
hasData: !!data
});
const requestOptions = {
url: fullUrl,
method: method.toUpperCase(),
timeout: this.timeout,
header: {
'Content-Type': 'application/json',
'X-Client-Version': `FindMe-MiniProgram/${config?.appVersion || '1.0.0'}`,
...options.headers
}
};
// 添加认证头
if (token) {
requestOptions.header['Authorization'] = `Bearer ${token}`;
}
// 处理请求数据
if (data) {
if (method.toUpperCase() === 'GET') {
// GET请求将数据转换为查询参数
const queryString = this.encodeParams(data);
if (queryString) {
requestOptions.url += (requestOptions.url.includes('?') ? '&' : '?') + queryString;
}
} else {
// 其他请求,将数据作为请求体
requestOptions.data = data;
}
}
return new Promise((resolve, reject) => {
wx.request({
...requestOptions,
success: (res) => {
console.log('API响应:', {
url: fullUrl,
statusCode: res.statusCode,
data: res.data
});
if (res.statusCode >= 200 && res.statusCode < 300) {
// 检查业务状态码
if (res.data && typeof res.data === 'object') {
if (res.data.code === 0 || res.data.code === 200) {
resolve(res.data);
} else {
reject(new Error(`HTTP ${res.statusCode}: ${res.data.message || 'request:ok'}`));
}
} else {
resolve(res.data);
}
} else {
reject(new Error(`HTTP ${res.statusCode}: ${res.data?.message || 'request failed'}`));
}
},
fail: (error) => {
console.error('API请求失败:', error);
reject(new Error(error.errMsg || '网络请求失败'));
}
});
});
}
// GET请求
async get(url, params = null, options = {}) {
return this.request('GET', url, params, options);
}
// POST请求
async post(url, data = null, options = {}) {
return this.request('POST', url, data, options);
}
// PUT请求
async put(url, data = null, options = {}) {
return this.request('PUT', url, data, options);
}
// DELETE请求
async delete(url, data = null, options = {}) {
return this.request('DELETE', url, data, options);
}
// 🔥 用户认证相关接口
// 发送验证码(生产级别实现,支持重试)
async sendVerifyCode(phone, retryCount = 0) {
try {
const response = await this.post('/api/v1/user/send-verify-code', { phone });
return response;
} catch (error) {
console.error('发送验证码失败:', error);
// 网络错误时自动重试最多重试2次
if (retryCount < 2 && this.isNetworkError(error)) {
console.log(`网络错误,正在重试... (${retryCount + 1}/2)`);
await this.delay(1000 * (retryCount + 1)); // 递增延迟
return this.sendVerifyCode(phone, retryCount + 1);
}
throw error;
}
}
// 判断是否为网络错误
isNetworkError(error) {
return error.message && (
error.message.includes('网络') ||
error.message.includes('timeout') ||
error.message.includes('Network') ||
error.message.includes('Failed to fetch')
);
}
// 延迟函数
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 用户登录
async login(phone, verifyCode) {
try {
// 获取设备信息
const deviceInfo = await this.getDeviceInfo();
const response = await this.post('/api/v1/user/login', {
phone,
verifyCode,
source: 'miniprogram', // 根据文档使用source字段小写
deviceId: deviceInfo.deviceId,
deviceType: deviceInfo.deviceType,
appVersion: deviceInfo.appVersion
});
// 不在这里保存数据,让认证管理器统一处理
console.log('登录API调用成功设备信息:', deviceInfo);
return response;
} catch (error) {
console.error('登录失败:', error);
throw error;
}
}
// 微信登录
async wechatLogin(code, userInfo = null) {
try {
// 获取设备信息
const deviceInfo = await this.getDeviceInfo();
const loginData = {
code,
source: 'miniprogram', // 根据文档使用source字段小写
deviceId: deviceInfo.deviceId,
deviceType: deviceInfo.deviceType,
appVersion: deviceInfo.appVersion
};
if (userInfo) {
loginData.userInfo = userInfo;
}
const response = await this.post('/api/v1/user/wechat-login', loginData);
// 不在这里保存数据,让认证管理器统一处理
console.log('微信登录API调用成功设备信息:', deviceInfo);
return response;
} catch (error) {
console.error('微信登录失败:', error);
throw error;
}
}
// 获取用户信息
async getUserInfo() {
try {
const response = await this.get('/api/v1/user/info');
return response;
} catch (error) {
console.error('获取用户信息失败:', error);
throw error;
}
}
// 🔥 账号同步相关接口
// 绑定手机号
async bindPhone(phone, verifyCode, autoMerge = false) {
try {
// 获取设备信息
const deviceInfo = await this.getDeviceInfo();
const response = await this.post('/api/v1/user/bind-phone', {
phone,
verifyCode,
deviceId: deviceInfo.deviceId, // 根据文档保留deviceId
autoMerge
});
return response;
} catch (error) {
console.error('绑定手机号失败:', error);
throw error;
}
}
// 检测可合并账号
async detectMerge(customId, autoMerge = false) {
try {
const response = await this.post('/api/v1/user/detect-merge', {
userCustomId: customId, // 根据文档使用userCustomId参数
autoMerge
});
return response;
} catch (error) {
console.error('检测可合并账号失败:', error);
throw error;
}
}
// 合并账号
async mergeAccount(primaryCustomId, secondaryCustomId, mergeReason = '用户手动合并') {
try {
const response = await this.post('/api/v1/user/merge-account', {
primaryUserCustomId: primaryCustomId, // 根据文档使用primaryUserCustomId参数
secondaryUserCustomId: secondaryCustomId, // 根据文档使用secondaryUserCustomId参数
mergeReason
});
return response;
} catch (error) {
console.error('合并账号失败:', error);
throw error;
}
}
// 更新用户资料
async updateUserProfile(data) {
try {
const response = await this.put('/api/v1/user/profile', data);
return response;
} catch (error) {
console.error('更新用户资料失败:', error);
throw error;
}
}
// 获取用户设置
async getUserSetting() {
try {
const response = await this.get('/api/v1/user/setting');
return response;
} catch (error) {
console.error('获取用户设置失败:', error);
throw error;
}
}
// 刷新token
async refreshToken(refreshToken) {
try {
const response = await this.post('/api/v1/auth/refresh', {
refresh_token: refreshToken
});
if (response && response.code === 200 && response.data) {
this.setToken(response.data.access_token);
// 更新本地存储 - 保持字段名一致性
const userInfo = wx.getStorageSync('userInfo') || {};
userInfo.token = response.data.access_token;
userInfo.refreshToken = response.data.refresh_token; // 保持一致的字段名
userInfo.expiresAt = response.data.expires_at * 1000; // 转换为毫秒时间戳
wx.setStorageSync('userInfo', userInfo);
}
return response;
} catch (error) {
console.error('刷新token失败:', error);
throw error;
}
}
// 用户登出
async logout() {
try {
const response = await this.post('/api/v1/user/logout');
// 清除本地token和用户信息
this.clearToken();
wx.removeStorageSync('userInfo');
return response;
} catch (error) {
console.error('登出失败:', error);
// 即使登出失败,也清除本地信息
this.clearToken();
wx.removeStorageSync('userInfo');
throw error;
}
}
// 🔥 位置相关接口
// 更新位置
async updateLocation(locationData) {
try {
const response = await this.post('/api/v1/location/update', locationData);
return response;
} catch (error) {
console.error('更新位置失败:', error);
throw error;
}
}
// 获取好友位置
async getFriendsLocation() {
try {
const response = await this.get('/api/v1/location/friends');
return response;
} catch (error) {
console.error('获取好友位置失败:', error);
throw error;
}
}
// 获取用户位置
async getUserLocation(userId) {
try {
const response = await this.get(`/api/v1/location/user/${userId}`);
return response;
} catch (error) {
console.error('获取用户位置失败:', error);
throw error;
}
}
// 获取附近用户
async getNearbyUsers(params = {}) {
try {
const response = await this.get('/api/v1/location/nearby', params);
return response;
} catch (error) {
console.error('获取附近用户失败:', error);
throw error;
}
}
// 获取位置历史
async getLocationHistory(params = {}) {
try {
const response = await this.get('/api/v1/location/history', params);
return response;
} catch (error) {
console.error('获取位置历史失败:', error);
throw error;
}
}
// 获取位置隐私设置
async getLocationPrivacy() {
try {
const response = await this.get('/api/v1/location/privacy');
return response;
} catch (error) {
console.error('获取位置隐私设置失败:', error);
throw error;
}
}
// 更新位置隐私设置
async updateLocationPrivacy(privacyData) {
try {
const response = await this.put('/api/v1/location/privacy', privacyData);
return response;
} catch (error) {
console.error('更新位置隐私设置失败:', error);
throw error;
}
}
// 获取天气信息
async getWeatherInfo(latitude, longitude) {
try {
const response = await this.get('/api/v1/location/weather', {
latitude,
longitude
});
return response;
} catch (error) {
console.error('获取天气信息失败:', error);
throw error;
}
}
// 🔥 社交相关接口根据好友功能API手册完整实现
// 获取好友列表
async getFriends() {
try {
const response = await this.get('/api/v1/social/friends');
return response;
} catch (error) {
console.error('获取好友列表失败:', error);
throw error;
}
}
// 获取好友详细信息
async getFriendDetail(customId, lat = null, lng = null) {
try {
let url = `/api/v1/social/friends/${customId}/detail`;
const params = {};
if (lat !== null && lng !== null) {
params.lat = lat;
params.lng = lng;
}
const response = await this.get(url, params);
return response;
} catch (error) {
console.error('获取好友详情失败:', error);
throw error;
}
}
// 搜索用户
async searchUsers(query, searchType = 'all', page = 1, pageSize = 10) {
try {
if (!query || typeof query !== 'string') {
throw new Error('搜索关键词不能为空');
}
const validSearchTypes = ['nickname', 'custom_id', 'phone', 'all'];
if (!validSearchTypes.includes(searchType)) {
throw new Error('无效的搜索类型');
}
if (pageSize < 1 || pageSize > 50) {
throw new Error('每页数量必须在1-50之间');
}
const response = await this.post('/api/v1/social/users/search', {
query: query.trim(),
searchType: searchType,
page: Math.max(1, page),
pageSize: Math.min(50, pageSize)
});
return response;
} catch (error) {
console.error('搜索用户失败:', error);
throw error;
}
}
// 添加好友
async addFriend(targetId, message = '') {
try {
if (!targetId || typeof targetId !== 'string') {
throw new Error('目标用户ID不能为空');
}
if (message && message.length > 100) {
throw new Error('好友申请留言不能超过100字符');
}
const response = await this.post('/api/v1/social/friend/add', {
targetId: targetId,
message: message.trim()
});
return response;
} catch (error) {
console.error('添加好友失败:', error);
throw error;
}
}
// 获取好友请求列表
async getFriendRequests() {
try {
const response = await this.get('/api/v1/social/friend/requests');
return response;
} catch (error) {
console.error('获取好友请求失败:', error);
throw error;
}
}
// 获取好友请求数量
async getFriendRequestsCount() {
try {
const response = await this.get('/api/v1/social/friend/requests/count');
return response;
} catch (error) {
console.error('获取好友请求数量失败:', error);
throw error;
}
}
// 处理好友请求
async handleFriendRequest(requestId, accept) {
try {
if (!requestId || typeof requestId !== 'string') {
throw new Error('请求ID不能为空');
}
if (typeof accept !== 'boolean') {
throw new Error('accept参数必须是布尔值');
}
const response = await this.post('/api/v1/social/friend/handle-request', {
requestId: requestId,
accept: accept
});
return response;
} catch (error) {
console.error('处理好友请求失败:', error);
throw error;
}
}
// 批量处理好友请求
async batchHandleFriendRequests(requestIds, accept) {
try {
if (!Array.isArray(requestIds) || requestIds.length === 0) {
throw new Error('请求ID列表不能为空');
}
if (requestIds.length > 20) {
throw new Error('一次最多处理20个请求');
}
if (typeof accept !== 'boolean') {
throw new Error('accept参数必须是布尔值');
}
const response = await this.post('/api/v1/social/friend/batch-handle-requests', {
requestIds: requestIds,
accept: accept
});
return response;
} catch (error) {
console.error('批量处理好友请求失败:', error);
throw error;
}
}
// 更新好友关系
async updateFriendRelation(friendId, updateData) {
try {
if (!friendId) {
throw new Error('好友ID不能为空');
}
const validRelations = ['情侣', '家人', '兄弟', '姐妹', '闺蜜', '死党'];
if (updateData.relation && !validRelations.includes(updateData.relation)) {
throw new Error('无效的关系标签');
}
if (updateData.remark && updateData.remark.length > 50) {
throw new Error('好友备注不能超过50字符');
}
const response = await this.put('/api/v1/social/friend', {
friendId: friendId,
...updateData
});
return response;
} catch (error) {
console.error('更新好友关系失败:', error);
throw error;
}
}
// 删除好友
async deleteFriend(friendCustomId) {
try {
if (!friendCustomId || typeof friendCustomId !== 'string') {
throw new Error('好友CustomID不能为空');
}
const response = await this.delete(`/api/v1/social/friend/${friendCustomId}`);
return response;
} catch (error) {
console.error('删除好友失败:', error);
throw error;
}
}
// 拉取好友通知
async pullFriendNotifications(limit = 10) {
try {
if (limit < 1 || limit > 50) {
throw new Error('拉取数量必须在1-50之间');
}
const response = await this.get('/api/v1/social/friend/notifications/pull', {
limit: limit
});
return response;
} catch (error) {
console.error('拉取好友通知失败:', error);
throw error;
}
}
// 获取通知统计
async getFriendNotificationStats() {
try {
const response = await this.get('/api/v1/social/friend/notifications/stats');
return response;
} catch (error) {
console.error('获取通知统计失败:', error);
throw error;
}
}
// 获取群组列表
async getGroups() {
try {
const response = await this.get('/api/v1/social/groups');
return response;
} catch (error) {
console.error('获取群组列表失败:', error);
throw error;
}
}
// 获取群组数量
async getGroupsCount() {
try {
const response = await this.get('/api/v1/social/groups/count');
return response;
} catch (error) {
console.error('获取群组数量失败:', error);
throw error;
}
}
// 🔥 聊天相关接口根据WebSocket即时通讯接口文档完整实现
// 获取会话列表
async getConversations() {
try {
const response = await this.get('/api/v1/chat/conversations');
return response;
} catch (error) {
console.error('获取会话列表失败:', error);
throw error;
}
}
// 获取聊天历史消息 - 根据API文档修正参数格式
async getChatMessages(targetId, chatType, params = {}) {
try {
const queryParams = {
receiverId: targetId, // 使用receiverId而不是conversationId
chatType: chatType, // 聊天类型0=单聊, 1=群聊
limit: params.limit || 20,
direction: params.direction || 'before',
lastMsgId: params.lastMsgId, // 分页参数
...params
};
const response = await this.get('/api/v1/chat/history', queryParams);
return response;
} catch (error) {
console.error('获取聊天消息失败:', error);
throw error;
}
}
// 🚫 发送消息已废弃 - 必须使用WebSocket
async sendMessage(targetId, content, msgType = 'text', chatType = 0) {
console.error('❌ HTTP发送消息已废弃根据API文档所有消息发送必须通过WebSocket');
throw new Error('消息发送必须使用WebSocketHTTP发送接口已废弃');
}
// 批量标记消息已读
async batchMarkRead(conversationId, messageIds) {
try {
const response = await this.post('/api/v1/chat/batch-read', {
conversationId: conversationId,
messageIds: messageIds
});
return response;
} catch (error) {
console.error('批量标记已读失败:', error);
throw error;
}
}
// 全部标记已读
async markAllRead(conversationId) {
try {
const response = await this.post('/api/v1/chat/mark-all-read', {
conversationId: conversationId
});
return response;
} catch (error) {
console.error('全部标记已读失败:', error);
throw error;
}
}
// 获取总未读数
async getTotalUnreadCount() {
try {
const response = await this.get('/api/v1/chat/unread/total');
return response;
} catch (error) {
console.error('获取总未读数失败:', error);
throw error;
}
}
// 更新会话设置
async updateConversationSettings(conversationId, settings) {
try {
const response = await this.put(`/api/v1/chat/conversation/${conversationId}`, settings);
return response;
} catch (error) {
console.error('更新会话设置失败:', error);
throw error;
}
}
// 删除会话
async deleteConversation(conversationId) {
try {
const response = await this.delete(`/api/v1/chat/conversation/${conversationId}`);
return response;
} catch (error) {
console.error('删除会话失败:', error);
throw error;
}
}
// 获取聊天设置
async getChatSettings() {
try {
const response = await this.get('/api/v1/chat/settings');
return response;
} catch (error) {
console.error('获取聊天设置失败:', error);
throw error;
}
}
// 更新聊天设置
async updateChatSettings(settings) {
try {
const response = await this.put('/api/v1/chat/settings', settings);
return response;
} catch (error) {
console.error('更新聊天设置失败:', error);
throw error;
}
}
// 拉取离线消息
async pullOfflineMessages(lastSeqId, limit = 50) {
try {
const response = await this.get('/api/v1/chat/sync/pull', {
lastSeqId: lastSeqId,
limit: limit
});
return response;
} catch (error) {
console.error('拉取离线消息失败:', error);
throw error;
}
}
// 确认消息状态
async ackMessageStatus(messageId, status, timestamp) {
try {
const response = await this.post('/api/v1/chat/sync/ack', {
messageId: messageId,
status: status,
timestamp: timestamp
});
return response;
} catch (error) {
console.error('确认消息状态失败:', error);
throw error;
}
}
// 标记消息已读(兼容方法)
async markMessagesRead(conversationId, messageIds) {
try {
if (Array.isArray(messageIds) && messageIds.length > 0) {
return await this.batchMarkRead(conversationId, messageIds);
} else {
return await this.markAllRead(conversationId);
}
} catch (error) {
console.error('标记消息已读失败:', error);
throw error;
}
}
// 发送虚拟弹幕
async sendDanmaku(content, color = '#FFFFFF', size = 1, duration = 5000, latitude, longitude, radius = 100) {
try {
if (!content || content.length > 255) {
throw new Error('弹幕内容不能为空且不能超过255字符');
}
const response = await this.post('/api/v1/chat/danmaku', {
content: content,
color: color,
size: size,
duration: duration,
latitude: latitude,
longitude: longitude,
radius: radius
});
return response;
} catch (error) {
console.error('发送弹幕失败:', error);
throw error;
}
}
// 查询附近弹幕
async getNearbyDanmaku(latitude, longitude, radius = 1000) {
try {
const response = await this.get('/api/v1/chat/danmaku/nearby', {
latitude: latitude,
longitude: longitude,
radius: radius
});
return response;
} catch (error) {
console.error('查询附近弹幕失败:', error);
throw error;
}
}
// 查询表情包
async getEmojiPackages() {
try {
const response = await this.get('/api/v1/chat/emoji/packages');
return response;
} catch (error) {
console.error('查询表情包失败:', error);
throw error;
}
}
// 🔥 文件上传接口
// 文件上传
async uploadFile(filePath, fileType = 'image', usageType = 'chat') {
try {
console.log('上传文件:', { filePath, fileType, usageType });
return new Promise((resolve, reject) => {
wx.uploadFile({
url: `${this.baseUrl}/api/v1/file/upload`,
filePath: filePath,
name: 'file',
formData: {
file_type: fileType,
usage_type: usageType
},
header: {
'Authorization': this.token ? `Bearer ${this.token}` : '',
'X-Client-Version': `FindMe-MiniProgram/${config?.appVersion || '1.0.0'}`
},
success: (res) => {
console.log('文件上传成功:', res);
try {
const data = JSON.parse(res.data);
if (data.code === 0) {
resolve(data);
} else {
reject(new Error(data.message || '上传失败'));
}
} catch (error) {
reject(new Error('响应解析失败'));
}
},
fail: (error) => {
console.error('文件上传失败:', error);
reject(new Error(error.errMsg || '上传失败'));
}
});
});
} catch (error) {
console.error('文件上传异常:', error);
throw error;
}
}
// 🔥 测试token有效性
async testTokenValidity() {
try {
const token = this.getToken();
console.log('开始测试token有效性:', {
hasToken: !!token,
tokenLength: token ? token.length : 0,
tokenStart: token ? token.substring(0, 20) + '...' : 'null'
});
if (!token) {
throw new Error('没有找到token');
}
const response = await this.getUserInfo();
console.log('Token有效性测试成功:', response);
return true;
} catch (error) {
console.error('Token有效性测试失败:', error);
return false;
}
}
}
// 创建全局实例
const apiClient = new ApiClient();
module.exports = apiClient;