添加copyright
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
`);
|
||||
|
||||
@@ -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 });
|
||||
|
||||
Reference in New Issue
Block a user