This commit is contained in:
CN-JS-HuiBai
2026-04-06 17:27:56 +08:00
parent 131c011c5c
commit 94ed27199a
4 changed files with 74 additions and 10 deletions

View File

@@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="LDNET-GA">
<title>LDNET-GA</title>
<link rel="icon" id="siteFavicon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📊</text></svg>">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
@@ -448,8 +449,16 @@
<input type="text" id="siteTitleInput" placeholder="例:数据可视化展示大屏">
</div>
<div class="form-group" style="margin-top: 15px;">
<label for="logoUrlInput">Logo URL (图片链接,为空则显示默认图标)</label>
<input type="url" id="logoUrlInput" placeholder="https://example.com/logo.png">
<label for="logoUrlInput">Logo URL (白天/默认,支持图片链接)</label>
<input type="url" id="logoUrlInput" placeholder="https://example.com/logo_light.png">
</div>
<div class="form-group" style="margin-top: 15px;">
<label for="logoUrlDarkInput">Logo URL (黑夜模式,可为空则使用默认)</label>
<input type="url" id="logoUrlDarkInput" placeholder="https://example.com/logo_dark.png">
</div>
<div class="form-group" style="margin-top: 15px;">
<label for="faviconUrlInput">Favicon URL (浏览器标签页图标)</label>
<input type="url" id="faviconUrlInput" placeholder="https://example.com/favicon.ico">
</div>
<div class="settings-section" style="margin-top: 25px; border-top: 1px solid var(--border-color); padding-top: 20px;">
<h4 style="font-size: 0.85rem; color: var(--accent-indigo); margin-bottom: 15px; text-transform: uppercase; letter-spacing: 0.5px;">界面外观 (Appearance)</h4>

View File

@@ -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 = `<img src="${escapeHtml(settings.logo_url)}" alt="Logo" class="logo-icon-img">`;
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 = `<img src="${escapeHtml(logoToUse)}" alt="Logo" class="logo-icon-img">`;
} 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

View File

@@ -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',

View File

@@ -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',
@@ -410,6 +412,8 @@ const serveIndex = async (req, res) => {
page_name: '数据可视化展示大屏',
title: '数据可视化展示大屏',
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,