request.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. import Vue from 'vue';
  2. import { popAll } from './formId.js';
  3. import apiUrl from './apiUrl.js';
  4. import siteInfo from 'siteInfo';
  5. const request = async function (args) {
  6. const header = {
  7. // #ifndef H5
  8. 'X-App-Platform': (args.header && args.header['X-App-Platform']) ? args.header['X-App-Platform'] : Vue.prototype.$platform,
  9. // #endif
  10. 'X-Form-Id-List': JSON.stringify(popAll()),
  11. 'X-Requested-With': (args.header && args.header['X-Requested-With']) ? args.header['X-Requested-With'] : 'XMLHttpRequest',
  12. 'X-App-Version': Vue.prototype.$appVersion,
  13. 'content-type': args.header && args.header.contentType ? args.header['content-type'] : 'application/x-www-form-urlencoded',
  14. // #ifdef MP-TOUTIAO
  15. 'X-tt-platform': Vue.prototype.$store.state.gConfig.systemInfo.appName,
  16. // #endif
  17. };
  18. await Vue.prototype.$store.dispatch('user/loadAccessTokenFormCache');
  19. if (Vue.prototype.$store.state.user && Vue.prototype.$store.state.user.accessToken) {
  20. header['X-Access-Token'] = Vue.prototype.$store.state.user.accessToken;
  21. }
  22. if (Vue.prototype.$store.state.user && Vue.prototype.$store.state.user.tempParentId !== 0) {
  23. header['X-User-Id'] = Vue.prototype.$store.state.user.tempParentId + '';
  24. }
  25. //多商户Token
  26. let obj = {};
  27. args.url.replace(/([^=&]+)=([^&]*)/g, function (m, key, value) {
  28. obj[decodeURIComponent(key)] = decodeURIComponent(value);
  29. });
  30. if (Vue.prototype.$utils.objectValues(apiUrl.mch).indexOf(obj.r) !== -1) {
  31. const mch_storage = Vue.prototype.$storage.getStorageSync('MCH2019');
  32. header['Mch-Access-Token'] = mch_storage.token;
  33. }
  34. // #ifdef H5
  35. let platform_storage = Vue.prototype.$storage.getStorageSync('platform');
  36. platform_storage = platform_storage === 'wxapp_wechat' ? 'wechat' : platform_storage;
  37. header['X-App-Platform'] = (args.header && args.header['X-App-Platform']) ? args.header['X-App-Platform'] : `${siteInfo.platform}`;
  38. // #endif
  39. const [error, response] = await uni.request({
  40. url: args.url,
  41. method: args.method || 'get',
  42. data: args.data,
  43. header: header
  44. });
  45. if (error) {
  46. let msg = {
  47. code: 400,
  48. msg: error.errMsg,
  49. data: error,
  50. };
  51. alertError(msg);
  52. return Promise.reject(msg);
  53. } else {
  54. return distinguishStatusCode(response);
  55. }
  56. };
  57. // #ifndef MP-ALIPAY
  58. const reloadPage = function () {
  59. let pages = getCurrentPages();
  60. let page = pages[pages.length - 1];
  61. let options = page.options || {};
  62. let route = page.route || '';
  63. if (route.indexOf('/') !== 0) {
  64. route = '/' + route;
  65. }
  66. let query = '';
  67. for (let k in options) {
  68. query = query + `${k}=${options[k]}&`;
  69. }
  70. uni.redirectTo({
  71. url: route + (query ? `?${query}` : ``),
  72. });
  73. };
  74. // #endif
  75. const alertError = function (error) {
  76. let confirmText = '刷新页面';
  77. // #ifdef MP-ALIPAY
  78. confirmText = '确认';
  79. // #endif
  80. uni.showModal({
  81. title: '网络错误',
  82. content: '网络开了小差,请刷新重试下哦~',
  83. cancelText: '复制错误',
  84. confirmText: confirmText,
  85. success: (e) => {
  86. if (e.cancel) {
  87. let data = `code: ${error.code}, \r\nmsg: ${error.msg}, \r\ndetail: `
  88. + (error.data ? (typeof error.data === 'string' ? error.data : JSON.stringify(error.data)) : null);
  89. Vue.prototype.$utils.uniCopy({
  90. data: data
  91. });
  92. }
  93. if (e.confirm) {
  94. // #ifndef MP-ALIPAY
  95. reloadPage();
  96. // #endif
  97. }
  98. },
  99. });
  100. };
  101. const distinguishDataCode = function (response) {
  102. if (response.data) {
  103. let {msg, code} = response.data;
  104. if (code >= 400) {
  105. alertError({
  106. code: code,
  107. msg: msg,
  108. data: response.data.error || (response.data.data || msg),
  109. });
  110. return Promise.reject(msg);
  111. } else if (code === 2) {
  112. // #ifdef H5
  113. if (Vue.prototype.$jwx.isWechat()) {
  114. Vue.prototype.$store.dispatch('user/showAttention', true);
  115. }
  116. // #endif
  117. return Promise.reject(msg);
  118. } else if (code === -1) {
  119. Vue.prototype.$store.dispatch('user/logout');
  120. Vue.prototype.$store.dispatch('user/accessToken');
  121. return Promise.reject(msg);
  122. } else if (code === -2) {
  123. uni.redirectTo({
  124. url: '/pages/disabled/disabled?text=' + response.data.data.text
  125. });
  126. } else if (code === -3) {
  127. uni.redirectTo({
  128. url: '/plugins/mch/mch/login/login'
  129. });
  130. return Promise.reject(msg);
  131. } else {
  132. return Promise.resolve(response.data);
  133. }
  134. } else {
  135. return Promise.reject({
  136. code: 200,
  137. msg: '数据不存在',
  138. data: response,
  139. });
  140. }
  141. };
  142. const distinguishStatusCode = function (response) {
  143. let msg = {
  144. code: 500,
  145. msg: '服务器内部错误',
  146. data: response,
  147. };
  148. switch (response.statusCode) {
  149. case 200:
  150. return distinguishDataCode(response);
  151. case 404:
  152. msg = {
  153. code: 404,
  154. msg: '资源获取不到',
  155. data: response,
  156. };
  157. break;
  158. case 500:
  159. msg = {
  160. code: 500,
  161. msg: '服务器内部错误',
  162. data: response,
  163. };
  164. break;
  165. case 503:
  166. msg = {
  167. code: 503,
  168. msg: '服务不可用',
  169. data: response,
  170. };
  171. break;
  172. case 504:
  173. msg = {
  174. code: 504,
  175. msg: '网关超时',
  176. data: response,
  177. };
  178. break;
  179. case 400:
  180. msg = {
  181. code: 400,
  182. msg: '服务器不理解请求的语法',
  183. data: response,
  184. };
  185. break;
  186. case 403:
  187. msg = {
  188. code: 403,
  189. msg: '服务器拒绝请求',
  190. data: response,
  191. };
  192. break;
  193. case 405:
  194. msg = {
  195. code: 405,
  196. msg: '方法禁用',
  197. data: response,
  198. };
  199. break;
  200. case 406:
  201. msg = {
  202. code: 406,
  203. msg: '无法使用请求的内容特性响应请求的网页',
  204. data: response,
  205. };
  206. break;
  207. case 407:
  208. msg = {
  209. code: 407,
  210. msg: '需要代理授权',
  211. data: response,
  212. };
  213. break;
  214. case 408:
  215. msg = {
  216. code: 408,
  217. msg: '请求超时',
  218. data: response,
  219. };
  220. break;
  221. case 409:
  222. msg = {
  223. code: 409,
  224. msg: '冲突',
  225. data: response,
  226. };
  227. break;
  228. case 410:
  229. msg = {
  230. code: 410,
  231. msg: '已删除',
  232. data: response,
  233. };
  234. break;
  235. case 411:
  236. msg = {
  237. code: 411,
  238. msg: '需要有效长度',
  239. data: response,
  240. };
  241. break;
  242. case 412:
  243. msg = {
  244. code: 412,
  245. msg: '服务器未满足请求者在请求中设置的其中一个前提条件',
  246. data: response,
  247. };
  248. break;
  249. case 413:
  250. msg = {
  251. code: 413,
  252. msg: '请求实体过大',
  253. data: response,
  254. };
  255. break;
  256. case 414:
  257. msg = {
  258. code: 414,
  259. msg: '求情URI过长',
  260. data: response,
  261. };
  262. break;
  263. case 415:
  264. msg = {
  265. code: 415,
  266. msg: '不支持的媒体类型',
  267. data: response,
  268. };
  269. break;
  270. case 416:
  271. msg = {
  272. code: 416,
  273. msg: '请求范围不符合要求',
  274. data: response,
  275. };
  276. break;
  277. case 417:
  278. msg = {
  279. code: 417,
  280. msg: '未满足期望值',
  281. data: response,
  282. };
  283. break;
  284. default:
  285. break;
  286. }
  287. alertError(msg);
  288. return Promise.reject(msg);
  289. };
  290. export default request;
  291. //
  292. //
  293. // class Request {
  294. // // 设置全局默认配置
  295. // setConfig(customConfig) {
  296. // // 深度合并对象,否则会造成对象深层属性丢失
  297. // this.config = deepMerge(this.config, customConfig);
  298. // }
  299. //
  300. // request(options = {}) {
  301. // // 检查请求拦截
  302. // if (this.interceptor.request && typeof this.interceptor.request === 'function') {
  303. // let tmpConfig = {};
  304. // let interceptorRequest = this.interceptor.request(options);
  305. // if (interceptorRequest === false) {
  306. // // 返回一个处于pending状态中的Promise,来取消原promise,避免进入then()回调
  307. // return new Promise(()=>{});
  308. // }
  309. // this.options = interceptorRequest;
  310. // }
  311. // options.dataType = options.dataType || this.config.dataType;
  312. // options.responseType = options.responseType || this.config.responseType;
  313. // options.url = options.url || '';
  314. // options.params = options.params || {};
  315. // options.header = Object.assign(this.config.header, options.header);
  316. // options.method = options.method || this.config.method;
  317. //
  318. // return new Promise((resolve, reject) => {
  319. // options.complete = (response) => {
  320. // // 请求返回后,隐藏loading(如果请求返回快的话,可能会没有loading)
  321. // uni.hideLoading();
  322. // // 清除定时器,如果请求回来了,就无需loading
  323. // clearTimeout(this.config.timer);
  324. // this.config.timer = null;
  325. // if (this.config.originalData) {
  326. // // 判断是否存在拦截器
  327. // if (this.interceptor.response && typeof this.interceptor.response === 'function') {
  328. // let resInterceptors = this.interceptor.response(response);
  329. // // 如果拦截器不返回false,就将拦截器返回的内容给this.$u.post的then回调
  330. // if (resInterceptors !== false) {
  331. // resolve(resInterceptors);
  332. // } else {
  333. // // 如果拦截器返回false,意味着拦截器定义者认为返回有问题,直接接入catch回调
  334. // reject(response);
  335. // }
  336. // } else {
  337. // // 如果要求返回原始数据,就算没有拦截器,也返回最原始的数据
  338. // resolve(response);
  339. // }
  340. // } else {
  341. // if (response.statusCode === 200) {
  342. // if (this.interceptor.response && typeof this.interceptor.response === 'function') {
  343. // let resInterceptors = this.interceptor.response(response.data);
  344. // if (resInterceptors !== false) {
  345. // resolve(resInterceptors);
  346. // } else {
  347. // reject(response.data);
  348. // }
  349. // } else {
  350. // // 如果不是返回原始数据(originalData=false),且没有拦截器的情况下,返回纯数据给then回调
  351. // resolve(response.data);
  352. // }
  353. // } else {
  354. // // 不返回原始数据的情况下,服务器状态码不为200,modal弹框提示
  355. // if(response.errMsg) {
  356. // uni.showModal({
  357. // title: response.errMsg
  358. // });
  359. // }
  360. // reject(response)
  361. // }
  362. // }
  363. // }
  364. //
  365. // // 判断用户传递的URL是否/开头,如果不是,加上/,这里使用了uView的test.js验证库的url()方法
  366. // options.url = Vue.prototype.$validation.url(options.url) ? options.url : (this.config.baseUrl + (options.url.indexOf('/') === 0 ?
  367. // options.url : '/' + options.url));
  368. // // 是否显示loading
  369. // // 加一个是否已有timer定时器的判断,否则有两个同时请求的时候,后者会清除前者的定时器id
  370. // // 而没有清除前者的定时器,导致前者超时,一直显示loading
  371. // if(this.config.showLoading && !this.config.timer) {
  372. // this.config.timer = setTimeout(() => {
  373. // uni.showLoading({
  374. // title: this.config.loadingText,
  375. // mask: this.config.loadingMask
  376. // })
  377. // this.config.timer = null;
  378. // }, this.config.loadingTime);
  379. // }
  380. // uni.request(options);
  381. // })
  382. // }
  383. //
  384. // constructor() {
  385. // this.config = {
  386. // baseUrl: '', // 请求的根域名
  387. // // 默认的请求头
  388. // header: {
  389. // 'X-App-Platform': Vue.prototype.$platform,
  390. // 'X-Form-Id-List': JSON.stringify(popAll()),
  391. // 'X-Requested-With': 'XMLHttpRequest',
  392. // 'X-App-Version': Vue.prototype.$appVersion,
  393. // 'content-type': 'application/x-www-form-urlencoded'
  394. // },
  395. // method: 'POST',
  396. // // 设置为json,返回后uni.request会对数据进行一次JSON.parse
  397. // dataType: 'json',
  398. // // 此参数无需处理,因为5+和支付宝小程序不支持,默认为text即可
  399. // responseType: 'text',
  400. // showLoading: true, // 是否显示请求中的loading
  401. // loadingText: '请求中...',
  402. // loadingTime: 800, // 在此时间内,请求还没回来的话,就显示加载中动画,单位ms
  403. // timer: null, // 定时器
  404. // originalData: false, // 是否在拦截器中返回服务端的原始数据,见文档说明
  405. // loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
  406. // }
  407. //
  408. // // 拦截器
  409. // this.interceptor = {
  410. // // 请求前的拦截
  411. // request: function(config) {
  412. // // //多商户Token
  413. // // let obj = {};
  414. // // config.url.replace(/([^=&]+)=([^&]*)/g, function (m, key, value) {
  415. // // obj[decodeURIComponent(key)] = decodeURIComponent(value);
  416. // // });
  417. // // if (Vue.prototype.$utils.objectValues(apiUrl.mch).indexOf(obj.r) !== -1) {
  418. // // const mch_storage = uni.getStorageSync('MCH2019');
  419. // // config.header['Mch-Access-Token'] = mch_storage.token;
  420. // // }
  421. // return config;
  422. // },
  423. // // 请求后的拦截
  424. // response: null
  425. // }
  426. //
  427. // }
  428. // }
  429. //
  430. // export {
  431. // Request
  432. // }