Compare commits

...

2 Commits

Author SHA1 Message Date
fish 5e9d9f00e8 更新数据库文件
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-26 10:02:16 +08:00
fish e155682b5f 合约列表按品种分节点展示
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-26 10:02:09 +08:00
3 changed files with 77 additions and 31 deletions
+25 -3
View File
@@ -24,11 +24,33 @@ def get_active_contracts(db: Session) -> list[str]:
@router.get("/", response_class=HTMLResponse) @router.get("/", response_class=HTMLResponse)
def contract_index(request: Request, db: Session = Depends(get_db)): def contract_index(request: Request, db: Session = Depends(get_db)):
active_contracts = get_active_contracts(db) from app.models import Product
# Build product → contracts mapping, ordered by product code
products = (
db.query(Product)
.order_by(Product.code)
.all()
)
product_groups = []
all_codes = []
for prod in products:
codes = [
c.code for c in prod.contracts if c.is_active
]
if codes:
product_groups.append({
"code": prod.code,
"name": prod.name,
"exchange": prod.exchange,
"contracts": codes,
})
all_codes.extend(codes)
latest = ( latest = (
db.query(DailyBar) db.query(DailyBar)
.filter(DailyBar.contract.in_(active_contracts)) .filter(DailyBar.contract.in_(all_codes))
.order_by(DailyBar.date.desc()) .order_by(DailyBar.date.desc())
.all() .all()
) )
@@ -42,7 +64,7 @@ def contract_index(request: Request, db: Session = Depends(get_db)):
template.render( template.render(
request=request, request=request,
active_nav="contracts", active_nav="contracts",
contracts=active_contracts, product_groups=product_groups,
contract_bars=contract_bars, contract_bars=contract_bars,
) )
) )
+30 -6
View File
@@ -5,12 +5,20 @@
{% block content %} {% block content %}
<div class="section-title">合约列表</div> {% for pg in product_groups %}
<div style="margin-bottom:24px;border:1px solid var(--border);border-radius:10px;overflow:hidden;">
<div class="table-wrap"> <div class="product-header"
<table> style="display:flex;align-items:center;gap:12px;padding:12px 18px;background:var(--th-bg);cursor:pointer;user-select:none;"
onclick="toggleProduct(this)">
<span class="collapse-arrow" style="font-size:0.75rem;transition:transform .2s;display:inline-block;transform:rotate(0deg);"></span>
<strong style="font-size:0.92rem;">{{ pg.code }} · {{ pg.name }}</strong>
<span style="font-size:0.78rem;color:var(--sub);">{{ pg.exchange }}</span>
<span style="font-size:0.78rem;color:var(--sub);margin-left:8px;">{{ pg.contracts|length }} 合约</span>
</div>
<div class="product-body">
<table>
<tr><th>合约</th><th>日期</th><th>开盘</th><th>收盘</th><th>最高</th><th>最低</th><th>振幅</th><th>操作</th></tr> <tr><th>合约</th><th>日期</th><th>开盘</th><th>收盘</th><th>最高</th><th>最低</th><th>振幅</th><th>操作</th></tr>
{% for c in contracts %} {% for c in pg.contracts %}
<tr> <tr>
<td><strong>{{ c }}</strong></td> <td><strong>{{ c }}</strong></td>
{% if c in contract_bars %} {% if c in contract_bars %}
@@ -32,6 +40,22 @@
<td><a href="/contracts/{{ c }}" style="color:var(--accent);text-decoration:none;">详情 →</a></td> <td><a href="/contracts/{{ c }}" style="color:var(--accent);text-decoration:none;">详情 →</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
</div>
</div> </div>
{% endfor %}
<script>
function toggleProduct(header) {
var body = header.nextElementSibling;
var arrow = header.querySelector('.collapse-arrow');
if (body.style.display === 'none') {
body.style.display = 'block';
arrow.style.transform = 'rotate(0deg)';
} else {
body.style.display = 'none';
arrow.style.transform = 'rotate(-90deg)';
}
}
</script>
{% endblock %} {% endblock %}
BIN
View File
Binary file not shown.