fix: lazy-load ReferenceError + localize Font Awesome

- app.js: remove window.Dashboard=... block that crashed the whole
  file before page scripts load (ReferenceError: Dashboard is not
  defined). Page objects are top-level const in global lexical
  scope; PAGE_OBJS map + indirect eval in loadScript onload now
  expose them to window for inline onclick / data-action lookups
- index.html: Font Awesome 6.5.1 localized (css/fontawesome.min.css
  + 8 webfont files) - no more cdnjs CDN (Edge Tracking Prevention
  blocked it, CN access unstable)
This commit is contained in:
2026-08-22 19:29:24 +08:00
parent 4ebabfc703
commit e5a1d693f1
11 changed files with 51 additions and 29 deletions

9
public/css/fontawesome.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title id="site-title">MC举报系统</title> <title id="site-title">MC举报系统</title>
<link rel="stylesheet" href="css/style.css"> <link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <!-- Font Awesome 本地化(避免 CDN 被浏览器跟踪防护拦截/国内访问慢) -->
<link rel="stylesheet" href="css/fontawesome.min.css">
</head> </head>
<body> <body>
<div id="top-bar"> <div id="top-bar">

View File

@@ -128,12 +128,49 @@ const App = {
bans: ['bans'], bans: ['bans'],
logs: ['logs'], logs: ['logs'],
}, },
// 脚本文件 → 顶层 const 页面对象(懒加载后经间接 eval 挂到 window)
PAGE_OBJS: {
'home.js': ['HomePage'],
'ticket-create.js': ['TicketCreate'],
'install.js': ['InstallPage'],
'login.js': ['LoginPage'],
'register.js': ['RegisterPage'],
'forgot.js': ['ForgotPage', 'ResetPage'],
'verify.js': ['VerifyPage'],
'dashboard.js': ['Dashboard'],
'unclaimed.js': ['UnclaimedPage'],
'tickets.js': ['TicketsPage'],
'ticket-detail.js': ['TicketDetail'],
'tracking.js': ['TrackingPage'],
'users.js': ['UsersPage'],
'notifications.js': ['NotificationsPage'],
'external-api.js': ['ExternalApiPage'],
'external-api-docs.js': ['ExternalApiDocsPage'],
'sources.js': ['SourcesPage'],
'templates.js': ['TemplatesPage'],
'settings-page.js': ['SettingsPage'],
'export-page.js': ['ExportPage'],
'polls.js': ['PollsPage'],
'features.js': ['FeaturesPage'],
'feature-detail.js': ['FeatureDetail'],
'servers.js': ['ServersPage'],
'bans.js': ['BansPage'],
'logs.js': ['LogsPage'],
},
loadScript(src) { loadScript(src) {
if (this._scriptCache[src]) return this._scriptCache[src]; if (this._scriptCache[src]) return this._scriptCache[src];
const p = new Promise((resolve, reject) => { const p = new Promise((resolve, reject) => {
const s = document.createElement('script'); const s = document.createElement('script');
s.src = src; s.src = src;
s.onload = () => resolve(); s.onload = () => {
// 页面脚本顶层 const 在全局词法环境, 用间接 eval 挂到 window,
// 供 inline onclick / data-action 的 window[obj] 查找
const objs = this.PAGE_OBJS[src.split('/').pop()] || [];
for (const o of objs) {
try { if (typeof window[o] === 'undefined') window[o] = (0, eval)(o); } catch {}
}
resolve();
};
s.onerror = () => { delete this._scriptCache[src]; reject(new Error('脚本加载失败: ' + src)); }; s.onerror = () => { delete this._scriptCache[src]; reject(new Error('脚本加载失败: ' + src)); };
document.head.appendChild(s); document.head.appendChild(s);
}); });
@@ -280,33 +317,8 @@ const App = {
}; };
document.addEventListener('DOMContentLoaded', () => App.init()); document.addEventListener('DOMContentLoaded', () => App.init());
window.App = App; // 页面对象(window.Dashboard 等)由各自脚本以顶层 const 定义, 全局词法环境可访问,
window.Dashboard = Dashboard; // 无需在此挂载(懒加载下此处引用会导致 ReferenceError 崩掉整个 app.js)
window.TicketsPage = TicketsPage;
window.TicketDetail = TicketDetail;
window.TicketCreate = TicketCreate;
window.TrackingPage = TrackingPage;
window.UnclaimedPage = UnclaimedPage;
window.UsersPage = UsersPage;
window.TemplatesPage = TemplatesPage;
window.NotificationsPage = NotificationsPage;
window.ExternalApiPage = ExternalApiPage;
window.SourcesPage = SourcesPage;
window.SettingsPage = SettingsPage;
window.ExportPage = ExportPage;
window.PollsPage = PollsPage;
window.FeaturesPage = FeaturesPage;
window.FeatureDetail = FeatureDetail;
window.ServersPage = ServersPage;
window.BansPage = BansPage;
window.LogsPage = LogsPage;
window.LoginPage = LoginPage;
window.RegisterPage = RegisterPage;
window.HomePage = HomePage;
window.InstallPage = InstallPage;
window.ForgotPage = ForgotPage;
window.ResetPage = ResetPage;
window.VerifyPage = VerifyPage;
window.U = U; window.U = U;
window.Auth = Auth; window.Auth = Auth;
window.API = API; window.API = API;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.