154 lines
4.1 KiB
JavaScript
154 lines
4.1 KiB
JavaScript
const NO_NETWORK_TEXT = '当前无网络,请检查网络连接'
|
||
let isNetworkOnline = true
|
||
let hasBoundNetworkListener = false
|
||
let hasBoundRequestInterceptor = false
|
||
let hasPatchedUviewRequest = false
|
||
let lastNoNetworkToastAt = 0
|
||
|
||
const showNoNetworkToast = () => {
|
||
const now = Date.now()
|
||
if (now - lastNoNetworkToastAt < 2000) return
|
||
lastNoNetworkToastAt = now
|
||
uni.showToast({
|
||
title: NO_NETWORK_TEXT,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
|
||
const updateNetworkOnlineStatus = (online) => {
|
||
isNetworkOnline = !!online
|
||
}
|
||
|
||
const initNetworkStatus = () => {
|
||
try {
|
||
const sysInfo = uni.getSystemInfoSync()
|
||
if (sysInfo && typeof sysInfo.networkType === 'string') {
|
||
updateNetworkOnlineStatus(sysInfo.networkType !== 'none')
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
|
||
const refreshNetworkStatusSync = () => {
|
||
try {
|
||
const sysInfo = uni.getSystemInfoSync()
|
||
if (sysInfo && typeof sysInfo.networkType === 'string') {
|
||
updateNetworkOnlineStatus(sysInfo.networkType !== 'none')
|
||
}
|
||
} catch (e) {}
|
||
return isNetworkOnline
|
||
}
|
||
|
||
const bindNetworkStatusListener = () => {
|
||
if (hasBoundNetworkListener) return
|
||
hasBoundNetworkListener = true
|
||
uni.onNetworkStatusChange((res) => {
|
||
updateNetworkOnlineStatus(res && res.isConnected)
|
||
if (res && res.isConnected === false) {
|
||
showNoNetworkToast()
|
||
}
|
||
})
|
||
}
|
||
|
||
const bindGlobalRequestInterceptor = () => {
|
||
if (hasBoundRequestInterceptor || typeof uni.addInterceptor !== 'function') return
|
||
hasBoundRequestInterceptor = true
|
||
uni.addInterceptor('request', {
|
||
invoke() {
|
||
if (!refreshNetworkStatusSync()) {
|
||
showNoNetworkToast()
|
||
return false
|
||
}
|
||
},
|
||
fail(err) {
|
||
const msg = (err && err.errMsg) ? String(err.errMsg).toLowerCase() : ''
|
||
if (msg.includes('fail') && (msg.includes('network') || msg.includes('internet') || msg.includes('offline'))) {
|
||
updateNetworkOnlineStatus(false)
|
||
showNoNetworkToast()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const isLikelyNetworkError = (err) => {
|
||
const msg = err && err.errMsg ? String(err.errMsg).toLowerCase() : String(err || '').toLowerCase()
|
||
if (!msg) return false
|
||
return (
|
||
msg.includes('request:fail') ||
|
||
msg.includes('network') ||
|
||
msg.includes('internet') ||
|
||
msg.includes('offline') ||
|
||
msg.includes('timeout') ||
|
||
msg.includes('disconnected') ||
|
||
msg.includes('dns')
|
||
)
|
||
}
|
||
|
||
const install = (Vue, vm) => {
|
||
initNetworkStatus()
|
||
bindNetworkStatusListener()
|
||
bindGlobalRequestInterceptor()
|
||
|
||
Vue.prototype.$u.http.setConfig({
|
||
baseUrl: 'https://yxd.ccttiot.com/prod-api',
|
||
// baseUrl: 'http://192.168.1.5:8081',
|
||
loadingText: '',
|
||
loadingTime: 800,
|
||
// 设置自定义头部content-type
|
||
header: {
|
||
'content-type': 'application/json;charset=UTF-8',
|
||
},
|
||
// ......
|
||
})
|
||
|
||
// 为uView请求增加统一网络失败兜底(避免页面忘记catch时控制台刷错)
|
||
if (!hasPatchedUviewRequest) {
|
||
hasPatchedUviewRequest = true
|
||
const rawRequest = Vue.prototype.$u.http.request.bind(Vue.prototype.$u.http)
|
||
Vue.prototype.$u.http.request = (options = {}) => {
|
||
if (!refreshNetworkStatusSync()) {
|
||
showNoNetworkToast()
|
||
// 与uView拦截return false行为保持一致:中断后不进入then/catch
|
||
return new Promise(() => {})
|
||
}
|
||
return rawRequest(options).catch((err) => {
|
||
if (isLikelyNetworkError(err)) {
|
||
updateNetworkOnlineStatus(false)
|
||
showNoNetworkToast()
|
||
return new Promise(() => {})
|
||
}
|
||
return Promise.reject(err)
|
||
})
|
||
}
|
||
}
|
||
|
||
// 请求拦截部分,如配置,每次请求前都会执行
|
||
Vue.prototype.$u.http.interceptor.request = (config) => {
|
||
if (!refreshNetworkStatusSync()) {
|
||
showNoNetworkToast()
|
||
// 返回false可中断请求(uView内置约定)
|
||
return false
|
||
}
|
||
|
||
config.header = config.header || {}
|
||
const token = uni.getStorageSync('token')
|
||
config.header.Authorization = token
|
||
// config.header.Tenant-Id=1
|
||
// #ifdef H5
|
||
config.header.Authorization = 'Bearer ' + token
|
||
// #endif
|
||
// 可以对某个url进行特别处理,此url参数为this.$u.get(url)中的url值
|
||
if (config.url == '/user/login') config.header.noToken = true
|
||
// 最后需要将config进行return
|
||
return config
|
||
}
|
||
|
||
// 响应拦截,如配置,每次请求结束都会执行本方法
|
||
Vue.prototype.$u.http.interceptor.response = (res) => {
|
||
return res
|
||
}
|
||
}
|
||
|
||
export default {
|
||
install
|
||
} |