index.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /**
  2. * request插件地址:https://ext.dcloud.net.cn/plugin?id=822
  3. */
  4. import store from '@/store'
  5. import { hasOwnProperty, isEmptyObject, filterNull } from '@/utils/util'
  6. import request from './request'
  7. import Config from '@/core/config'
  8. // 后端api地址
  9. const apiUrl = Config.get('apiUrl')
  10. // 可以new多个request来支持多个域名请求
  11. const $http = new request({
  12. // 接口请求地址
  13. baseUrl: apiUrl,
  14. // 服务器本地上传文件地址
  15. fileUrl: apiUrl,
  16. // 服务器上传图片默认url
  17. defaultUploadUrl: 'upload/image',
  18. // 设置请求头(如果使用报错跨域问题,可能是content-type请求类型和后台那边设置的不一致)
  19. header: {
  20. 'Content-Type': 'application/json;charset=utf-8'
  21. },
  22. // 请求超时时间, 单位ms(默认15000)
  23. timeout: 15000,
  24. // 默认配置(可不写)
  25. config: {
  26. // 是否自动提示错误
  27. isPrompt: true,
  28. // 是否显示加载动画
  29. load: true,
  30. // 是否使用数据工厂
  31. isFactory: true
  32. }
  33. })
  34. // 当前接口请求数
  35. let requestNum = 0
  36. // 请求开始拦截器
  37. $http.requestStart = options => {
  38. if (options.load) {
  39. if (requestNum <= 0) {
  40. // 打开加载动画
  41. uni.showLoading({
  42. title: '加载中',
  43. mask: true
  44. })
  45. }
  46. requestNum += 1
  47. }
  48. // 图片上传大小限制
  49. if (options.method == "FILE" && options.maxSize) {
  50. // 文件最大字节: options.maxSize 可以在调用方法的时候加入参数
  51. const maxSize = options.maxSize
  52. for (let item of options.files) {
  53. if (item.size > maxSize) {
  54. setTimeout(() => {
  55. uni.showToast({
  56. title: "图片过大,请重新上传",
  57. icon: "none"
  58. })
  59. }, 10)
  60. return false
  61. }
  62. }
  63. }
  64. // 请求前加入当前终端
  65. options.header['platform'] = store.getters.platform
  66. // 请求前加入Token
  67. options.header['Access-Token'] = store.getters.token
  68. // 请求前加入domain (仅H5端)
  69. // #ifdef H5
  70. options.header['domain'] = window.location.hostname
  71. // #endif
  72. // 剔除data中为null的属性 (解决传参字符串'null'的问题)
  73. if (hasOwnProperty(options, 'data') && !isEmptyObject(options.data)) {
  74. options.data = filterNull(options.data)
  75. }
  76. // return false 表示请求拦截,不会继续请求
  77. return options
  78. }
  79. // 请求结束
  80. $http.requestEnd = options => {
  81. // 判断当前接口是否需要加载动画
  82. if (options.load) {
  83. requestNum = requestNum - 1
  84. if (requestNum <= 0) {
  85. uni.hideLoading()
  86. }
  87. }
  88. }
  89. // 当前是否显示modal
  90. let loginModal = false
  91. // 所有接口数据处理(可在接口里设置不调用此方法)
  92. // 此方法需要开发者根据各自的接口返回类型修改,以下只是模板
  93. $http.dataFactory = async res => {
  94. // console.log("接口请求数据", {
  95. // url: res.url,
  96. // resolve: res.response,
  97. // header: res.header,
  98. // data: res.data,
  99. // method: res.method,
  100. // })
  101. if (!res.response.statusCode || res.response.statusCode != 200) {
  102. // 返回错误的结果(catch接受数据)
  103. return Promise.reject({
  104. statusCode: res.response.statusCode,
  105. errMsg: 'http状态码错误'
  106. })
  107. }
  108. let httpData = res.response.data
  109. if (typeof httpData == "string") {
  110. try {
  111. httpData = JSON.parse(httpData)
  112. } catch (error) {
  113. httpData = false
  114. }
  115. }
  116. if (httpData === false || typeof httpData !== 'object') {
  117. // 返回错误的结果(catch接受数据)
  118. return Promise.reject({
  119. statusCode: res.response.statusCode,
  120. errMsg: "请检查api地址能否访问正常"
  121. })
  122. }
  123. /*********以下只是模板(及共参考),需要开发者根据各自的接口返回类型修改*********/
  124. // 判断数据是否请求成功
  125. // result.status [ 200正常 500有错误 401未登录 403没有权限访问 ]
  126. if (httpData.status == 200) {
  127. // 返回正确的结果(then接受数据)
  128. return Promise.resolve(httpData)
  129. }
  130. // 判断是否需要登录
  131. if (httpData.status == 401) {
  132. // 401也有可能是后端登录态到期, 所以要清空本地的登录状态
  133. store.dispatch('Logout')
  134. // 防止重复弹窗
  135. if (!loginModal) {
  136. loginModal = true
  137. // 弹窗告诉用户去登录
  138. uni.showModal({
  139. title: '温馨提示',
  140. content: '此时此刻需要您登录喔~',
  141. // showCancel: false,
  142. confirmText: "去登录",
  143. cancelText: "再逛会",
  144. success: res => {
  145. if (res.confirm) {
  146. uni.navigateTo({
  147. url: "/pages/login/index"
  148. })
  149. }
  150. if (res.cancel && getCurrentPages().length > 1) {
  151. uni.navigateBack()
  152. }
  153. loginModal = false
  154. }
  155. })
  156. }
  157. // 返回错误的结果(catch接受数据)
  158. return Promise.reject({
  159. statusCode: 0,
  160. errMsg: httpData.message,
  161. result: httpData
  162. })
  163. }
  164. // 其他错误提示
  165. if (httpData.status == 500) {
  166. if (res.isPrompt && httpData.data.isPrompt) {
  167. setTimeout(() => {
  168. uni.showToast({
  169. title: httpData.message,
  170. icon: "none",
  171. duration: 2500
  172. })
  173. }, 10)
  174. }
  175. // 返回错误的结果(catch接受数据)
  176. return Promise.reject({
  177. statusCode: 0,
  178. errMsg: httpData.message,
  179. result: httpData
  180. })
  181. }
  182. /*********以上只是模板(及共参考),需要开发者根据各自的接口返回类型修改*********/
  183. }
  184. // 错误回调
  185. $http.requestError = e => {
  186. if (e.statusCode === 0) {
  187. throw e
  188. } else {
  189. setTimeout(() => showRequestError(e), 10)
  190. }
  191. }
  192. // 显示请求错误信息
  193. const showRequestError = (e) => {
  194. let errMsg = `网络请求出错:${e.errMsg}`
  195. // #ifdef MP-WEIXIN
  196. if (e.errMsg === 'request:fail url not in domain list') {
  197. errMsg = '当前API域名未添加到微信小程序授权名单 ' + e.errMsg
  198. }
  199. // #endif
  200. if (e.errMsg === 'request:fail') {
  201. errMsg = '网络请求错误:请检查api地址能否访问正常'
  202. }
  203. uni.showToast({
  204. title: errMsg,
  205. icon: "none",
  206. duration: 3500
  207. })
  208. }
  209. export default $http