允许编辑配置

This commit is contained in:
CN-JS-HuiBai
2026-04-06 00:31:05 +08:00
parent a35dac78f8
commit 542258a271
3 changed files with 60 additions and 8 deletions

View File

@@ -479,8 +479,9 @@
<label>Blackbox 目标 (instance_name)</label> <label>Blackbox 目标 (instance_name)</label>
<input type="text" id="routeTargetInput" placeholder="例China-USA-Latency"> <input type="text" id="routeTargetInput" placeholder="例China-USA-Latency">
</div> </div>
<div class="form-actions" style="padding-bottom: 0;"> <div class="form-actions" style="padding-bottom: 0; display: flex; gap: 8px;">
<button class="btn btn-add" id="btnAddRoute" style="padding: 10px 24px;">添加线路</button> <button class="btn btn-add" id="btnAddRoute" style="padding: 10px 24px;">添加线路</button>
<button class="btn btn-test" id="btnCancelEditRoute" style="display: none; padding: 10px 15px; background: rgba(0,0,0,0.3);">取消</button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -75,6 +75,7 @@
routeTargetInput: document.getElementById('routeTargetInput'), routeTargetInput: document.getElementById('routeTargetInput'),
btnAddRoute: document.getElementById('btnAddRoute'), btnAddRoute: document.getElementById('btnAddRoute'),
latencyRoutesList: document.getElementById('latencyRoutesList'), latencyRoutesList: document.getElementById('latencyRoutesList'),
btnCancelEditRoute: document.getElementById('btnCancelEditRoute'),
detailDiskTotal: document.getElementById('detailDiskTotal'), detailDiskTotal: document.getElementById('detailDiskTotal'),
// Server Details Modal // Server Details Modal
serverDetailModal: document.getElementById('serverDetailModal'), serverDetailModal: document.getElementById('serverDetailModal'),
@@ -131,6 +132,7 @@
} }
let myMap2D = null; let myMap2D = null;
let editingRouteId = null;
// ---- Initialize ---- // ---- Initialize ----
function init() { function init() {
@@ -163,6 +165,10 @@
}); });
} }
if (dom.btnCancelEditRoute) {
dom.btnCancelEditRoute.onclick = cancelEditRoute;
}
dom.settingsModal.addEventListener('click', (e) => { dom.settingsModal.addEventListener('click', (e) => {
if (e.target === dom.settingsModal) closeSettings(); if (e.target === dom.settingsModal) closeSettings();
}); });
@@ -1541,11 +1547,40 @@
<span>目标: ${escapeHtml(route.latency_target)}</span> <span>目标: ${escapeHtml(route.latency_target)}</span>
</div> </div>
</div> </div>
<button class="btn btn-delete" onclick="deleteLatencyRoute(${route.id})" style="padding: 4px 10px; font-size: 0.72rem;">删除</button> <div class="route-actions" style="display: flex; gap: 8px;">
<button class="btn btn-test" onclick="editRoute(${route.id}, ${route.source_id}, '${escapeHtml(route.latency_source)}', '${escapeHtml(route.latency_dest)}', '${escapeHtml(route.latency_target)}')" style="padding: 4px 10px; font-size: 0.72rem;">编辑</button>
<button class="btn btn-delete" onclick="deleteLatencyRoute(${route.id})" style="padding: 4px 10px; font-size: 0.72rem;">删除</button>
</div>
</div> </div>
`).join(''); `).join('');
} }
window.editRoute = function(id, source_id, source, dest, target) {
editingRouteId = id;
dom.routeSourceSelect.value = source_id;
dom.routeSourceInput.value = source;
dom.routeDestInput.value = dest;
dom.routeTargetInput.value = target;
dom.btnAddRoute.textContent = '保存修改';
dom.btnCancelEditRoute.style.display = 'block';
// Select the tab just in case (though it's already there)
const tab = Array.from(dom.modalTabs).find(t => t.dataset.tab === 'routes');
if (tab) tab.click();
};
function cancelEditRoute() {
editingRouteId = null;
dom.routeSourceSelect.value = "";
dom.routeSourceInput.value = "";
dom.routeDestInput.value = "";
dom.routeTargetInput.value = "";
dom.btnAddRoute.textContent = '添加线路';
dom.btnCancelEditRoute.style.display = 'none';
}
async function addLatencyRoute() { async function addLatencyRoute() {
if (!user) { if (!user) {
showSiteMessage('请先登录及进行身份验证', 'error'); showSiteMessage('请先登录及进行身份验证', 'error');
@@ -1563,21 +1598,24 @@
return; return;
} }
const url = editingRouteId ? `/api/latency-routes/${editingRouteId}` : '/api/latency-routes';
const method = editingRouteId ? 'PUT' : 'POST';
try { try {
const response = await fetch('/api/latency-routes', { const response = await fetch(url, {
method: 'POST', method,
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ source_id: parseInt(source_id), latency_source, latency_dest, latency_target }) body: JSON.stringify({ source_id: parseInt(source_id), latency_source, latency_dest, latency_target })
}); });
if (response.ok) { if (response.ok) {
showSiteMessage('线路添加成功', 'success'); showSiteMessage(editingRouteId ? '线路更新成功' : '线路添加成功', 'success');
dom.routeSourceInput.value = ''; cancelEditRoute();
dom.routeDestInput.value = '';
dom.routeTargetInput.value = '';
loadLatencyRoutes(); loadLatencyRoutes();
fetchLatency(); fetchLatency();
} else { } else {
const err = await response.json();
showSiteMessage(`操作失败: ${err.error}`, 'error');
if (response.status === 401) openLoginModal(); if (response.status === 401) openLoginModal();
} }
} catch (err) { } catch (err) {

View File

@@ -892,6 +892,19 @@ app.delete('/api/latency-routes/:id', requireAuth, async (req, res) => {
} }
}); });
app.put('/api/latency-routes/:id', requireAuth, async (req, res) => {
const { source_id, latency_source, latency_dest, latency_target } = req.body;
try {
await db.query(
'UPDATE latency_routes SET source_id = ?, latency_source = ?, latency_dest = ?, latency_target = ? WHERE id = ?',
[source_id, latency_source, latency_dest, latency_target, req.params.id]
);
res.json({ success: true });
} catch (err) {
res.status(500).json({ error: 'Failed to update latency route' });
}
});
// ==================== Metrics Latency ==================== // ==================== Metrics Latency ====================
app.get('/api/metrics/latency', async (req, res) => { app.get('/api/metrics/latency', async (req, res) => {