Files
2026-08-16 17:23:53 +08:00

15 lines
4.4 KiB
JavaScript

const state={reports:[],category:'all',year:2026,month:8,selected:null};
const $=s=>document.querySelector(s); const pad=n=>String(n).padStart(2,'0');
const categoryNames={all:'全部报告',daily:'每日复盘',intraday:'盘中项目',sector:'行业观察',stock:'个股跟踪'};
function formatDate(d){return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`}
function categoryKey(r){return r.category||'all'}
function visible(){const q=($('#search-input').value||'').trim().toLowerCase();return state.reports.filter(r=>(state.category==='all'||categoryKey(r)===state.category)&&(!q||`${r.title} ${r.summary} ${(r.tags||[]).join(' ')}`.toLowerCase().includes(q)))}
function renderNav(){const counts=state.reports.reduce((a,r)=>(a[categoryKey(r)]=(a[categoryKey(r)]||0)+1,a),{});$('#category-nav').innerHTML=Object.entries(categoryNames).map(([key,name])=>`<a href="#" class="nav-item ${key===state.category?'active':''}" data-category="${key}"><span>${name}</span><b>${key==='all'?state.reports.length:counts[key]||0}</b></a>`).join('');document.querySelectorAll('.nav-item').forEach(a=>a.onclick=e=>{e.preventDefault();state.category=a.dataset.category;renderAll()})}
function renderCalendar(){const first=new Date(state.year,state.month-1,1), start=(first.getDay()+6)%7, days=new Date(state.year,state.month,0).getDate();$('#calendar-title').textContent=`${state.year}${pad(state.month)}月`;let html='';for(let i=0;i<start;i++)html+='<div class="day empty-day"></div>';for(let d=1;d<=days;d++){const date=`${state.year}-${pad(state.month)}-${pad(d)}`, has=visible().some(r=>r.date===date);html+=`<button class="day ${has?'has-report':''} ${state.selected===date?'selected':''} ${formatDate(new Date())===date?'today':''}" data-date="${date}">${d}</button>`}$('#calendar').innerHTML=html;document.querySelectorAll('.day[data-date]').forEach(b=>b.onclick=()=>{state.selected=b.dataset.date;renderAll()})}
function card(r){return `<a class="report-card" href="${r.path}" target="_blank"><div><h4>${r.title}</h4><p>${r.summary||'暂无摘要'}</p></div><div class="report-meta">${r.categoryName||categoryNames[r.category]||'报告'} <span class="tag">${(r.tags||[])[0]||'REPORT'}</span> ↗</div></a>`}
function renderReports(){const date=state.selected;const rows=visible().filter(r=>!date||r.date===date);$('#selected-label').textContent=date?date.replaceAll('-',' / '):'选择一个日期';$('#selected-count').textContent=`${rows.length} REPORTS`;$('#report-list').innerHTML=rows.length?rows.map(card).join(''):'<div class="empty">这一天还没有报告,或当前筛选条件下暂无匹配内容。</div>'}
function renderRecent(){const rows=[...visible()].sort((a,b)=>b.date.localeCompare(a.date)).slice(0,3);$('#recent-list').innerHTML=rows.length?rows.map(r=>`<a class="recent-card" href="${r.path}" target="_blank"><p class="eyebrow accent">${r.date} · ${r.categoryName||categoryNames[r.category]}</p><h4>${r.title}</h4><p>${r.summary||'打开查看详细研究内容'}</p><span class="report-meta">READ REPORT ↗</span></a>`).join(''):'<div class="empty">暂无报告</div>'}
function renderAll(){renderNav();renderCalendar();renderReports();renderRecent();$('#report-count').textContent=String(state.reports.length).padStart(2,'0');$('#category-count').textContent=String(new Set(state.reports.map(categoryKey)).size).padStart(2,'0');$('#sync-time').textContent=new Date().toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'});}
$('#prev-month').onclick=()=>{state.month--;if(state.month<1){state.month=12;state.year--}state.selected=null;renderAll()};$('#next-month').onclick=()=>{state.month++;if(state.month>12){state.month=1;state.year++}state.selected=null;renderAll()};$('#today-btn').onclick=()=>{const d=new Date();state.year=d.getFullYear();state.month=d.getMonth()+1;state.selected=formatDate(d);renderAll()};$('#all-reports').onclick=()=>{state.selected=null;renderAll()};$('#search-input').oninput=()=>renderAll();$('#footer-year').textContent=new Date().getFullYear();
fetch('data/reports.json').then(r=>r.json()).then(data=>{state.reports=data;const latest=[...data].sort((a,b)=>b.date.localeCompare(a.date))[0];if(latest){const d=new Date(`${latest.date}T00:00:00`);state.year=d.getFullYear();state.month=d.getMonth()+1;state.selected=latest.date}renderAll()}).catch(()=>{$('#report-list').innerHTML='<div class="empty">索引文件暂不可用。请运行 scripts/build-index.mjs 后重新上传。</div>'});