diff --git a/js/about.js b/js/about.js index e1faaa4..83675fe 100644 --- a/js/about.js +++ b/js/about.js @@ -17,7 +17,6 @@ function setStoredTheme(theme) { localStorage.setItem(cacheKey, JSON.stringify({ value: theme, time: new Date().getTime() })); - console.log("已保存主题设置:", theme); } // 公共方法:获取本地存储的主题设置 @@ -33,7 +32,6 @@ function getStoredTheme() { const night = hour >= 18 || prefersDark; theme = night ? 'night' : 'day'; setStoredTheme(theme) - console.log("已初始化主题设置:", theme); } else if (saved.value) { theme = saved.value; } @@ -41,10 +39,16 @@ function getStoredTheme() { } $(document).ready(function () { - // 启动应用核心 const app = new AppCore(); }); +function escapeHtml(s) { + if (s == null) return ''; + return String(s).replace(/[&<>\"]/g, function (c) { + return ({'&': '&', '<': '<', '>': '>', '"': '"'})[c]; + }); +} + class AppCore { constructor() { this.i18n = new I18nManager(); @@ -59,7 +63,7 @@ class AppCore { =========================== */ class I18nManager { constructor() { - this.lang = localStorage.getItem('lang') || (navigator.language.startsWith('zh') ? 'zh' : 'en'); + this.lang = getStoredLanguage(); this.dict = { zh: { "nav.home": "首页", @@ -282,20 +286,20 @@ class DataManager { // Fix: API field compatibility const stars = repo.stargazers_count !== undefined ? repo.stargazers_count : (repo.stars || 0); const forks = repo.forks_count !== undefined ? repo.forks_count : (repo.forks || 0); - const desc = repo.description || repo.desc || 'No description.'; + const descRaw = repo.description || repo.desc || 'No description.'; const url = repo.html_url || repo.url || '#'; - const dShort = (desc || '').length > 120 ? (desc.slice(0, 117) + '...') : desc; + const dShort = (descRaw || '').length > 120 ? (descRaw.slice(0, 117) + '...') : descRaw; html += ` -
+
- ${repo.name} + ${escapeHtml(repo.name)} ${stars} ${forks}
-
${dShort}
+
${escapeHtml(dShort)}
`; }); $('#projects-container').html(html); @@ -371,7 +375,7 @@ class DataManager { renderBlog(list) { let html = ''; - const lang = localStorage.getItem('lang') || (navigator.language && navigator.language.startsWith('zh') ? 'zh' : 'en'); + const lang = getStoredLanguage(); const fmtDate = (dStr) => { if (!dStr) return ''; const d = new Date(dStr); @@ -398,12 +402,12 @@ class DataManager { const link = post.link || post.url || '#'; html += ` -
+
-
${post.title}
-
${date}
+
${escapeHtml(post.title)}
+
${escapeHtml(date)}
-
${cat}
+
${escapeHtml(cat)}
`; }); $('#blog-container').html(html); @@ -459,11 +463,12 @@ class UIManager { } initArtalk() { - // Safe initialization const isHttps = location.protocol === 'https:'; const isLocal = !!(window.SiteConfig?.dev?.isLocal); if (!isHttps || isLocal) { - $('#artalk-container').html(`
${(new I18nManager()).dict[(localStorage.getItem('lang') || 'zh')]['comment.closed']}
`); + const lang = getStoredLanguage(); + const msg = lang === 'zh' ? '当前评论区已关闭' : 'Comments are closed'; + $('#artalk-container').html(`
${msg}
`); return; } if (typeof Artalk !== 'undefined' && window.SiteConfig?.artalk) { @@ -478,10 +483,14 @@ class UIManager { }); } catch (e) { console.error("Artalk Error", e); - $('#artalk-container').html(`
${(new I18nManager()).dict[(localStorage.getItem('lang') || 'zh')]['comment.closed']}
`); + const lang = getStoredLanguage(); + const msg = lang === 'zh' ? '当前评论区已关闭' : 'Comments are closed'; + $('#artalk-container').html(`
${msg}
`); } } else { - $('#artalk-container').html(`
${(new I18nManager()).dict[(localStorage.getItem('lang') || 'zh')]['comment.closed']}
`); + const lang = getStoredLanguage(); + const msg = lang === 'zh' ? '当前评论区已关闭' : 'Comments are closed'; + $('#artalk-container').html(`
${msg}
`); } } @@ -633,6 +642,7 @@ class UIManager { }; main.addEventListener('click', () => { menu.classList.toggle('open'); + main.setAttribute('aria-expanded', menu.classList.contains('open') ? 'true' : 'false'); updateLabels(); }); fLang.addEventListener('click', () => { @@ -668,10 +678,7 @@ class UIManager { let isDragging = false; let initialX, initialY, currentX, currentY, xOffset = 0, yOffset = 0; - const windowWidth = window.innerWidth; - const windowHeight = window.innerHeight; - const fabWidth = fab.offsetWidth; - const fabHeight = fab.offsetHeight; + fab.style.willChange = 'transform'; // 拖拽相关方法 const setTranslate = (xPos, yPos, el) => { @@ -706,9 +713,13 @@ class UIManager { currentY = e.clientY - initialY; } - // 限制在屏幕内 - currentX = Math.max(0, Math.min(currentX, windowWidth - fabWidth)); - currentY = Math.max(0, Math.min(currentY, windowHeight - fabHeight)); + const ww = window.innerWidth; + const wh = window.innerHeight; + const rect = fab.getBoundingClientRect(); + const fw = rect.width; + const fh = rect.height; + currentX = Math.max(0, Math.min(currentX, ww - fw)); + currentY = Math.max(0, Math.min(currentY, wh - fh)); xOffset = currentX; yOffset = currentY;