优化项目配置和页面结构
- 更新settings.local.json,移除冗余的权限设置,添加新的Playwright相关权限。 - 删除exhibition_demo_project_2025.md文档,清理不再使用的文件。 - 更新多个HTML页面,统一viewport设置,添加页面加载动画、错误处理和性能优化脚本。 - 统一使用Tailwind CSS的引入方式,提升页面加载性能。 - 增强导航组件,支持移动端菜单和返回顶部功能,改善用户体验。
This commit is contained in:
279
web_frontend/web_result/js/error-handler.js
Normal file
279
web_frontend/web_result/js/error-handler.js
Normal file
@@ -0,0 +1,279 @@
|
||||
// 错误处理和兼容性脚本
|
||||
(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();
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user