Files
ArmorandClaude Opus 4.7 ac5141fd02 feat: docking log management, sim_time DB-only, modal helpers
- Add docking_log_list and docking_log_delete routes with dedicated page
- _append_docking_log: detect existing state interval before creating new entry
- _append_undocking_log: find entry by node title+at_time, accept docked_at param
- Fix _entry_state_label and _entry_location to return time-correct values
- Add api_set_sim_time POST endpoint; remove sim_time from all url_for() calls
- _resolve_simulation_time simplified to DB-only (no URL param)
- app.js: add openModal/closeModal/toggleTheme helpers
- base.html: add 对接日志管理 nav item, remove Today button

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-05 16:19:32 +08:00

78 lines
2.4 KiB
JavaScript

// ─── Sidebar ───
function initSidebar() {
document.querySelectorAll('.ni[data-pg]').forEach(el => {
el.addEventListener('click', function(e) {
e.preventDefault();
window.location.href = this.getAttribute('href');
});
});
document.querySelectorAll('.nst').forEach(el => {
el.addEventListener('click', function() { this.classList.toggle('on'); });
});
}
initSidebar();
// ─── Modal Helpers ───
function openModal(id) {
const el = document.getElementById(id);
if (el) el.classList.add('open');
}
function closeModal(id) {
const el = document.getElementById(id);
if (el) el.classList.remove('open');
}
document.addEventListener('keydown', function(e) {
if (e.key !== 'Escape') return;
document.querySelectorAll('.modal-bg.open').forEach(el => el.classList.remove('open'));
});
// ─── Global Time Control ───
function openTimeModal() {
const display = document.getElementById('sim-time-display');
if (!display) return;
const modal = document.getElementById('time-modal');
const input = document.getElementById('time-input');
if (modal && input) {
input.value = display.textContent.trim().replace(' ', 'T');
modal.classList.add('open');
}
}
function closeTimeModal() {
const modal = document.getElementById('time-modal');
if (modal) modal.classList.remove('open');
}
async function applyTime() {
const input = document.getElementById('time-input');
if (!input || !input.value) return;
await setSimTimeAndReload(input.value.replace('T', ' ') + ':00');
}
async function shiftTime(days) {
const display = document.getElementById('sim-time-display');
if (!display) return;
const d = new Date(display.textContent.trim().replace(' ', 'T') + 'Z');
d.setUTCDate(d.getUTCDate() + days);
await setSimTimeAndReload(d.toISOString().slice(0, 10) + ' 09:00');
}
async function resetTime() {
await setSimTimeAndReload('2060-03-12 09:00');
}
function toggleTheme() {
const root = document.documentElement;
const current = root.dataset.theme || 'dark';
const next = current === 'dark' ? 'light' : 'dark';
root.dataset.theme = next;
root.style.colorScheme = next;
try { localStorage.setItem('ksp-theme', next); } catch(e) {}
}
async function setSimTimeAndReload(timeStr) {
try {
await fetch('/api/v1/sim-time', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({sim_time: timeStr})
});
} catch(e) {}
location.reload();
}