- 更新settings.local.json,移除冗余的权限设置,添加新的Playwright相关权限。 - 删除exhibition_demo_project_2025.md文档,清理不再使用的文件。 - 更新多个HTML页面,统一viewport设置,添加页面加载动画、错误处理和性能优化脚本。 - 统一使用Tailwind CSS的引入方式,提升页面加载性能。 - 增强导航组件,支持移动端菜单和返回顶部功能,改善用户体验。
279 lines
9.6 KiB
JavaScript
279 lines
9.6 KiB
JavaScript
// 错误处理和兼容性脚本
|
||
(function() {
|
||
'use strict';
|
||
|
||
// 全局错误处理
|
||
window.addEventListener('error', function(event) {
|
||
console.error('Global error:', {
|
||
message: event.message,
|
||
filename: event.filename,
|
||
lineno: event.lineno,
|
||
colno: event.colno,
|
||
error: event.error
|
||
});
|
||
|
||
// 发送错误到控制台(便于调试)
|
||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
||
console.group('Error Details:');
|
||
console.log('Message:', event.message);
|
||
console.log('File:', event.filename);
|
||
console.log('Line:', event.lineno + ':' + event.colno);
|
||
if (event.error && event.error.stack) {
|
||
console.log('Stack:', event.error.stack);
|
||
}
|
||
console.groupEnd();
|
||
}
|
||
|
||
return true; // 阻止默认错误处理
|
||
});
|
||
|
||
// Promise 错误处理
|
||
window.addEventListener('unhandledrejection', function(event) {
|
||
console.error('Unhandled promise rejection:', event.reason);
|
||
|
||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
||
console.group('Promise Rejection:');
|
||
console.log('Reason:', event.reason);
|
||
if (event.reason && event.reason.stack) {
|
||
console.log('Stack:', event.reason.stack);
|
||
}
|
||
console.groupEnd();
|
||
}
|
||
|
||
event.preventDefault(); // 阻止默认处理
|
||
});
|
||
|
||
// DOM 查询安全包装
|
||
function safeQuerySelector(selector) {
|
||
try {
|
||
return document.querySelector(selector);
|
||
} catch (e) {
|
||
console.warn('Invalid selector:', selector, e);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
function safeQuerySelectorAll(selector) {
|
||
try {
|
||
return document.querySelectorAll(selector);
|
||
} catch (e) {
|
||
console.warn('Invalid selector:', selector, e);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
// 安全的getElementById
|
||
function safeGetElementById(id) {
|
||
try {
|
||
return document.getElementById(id);
|
||
} catch (e) {
|
||
console.warn('Invalid element ID:', id, e);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
// 修复常见的兼容性问题
|
||
function fixCompatibilityIssues() {
|
||
// 修复classList不支持的情况(简化版本以避免Illegal invocation)
|
||
try {
|
||
// 安全检测classList支持
|
||
var testElement = document.createElement('div');
|
||
if (!testElement.classList) {
|
||
// 简单的classList polyfill
|
||
window.ClassListPolyfill = {
|
||
addClass: function(element, className) {
|
||
if (element && className) {
|
||
var classes = element.className ? element.className.split(' ') : [];
|
||
if (classes.indexOf(className) === -1) {
|
||
classes.push(className);
|
||
element.className = classes.join(' ').trim();
|
||
}
|
||
}
|
||
},
|
||
removeClass: function(element, className) {
|
||
if (element && className) {
|
||
var classes = element.className ? element.className.split(' ') : [];
|
||
var index = classes.indexOf(className);
|
||
if (index !== -1) {
|
||
classes.splice(index, 1);
|
||
element.className = classes.join(' ').trim();
|
||
}
|
||
}
|
||
},
|
||
hasClass: function(element, className) {
|
||
if (!element || !className) return false;
|
||
var classes = element.className ? element.className.split(' ') : [];
|
||
return classes.indexOf(className) !== -1;
|
||
}
|
||
};
|
||
}
|
||
} catch (e) {
|
||
// 如果检测失败,忽略错误
|
||
console.warn('classList detection failed:', e);
|
||
}
|
||
|
||
// 修复addEventListener不支持的情况
|
||
if (!Element.prototype.addEventListener && Element.prototype.attachEvent) {
|
||
Element.prototype.addEventListener = function(event, listener) {
|
||
this.attachEvent('on' + event, listener);
|
||
};
|
||
Element.prototype.removeEventListener = function(event, listener) {
|
||
this.detachEvent('on' + event, listener);
|
||
};
|
||
}
|
||
|
||
// 修复Array.from不支持的情况
|
||
if (!Array.from) {
|
||
Array.from = function(arrayLike) {
|
||
var result = [];
|
||
for (var i = 0; i < arrayLike.length; i++) {
|
||
result.push(arrayLike[i]);
|
||
}
|
||
return result;
|
||
};
|
||
}
|
||
|
||
// 修复forEach不支持的情况
|
||
if (!NodeList.prototype.forEach) {
|
||
NodeList.prototype.forEach = function(callback, thisArg) {
|
||
for (var i = 0; i < this.length; i++) {
|
||
callback.call(thisArg, this[i], i, this);
|
||
}
|
||
};
|
||
}
|
||
}
|
||
|
||
// 检测浏览器支持情况
|
||
function detectBrowserSupport() {
|
||
const features = {
|
||
es6: {
|
||
arrow: false,
|
||
const: false,
|
||
let: false,
|
||
template: false,
|
||
destructuring: false
|
||
},
|
||
dom: {
|
||
classList: (function() {
|
||
try {
|
||
var testElement = document.createElement('div');
|
||
return !!testElement.classList;
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
})(),
|
||
querySelector: !!document.querySelector,
|
||
addEventListener: !!window.addEventListener
|
||
},
|
||
css: {
|
||
grid: typeof CSS !== 'undefined' && CSS.supports && CSS.supports('display', 'grid'),
|
||
flexbox: typeof CSS !== 'undefined' && CSS.supports && CSS.supports('display', 'flex'),
|
||
transform: typeof CSS !== 'undefined' && CSS.supports && CSS.supports('transform', 'translateX(0)')
|
||
}
|
||
};
|
||
|
||
// 测试ES6功能
|
||
try {
|
||
eval('const x = 1');
|
||
features.es6.const = true;
|
||
} catch (e) {}
|
||
|
||
try {
|
||
eval('let x = 1');
|
||
features.es6.let = true;
|
||
} catch (e) {}
|
||
|
||
try {
|
||
eval('`template`');
|
||
features.es6.template = true;
|
||
} catch (e) {}
|
||
|
||
try {
|
||
eval('() => {}');
|
||
features.es6.arrow = true;
|
||
} catch (e) {}
|
||
|
||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
||
console.group('Browser Support:');
|
||
console.table(features);
|
||
console.groupEnd();
|
||
}
|
||
|
||
return features;
|
||
}
|
||
|
||
// 修复具体的错误
|
||
function fixSpecificErrors() {
|
||
// 确保所有必要的元素存在
|
||
const requiredElements = [
|
||
'navbar',
|
||
'mobile-menu-button',
|
||
'mobile-menu',
|
||
'mobile-menu-overlay',
|
||
'close-menu'
|
||
];
|
||
|
||
setTimeout(function() {
|
||
requiredElements.forEach(function(id) {
|
||
const element = document.getElementById(id);
|
||
if (!element) {
|
||
console.warn('Missing required element:', id);
|
||
|
||
// 尝试创建缺失的元素(某些情况下)
|
||
if (id === 'mobile-menu-overlay' && !document.getElementById(id)) {
|
||
const overlay = document.createElement('div');
|
||
overlay.id = id;
|
||
overlay.className = 'mobile-menu-overlay hidden';
|
||
document.body.appendChild(overlay);
|
||
console.log('Created missing overlay element');
|
||
}
|
||
}
|
||
});
|
||
}, 1000);
|
||
}
|
||
|
||
// 安全的脚本加载
|
||
function safeLoadScript(src, callback) {
|
||
const script = document.createElement('script');
|
||
script.src = src;
|
||
script.onload = function() {
|
||
if (callback) callback();
|
||
};
|
||
script.onerror = function() {
|
||
console.error('Failed to load script:', src);
|
||
};
|
||
document.head.appendChild(script);
|
||
}
|
||
|
||
// 初始化错误处理
|
||
function init() {
|
||
// 修复兼容性问题
|
||
fixCompatibilityIssues();
|
||
|
||
// 检测浏览器支持
|
||
detectBrowserSupport();
|
||
|
||
// 修复具体错误
|
||
fixSpecificErrors();
|
||
|
||
// 为调试添加全局工具
|
||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
||
window.debugTools = {
|
||
safeQuerySelector: safeQuerySelector,
|
||
safeQuerySelectorAll: safeQuerySelectorAll,
|
||
safeGetElementById: safeGetElementById,
|
||
fixCompatibilityIssues: fixCompatibilityIssues,
|
||
detectBrowserSupport: detectBrowserSupport
|
||
};
|
||
}
|
||
|
||
console.log('Error handler initialized');
|
||
}
|
||
|
||
// 在DOM加载后初始化
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', init);
|
||
} else {
|
||
init();
|
||
}
|
||
})(); |