alphax/static/watchlist.html
2026-05-16 15:45:59 +08:00

31 lines
5.1 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 Crypto{% endblock %}
{% block extra_head_css %}
<style>
.shell{width:min(100% - 40px,1180px);margin:0 auto;padding:24px 0 48px}.page-head{margin-bottom:20px}.page-head h1{font-size:28px;letter-spacing:-.8px}.page-head p{color:var(--stone);font-size:14px;margin-top:4px}.grid{display:grid;grid-template-columns:1fr;gap:16px}.panel{border:1px solid var(--hairline-soft);background:var(--canvas);border-radius:var(--radius-xl);padding:18px}.panel h2{font-size:16px;margin-bottom:12px}.actions{display:flex;gap:8px;flex-wrap:wrap}.input{height:42px;border:1px solid var(--hairline-strong);border-radius:var(--radius-full);padding:0 14px;outline:none;min-width:220px}.btn{border:1px solid var(--hairline-strong);background:var(--canvas);border-radius:var(--radius-full);padding:9px 14px;font-size:13px;font-weight:700;cursor:pointer}.btn.primary{background:var(--primary);color:var(--on-primary);border-color:var(--primary)}.tokens{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}.token{display:inline-flex;align-items:center;gap:6px;background:var(--surface);border-radius:var(--radius-full);padding:6px 10px;font-size:13px;font-weight:800}.token button{border:0;background:transparent;color:var(--stone);cursor:pointer;font-weight:900}.watch-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-top:14px}.watch-card{border:1px solid var(--hairline-soft);border-radius:var(--radius-lg);padding:14px;background:var(--surface)}.watch-card b{font-size:16px}.meta{font-size:12px;color:var(--stone);margin-top:6px}.status{display:inline-flex;margin-top:8px;border-radius:var(--radius-full);padding:3px 8px;font-size:11px;font-weight:800}.status.buy{color:var(--green);background:var(--green-light)}.status.wait{color:var(--yellow-dark);background:var(--yellow-light)}.status.obs{color:var(--blue);background:rgba(66,98,255,.06)}.empty{color:var(--stone);font-size:13px;padding:12px 0}@media(max-width:820px){.watch-cards{grid-template-columns:1fr}.shell{width:min(100% - 24px,1180px);padding-top:16px}.actions .input{flex:1;min-width:160px}.btn{min-height:44px}}
</style>
{% endblock %}
{% block content %}
<div class="shell">
<div class="page-head"><h1>关注</h1><p>集中维护你关心的币种;看板里可以用“只看关注池”快速筛选。</p></div>
<div class="grid">
<section class="panel">
<h2>我的关注池</h2>
<div class="actions"><input class="input" id="symbolInput" placeholder="输入币种,如 ENS"><button class="btn primary" onclick="addSymbol()">加入关注</button><a class="btn" href="/app">回看板</a></div>
<div class="tokens" id="tokens"></div>
</section>
<section class="panel"><h2>关注池实时状态</h2><div class="watch-cards" id="watchCards"></div></section>
</div>
</div>
{% endblock %}
{% block extra_script %}
<script>
var personalization={watchlist:[]};var active=[];
function norm(s){s=String(s||'').trim().toUpperCase();return s?(s.indexOf('/')>=0?s:s+'/USDT'):''}function base(s){return String(s||'').replace('/USDT','')}function priceDecimals(p){p=Math.abs(Number(p||0));if(p<=0)return 2;if(p<0.0001)return 8;if(p<0.001)return 7;if(p<0.01)return 6;if(p<0.1)return 5;if(p<1)return 4;if(p<10)return 3;return 2}function fmtPrice(p){p=Number(p||0);return p>0?('$'+p.toFixed(priceDecimals(p))):'--'}
async function loadAll(){try{var p=await fetch('/api/personalization');if(p.ok)personalization=await p.json()}catch(e){}try{active=await (await fetch('/api/recommendations/active?actionable_only=false&hours=12')).json()}catch(e){active=[]}render()}
function render(){var wl=personalization.watchlist||[];tokens.innerHTML=wl.length?wl.map(s=>'<span class="token">'+base(s)+'<button onclick="removeSymbol(\''+base(s)+'\')">×</button></span>').join(''):'<div class="empty">暂无关注币</div>';renderWatchCards(wl)}
function renderWatchCards(wl){var map={};active.forEach(x=>map[x.symbol]=x);watchCards.innerHTML=wl.length?wl.map(s=>{var x=map[s]||{};var st=x.execution_status==='buy_now'?'buy':x.execution_status==='wait_pullback'?'wait':'obs';var label=x.execution_status==='buy_now'?'入场窗口':x.execution_status==='wait_pullback'?'等回踩':x.symbol?'观察中':'暂无信号';return '<div class="watch-card"><b>'+base(s)+'</b><div class="meta">当前价 '+fmtPrice(x.current_price)+'</div><span class="status '+st+'">'+label+'</span><div class="meta">最后信号 '+(x.rec_time?fmtTime(x.rec_time):'--')+'</div></div>'}).join(''):'<div class="empty">先加入关注币,系统会自动显示它们的实时状态。</div>'}
async function addSymbol(){var s=norm(symbolInput.value);if(!s)return;await fetch('/api/watchlist',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({symbol:s})});symbolInput.value='';loadAll()}async function removeSymbol(s){await fetch('/api/watchlist/'+encodeURIComponent(s),{method:'DELETE'});loadAll()}function fmtTime(t){if(!t)return'--';var diff=(Date.now()-new Date(t).getTime())/1000;if(diff<60)return'刚刚';if(diff<3600)return Math.round(diff/60)+'分钟前';if(diff<86400)return Math.round(diff/3600)+'小时前';var d=new Date(t);return(d.getMonth()+1)+'/'+d.getDate()}loadAll();
</script>
{% endblock %}