优化数据库稳定性
This commit is contained in:
@@ -164,6 +164,8 @@
|
||||
|
||||
let myMap2D = null;
|
||||
let editingRouteId = null;
|
||||
let allStoredSources = [];
|
||||
let allStoredLatencyRoutes = [];
|
||||
|
||||
async function fetchJsonWithFallback(urls) {
|
||||
let lastError = null;
|
||||
@@ -330,6 +332,31 @@
|
||||
dom.btnChangePassword.addEventListener('click', saveChangePassword);
|
||||
}
|
||||
|
||||
// Settings management event delegation
|
||||
if (dom.sourceItems) {
|
||||
dom.sourceItems.addEventListener('click', (e) => {
|
||||
const btnEdit = e.target.closest('.btn-edit-source');
|
||||
const btnDelete = e.target.closest('.btn-delete-source');
|
||||
if (btnEdit) {
|
||||
window.editSource(parseInt(btnEdit.getAttribute('data-id'), 10));
|
||||
} else if (btnDelete) {
|
||||
window.deleteSource(parseInt(btnDelete.getAttribute('data-id'), 10));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (dom.latencyRoutesList) {
|
||||
dom.latencyRoutesList.addEventListener('click', (e) => {
|
||||
const btnEdit = e.target.closest('.btn-edit-route');
|
||||
const btnDelete = e.target.closest('.btn-delete-route');
|
||||
if (btnEdit) {
|
||||
window.editRoute(parseInt(btnEdit.getAttribute('data-id'), 10));
|
||||
} else if (btnDelete) {
|
||||
window.deleteLatencyRoute(parseInt(btnDelete.getAttribute('data-id'), 10));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Globe expansion (FLIP animation via Web Animations API)
|
||||
let savedGlobeRect = null;
|
||||
let globeAnimating = false;
|
||||
@@ -1811,8 +1838,8 @@
|
||||
card.className = 'detail-metric-card';
|
||||
card.style.flex = '1 1 calc(50% - 10px)';
|
||||
card.innerHTML = `
|
||||
<span class="detail-metric-label">${item.name}</span>
|
||||
<span class="detail-metric-value">${item.value || '-'}</span>
|
||||
<span class="detail-metric-label">${escapeHtml(item.name)}</span>
|
||||
<span class="detail-metric-value">${escapeHtml(item.value || '-')}</span>
|
||||
`;
|
||||
customDataContainer.appendChild(card);
|
||||
});
|
||||
@@ -1830,6 +1857,19 @@
|
||||
diskMetricItem.after(dom.detailPartitionsContainer);
|
||||
}
|
||||
|
||||
dom.detailPartitionsList.innerHTML = data.partitions.map(p => `
|
||||
<div class="partition-row">
|
||||
<div class="partition-info">
|
||||
<span class="partition-name">${escapeHtml(p.mountpoint || p.device)}</span>
|
||||
<span class="partition-usage-text">${escapeHtml(formatBytes(p.used))} / ${escapeHtml(formatBytes(p.total))}</span>
|
||||
</div>
|
||||
<div class="partition-bar-bg">
|
||||
<div class="partition-bar-fill ${getUsageClass(p.percent)}" style="width: ${p.percent}%"></div>
|
||||
</div>
|
||||
<span class="partition-percent">${p.percent.toFixed(1)}%</span>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
dom.partitionHeader.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
dom.detailPartitionsContainer.classList.toggle('active');
|
||||
@@ -2309,6 +2349,7 @@
|
||||
return;
|
||||
}
|
||||
const routes = await response.json();
|
||||
allStoredLatencyRoutes = routes;
|
||||
renderLatencyRoutes(routes);
|
||||
} catch (err) {
|
||||
console.error('Error loading latency routes:', err);
|
||||
@@ -2322,7 +2363,7 @@
|
||||
}
|
||||
|
||||
dom.latencyRoutesList.innerHTML = routes.map(route => `
|
||||
<div class="latency-route-item" style="display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: rgba(255,255,255,0.03); border: 1px solid var(--border-color); border-radius: 8px;">
|
||||
<div class="latency-route-item" data-id="${route.id}" style="display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: rgba(255,255,255,0.03); border: 1px solid var(--border-color); border-radius: 8px;">
|
||||
<div class="route-info" style="display: flex; flex-direction: column; gap: 4px;">
|
||||
<div style="font-weight: 600; font-size: 0.88rem; color: var(--text-primary);">
|
||||
${escapeHtml(route.latency_source)} ↔ ${escapeHtml(route.latency_dest)}
|
||||
@@ -2333,8 +2374,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
<button class="btn btn-test btn-edit-route" data-id="${route.id}" style="padding: 4px 10px; font-size: 0.72rem;">编辑</button>
|
||||
<button class="btn btn-delete btn-delete-route" data-id="${route.id}" style="padding: 4px 10px; font-size: 0.72rem;">删除</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
@@ -2555,6 +2596,7 @@
|
||||
}
|
||||
const sources = await response.json();
|
||||
const sourcesArray = Array.isArray(sources) ? sources : [];
|
||||
allStoredSources = sourcesArray;
|
||||
const promSources = sourcesArray.filter(s => s.type !== 'blackbox');
|
||||
if (dom.totalServersLabel) dom.totalServersLabel.textContent = `服务器总数 (${promSources.length} 数据源)`;
|
||||
updateSourceFilterOptions(sourcesArray);
|
||||
@@ -2587,8 +2629,8 @@
|
||||
${source.description ? `<div class="source-item-desc">${escapeHtml(source.description)}</div>` : ''}
|
||||
</div>
|
||||
<div class="source-item-actions">
|
||||
<button class="btn btn-secondary btn-sm" onclick="editSource(${JSON.stringify(source).replace(/"/g, '"')})">编辑</button>
|
||||
<button class="btn btn-delete btn-sm" onclick="deleteSource(${source.id})">删除</button>
|
||||
<button class="btn btn-secondary btn-sm btn-edit-source" data-id="${source.id}">编辑</button>
|
||||
<button class="btn btn-delete btn-sm btn-delete-source" data-id="${source.id}">删除</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
Reference in New Issue
Block a user