import ivyStore from './ivyStore' import './inner/rem' import * as utils from './utils' export function init(objects) { ivyStore.objects = objects objects.Vue.use(objects.Mint) Object.assign(objects.Vue.prototype, { $Indicator: objects.Mint.Indicator, $Toast: objects.Mint.Toast, $MessageBox: objects.Mint.MessageBox, }) console.log('inited') addGlobalFunc() utils.addDateFormat() addGlobalErrorHandler() } export default init function addGlobalFunc() { Number.prototype.toWidth = function(width) { return this.toString().padStart(width, '0') } } function addGlobalErrorHandler() { let {Vue, axios, Mint: {Toast}} = ivyStore.objects Vue.config.productionTip = false Vue.config.errorHandler = err => { console.error(err) alertOnce(`${err.message} ${err.stack}`, 'error') } window.onerror = handleError window.addEventListener('error', Vue.config.errorHandler) window.onunhandledrejection = handleRejection window.addEventListener("unhandledrejection", handleRejection) // 处理config中的loading选项,自动维护loading状态 function updateLoading(config, v) { if (v && !config.disableLoading) { showLoading() } if (!v && !config.disableLoading) { hideLoading() } if (!config.loading) return if (typeof config.loading === 'function') { return config.loading(v) } config.loading.loading = v } axios.interceptors.request.use((config) => { updateLoading(config, true) let defaultParam = ivyStore.globalParameter() if (config.method === 'post') { config.data = {...defaultParam, ...config.data} } else { config.params = {...defaultParam, ...config.params} } return config }, (error) => { return Promise.reject(error) }) // 如果服务器返回错误,直接弹框提示,方便诊断问题 axios.interceptors.response.use((response) => { updateLoading(response.config, false) if (response.config.disableAlert) { // 不要默认的alert,那么直接返回结果给上层调用者,让他们处理 return response } if (response.status !== 200 || response.data.code) { Toast(`服务器返回错误:${response.status === 200 && response.data.message || response.data || ''}`) return Promise.reject(response) } return response }, (error) => { updateLoading(error.config, false) Toast({ message: `网络错误:${error.message}`, iconClass: 'toast-icon-warning' }) // 如果没有有意义的错误消息提示,一般是被取消的网络请求,忽略 return Promise.reject({ message: `network error. message: ${error.message} url: ${error.config.url} data: ${error.config.data}`, ignore: error.message === 'Network Error', }) }) } // 处理全局未处理的错误 function alertOnce(message, type) { if (ivyStore.alerted) return if (typeof message !== 'string') { message = JSON.stringify(message) } // iphone6p在某些情况下滑动屏幕会导致出现错误弹框 if (message.includes('TapGesture') && message.includes('permission.play') || message.includes('operation was aborted')) return ivyStore.alerted = true window.alert(`${type}: ${message}`) } function handleError(errorMessage, scriptURI, lineNumber, columnNumber, errorObj) { console.error(errorObj) alertOnce({errorMessage, scriptURI, lineNumber, columnNumber, errorObj}, 'error') } function handleRejection(event) { console.error(event) let {reason} = event if (reason && reason.ignore) { // 部分错误不要弹框,忽略 return } let msg = reason ? reason.message + (reason.stack || '') : '' if (msg) { return alertOnce(msg, 'rejection') } try { alertOnce('' + msg + JSON.stringify(event), 'rejection') } catch (e) { alertOnce('unknown event', 'rejection') } } let loadingCount = 0 function showLoading() { if (loadingCount === 0) { ivyStore.objects.Mint.Indicator.open({ text: '加载中...', }) } loadingCount ++ } async function hideLoading() { await utils.sleep(200) loadingCount -- if (loadingCount === 0) { ivyStore.objects.Mint.Indicator.close() } }