request.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. import env from '../config/env.js'
  2. // Loading 管理器
  3. const loadingManager = {
  4. loadingCount: 0,
  5. loadingTimer: null,
  6. // 显示 loading
  7. show(options = {}) {
  8. const config = {
  9. title: '加载中...',
  10. mask: true,
  11. delay: 300,
  12. ...options
  13. }
  14. // 如果已经有 loading 在显示,只增加计数
  15. if (this.loadingCount > 0) {
  16. this.loadingCount++
  17. return
  18. }
  19. // 延迟显示,避免快速请求造成闪烁
  20. this.loadingTimer = setTimeout(() => {
  21. if (this.loadingCount > 0) {
  22. uni.showLoading({
  23. title: config.title,
  24. mask: config.mask
  25. })
  26. }
  27. }, config.delay)
  28. this.loadingCount++
  29. },
  30. // 隐藏 loading
  31. hide() {
  32. this.loadingCount = Math.max(0, this.loadingCount - 1)
  33. if (this.loadingCount === 0) {
  34. // 清除延迟显示的定时器
  35. if (this.loadingTimer) {
  36. clearTimeout(this.loadingTimer)
  37. this.loadingTimer = null
  38. }
  39. // 隐藏 loading
  40. uni.hideLoading()
  41. }
  42. },
  43. // 强制隐藏所有 loading
  44. forceHide() {
  45. this.loadingCount = 0
  46. if (this.loadingTimer) {
  47. clearTimeout(this.loadingTimer)
  48. this.loadingTimer = null
  49. }
  50. uni.hideLoading()
  51. }
  52. }
  53. const request = {
  54. async get(url, params = {}, options = {}) {
  55. return this.request(url, 'GET', params, options)
  56. },
  57. async post(url, data = {}, options = {}) {
  58. return this.request(url, 'POST', data, options)
  59. },
  60. async put(url, data = {}, options = {}) {
  61. return this.request(url, 'PUT', data, options)
  62. },
  63. async delete(url, data = {}, options = {}) {
  64. return this.request(url, 'DELETE', data, options)
  65. },
  66. async request(url, method, data, options = {}) {
  67. // 解析 loading 配置
  68. let loadingConfig
  69. if (options.loading === false) {
  70. // 如果明确设置为 false,则不显示 loading
  71. loadingConfig = false
  72. } else {
  73. // 否则使用默认配置并合并用户配置
  74. loadingConfig = {
  75. show: true,
  76. title: '加载中...',
  77. mask: true,
  78. delay: 300,
  79. timeout: 10000,
  80. ...(typeof options.loading === 'object' ? options.loading : {})
  81. }
  82. }
  83. // 解析请求配置
  84. const requestConfig = {
  85. timeout: 15000, // 默认网络超时 15 秒
  86. ...options.request
  87. }
  88. // 如果 loading 配置为 false,则不显示 loading
  89. const shouldShowLoading = loadingConfig !== false && loadingConfig.show !== false
  90. // 显示 loading
  91. if (shouldShowLoading) {
  92. loadingManager.show(loadingConfig)
  93. }
  94. // 获取设备信息
  95. const deviceInfo = uni.getStorageSync("deviceInfo") || {};
  96. const sbbs = deviceInfo.deviceId || '';
  97. const sbmc = deviceInfo.model || '';
  98. // 处理URL,添加设备参数
  99. const separator = url.includes('?') ? '&' : '?';
  100. const finalUrl = `${url}${separator}sbbs=${sbbs}&sbmc=${sbmc}`;
  101. // 超时处理
  102. let timeoutTimer = null
  103. if (shouldShowLoading && loadingConfig.timeout) {
  104. timeoutTimer = setTimeout(() => {
  105. loadingManager.hide()
  106. uni.showToast({
  107. title: '请求超时',
  108. icon: 'none'
  109. })
  110. }, loadingConfig.timeout)
  111. }
  112. // 数据格式转换
  113. let requestData = data;
  114. if (options.formData && data && typeof data === 'object') {
  115. // 转换为表单格式
  116. requestData = Object.keys(data).map(key => {
  117. const value = data[key];
  118. if (Array.isArray(value)) {
  119. // 数组数据转换为多个同名参数
  120. return value.map(item => `${encodeURIComponent(key)}=${encodeURIComponent(item)}`).join('&');
  121. } else {
  122. return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
  123. }
  124. }).join('&');
  125. }
  126. return new Promise((resolve, reject) => {
  127. uni.request({
  128. url: `${env.baseUrl}${finalUrl}`,
  129. method,
  130. data: requestData,
  131. timeout: requestConfig.timeout, // 设置网络超时
  132. header: (() => {
  133. const headers = {};
  134. // 根据选项决定Content-Type
  135. if (options.formData) {
  136. // 使用表单格式,让浏览器自动设置Content-Type
  137. headers['content-type'] = 'application/x-www-form-urlencoded';
  138. } else {
  139. // 默认使用JSON格式
  140. headers['content-type'] = 'application/json';
  141. }
  142. const jsessionId = uni.getStorageSync('JSESSIONID');
  143. if (jsessionId) {
  144. headers['Cookie'] = `JSESSIONID=${jsessionId}`;
  145. }
  146. return headers;
  147. })(),
  148. success: (res) => {
  149. // 清除超时定时器
  150. if (timeoutTimer) {
  151. clearTimeout(timeoutTimer)
  152. }
  153. // 获取响应头
  154. const headers = res.header;
  155. // console.log('响应头:', headers);
  156. // 处理Set-Cookie,获取JSESSIONID
  157. const setCookie = headers['set-cookie'] || headers['Set-Cookie'];
  158. if (setCookie) {
  159. const match = setCookie.match(/JSESSIONID=([^;]+)/);
  160. if (match && match[1]) {
  161. // console.log('获取到新的JSESSIONID:', match[1]);
  162. uni.setStorageSync('JSESSIONID', match[1]);
  163. }
  164. }
  165. if (res.statusCode === 200) {
  166. // 将响应头信息附加到返回数据中
  167. const responseData = {
  168. data: res.data,
  169. };
  170. resolve(responseData);
  171. } else {
  172. reject(res);
  173. }
  174. },
  175. fail: (err) => {
  176. // 清除超时定时器
  177. if (timeoutTimer) {
  178. clearTimeout(timeoutTimer)
  179. }
  180. uni.showToast({
  181. title: '网络请求失败',
  182. icon: 'none'
  183. })
  184. reject(err)
  185. },
  186. complete: () => {
  187. // 隐藏 loading
  188. if (shouldShowLoading) {
  189. loadingManager.hide()
  190. }
  191. // console.log('请求完成');
  192. }
  193. })
  194. })
  195. }
  196. }
  197. // 添加一些便捷方法
  198. request.loadingManager = loadingManager
  199. // 静默请求(不显示 loading)
  200. request.silent = {
  201. get: (url, params = {}) => request.get(url, params, { loading: false }),
  202. post: (url, data = {}) => request.post(url, data, { loading: false }),
  203. put: (url, data = {}) => request.put(url, data, { loading: false }),
  204. delete: (url, data = {}) => request.delete(url, data, { loading: false })
  205. }
  206. // 带自定义 loading 文字的请求
  207. request.withLoading = (title) => ({
  208. get: (url, params = {}) => request.get(url, params, { loading: { title } }),
  209. post: (url, data = {}) => request.post(url, data, { loading: { title } }),
  210. put: (url, data = {}) => request.put(url, data, { loading: { title } }),
  211. delete: (url, data = {}) => request.delete(url, data, { loading: { title } })
  212. })
  213. export default request