You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
8.5 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
var _window = typeof window !== 'undefined' ? window : {};
</script>
<!-- 早期错误捕获 - 在应用初始化之前就开始监听错误 -->
<script>
(function() {
'use strict';
// 错误上报接口
var ERROR_REPORT_API = 'https://tj-h5.hnxdfe.com/api/H5/test';
// 临时存储错误,等到应用初始化后统一上报
window.__ERROR_BUFFER__ = [];
// 判断是否应该忽略的错误
function shouldIgnoreError(error) {
// 忽略请求中止错误(页面跳转时常见)
if (error && error.errMsg === 'request:fail abort') {
return true;
}
if (error && error.message && error.message.includes('abort')) {
return true;
}
if (error && error.name === 'AbortError') {
return true;
}
return false;
}
// 发送错误到服务器
function sendError(errorInfo) {
try {
// 优先使用 sendBeacon即使页面关闭也能发送
if (navigator.sendBeacon) {
var data = JSON.stringify(errorInfo);
var blob = new Blob([data], { type: 'application/json' });
return navigator.sendBeacon(ERROR_REPORT_API, blob);
}
// 备用:使用 fetch
fetch(ERROR_REPORT_API, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(errorInfo),
keepalive: true
}).catch(function() {
// 静默失败
});
} catch (e) {
// 静默失败,避免二次错误
}
}
// 构建错误信息
function buildErrorInfo(error, type) {
var errorInfo = {
type: type || 'error',
message: '',
stack: '',
url: '',
ua: '',
timestamp: new Date().toISOString(),
phase: 'early', // 标记为早期错误
rawError: null // 保留原始错误对象(用于调试)
};
try {
errorInfo.url = window.location.href || '';
errorInfo.ua = navigator.userAgent || '';
// 如果是 Error 实例
if (error instanceof Error) {
errorInfo.message = error.message || String(error);
errorInfo.stack = error.stack || '';
}
// 如果是字符串
else if (typeof error === 'string') {
errorInfo.message = error;
}
// 如果是对象
else if (error && typeof error === 'object') {
try {
// 检查 message 是否是 "{}" 或空字符串
var msg = error.message || '';
if (msg === '{}' || msg === '' || msg === 'undefined' || msg === 'null') {
// 尝试从其他字段获取信息
if (error.reason) {
errorInfo.message = String(error.reason);
} else if (error.name) {
errorInfo.message = error.name;
} else if (error.toString && typeof error.toString === 'function') {
var str = error.toString();
if (str && str !== '[object Object]') {
errorInfo.message = str;
} else {
errorInfo.message = '未知错误对象(无有效信息)';
}
} else {
// 尝试序列化对象
var jsonStr = JSON.stringify(error);
if (jsonStr && jsonStr !== '{}') {
errorInfo.message = jsonStr;
} else {
errorInfo.message = '错误对象为空';
}
}
} else {
errorInfo.message = msg;
}
errorInfo.stack = error.stack || '';
// 如果没有 stack尝试构建堆栈信息
if (!errorInfo.stack && error.filename) {
errorInfo.stack = 'at ' + error.filename;
if (error.lineno) {
errorInfo.stack += ':' + error.lineno;
if (error.colno) {
errorInfo.stack += ':' + error.colno;
}
}
}
} catch (e) {
errorInfo.message = '解析错误对象失败: ' + String(e);
errorInfo.stack = '';
}
}
// 如果是 null 或 undefined
else if (error === null || error === undefined) {
errorInfo.message = '错误对象为 ' + String(error);
}
// 其他情况
else {
errorInfo.message = String(error) || '未知错误';
errorInfo.stack = '';
}
// 保留原始错误对象的前几个键(用于调试)
if (error && typeof error === 'object') {
var keys = Object.keys(error).slice(0, 5);
if (keys.length > 0) {
errorInfo.rawError = {};
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (typeof error[key] !== 'function') {
errorInfo.rawError[key] = String(error[key]).substring(0, 100);
}
}
}
}
// 如果 message 还是空的或 {}
if (!errorInfo.message || errorInfo.message === '{}' || errorInfo.message === 'undefined') {
errorInfo.message = '无法获取错误详情(错误对象为空或无效)';
}
} catch (e) {
errorInfo.message = '构建错误信息异常: ' + String(e);
errorInfo.stack = '';
}
return errorInfo;
}
// 捕获 JavaScript 错误
window.addEventListener('error', function(event) {
// 检查是否应该忽略此错误
var errorToCheck = event.error || event;
if (shouldIgnoreError(errorToCheck)) {
console.warn('[早期错误捕获] 忽略请求中止错误', errorToCheck);
return;
}
var errorInfo;
if (event.error) {
errorInfo = buildErrorInfo(event.error, 'error');
} else {
errorInfo = buildErrorInfo({
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno
}, 'error');
}
// 发送错误
sendError(errorInfo);
// 同时存储到缓冲区
window.__ERROR_BUFFER__.push(errorInfo);
}, true);
// 捕获 Promise rejection 错误
window.addEventListener('unhandledrejection', function(event) {
// 检查是否应该忽略此错误
if (shouldIgnoreError(event.reason)) {
console.warn('[早期错误捕获] 忽略请求中止错误', event.reason);
return;
}
var errorInfo = buildErrorInfo({
message: 'Promise rejection',
reason: event.reason
}, 'promise');
// 发送错误
sendError(errorInfo);
// 同时存储到缓冲区
window.__ERROR_BUFFER__.push(errorInfo);
});
// 上报缓冲区的错误(供后续应用调用)
window.flushErrorBuffer = function() {
if (window.__ERROR_BUFFER__ && window.__ERROR_BUFFER__.length > 0) {
var buffer = window.__ERROR_BUFFER__;
window.__ERROR_BUFFER__ = [];
return buffer;
}
return [];
};
console.log('[早期错误捕获] 已初始化');
})();
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>