alphax/static/data_export.html
2026-06-07 20:58:35 +08:00

55 lines
6.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "base.html" %}
{% block title %}AlphaX Agent — 数据导出{% endblock %}
{% block extra_head_css %}
<style>
.shell{width:min(100% - 40px,1120px);margin:0 auto;padding:28px 0 56px}.hero{position:relative;overflow:hidden;border:1px solid var(--hairline-soft);border-radius:24px;background:linear-gradient(135deg,#0f172a 0%,#1f3a5f 52%,#0f766e 100%);padding:26px;color:white;box-shadow:0 24px 70px rgba(15,23,42,.18)}.hero:after{content:"";position:absolute;right:-80px;top:-80px;width:260px;height:260px;border-radius:999px;background:rgba(255,255,255,.14);filter:blur(4px)}.hero h1{position:relative;font-size:30px;font-weight:950;letter-spacing:-.9px;margin:0}.hero p{position:relative;margin:8px 0 0;max-width:760px;color:rgba(255,255,255,.78);line-height:1.65;font-size:13px}.grid{display:grid;grid-template-columns:1fr 360px;gap:14px;margin-top:14px}.panel{border:1px solid var(--hairline-soft);background:var(--canvas);border-radius:var(--radius-md);padding:16px}.panel-title{font-size:15px;font-weight:950;color:var(--ink);margin-bottom:8px}.hint{color:var(--stone);font-size:12px;line-height:1.6}.quick{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-top:14px}.choice{border:1px solid var(--hairline-soft);background:var(--surface);border-radius:16px;padding:14px;text-align:left;cursor:pointer;transition:.15s}.choice:hover,.choice.active{border-color:rgba(66,98,255,.35);background:rgba(66,98,255,.055);transform:translateY(-1px)}.choice b{display:block;font-size:18px;color:var(--ink);font-weight:950}.choice span{display:block;margin-top:4px;color:var(--stone);font-size:11px;font-weight:850}.custom{display:flex;gap:8px;align-items:center;margin-top:14px}.input{height:40px;border:1px solid var(--hairline-strong);border-radius:12px;background:var(--canvas);padding:0 12px;color:var(--ink);font-weight:850;width:110px}.btn{height:42px;border:0;border-radius:999px;background:var(--ink);color:var(--canvas);padding:0 18px;font-weight:950;cursor:pointer}.btn:disabled{opacity:.55;cursor:default}.status{margin-top:12px;border:1px solid rgba(66,98,255,.16);background:rgba(66,98,255,.05);border-radius:14px;padding:11px;color:var(--slate);font-size:12px;line-height:1.55}.list{display:grid;gap:8px;margin-top:10px}.item{display:flex;justify-content:space-between;gap:12px;border-bottom:1px solid var(--hairline-soft);padding:9px 0;font-size:12px}.item:last-child{border-bottom:0}.item b{color:var(--ink)}.item span{color:var(--stone);text-align:right}@media(max-width:900px){.grid{grid-template-columns:1fr}.quick{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:560px){.shell{width:min(100% - 24px,1120px)}.quick{grid-template-columns:1fr}.custom{align-items:stretch;flex-direction:column}.input{width:100%}}
</style>
{% endblock %}
{% block content %}
<div class="shell">
<section class="hero">
<h1>数据导出</h1>
<p>把线上最近一段时间的链路、推荐、挂单、成交、复盘、推送和配置快照打包下载。下载后的 ZIP 可以直接拿来做本地分析、策略复盘和功能优化。</p>
</section>
<div class="grid">
<section class="panel">
<div class="panel-title">选择导出窗口</div>
<div class="hint">推荐先导出 24 小时用于快速排查;做策略复盘时导出 7 天或 30 天。导出包是 ZIP里面按表拆分 JSON 文件。</div>
<div class="quick" id="quickChoices">
<button class="choice active" type="button" data-hours="24" onclick="chooseHours(24,this)"><b>24 小时</b><span>最近链路排查</span></button>
<button class="choice" type="button" data-hours="72" onclick="chooseHours(72,this)"><b>3 天</b><span>短周期异常</span></button>
<button class="choice" type="button" data-hours="168" onclick="chooseHours(168,this)"><b>7 天</b><span>策略小复盘</span></button>
<button class="choice" type="button" data-hours="720" onclick="chooseHours(720,this)"><b>30 天</b><span>完整表现分析</span></button>
</div>
<div class="custom">
<input class="input" id="customDays" type="number" min="1" max="90" value="1">
<span class="hint"></span>
<button class="btn" id="downloadBtn" type="button" onclick="downloadExport()">下载导出包</button>
</div>
<div class="status" id="exportStatus">当前选择:最近 24 小时。</div>
</section>
<aside class="panel">
<div class="panel-title">导出内容</div>
<div class="list">
<div class="item"><b>推荐链路</b><span>recommendation / screening_log / cron_run_log</span></div>
<div class="item"><b>策略交易</b><span>挂单 / 持仓 / 交易事件</span></div>
<div class="item"><b>复盘迭代</b><span>review / missed / strategy rules</span></div>
<div class="item"><b>证据源</b><span>舆情 / AI 记录</span></div>
<div class="item"><b>运行配置</b><span>策略与系统配置快照</span></div>
</div>
</aside>
</div>
</div>
{% endblock %}
{% block extra_script %}
<script>
var selectedHours=24;
function $(id){return document.getElementById(id)}
function chooseHours(hours,el){selectedHours=hours;Array.prototype.forEach.call(document.querySelectorAll('.choice'),function(x){x.classList.remove('active')});if(el)el.classList.add('active');$('customDays').value=Math.max(1,Math.round(hours/24));$('exportStatus').textContent='当前选择:最近 '+labelHours(hours)+'。'}
function labelHours(hours){if(hours===24)return'24 小时';if(hours%24===0)return (hours/24)+' 天';return hours+' 小时'}
async function downloadExport(){var days=Number($('customDays').value||1);if(days>0)selectedHours=Math.max(1,Math.min(2160,Math.round(days*24)));var btn=$('downloadBtn');btn.disabled=true;btn.textContent='打包中...';$('exportStatus').textContent='正在生成最近 '+labelHours(selectedHours)+' 的导出包,请稍等...';try{var resp=await fetch('/api/admin/data-export?hours='+encodeURIComponent(selectedHours));if(!resp.ok){var t=await resp.text();throw new Error(t||'导出失败')}var blob=await resp.blob();var name='alphax_export_'+selectedHours+'h.zip';var cd=resp.headers.get('content-disposition')||'';var m=cd.match(/filename="([^"]+)"/);if(m)name=m[1];var url=URL.createObjectURL(blob);var a=document.createElement('a');a.href=url;a.download=name;document.body.appendChild(a);a.click();a.remove();URL.revokeObjectURL(url);$('exportStatus').textContent='导出完成:'+name+'。下载后可以把 ZIP 给我做本地分析。'}catch(e){$('exportStatus').textContent='导出失败:'+e.message}finally{btn.disabled=false;btn.textContent='下载导出包'}}
</script>
{% endblock %}