Templates: - mission_timeline_preview: client-side rendering with lane stacking, wheel zoom, drag pan, percentage-based layout, event dedup, scale labels - asset_detail: dock/undock modals with time selection, future event warning, Mission Label column replacing Location/State - asset_entry_form: all_locations expanded to 72 items (draft board hierarchy), all_states dynamic from DB, event point dropdown uses same list - Remove sim_time from all template url_for links - base.html: remove Today button JS: - app.js: sim_time controls use POST /api/v1/sim-time API instead of URL param Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
120 lines
5.3 KiB
HTML
120 lines
5.3 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN" data-theme="dark">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>{{ title }} · {{ config["PROJECT_TITLE"] }}</title>
|
||
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
||
<script>
|
||
// Inline theme init to prevent FOUC
|
||
(() => {
|
||
const k = 'ksp-theme', c = 'ksp_theme';
|
||
const saved = (() => { try { return localStorage.getItem(k); } catch(e) { return null; } })()
|
||
|| (document.cookie.match(/(?:^|; )ksp_theme=(dark|light)(?:;|$)/) || [])[1];
|
||
const theme = saved || 'dark';
|
||
document.documentElement.dataset.theme = theme;
|
||
document.documentElement.style.colorScheme = theme;
|
||
})();
|
||
</script>
|
||
</head>
|
||
<body>
|
||
<!-- ═══ TOPBAR ═══ -->
|
||
<div id="topbar">
|
||
<div class="brand"><b>KSP</b> 管理后台</div>
|
||
<div class="tb-sp"></div>
|
||
<div class="tb-time">
|
||
<span class="l">Sim Time</span>
|
||
<span class="td" id="sim-time-display" onclick="openTimeModal()">{{ simulation_time_display or '2060-03-12 09:00' }}</span>
|
||
<button class="b" onclick="shiftTime(-1)">−1d</button>
|
||
<button class="b" onclick="shiftTime(1)">+1d</button>
|
||
<button class="b" onclick="shiftTime(7)">+7d</button>
|
||
</div>
|
||
<button class="b" onclick="toggleTheme()" title="Toggle theme" style="margin-left:4px">◐</button>
|
||
</div>
|
||
|
||
<div id="layout">
|
||
<!-- ═══ SIDEBAR ═══ -->
|
||
<nav id="sidebar">
|
||
<a class="ni{% if active_page == 'overview' %} act{% endif %}" href="{{ url_for('web.dashboard') }}">
|
||
<span class="ic">◉</span>任务总览
|
||
</a>
|
||
|
||
<div class="nst" onclick="this.classList.toggle('on')">
|
||
<span class="ar">▾</span>任务运营
|
||
</div>
|
||
<div class="niw">
|
||
<a class="ni su{% if active_page == 'assets' %} act{% endif %}" href="{{ url_for('web.asset_list') }}">
|
||
<span class="ic">◆</span>任务资产
|
||
</a>
|
||
<a class="ni su{% if active_page == 'missions' %} act{% endif %}" href="{{ url_for('web.mission_list') }}">
|
||
<span class="ic">◈</span>任务列表
|
||
</a>
|
||
<a class="ni su{% if active_page == 'timeline' %} act{% endif %}" href="{{ url_for('web.mission_timeline_preview') }}">
|
||
<span class="ic">◫</span>时间线
|
||
</a>
|
||
<a class="ni su{% if active_page == 'location' %} act{% endif %}" href="{{ url_for('web.mission_location_board_preview') }}">
|
||
<span class="ic">◎</span>地点板
|
||
</a>
|
||
</div>
|
||
|
||
<div class="nst" onclick="this.classList.toggle('on')">
|
||
<span class="ar">▾</span>数据中心
|
||
</div>
|
||
<div class="niw">
|
||
<a class="ni su{% if active_page == 'engines' %} act{% endif %}" href="{{ url_for('web.engine_list') }}">
|
||
<span class="ic">⚙</span>引擎目录
|
||
</a>
|
||
<a class="ni su{% if active_page == 'comms' %} act{% endif %}" href="{{ url_for('web.communication_list') }}">
|
||
<span class="ic">◎</span>通信部件
|
||
</a>
|
||
<a class="ni su{% if active_page == 'tanks' %} act{% endif %}" href="{{ url_for('web.tank_list') }}">
|
||
<span class="ic">⬡</span>燃料箱规格
|
||
</a>
|
||
<a class="ni su{% if active_page == 'vehicles' %} act{% endif %}" href="{{ url_for('web.vehicle_list') }}">
|
||
<span class="ic">⇧</span>载具成本
|
||
</a>
|
||
</div>
|
||
|
||
<a class="ni{% if active_page == 'converter' %} act{% endif %}" href="{{ url_for('web.fuel_converter') }}">
|
||
<span class="ic">⇄</span>燃料换算
|
||
</a>
|
||
|
||
<a class="ni" href="{{ url_for('api.health') }}">
|
||
<span class="ic">📡</span>API 健康检查
|
||
</a>
|
||
</nav>
|
||
|
||
<!-- ═══ CONTENT ═══ -->
|
||
<main id="content">
|
||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||
{% if messages %}
|
||
<div class="flash-stack">
|
||
{% for category, message in messages %}
|
||
<div class="flash-message {{ category }}">{{ message }}</div>
|
||
{% endfor %}
|
||
</div>
|
||
{% endif %}
|
||
{% endwith %}
|
||
{% block content %}{% endblock %}
|
||
</main>
|
||
</div>
|
||
|
||
<!-- ═══ TIME MODAL ═══ -->
|
||
<div class="modal-bg" id="time-modal">
|
||
<div class="modal">
|
||
<h2>Set Simulation Time</h2>
|
||
<div class="fg">
|
||
<label>Time<input type="datetime-local" id="time-input" step="60"></label>
|
||
</div>
|
||
<div class="btn-row">
|
||
<button class="b" onclick="closeTimeModal()">Cancel</button>
|
||
<button class="b ac" onclick="applyTime()">Apply</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="{{ url_for('static', filename='app.js') }}"></script>
|
||
{% block scripts %}{% endblock %}
|
||
</body>
|
||
</html>
|