系统管理页改为 Tab 布局,按数据同步、品种管理、合约管理分栏
This commit is contained in:
+104
-30
@@ -5,20 +5,70 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.tabs { display: flex; gap: 0; margin-bottom: 24px; border-bottom: 2px solid var(--border); }
|
||||||
|
.tab-btn {
|
||||||
|
padding: 10px 20px; border: none; background: none;
|
||||||
|
font-size: 0.88rem; font-weight: 500; color: var(--sub);
|
||||||
|
cursor: pointer; border-bottom: 2px solid transparent;
|
||||||
|
margin-bottom: -2px; transition: color .12s, border-color .12s;
|
||||||
|
}
|
||||||
|
.tab-btn:hover { color: var(--fg); }
|
||||||
|
.tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
|
||||||
|
.tab-panel { display: none; }
|
||||||
|
.tab-panel.active { display: block; }
|
||||||
|
</style>
|
||||||
|
|
||||||
{# ── Sync Bar ── #}
|
{% set tab = request.query_params.get('tab', 'sync') %}
|
||||||
<div style="display:flex;align-items:center;gap:12px;margin-bottom:20px;padding:14px 18px;background:var(--surface);border:1px solid var(--border);border-radius:10px;">
|
|
||||||
<span style="font-size:0.85rem;color:var(--sub);">数据同步</span>
|
<div class="tabs">
|
||||||
|
<button class="tab-btn{% if tab == 'sync' %} active{% endif %}" onclick="switchTab('sync')">📡 数据同步</button>
|
||||||
|
<button class="tab-btn{% if tab == 'product' %} active{% endif %}" onclick="switchTab('product')">🏷️ 品种管理</button>
|
||||||
|
<button class="tab-btn{% if tab == 'contract' %} active{% endif %}" onclick="switchTab('contract')">📋 合约管理</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# ═══════════════════ Tab: 数据同步 ═══════════════════ #}
|
||||||
|
<div class="tab-panel{% if tab == 'sync' %} active{% endif %}" id="tab-sync">
|
||||||
|
<div style="display:flex;align-items:center;gap:12px;margin-bottom:16px;padding:14px 18px;background:var(--surface);border:1px solid var(--border);border-radius:10px;">
|
||||||
|
<span style="font-size:0.85rem;color:var(--sub);">全部合约</span>
|
||||||
<form method="post" action="/admin/sync" style="display:inline;">
|
<form method="post" action="/admin/sync" style="display:inline;">
|
||||||
<button type="submit" class="btn btn-primary" style="font-size:0.82rem;padding:6px 16px;">同步全部合约</button>
|
<button type="submit" class="btn btn-primary" style="font-size:0.82rem;padding:6px 16px;">同步全部</button>
|
||||||
</form>
|
</form>
|
||||||
{% if request.query_params.get('synced') %}
|
{% if request.query_params.get('synced') %}
|
||||||
<span style="font-size:0.82rem;color:var(--success-fg);">✓ 已同步 {{ request.query_params.synced }} 条</span>
|
<span style="font-size:0.82rem;color:var(--success-fg);">✓ 已同步 {{ request.query_params.synced }} 条</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{# ── New Product ── #}
|
|
||||||
<div class="section-title">新建品种</div>
|
{% if products %}
|
||||||
|
<div class="table-wrap">
|
||||||
|
<table>
|
||||||
|
<tr><th>合约</th><th>品种</th><th>状态</th><th>操作</th></tr>
|
||||||
|
{% for p in products %}
|
||||||
|
{% for c in p.contracts %}
|
||||||
|
<tr>
|
||||||
|
<td><strong>{{ c.code }}</strong></td>
|
||||||
|
<td>{{ p.name }}</td>
|
||||||
|
<td>{% if c.is_active %}<span class="badge badge-up">启用</span>{% else %}<span class="badge badge-down">停用</span>{% endif %}</td>
|
||||||
|
<td>
|
||||||
|
<a href="/contracts/{{ c.code }}" style="color:var(--accent);text-decoration:none;font-size:0.82rem;">查看</a>
|
||||||
|
<form method="post" action="/admin/sync/{{ c.code }}" style="display:inline;margin-left:8px;">
|
||||||
|
<button style="background:none;border:none;color:var(--accent);cursor:pointer;font-size:0.82rem;">↻ 同步</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div style="text-align:center;padding:40px;color:var(--sub);">暂无品种,请先在「品种管理」中新建。</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# ═══════════════════ Tab: 品种管理 ═══════════════════ #}
|
||||||
|
<div class="tab-panel{% if tab == 'product' %} active{% endif %}" id="tab-product">
|
||||||
<div class="form-card" style="margin-bottom:24px;">
|
<div class="form-card" style="margin-bottom:24px;">
|
||||||
|
<div class="section-title">新建品种</div>
|
||||||
<form method="post" action="/admin/product" style="display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;">
|
<form method="post" action="/admin/product" style="display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;">
|
||||||
<div class="form-group" style="margin-bottom:0;flex:1;min-width:120px;">
|
<div class="form-group" style="margin-bottom:0;flex:1;min-width:120px;">
|
||||||
<label>品种代码</label>
|
<label>品种代码</label>
|
||||||
@@ -40,11 +90,36 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# ── Product List ── #}
|
{% if products %}
|
||||||
|
<div class="table-wrap">
|
||||||
|
<table>
|
||||||
|
<tr><th>代码</th><th>名称</th><th>交易所</th><th>合约数</th><th>操作</th></tr>
|
||||||
{% for p in products %}
|
{% for p in products %}
|
||||||
<div class="section-title">{{ p.code }} · {{ p.name }} <span style="font-weight:400;color:var(--sub);font-size:0.78rem;">{{ p.exchange }}</span></div>
|
<tr>
|
||||||
|
<td><strong>{{ p.code }}</strong></td>
|
||||||
|
<td>{{ p.name }}</td>
|
||||||
|
<td>{{ p.exchange }}</td>
|
||||||
|
<td>{{ p.contracts|length }}</td>
|
||||||
|
<td>
|
||||||
|
<form method="post" action="/admin/product/{{ p.id }}/delete" onsubmit="return confirm('删除品种 {{ p.code }} 及其所有合约?')" style="display:inline;">
|
||||||
|
<button style="background:none;border:none;color:var(--danger);cursor:pointer;font-size:0.82rem;">删除</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div style="text-align:center;padding:40px;color:var(--sub);">暂无品种,请先新建。</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# ═══════════════════ Tab: 合约管理 ═══════════════════ #}
|
||||||
|
<div class="tab-panel{% if tab == 'contract' %} active{% endif %}" id="tab-contract">
|
||||||
|
{% if products %}
|
||||||
|
{% for p in products %}
|
||||||
|
<div class="section-title" style="margin-top:{% if not loop.first %}24px{% else %}0{% endif %};">{{ p.code }} · {{ p.name }}</div>
|
||||||
|
|
||||||
{# ── New Contract ── #}
|
|
||||||
<div class="form-card" style="margin-bottom:12px;">
|
<div class="form-card" style="margin-bottom:12px;">
|
||||||
<form method="post" action="/admin/contract" style="display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;">
|
<form method="post" action="/admin/contract" style="display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;">
|
||||||
<input type="hidden" name="product_id" value="{{ p.id }}">
|
<input type="hidden" name="product_id" value="{{ p.id }}">
|
||||||
@@ -60,27 +135,16 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# ── Contract List ── #}
|
|
||||||
{% if p.contracts %}
|
{% if p.contracts %}
|
||||||
<div class="table-wrap" style="margin-bottom:20px;">
|
<div class="table-wrap" style="margin-bottom:20px;">
|
||||||
<table>
|
<table>
|
||||||
<tr><th>合约代码</th><th>名称</th><th>状态</th><th>行情</th><th>操作</th></tr>
|
<tr><th>合约代码</th><th>名称</th><th>状态</th><th>操作</th></tr>
|
||||||
{% for c in p.contracts %}
|
{% for c in p.contracts %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{{ c.code }}</strong></td>
|
<td><strong>{{ c.code }}</strong></td>
|
||||||
<td>{{ c.name }}</td>
|
<td>{{ c.name }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if c.is_active %}
|
{% if c.is_active %}<span class="badge badge-up">启用</span>{% else %}<span class="badge badge-down">停用</span>{% endif %}
|
||||||
<span class="badge badge-up">启用</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="badge badge-down">停用</span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="/contracts/{{ c.code }}" style="color:var(--accent);text-decoration:none;">查看</a>
|
|
||||||
<form method="post" action="/admin/sync/{{ c.code }}" style="display:inline;margin-left:8px;">
|
|
||||||
<button style="background:none;border:none;color:var(--accent);cursor:pointer;font-size:0.78rem;">↻ 同步</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<form method="post" action="/admin/contract/{{ c.id }}/toggle" style="display:inline;">
|
<form method="post" action="/admin/contract/{{ c.id }}/toggle" style="display:inline;">
|
||||||
@@ -88,7 +152,7 @@
|
|||||||
{% if c.is_active %}停用{% else %}启用{% endif %}
|
{% if c.is_active %}停用{% else %}启用{% endif %}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<form method="post" action="/admin/contract/{{ c.id }}/delete" style="display:inline;" onsubmit="return confirm('删除 {{ c.code }}?此操作不可恢复。')">
|
<form method="post" action="/admin/contract/{{ c.id }}/delete" style="display:inline;" onsubmit="return confirm('删除 {{ c.code }}?')">
|
||||||
<button style="background:none;border:none;color:var(--danger);cursor:pointer;font-size:0.82rem;">删除</button>
|
<button style="background:none;border:none;color:var(--danger);cursor:pointer;font-size:0.82rem;">删除</button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
@@ -96,14 +160,24 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<form method="post" action="/admin/product/{{ p.id }}/delete" onsubmit="return confirm('删除品种 {{ p.code }} 及其所有合约?')" style="text-align:right;margin-bottom:28px;">
|
|
||||||
<button style="background:none;border:none;color:var(--danger);cursor:pointer;font-size:0.82rem;">删除品种 {{ p.code }}</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div style="text-align:center;padding:40px;color:var(--sub);">暂无品种,请先新建。</div>
|
<div style="color:var(--sub);font-size:0.85rem;margin-bottom:16px;">暂无合约</div>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<div style="text-align:center;padding:40px;color:var(--sub);">暂无品种,请先在「品种管理」中新建。</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function switchTab(name) {
|
||||||
|
document.querySelectorAll('.tab-btn').forEach(function(b) { b.classList.remove('active'); });
|
||||||
|
document.querySelectorAll('.tab-panel').forEach(function(p) { p.classList.remove('active'); });
|
||||||
|
document.querySelector('.tab-btn[onclick="switchTab(\'' + name + '\')"]').classList.add('active');
|
||||||
|
document.getElementById('tab-' + name).classList.add('active');
|
||||||
|
var url = new URL(window.location);
|
||||||
|
url.searchParams.set('tab', name);
|
||||||
|
history.replaceState(null, '', url);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user