/** * Used to configure the global error handling function, which can monitor vue errors, script errors, static resource errors and Promise errors */ import type { ErrorLogInfo } from '/#/store'; import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog'; import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; import { App } from 'vue'; import projectSetting from '/@/settings/projectSetting'; /** * Handling error stack information * @param error */ function processStackMsg(error: Error) { if (!error.stack) { return ''; } let stack = error.stack .replace(/\n/gi, '') // Remove line breaks to save the size of the transmitted content .replace(/\bat\b/gi, '@') // At in chrome, @ in ff .split('@') // Split information with @ .slice(0, 9) // The maximum stack length (Error.stackTraceLimit = 10), so only take the first 10 .map((v) => v.replace(/^\s*|\s*$/g, '')) // Remove extra spaces .join('~') // Manually add separators for later display .replace(/\?[^:]+/gi, ''); // Remove redundant parameters of js file links (?x=1 and the like) const msg = error.toString(); if (stack.indexOf(msg) < 0) { stack = msg + '@' + stack; } return stack; } /** * get comp name * @param vm */ function formatComponentName(vm: any) { if (vm.$root === vm) { return { name: 'root', path: 'root', }; } const options = vm.$options as any; if (!options) { return { name: 'anonymous', path: 'anonymous', }; } const name = options.name || options._componentTag; return { name: name, path: options.__file, }; } /** * Configure Vue error handling function */ function vueErrorHandler(err: Error, vm: any, info: string) { const errorLogStore = useErrorLogStoreWithOut(); const { name, path } = formatComponentName(vm); errorLogStore.addErrorLogInfo({ type: ErrorTypeEnum.VUE, name, file: path, message: err.message, stack: processStackMsg(err), detail: info, url: window.location.href, }); } /** * Configure script error handling function */ export function scriptErrorHandler(event: Event | string, source?: string, lineno?: number, colno?: number, error?: Error) { if (event === 'Script error.' && !source) { return false; } const errorInfo: Partial = {}; colno = colno || (window.event && (window.event as any).errorCharacter) || 0; errorInfo.message = event as string; if (error?.stack) { errorInfo.stack = error.stack; } else { errorInfo.stack = ''; } const name = source ? source.substr(source.lastIndexOf('/') + 1) : 'script'; const errorLogStore = useErrorLogStoreWithOut(); errorLogStore.addErrorLogInfo({ type: ErrorTypeEnum.SCRIPT, name: name, file: source as string, detail: 'lineno' + lineno, url: window.location.href, ...(errorInfo as Pick), }); return true; } /** * Configure Promise error handling function */ function registerPromiseErrorHandler() { window.addEventListener( 'unhandledrejection', function (event) { const errorLogStore = useErrorLogStoreWithOut(); errorLogStore.addErrorLogInfo({ type: ErrorTypeEnum.PROMISE, name: 'Promise Error!', file: 'none', detail: 'promise error!', url: window.location.href, stack: 'promise error!', message: event.reason, }); }, true ); } /** * Configure monitoring resource loading error handling function */ function registerResourceErrorHandler() { // Monitoring resource loading error(img,script,css,and jsonp) window.addEventListener( 'error', function (e: Event) { const target = e.target ? e.target : (e.srcElement as any); const errorLogStore = useErrorLogStoreWithOut(); errorLogStore.addErrorLogInfo({ type: ErrorTypeEnum.RESOURCE, name: 'Resource Error!', file: (e.target || ({} as any)).currentSrc, detail: JSON.stringify({ tagName: target.localName, html: target.outerHTML, type: e.type, }), url: window.location.href, stack: 'resource is not found', message: (e.target || ({} as any)).localName + ' is load error', }); }, true ); } /** * Configure global error handling * @param app */ export function setupErrorHandle(app: App) { const { useErrorHandle } = projectSetting; if (!useErrorHandle) { return; } // Vue exception monitoring; app.config.errorHandler = vueErrorHandler; // script error window.onerror = scriptErrorHandler; // promise exception registerPromiseErrorHandler(); // Static resource exception registerResourceErrorHandler(); }