BaseAppServerRequestModule.ts 9.0 KB

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