添加copyright

This commit is contained in:
CN-JS-HuiBai
2026-04-06 16:58:58 +08:00
parent d469dacc08
commit b4415f25ac
5 changed files with 157 additions and 9 deletions

View File

@@ -2695,4 +2695,72 @@ input:checked+.slider:before {
color: var(--accent-indigo);
background: rgba(99, 102, 241, 0.1);
border-color: var(--accent-indigo);
}
/* ---- Footer ---- */
.site-footer {
margin-top: 40px;
padding: 30px 28px;
border-top: 1px solid var(--border-color);
background: rgba(10, 14, 26, 0.4);
backdrop-filter: blur(10px);
position: relative;
z-index: 10;
}
:root.light-theme .site-footer {
background: rgba(255, 255, 255, 0.4);
}
.footer-content {
max-width: 1600px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
}
.copyright {
font-size: 0.88rem;
color: var(--text-muted);
font-weight: 500;
}
.filings {
display: flex;
align-items: center;
gap: 20px;
}
.filings a {
font-size: 0.82rem;
color: var(--text-muted);
text-decoration: none;
transition: color 0.2s;
display: flex;
align-items: center;
}
.filings a:hover {
color: var(--accent-indigo);
}
@media (max-width: 768px) {
.site-footer {
padding: 24px 16px;
margin-top: 20px;
}
.footer-content {
flex-direction: column;
text-align: center;
gap: 12px;
}
.filings {
flex-direction: column;
gap: 8px;
}
}

View File

@@ -354,6 +354,20 @@
</section>
</main>
<!-- Footer -->
<footer class="site-footer">
<div class="footer-content">
<div class="copyright">© <span id="copyrightYear"></span> LDNET-GA-Service. All rights reserved.</div>
<div class="filings">
<a href="https://beian.miit.gov.cn/" target="_blank" id="icpFilingDisplay" style="display: none;"></a>
<a href="http://www.beian.gov.cn/portal/registerSystemInfo" target="_blank" id="psFilingDisplay" style="display: none;">
<img src="https://www.beian.gov.cn/img/ghs.png" alt="公安备案" style="width: 14px; height: 14px; vertical-align: middle; margin-right: 2px;">
<span id="psFilingText"></span>
</a>
</div>
</div>
</footer>
<!-- Settings Modal -->
<div class="modal-overlay" id="settingsModal">
<div class="modal">
@@ -467,6 +481,14 @@
<option value="both">统计上行+下行 (Sum)</option>
</select>
</div>
<div class="form-group" style="margin-top: 15px;">
<label for="icpFilingInput">ICP 备案号 (如京ICP备12345678号)</label>
<input type="text" id="icpFilingInput" placeholder="请输入 ICP 备案号">
</div>
<div class="form-group" style="margin-top: 15px;">
<label for="psFilingInput">公安备案号 (如:京公网安备 11010102000001号)</label>
<input type="text" id="psFilingInput" placeholder="请输入公安备案号">
</div>
<div class="form-actions" style="margin-top: 25px; display: flex; justify-content: flex-end;">
<button class="btn btn-add" id="btnSaveSiteSettings">保存基础设置</button>
</div>

View File

@@ -105,7 +105,14 @@
partitionSummary: document.getElementById('partitionSummary'),
partitionHeader: document.getElementById('partitionHeader'),
globeCard: document.getElementById('globeCard'),
btnExpandGlobe: document.getElementById('btnExpandGlobe')
btnExpandGlobe: document.getElementById('btnExpandGlobe'),
// Footer & Filing
icpFilingInput: document.getElementById('icpFilingInput'),
psFilingInput: document.getElementById('psFilingInput'),
icpFilingDisplay: document.getElementById('icpFilingDisplay'),
psFilingDisplay: document.getElementById('psFilingDisplay'),
psFilingText: document.getElementById('psFilingText'),
copyrightYear: document.getElementById('copyrightYear')
};
// ---- State ----
@@ -146,6 +153,11 @@
updateGaugesTime();
setInterval(updateGaugesTime, 1000);
// Initial footer year
if (dom.copyrightYear) {
dom.copyrightYear.textContent = new Date().getFullYear();
}
// Initial theme check (localStorage handled after site settings load to ensure priority)
// Network chart
@@ -473,6 +485,8 @@
if (dom.defaultThemeInput) dom.defaultThemeInput.value = window.SITE_SETTINGS.default_theme || 'dark';
if (dom.show95BandwidthInput) dom.show95BandwidthInput.value = window.SITE_SETTINGS.show_95_bandwidth ? "1" : "0";
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 || '';
// Latency routes loaded separately in openSettings or on startup
}
@@ -1639,6 +1653,8 @@
networkChart.draw();
}
}
if (dom.icpFilingInput) dom.icpFilingInput.value = settings.icp_filing || '';
if (dom.psFilingInput) dom.psFilingInput.value = settings.ps_filing || '';
// Apply to UI
applySiteSettings(settings);
@@ -1726,6 +1742,25 @@
applyTheme(settings.default_theme);
}
}
// Filing info
if (dom.icpFilingDisplay) {
if (settings.icp_filing) {
dom.icpFilingDisplay.textContent = settings.icp_filing;
dom.icpFilingDisplay.style.display = 'inline-block';
} else {
dom.icpFilingDisplay.style.display = 'none';
}
}
if (dom.psFilingDisplay) {
if (settings.ps_filing) {
if (dom.psFilingText) dom.psFilingText.textContent = settings.ps_filing;
dom.psFilingDisplay.style.display = 'inline-block';
} else {
dom.psFilingDisplay.style.display = 'none';
}
}
}
async function saveSiteSettings() {
@@ -1741,7 +1776,9 @@
logo_url: dom.logoUrlInput.value.trim(),
default_theme: dom.defaultThemeInput.value,
show_95_bandwidth: dom.show95BandwidthInput.value === "1" ? 1 : 0,
p95_type: dom.p95TypeSelect.value
p95_type: dom.p95TypeSelect.value,
icp_filing: dom.icpFilingInput ? dom.icpFilingInput.value : '',
ps_filing: dom.psFilingInput ? dom.psFilingInput.value : ''
};
// If user sets default to auto, we should clear their manual override or set it to auto

