index.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /**
  2. * Used to configure the global error handling function, which can monitor vue errors, script errors, static resource errors and Promise errors
  3. */
  4. import { errorStore, ErrorInfo } from '/@/store/modules/error';
  5. import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
  6. import { App } from 'vue';
  7. import projectSetting from '/@/settings/projectSetting';
  8. /**
  9. * Handling error stack information
  10. * @param error
  11. */
  12. function processStackMsg(error: Error) {
  13. if (!error.stack) {
  14. return '';
  15. }
  16. let stack = error.stack
  17. .replace(/\n/gi, '') // Remove line breaks to save the size of the transmitted content
  18. .replace(/\bat\b/gi, '@') // At in chrome, @ in ff
  19. .split('@') // Split information with @
  20. .slice(0, 9) // The maximum stack length (Error.stackTraceLimit = 10), so only take the first 10
  21. .map((v) => v.replace(/^\s*|\s*$/g, '')) // Remove extra spaces
  22. .join('~') // Manually add separators for later display
  23. .replace(/\?[^:]+/gi, ''); // Remove redundant parameters of js file links (?x=1 and the like)
  24. const msg = error.toString();
  25. if (stack.indexOf(msg) < 0) {
  26. stack = msg + '@' + stack;
  27. }
  28. return stack;
  29. }
  30. /**
  31. * get comp name
  32. * @param vm
  33. */
  34. function formatComponentName(vm: any) {
  35. if (vm.$root === vm) {
  36. return {
  37. name: 'root',
  38. path: 'root',
  39. };
  40. }
  41. const options = vm.$options as any;
  42. if (!options) {
  43. return {
  44. name: 'anonymous',
  45. path: 'anonymous',
  46. };
  47. }
  48. const name = options.name || options._componentTag;
  49. return {
  50. name: name,
  51. path: options.__file,
  52. };
  53. }
  54. /**
  55. * Configure Vue error handling function
  56. */
  57. function vueErrorHandler(err: Error, vm: any, info: string) {
  58. const { name, path } = formatComponentName(vm);
  59. errorStore.commitErrorInfoState({
  60. type: ErrorTypeEnum.VUE,
  61. name,
  62. file: path,
  63. message: err.message,
  64. stack: processStackMsg(err),
  65. detail: info,
  66. url: window.location.href,
  67. });
  68. }
  69. /**
  70. * Configure script error handling function
  71. */
  72. export function scriptErrorHandler(
  73. event: Event | string,
  74. source?: string,
  75. lineno?: number,
  76. colno?: number,
  77. error?: Error
  78. ) {
  79. if (event === 'Script error.' && !source) {
  80. return false;
  81. }
  82. const errorInfo: Partial<ErrorInfo> = {};
  83. colno = colno || (window.event && (window.event as any).errorCharacter) || 0;
  84. errorInfo.message = event as string;
  85. if (error?.stack) {
  86. errorInfo.stack = error.stack;
  87. } else {
  88. errorInfo.stack = '';
  89. }
  90. const name = source ? source.substr(source.lastIndexOf('/') + 1) : 'script';
  91. errorStore.commitErrorInfoState({
  92. type: ErrorTypeEnum.SCRIPT,
  93. name: name,
  94. file: source as string,
  95. detail: 'lineno' + lineno,
  96. url: window.location.href,
  97. ...(errorInfo as Pick<ErrorInfo, 'message' | 'stack'>),
  98. });
  99. return true;
  100. }
  101. /**
  102. * Configure Promise error handling function
  103. */
  104. function registerPromiseErrorHandler() {
  105. window.addEventListener(
  106. 'unhandledrejection',
  107. function (event: any) {
  108. errorStore.commitErrorInfoState({
  109. type: ErrorTypeEnum.PROMISE,
  110. name: 'Promise Error!',
  111. file: 'none',
  112. detail: 'promise error!',
  113. url: window.location.href,
  114. stack: 'promise error!',
  115. message: event.reason,
  116. });
  117. },
  118. true
  119. );
  120. }
  121. /**
  122. * Configure monitoring resource loading error handling function
  123. */
  124. function registerResourceErrorHandler() {
  125. // Monitoring resource loading error(img,script,css,and jsonp)
  126. window.addEventListener(
  127. 'error',
  128. function (e: Event) {
  129. const target = e.target ? e.target : (e.srcElement as any);
  130. errorStore.commitErrorInfoState({
  131. type: ErrorTypeEnum.RESOURCE,
  132. name: 'Resouce Error!',
  133. file: (e.target || ({} as any)).currentSrc,
  134. detail: JSON.stringify({
  135. tagName: target.localName,
  136. html: target.outerHTML,
  137. type: e.type,
  138. }),
  139. url: window.location.href,
  140. stack: 'resouce is not found',
  141. message: (e.target || ({} as any)).localName + ' is load error',
  142. });
  143. },
  144. true
  145. );
  146. }
  147. /**
  148. * Configure global error handling
  149. * @param app
  150. */
  151. export function setupErrorHandle(app: App) {
  152. const { useErrorHandle } = projectSetting;
  153. if (!useErrorHandle) return;
  154. // Vue exception monitoring;
  155. app.config.errorHandler = vueErrorHandler;
  156. // script error
  157. window.onerror = scriptErrorHandler;
  158. // promise exception
  159. registerPromiseErrorHandler();
  160. // Static resource exception
  161. registerResourceErrorHandler();
  162. }