From 94ed27199afb56ceb5bb79dcb99a025ee82ca56c Mon Sep 17 00:00:00 2001 From: CN-JS-HuiBai Date: Mon, 6 Apr 2026 17:27:56 +0800 Subject: [PATCH] Dlogo --- public/index.html | 13 ++++++++++-- public/js/app.js | 41 +++++++++++++++++++++++++++++++++--- server/db-integrity-check.js | 12 +++++++++++ server/index.js | 18 +++++++++++----- 4 files changed, 74 insertions(+), 10 deletions(-) diff --git a/public/index.html b/public/index.html index 9b97a33..4a3f272 100644 --- a/public/index.html +++ b/public/index.html @@ -6,6 +6,7 @@ LDNET-GA +
- - + + +
+
+ + +
+
+ +

界面外观 (Appearance)

diff --git a/public/js/app.js b/public/js/app.js index 5836ae3..d1ed0b5 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -41,6 +41,8 @@ formMessage: document.getElementById('formMessage'), sourceItems: document.getElementById('sourceItems'), serverSourceOption: document.getElementById('serverSourceOption'), + faviconUrlInput: document.getElementById('faviconUrlInput'), + logoUrlDarkInput: document.getElementById('logoUrlDarkInput'), // Site Settings modalTabs: document.querySelectorAll('.modal-tab'), tabContents: document.querySelectorAll('.tab-content'), @@ -53,6 +55,7 @@ logoIconContainer: document.getElementById('logoIconContainer'), defaultThemeInput: document.getElementById('defaultThemeInput'), show95BandwidthInput: document.getElementById('show95BandwidthInput'), + siteFavicon: document.getElementById('siteFavicon'), // Auth & Theme elements themeToggle: document.getElementById('themeToggle'), sunIcon: document.querySelector('.sun-icon'), @@ -487,6 +490,8 @@ if (dom.p95TypeSelect) dom.p95TypeSelect.value = window.SITE_SETTINGS.p95_type || 'tx'; if (dom.icpFilingInput) dom.icpFilingInput.value = window.SITE_SETTINGS.icp_filing || ''; if (dom.psFilingInput) dom.psFilingInput.value = window.SITE_SETTINGS.ps_filing || ''; + if (dom.logoUrlDarkInput) dom.logoUrlDarkInput.value = window.SITE_SETTINGS.logo_url_dark || ''; + if (dom.faviconUrlInput) dom.faviconUrlInput.value = window.SITE_SETTINGS.favicon_url || ''; // Latency routes loaded separately in openSettings or on startup } @@ -551,6 +556,10 @@ localStorage.setItem('theme', theme); updateThemeIcons(theme); updateMap2DTheme(theme); + // After theme toggle, re-apply site settings to handle potential logo change + if (window.SITE_SETTINGS) { + applySiteSettings(window.SITE_SETTINGS); + } } function applyTheme(theme) { @@ -564,6 +573,19 @@ document.documentElement.classList.toggle('light-theme', isLight); updateThemeIcons(actualTheme); updateMap2DTheme(actualTheme); + + // After theme change, re-apply site settings to handle potential logo change + if (window.SITE_SETTINGS) { + applySiteSettings(window.SITE_SETTINGS); + } + } + + function updateFavicon(url) { + if (!url) return; + const link = dom.siteFavicon || document.querySelector("link[rel*='icon']"); + if (link) { + link.href = url; + } } function updateThemeIcons(theme) { @@ -1655,6 +1677,8 @@ } if (dom.icpFilingInput) dom.icpFilingInput.value = settings.icp_filing || ''; if (dom.psFilingInput) dom.psFilingInput.value = settings.ps_filing || ''; + if (dom.logoUrlDarkInput) dom.logoUrlDarkInput.value = settings.logo_url_dark || ''; + if (dom.faviconUrlInput) dom.faviconUrlInput.value = settings.favicon_url || ''; // Apply to UI applySiteSettings(settings); @@ -1693,8 +1717,14 @@ } // Logo Icon - if (settings.logo_url) { - dom.logoIconContainer.innerHTML = `Logo`; + let logoToUse = settings.logo_url; + const currentTheme = document.documentElement.classList.contains('light-theme') ? 'light' : 'dark'; + if (currentTheme === 'dark' && settings.logo_url_dark) { + logoToUse = settings.logo_url_dark; + } + + if (logoToUse) { + dom.logoIconContainer.innerHTML = `Logo`; } else { // Restore default SVG dom.logoIconContainer.innerHTML = ` @@ -1713,6 +1743,9 @@ `; } + // Favicon + updateFavicon(settings.favicon_url); + // P95 setting if (settings.show_95_bandwidth !== undefined || settings.p95_type !== undefined) { if (networkChart) { @@ -1786,7 +1819,9 @@ show_95_bandwidth: dom.show95BandwidthInput.value === "1" ? 1 : 0, p95_type: dom.p95TypeSelect.value, ps_filing: dom.psFilingInput ? dom.psFilingInput.value : '', - icp_filing: dom.icpFilingInput ? dom.icpFilingInput.value : '' + icp_filing: dom.icpFilingInput ? dom.icpFilingInput.value : '', + logo_url_dark: dom.logoUrlDarkInput ? dom.logoUrlDarkInput.value.trim() : '', + favicon_url: dom.faviconUrlInput ? dom.faviconUrlInput.value.trim() : '' }; // If user sets default to auto, we should clear their manual override or set it to auto diff --git a/server/db-integrity-check.js b/server/db-integrity-check.js index 9527efd..f17e77d 100644 --- a/server/db-integrity-check.js +++ b/server/db-integrity-check.js @@ -97,6 +97,16 @@ async function checkAndFixDatabase() { await db.query("ALTER TABLE site_settings ADD COLUMN ps_filing VARCHAR(255) AFTER icp_filing"); console.log(`[Database Integrity] ✅ Column 'ps_filing' added.`); } + if (!columnNames.includes('logo_url_dark')) { + console.log(`[Database Integrity] ⚠️ Missing column 'logo_url_dark' in 'site_settings'. Adding it...`); + await db.query("ALTER TABLE site_settings ADD COLUMN logo_url_dark TEXT AFTER logo_url"); + console.log(`[Database Integrity] ✅ Column 'logo_url_dark' added.`); + } + if (!columnNames.includes('favicon_url')) { + console.log(`[Database Integrity] ⚠️ Missing column 'favicon_url' in 'site_settings'. Adding it...`); + await db.query("ALTER TABLE site_settings ADD COLUMN favicon_url TEXT AFTER logo_url_dark"); + console.log(`[Database Integrity] ✅ Column 'favicon_url' added.`); + } } catch (err) { console.error('[Database Integrity] ❌ Error checking integrity:', err.message); } @@ -135,6 +145,8 @@ async function createTable(tableName) { page_name VARCHAR(255) DEFAULT '数据可视化展示大屏', title VARCHAR(255) DEFAULT '数据可视化展示大屏', logo_url TEXT, + logo_url_dark TEXT, + favicon_url TEXT, default_theme VARCHAR(20) DEFAULT 'dark', show_95_bandwidth TINYINT(1) DEFAULT 0, p95_type VARCHAR(20) DEFAULT 'tx', diff --git a/server/index.js b/server/index.js index 8ab7f57..dff8037 100644 --- a/server/index.js +++ b/server/index.js @@ -262,6 +262,8 @@ app.post('/api/setup/init', async (req, res) => { page_name VARCHAR(255) DEFAULT '数据可视化展示大屏', title VARCHAR(255) DEFAULT '数据可视化展示大屏', logo_url TEXT, + logo_url_dark TEXT, + favicon_url TEXT, default_theme VARCHAR(20) DEFAULT 'dark', show_95_bandwidth TINYINT(1) DEFAULT 0, p95_type VARCHAR(20) DEFAULT 'tx', @@ -409,7 +411,9 @@ const serveIndex = async (req, res) => { let settings = { page_name: '数据可视化展示大屏', title: '数据可视化展示大屏', - logo_url: null, + logo_url: null, + logo_url_dark: null, + favicon_url: null, default_theme: 'dark', blackbox_source_id: null, latency_source: null, @@ -563,6 +567,8 @@ app.get('/api/settings', async (req, res) => { page_name: '数据可视化展示大屏', title: '数据可视化展示大屏', logo_url: null, + logo_url_dark: null, + favicon_url: null, show_95_bandwidth: 0, p95_type: 'tx', blackbox_source_id: null, @@ -582,15 +588,17 @@ app.get('/api/settings', async (req, res) => { // Update site settings app.post('/api/settings', requireAuth, async (req, res) => { - const { page_name, title, logo_url, default_theme, show_95_bandwidth, p95_type, blackbox_source_id, latency_source, latency_dest, latency_target, icp_filing, ps_filing } = req.body; + const { page_name, title, logo_url, logo_url_dark, favicon_url, default_theme, show_95_bandwidth, p95_type, blackbox_source_id, latency_source, latency_dest, latency_target, icp_filing, ps_filing } = req.body; try { await db.query( - `INSERT INTO site_settings (id, page_name, title, logo_url, default_theme, show_95_bandwidth, p95_type, blackbox_source_id, latency_source, latency_dest, latency_target, icp_filing, ps_filing) - VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `INSERT INTO site_settings (id, page_name, title, logo_url, logo_url_dark, favicon_url, default_theme, show_95_bandwidth, p95_type, blackbox_source_id, latency_source, latency_dest, latency_target, icp_filing, ps_filing) + VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE page_name = VALUES(page_name), title = VALUES(title), logo_url = VALUES(logo_url), + logo_url_dark = VALUES(logo_url_dark), + favicon_url = VALUES(favicon_url), default_theme = VALUES(default_theme), show_95_bandwidth = VALUES(show_95_bandwidth), p95_type = VALUES(p95_type), @@ -601,7 +609,7 @@ app.post('/api/settings', requireAuth, async (req, res) => { icp_filing = VALUES(icp_filing), ps_filing = VALUES(ps_filing)`, [ - page_name, title, logo_url, default_theme, + page_name, title, logo_url, logo_url_dark, favicon_url, default_theme, show_95_bandwidth ? 1 : 0, p95_type || 'tx', blackbox_source_id || null, latency_source || null, latency_dest || null, latency_target || null,