import Config from './config.js' import Util from './util.js' import store from '@/store/index.js' import Platform from './platform.js' const { appType, appTypeName } = Platform.getPlatformInfo(); let _Lang = null; function getLang() { if (!_Lang) { _Lang = require('./lang.js').default; } return _Lang; } const DEFAULT_TIMEOUT = 15000; const DEFAULT_MAX_RETRIES = 2; const RETRY_DELAY_BASE = 2000; function _shouldRetry(errMsg) { if (!errMsg) return false; if (errMsg === 'request:fail url not in domain list') return false; if (errMsg === 'request:fail abort') return false; const retryableErrors = [ 'request:fail timeout', 'request:fail connect', 'request:fail network' ]; return retryableErrors.some(err => errMsg.startsWith(err)); } function _classifyError(errMsg, statusCode) { if (!errMsg && !statusCode) return 'unknown'; if (errMsg === 'request:fail abort') return 'aborted'; if (errMsg && errMsg.indexOf('timeout') !== -1) return 'timeout'; if (errMsg && (errMsg.indexOf('connect') !== -1 || errMsg.indexOf('network') !== -1)) return 'networkError'; if (statusCode && statusCode >= 500) return 'serverError'; if (errMsg && errMsg.indexOf('url not in domain list') !== -1) return 'domainNotInList'; return 'unknown'; } function _sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function _makeRequest(url, method, data, header, dataType, responseType, timeout) { return new Promise((resolve, reject) => { uni.request({ url: url, method: method, data: data, header: header, dataType: dataType, responseType: responseType, timeout: timeout, success: (res) => { if (res.statusCode && [200, 500].indexOf(res.statusCode) == -1) { reject({ errMsg: `request:fail statusCode=${res.statusCode}`, statusCode: res.statusCode }); return; } if (res.data.code == -3 && store.state.siteState > 0) { store.commit('setSiteState', -3); Util.redirectTo('/pages_tool/storeclose/storeclose', {}, 'reLaunch'); return; } if (res.data.refreshtoken) { store.commit('setToken', res.data.refreshtoken); } if (res.data.code == -10009 || res.data.code == -10010) { store.commit('setToken', ''); store.commit('setMemberInfo', ''); } resolve(res.data); }, fail: (res) => { reject(res); } }); }); } async function _requestWithRetry(params, url, method, data, header, dataType, responseType) { const timeout = params.timeout || DEFAULT_TIMEOUT; const maxRetries = params.noRetry ? 0 : (params.maxRetries || DEFAULT_MAX_RETRIES); let lastError = null; let lastStatusCode = null; for (let attempt = 0; attempt <= maxRetries; attempt++) { try { const result = await _makeRequest(url, method, data, header, dataType, responseType, timeout); return result; } catch (err) { lastError = err; lastStatusCode = err && err.statusCode; if (attempt >= maxRetries || !_shouldRetry(err.errMsg)) { break; } const delay = RETRY_DELAY_BASE * Math.pow(2, attempt); await _sleep(delay); } } if (params.silentError) { throw lastError; } const errorType = _classifyError(lastError && lastError.errMsg, lastStatusCode); const lang = getLang(); if (errorType === 'domainNotInList') { uni.showToast({ title: lang.lang('http.domainNotInList', { url: Config.baseUrl }), 'icon': 'none', duration: 10000 }); } else { const i18nKey = 'http.' + errorType; uni.showToast({ title: lang.lang(i18nKey), 'icon': 'none', duration: 10000 }); } throw lastError; } export default { sendRequest(params) { if (!Config.baseUrl) { uni.showToast({ title: getLang().lang('http.baseUrlNotConfigured'), 'icon': 'none', duration: 10000 }); return; } const _isRemoteOnly = getLang().isRemoteOnly && getLang().isRemoteOnly(); const _bootDone = getLang().isBootCompleted && getLang().isBootCompleted(); if (_isRemoteOnly && !_bootDone) { let bootPromise = null; try { const app = getApp(); if (app && app.$langReady) bootPromise = app.$langReady; } catch (e) {} if (!bootPromise) bootPromise = getLang().boot(); if (params.async === false) { return bootPromise.then(() => this._sendRequestNow(params)); } else { bootPromise.then(() => this._sendRequestNow(params)); return; } } return this._sendRequestNow(params); }, _sendRequestNow(params) { var method = params.data != undefined ? 'POST' : 'GET', url = (Config.baseUrl + params.url).replace(/(? { typeof params.complete == 'function' && params.complete(res); return res; }) .catch(err => { typeof params.complete == 'function' && params.complete(); throw err; }); } else { _requestWithRetry(params, url, method, data, header, dataType, responseType) .then(res => { typeof params.success == 'function' && params.success(res); typeof params.complete == 'function' && params.complete(res); }) .catch(err => { typeof params.fail == 'function' && params.fail(err); typeof params.complete == 'function' && params.complete(); }); } }, uploadBase64(params) { uni.request({ url: Config.baseUrl + '/api/upload/headimgBase64', method: 'POST', header: { 'content-type': 'application/x-www-form-urlencoded;application/json' }, data: { app_type: appType, app_type_name: appTypeName, images: params.base64 }, dataType: 'json', responseType: 'text', success: res => { typeof params.success == 'function' && params.success(res.data); }, fail: () => { typeof params.fail == 'function' && params.fail(res); } }); }, pullImage(params) { uni.request({ url: Config.baseUrl + '/api/upload/headimgPull', method: 'POST', header: { 'content-type': 'application/x-www-form-urlencoded;application/json' }, data: { app_type: appType, app_type_name: appTypeName, path: params.path }, dataType: 'json', responseType: 'text', success: res => { typeof params.success == 'function' && params.success(res.data); }, fail: () => { typeof params.fail == 'function' && params.fail(res); } }); }, upload(params) { uni.uploadFile({ url: Config.baseUrl + params.url, filePath: params.filePath, name: params.name || 'file', fileType: params.fileType || 'image', formData: { app_type: appType, app_type_name: appTypeName, }, header: { 'content-type': 'application/x-www-form-urlencoded;application/json' }, success: (res) => { typeof params.success == 'function' && params.success(JSON.parse(res.data)); }, fail: (res) => { typeof params.fail == 'function' && params.fail(res); } }); } }