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 }