BaseAppServerRequestModule.ts 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. import BugReporter from "@/common/BugReporter";
  2. import ApiCofig from "@/common/config/ApiCofig";
  3. import AppCofig, { isDev } from "@/common/config/AppCofig";
  4. import { RequestCoreInstance, RequestApiError, UniappImplementer, StringUtils, appendGetUrlParams, appendPostParams, RequestResponse, RequestOptions, type RequestApiInfoStruct, RequestApiResult, type RequestApiErrorType, defaultResponseDataGetErrorInfo, defaultResponseDataHandlerCatch } from "@imengyu/imengyu-utils";
  5. import type { DataModel, KeyValue, NewDataModel } from "@imengyu/js-request-transform";
  6. /**
  7. * 说明:业务相关的请求模块
  8. * * 请求数据处理函数。
  9. * * 自定义请求模块。
  10. * * 自定义错误报告处理函数。
  11. */
  12. function matchNotReportMessage(code: number, str: string) {
  13. if (ApiCofig.notReportErrorCode.includes(code))
  14. return true;
  15. for (let i = 0; i < ApiCofig.notReportMessages.length; i++) {
  16. if (ApiCofig.notReportMessages[i].test(str))
  17. return true;
  18. }
  19. return false;
  20. }
  21. //错误报告处理
  22. export function reportError<T extends DataModel>(instance: RequestCoreInstance<T>, response: RequestApiError | Error) {
  23. if (isDev) {
  24. //开发模式下直接弹窗显示
  25. if (response instanceof RequestApiError) {
  26. uni.showModal({
  27. title: `请求错误 ${response.apiName} : ${response.errorMessage}`,
  28. content: response.toString() +
  29. '\r\n请求接口:' + response.apiName +
  30. '\r\n请求地址:' + response.apiUrl +
  31. '\r\n请求参数:' + JSON.stringify(response.apiRawReq) +
  32. '\r\n返回参数:' + JSON.stringify(response.rawData) +
  33. '\r\n状态码:' + response.code +
  34. '\r\n信息:' + response.errorCodeMessage,
  35. type: 'error',
  36. showCancel: false,
  37. });
  38. } else {
  39. uni.showModal({
  40. title: '错误报告 代码错误',
  41. content: response?.stack || ('' + response),
  42. type: 'error',
  43. showCancel: false,
  44. });
  45. }
  46. } else {
  47. //生产模式下收集错误信息,报告错误服务器
  48. let errMsg = '';
  49. if (response instanceof RequestApiError) {
  50. BugReporter.reportRequestBug({
  51. errorType: response.errorType,
  52. errorMessage: response.errorMessage,
  53. apiName: response.apiName,
  54. apiUrl: response.apiUrl,
  55. rawRequest: response.apiRawReq,
  56. rawData: response.rawData,
  57. code: response.code.toString(),
  58. errorCodeMessage: response.errorCodeMessage,
  59. data: response.rawData,
  60. });
  61. } else {
  62. errMsg += '服务出现了异常,请稍后重试或联系客服。';
  63. errMsg += '版本:' + AppCofig.version;
  64. uni.showModal({
  65. title: '抱歉',
  66. content: errMsg,
  67. showCancel: false,
  68. });
  69. BugReporter.reportError(response);
  70. }
  71. }
  72. }
  73. export class BaseAppServerRequestModule<T extends DataModel> extends RequestCoreInstance<T> {
  74. constructor(baseUrl: string) {
  75. super(UniappImplementer);
  76. this.config.baseUrl = baseUrl;
  77. this.config.errCodes = [];
  78. //请求拦截器
  79. this.config.requestInterceptor = (url, req) => {
  80. //获取app中的token,追加到头;
  81. const app = getApp();
  82. if (StringUtils.isNullOrEmpty((req.headers as KeyValue).token as string)) {
  83. const t = app?.globalData?.token ?? '';
  84. req.headers['token'] = t
  85. req.headers['__token__'] = t;
  86. }
  87. const main_body_user_id = app?.globalData?.userId ?? '';
  88. const append_main_body_user_id = !(url.includes('content/content'));
  89. if (req.method == 'GET') {
  90. //追加GET参数
  91. url = appendGetUrlParams(url, 'main_body_id', ApiCofig.mainBodyId);
  92. //url = appendGetUrlParams(url, 'platform', ApiCofig.platformId);
  93. if (append_main_body_user_id)
  94. url = appendGetUrlParams(url, 'main_body_user_id', main_body_user_id);
  95. } else {
  96. req.data = appendPostParams(req.data,'main_body_id', ApiCofig.mainBodyId);
  97. //req.data = appendPostParams(req.data,'platform', ApiCofig.platformId);
  98. if (append_main_body_user_id)
  99. req.data = appendPostParams(req.data,'main_body_user_id', main_body_user_id);
  100. }
  101. return { newUrl: url, newReq: req };
  102. };
  103. //响应数据处理函数
  104. this.config.responseDataHandler = async function responseDataHandler<T extends DataModel>(response: RequestResponse, req: RequestOptions, resultModelClass: NewDataModel | undefined, instance: RequestCoreInstance<T>, apiInfo: RequestApiInfoStruct): Promise<RequestApiResult<T>> {
  105. const method = req.method || 'GET';
  106. try {
  107. const json = await response.json();
  108. if (response.ok) {
  109. if (!json) {
  110. throw new RequestApiError(
  111. 'businessError',
  112. '后端未返回数据',
  113. '',
  114. response.status,
  115. null,
  116. null,
  117. response.headers,
  118. apiInfo
  119. );
  120. }
  121. //code == 0 错误
  122. if (json.code === 0) {
  123. throw createError(json);
  124. }
  125. //处理后端的数据
  126. let message = '未知错误';
  127. let data = {} as any;
  128. //后端返回格式不统一,所以在这里处理格式
  129. if (typeof json.data === 'object') {
  130. data = json.data;
  131. message = json.data?.msg || response.statusText;
  132. }
  133. else {
  134. //否则返回上层对象
  135. data = json;
  136. message = json.msg || response.statusText;
  137. }
  138. return new RequestApiResult(
  139. resultModelClass ?? instance.config.modelClassCreator,
  140. json?.code || response.status,
  141. message,
  142. data,
  143. json,
  144. response.headers,
  145. apiInfo
  146. );
  147. }
  148. else {
  149. throw createError(json);
  150. }
  151. function createError(json: any): RequestApiError {
  152. let errType : RequestApiErrorType = 'unknow';
  153. let errString = '';
  154. let errCodeStr = '';
  155. let errData = json.data;
  156. if (typeof json.message === 'string')
  157. errString = json.message;
  158. if (typeof json.msg === 'string')
  159. errString += json.msg;
  160. if (StringUtils.isStringAllEnglish(errString))
  161. errString = '服务器返回:' + errString;
  162. //错误处理
  163. if (errString) {
  164. //如果后端有返回错误信息,则收集错误信息并返回
  165. errType = 'businessError';
  166. if (typeof json.data === 'object' && json.data?.errmsg) {
  167. errString += '\n' + json.data.errmsg;
  168. }
  169. if (typeof json.errors === 'object') {
  170. for (const key in json.errors) {
  171. if (Object.prototype.hasOwnProperty.call(json.errors, key)) {
  172. errString += '\n' + json.errors[key];
  173. }
  174. }
  175. }
  176. } else {
  177. const res = defaultResponseDataGetErrorInfo(response, json);
  178. errType = res.errType;
  179. errString = res.errString;
  180. errCodeStr = res.errCodeStr;
  181. }
  182. return new RequestApiError(
  183. errType,
  184. errString,
  185. errCodeStr,
  186. response.status,
  187. errData,
  188. json,
  189. response.headers,
  190. apiInfo
  191. );
  192. }
  193. } catch (err) {
  194. if (err instanceof RequestApiError) {
  195. throw err;
  196. }
  197. //错误统一处理
  198. return new Promise<RequestApiResult<T>>((resolve, reject) => {
  199. defaultResponseDataHandlerCatch(method, req, response, null, err as any, apiInfo, response.url, reject, instance);
  200. });
  201. }
  202. };
  203. //响应错误处理函数
  204. this.config.responseErrorHandler = (err: any, instance: RequestCoreInstance<T>, apiInfo: RequestApiInfoStruct) => {
  205. if (err instanceof RequestApiError) {
  206. return err;
  207. }
  208. function createNetworkError(errMsg: string): RequestApiError {
  209. return new RequestApiError(
  210. 'networkError',
  211. errMsg,
  212. '',
  213. 0,
  214. null,
  215. null,
  216. apiInfo.apiRawReq?.headers as any,
  217. apiInfo
  218. );
  219. }
  220. if (err.errMsg) {
  221. if (err.errMsg.includes('timeout'))
  222. return createNetworkError('网络请求超时,请稍后重试');
  223. if (err.errMsg.includes('fail'))
  224. return createNetworkError('网络连接失败,请检查网络设置');
  225. return createNetworkError(err.errMsg);
  226. }
  227. return new RequestApiError(
  228. 'scriptError',
  229. '服务器返回错误',
  230. '',
  231. 0,
  232. null,
  233. null,
  234. apiInfo.apiRawReq?.headers as any,
  235. apiInfo
  236. );
  237. };
  238. //错误报告处理
  239. this.config.responseErrorReportInterceptor = (instance, response) => {
  240. return (
  241. (response.errorType !== 'businessError' && response.errorType !== 'networkError') ||
  242. matchNotReportMessage(response.code, response.errorMessage) === true
  243. );
  244. };
  245. //错误报告处理函数
  246. this.config.reportError = reportError;
  247. }
  248. }