App.vue
onShow: function () {
uni.onNetworkStatusChange((res) => {
uni.setStorageSync('networkConnected', res.isConnected);
});
},
common.js
/**
* 显示消息提示框
* @param content 提示的标题
*/
export function toast(content) {
uni.showToast({
icon: 'none',
title: content
})
}
/**
* 显示模态弹窗
* @param content 提示的标题
*/
export function showConfirm(content,showCancel) {
return new Promise((resolve, reject) => {
uni.showModal({
title: '提示',
content: content,
cancelText: '取消',
confirmText: '确定',
showCancel: showCancel==null?true:showCancel,
success: function(res) {
resolve(res)
}
})
})
}
/**
* 参数处理
* @param params 参数
*/
export function tansParams(params) {
let result = ''
for (const propName of Object.keys(params)) {
const value = params[propName]
var part = encodeURIComponent(propName) + "="
if (value !== null && value !== "" && typeof (value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
let params = propName + '[' + key + ']'
var subPart = encodeURIComponent(params) + "="
result += subPart + encodeURIComponent(value[key]) + "&"
}
}
} else {
result += part + encodeURIComponent(value) + "&"
}
}
}
return result
}
pathDataCache.js
//设置
export function setPathAndData(pathAndParameter, data) {
let obj = uni.getStorageSync('path_data_cache') || {};
obj[pathAndParameter]= data;
uni.setStorageSync('path_data_cache', obj);
}
// 获取
export function getPathAndData(pathAndParameter) {
let obj = uni.getStorageSync('path_data_cache');
return obj?.[pathAndParameter];
}
data.js
// 本地静态那些接口需要缓存数据
export const localityUrlPathList = [
'/user/api/mingmenHomePageInfo/getByType',
'/user/api/dict/AI_IS_OPEN'
]
request.js 这个文件实现了无网读取缓存的功能
import store from '@/store'
import config from '@/config'
import {
getToken,
removeToken
} from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import {
toast,
showConfirm,
tansParams
} from '@/utils/common'
import {
setPathAndData,
getPathAndData
} from '@/utils/pathDataCache.js'
import {
localityUrlPathList
} from './data.js'
let timeout = 40000
const baseUrl = config.baseUrl
// 添加全局变量控制弹窗状态
let isShowingLoginModal = false
// 需要缓存接口url的数组
let cachePathList = uni.getStorageSync('setUrlPathDataList') || localityUrlPathList;
const request = async config => {
const networkConnected = uni.getStorageSync('networkConnected');
// console.log('cachePathList', cachePathList);
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
config.header = config.header || {}
if (getToken() && !isToken) {
config.header['Authorization'] = 'Bearer ' + getToken()
}
// get请求映射params参数.
// console.log('config.url',config.url);
//console.log('getUrlPath',getUrlPath(config.url));
if (config.params) {
let url = config.url + '?' + tansParams(config.params)
url = url.slice(0, -1)
config.url = url
}
// console.log('是否有网络',uni.getStorageSync('networkConnected'));
if (cachePathList.includes(getUrlPath(config.url))) {
let setDataKey = serializeRequest(config.method || 'get', config.url, config.data);
// 包含需缓存
if (networkConnected) {
//有网络,请求并缓存
try {
let respData = await realRequest(config)
// console.log('setDataKey', setDataKey, respData);
setPathAndData(setDataKey, respData);
return Promise.resolve(respData);
} catch (error) {
// console.log('error', error);
return Promise.reject(error);
}
} else {
//无网络,取缓存,没有则报错
let dataa = getPathAndData(setDataKey);
// console.log('获取数据',dataa,setDataKey);
if (!dataa) {
// console.log('无网络,无缓存');
return Promise.reject('nocatch');
}
return Promise.resolve(dataa);
}
} else {
// 不包含 正常请求
// console.log('config',config);
return realRequest(config);
}
}
// 处理未授权错误
function handleUnauthorized(reject) {
// 如果已经有弹窗显示,则不再重复显示
if (isShowingLoginModal) {
reject('无效的会话,或者会话已过期,请重新登录。')
return
}
isShowingLoginModal = true
showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => {
isShowingLoginModal = false
if (res.confirm) {
removeToken()
uni.reLaunch({
url: '/pages/login'
})
}
}).catch(() => {
isShowingLoginModal = false
})
reject('无效的会话,或者会话已过期,请重新登录。')
}
// 处理请求错误
function handleRequestError(error, reject) {
let {
message
} = error
if (message === 'Network Error') {
message = '后端接口连接异常'
} else if (message.includes('timeout')) {
message = '系统接口请求超时'
} else if (message.includes('Request failed with status code')) {
message = '系统接口' + message.substr(message.length - 3) + '异常'
}
toast(message)
reject(error)
}
function getUrlPath(url) {
return url.split('?')[0];
}
/**
* 真实请求
* @param {Object} config
*/
function realRequest(config) {
const networkConnected = uni.getStorageSync('networkConnected');
return new Promise((resolve, reject) => {
uni.request({
method: config.method || 'get',
timeout: config.timeout || timeout,
url: config.baseUrl || baseUrl + config.url,
data: config.data,
header: config.header,
dataType: 'json'
}).then(response => {
let [error, res] = response
// console.log('response',config.method,config.url,response,error);
// console.log('getToken()',getToken());
if (res.data.error) {
// console.log('500错误的地方',networkConnected,error);
if (networkConnected) {
toast('服务器忙')
} else {
uni.showToast({
icon: 'none',
title: '网络异常,请检查网络设置',
duration: 2000,
});
}
reject('服务器忙')
return
}
const code = res.data.code || 200
const msg = errorCode[code] || res.data.msg || errorCode['default']
if (code === 401) {
// 处理401未授权错误
handleUnauthorized(reject)
} else if (code === 500) {
// 判断是否有网络
if (networkConnected) {
uni.showToast({
icon: 'none',
title: msg,
duration: 2000
});
} else {
uni.showToast({
icon: 'none',
title: '网络异常,请检查网络设置',
duration: 2000,
});
}
reject('500');
} else if (code == 1) {
toast(msg)
reject(code)
} else if (code == 2001) {
toast(msg)
reject(code)
} else if (code > 8000 && code < 9000) {
reject(code)
} else if (code !== 200) {
showConfirm('后端服务错误,请稍后在试', false).then(res => {
if (res.confirm) {
// 用户确认后的操作
}
})
reject(code);
}
resolve(res.data);
}).catch(error => {
handleRequestError(error, reject)
})
})
}
/**
* http请求方式,路径,参数系列化
*/
function serializeRequest(method, path, params = {}) {
const methodUpper = method.toUpperCase();
const queryString = Object.keys(params)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
.join('&');
return queryString ?
`${methodUpper}${path}?${queryString}` :
`${methodUpper}${path}`;
}
export default request