智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

285 lines
6.7 KiB

import {
Api_url,
isMockEnabled,
isDebug
} from './config'
import mockService from '@/mock/index.js'
// import {Token} from './token.js'
// var token = new Token();
// 防抖函数
const debounce = (fn, delay = 1000) => {
let timer = null;
return function (...args) {
return new Promise((resolve, reject) => {
if (timer) clearTimeout(timer);
timer = setTimeout(async () => {
try {
const result = await fn.apply(this, args);
resolve(result);
} catch (error) {
reject(error);
}
}, delay);
});
}
}
// 请求拦截器
const requestInterceptor = (config) => {
// 在这里可以统一处理请求头、token等
const token = uni.getStorageSync("token");
if (token) {
config.header = {
...config.header,
'token': token
}
}
return config;
}
// 响应拦截器
const responseInterceptor = (response) => {
const { statusCode, data } = response;
console.log('响应拦截器处理:', { statusCode, data });
// 处理HTTP状态码
if (statusCode >= 200 && statusCode < 300) {
// 处理业务状态码
if (data && typeof data.code !== 'undefined') {
console.log('业务状态码:', data.code);
if (data.code === 1) { // 成功状态码为1
// 登录成功,保存token
if (data.data && data.data.token) {
uni.setStorageSync("token", data.data.token);
// 保存用户类型
if (data.data.user_type) {
uni.setStorageSync("userType", data.data.user_type);
}
// 保存过期时间
if (data.data.expires_time) {
uni.setStorageSync("expires_time", data.data.expires_time);
}
}
return data;
} else if (data.code === 401) {
console.error('401错误 - 未授权');
// 未授权或token过期,清除所有用户缓存信息
// 清除token
uni.removeStorageSync("token");
// 清除用户信息
uni.removeStorageSync("userInfo");
// 清除用户类型
uni.removeStorageSync("userType");
// 清除用户角色
uni.removeStorageSync("userRoles");
// 清除过期时间
uni.removeStorageSync("expires_time");
// 清除底部菜单选中状态
uni.removeStorageSync("tabBerIndex");
// 检查是否是从登录页退出的请求
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const isFromLoginPage = currentPage && currentPage.route && currentPage.route.includes('/pages/student/login/login');
// 如果不是从登录页退出的请求,才显示提示信息
if (!isFromLoginPage) {
uni.showToast({
title: data.msg || '登录已过期,请重新登录',
icon: 'none'
});
}
setTimeout(() => {
uni.reLaunch({
url: '/pages/student/login/login?code=401'
});
}, 1500);
throw new Error(data.msg || '未授权');
} else {
// 其他业务错误
console.error('业务错误:', data);
throw new Error(data.msg || '请求失败');
}
}
return data;
}
// HTTP错误处理
console.error('HTTP错误:', response);
uni.showToast({
title: '网络请求失败',
icon: 'none'
});
throw new Error('网络请求失败');
};
export default {
// 存储正在进行的请求
pendingRequests: new Map(),
// 生成请求的唯一key
generateRequestKey(config) {
const { url, method, data } = config;
return [url, method, JSON.stringify(data)].join('&');
},
// 取消重复请求
cancelRequest(config) {
const requestKey = this.generateRequestKey(config);
if (this.pendingRequests.has(requestKey)) {
const controller = this.pendingRequests.get(requestKey);
controller.abort();
this.pendingRequests.delete(requestKey);
}
},
// 增强请求处理,支持Mock数据回退
async uni_request(options) {
if (isDebug) {
console.log('发起请求:', options);
}
// 检查是否应该使用Mock数据
if (mockService.shouldUseMock(options.url)) {
if (isDebug) {
console.log('使用Mock数据:', options.url);
}
try {
const mockResponse = await mockService.getMockData(options.url, options.data);
if (mockResponse) {
return mockResponse;
}
} catch (error) {
console.error('Mock数据获取失败:', error);
}
}
return new Promise((resolve, reject) => {
// 创建请求配置
const config = {
url: Api_url + options.url,
data: options.data,
method: options.method || 'GET',
header: {
'token': uni.getStorageSync("token")
},
timeout: 10000 // 设置10秒超时
};
if (isDebug) {
console.log('请求配置:', config);
}
// 应用请求拦截器
const interceptedConfig = requestInterceptor(config);
uni.showLoading({
title: '加载中...'
});
if (isDebug) {
console.log('即将发起uni.request');
}
uni.request({
...interceptedConfig,
success: (res) => {
if (isDebug) {
console.log('请求成功响应:', res);
}
try {
const response = responseInterceptor(res);
resolve(response);
} catch (error) {
console.error('请求处理失败:', error);
// API失败时尝试使用Mock数据
this.tryMockFallback(options, resolve, reject);
}
},
fail: (error) => {
console.error('请求失败:', error);
// API失败时尝试使用Mock数据
this.tryMockFallback(options, resolve, reject);
},
complete: () => {
if (isDebug) {
console.log('请求完成');
}
uni.hideLoading();
}
});
});
},
// Mock数据回退处理
async tryMockFallback(options, resolve, reject) {
if (isMockEnabled) {
if (isDebug) {
console.log('API失败,尝试使用Mock数据:', options.url);
}
try {
const mockResponse = await mockService.getMockData(options.url, options.data);
if (mockResponse) {
uni.showToast({
title: '使用模拟数据',
icon: 'none',
duration: 1000
});
resolve(mockResponse);
return;
}
} catch (mockError) {
console.error('Mock数据获取失败:', mockError);
}
}
// 如果Mock也失败,返回错误
uni.showToast({
title: '网络请求失败',
icon: 'none'
});
reject(new Error('网络请求失败'));
},
// 封装请求方法
post(url, data = {}) {
return this.uni_request({
url,
data,
method: 'POST'
});
},
get(url, data = {}) {
console.log('调用get方法:', { url, data });
return this.uni_request({
url,
data,
method: 'GET'
});
},
put(url, data = {}) {
return this.uni_request({
url,
data,
method: 'PUT'
});
},
// 统一的错误处理
handleError(error) {
if (error.statusCode === 401) {
uni.navigateTo({
url: `/pages/student/login/login?res_codes=${error.data.code}`
})
} else {
uni.showToast({
title: error.data?.msg || '请求异常',
icon: 'none'
})
}
}
}