View File

@@ -87,6 +87,16 @@ async function checkAndFixDatabase() {
await db.query("ALTER TABLE site_settings ADD COLUMN latency_target VARCHAR(255) AFTER latency_dest");
console.log(`[Database Integrity] ✅ Column 'latency_target' added.`);
}
if (!columnNames.includes('icp_filing')) {
console.log(`[Database Integrity] ⚠️ Missing column 'icp_filing' in 'site_settings'. Adding it...`);
await db.query("ALTER TABLE site_settings ADD COLUMN icp_filing VARCHAR(255) AFTER latency_target");
console.log(`[Database Integrity] ✅ Column 'icp_filing' added.`);
}
if (!columnNames.includes('ps_filing')) {
console.log(`[Database Integrity] ⚠️ Missing column 'ps_filing' in 'site_settings'. Adding it...`);
await db.query("ALTER TABLE site_settings ADD COLUMN ps_filing VARCHAR(255) AFTER icp_filing");
console.log(`[Database Integrity] ✅ Column 'ps_filing' added.`);
}
} catch (err) {
console.error('[Database Integrity] ❌ Error checking integrity:', err.message);
}
@@ -132,6 +142,8 @@ async function createTable(tableName) {
latency_source VARCHAR(100),
latency_dest VARCHAR(100),
latency_target VARCHAR(255),
icp_filing VARCHAR(255),
ps_filing VARCHAR(255),
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
`);

View File

@@ -269,6 +269,8 @@ app.post('/api/setup/init', async (req, res) => {
latency_source VARCHAR(100),
latency_dest VARCHAR(100),
latency_target VARCHAR(255),
icp_filing VARCHAR(255),
ps_filing VARCHAR(255),
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
`);
@@ -412,7 +414,9 @@ const serveIndex = async (req, res) => {
blackbox_source_id: null,
latency_source: null,
latency_dest: null,
latency_target: null
latency_target: null,
icp_filing: null,
ps_filing: null
};
if (isDbInitialized) {
@@ -564,7 +568,9 @@ app.get('/api/settings', async (req, res) => {
blackbox_source_id: null,
latency_source: null,
latency_dest: null,
latency_target: null
latency_target: null,
icp_filing: null,
ps_filing: null
});
}
res.json(rows[0]);
@@ -576,11 +582,11 @@ 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 } = req.body;
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;
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)
VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`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, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
page_name = VALUES(page_name),
title = VALUES(title),
@@ -591,12 +597,15 @@ app.post('/api/settings', requireAuth, async (req, res) => {
blackbox_source_id = VALUES(blackbox_source_id),
latency_source = VALUES(latency_source),
latency_dest = VALUES(latency_dest),
latency_target = VALUES(latency_target)`,
latency_target = VALUES(latency_target),
icp_filing = VALUES(icp_filing),
ps_filing = VALUES(ps_filing)`,
[
page_name, title, logo_url, default_theme,
show_95_bandwidth ? 1 : 0, p95_type || 'tx',
blackbox_source_id || null, latency_source || null,
latency_dest || null, latency_target || null
latency_dest || null, latency_target || null,
icp_filing || null, ps_filing || null
]
);
res.json({ success: true });