/* 数据管理 */ const tableNames = { stocks: '股票', stock_daily: '日线行情', news: '财经新闻', institutions: '机构', inst_ratings: '机构评级', fund_holdings: '基金持仓', watchlist: '自选股', analysis_cache: '研报缓存', analysis_history: 'AI分析历史', strategy_backtests: '策略回测', market_index: '市场指数' }; async function refreshStats() { try { const d = await api('/api/admin/stats'); $('#dbBox').innerHTML = Object.entries(d.tables).map(([k, v]) => `
${tableNames[k] || k}${v}
`).join(''); $('#vecBox').innerHTML = `
📰 新闻向量索引 (stock_news_v1) ${d.vector.news}
🏢 公司概况索引 (stock_profiles_v1) ${d.vector.profiles}
数据模式 ${d.is_mock ? '模拟数据' : '真实数据'}
`; } catch (e) { $('#dbBox').innerHTML = '
加载失败
'; } } async function rebuildBt() { if (!confirm('将重新跑全市场 6 策略 × 全部股票回测(几秒完成),确定?')) return; try { await api('/api/backtest/rebuild', { method: 'POST' }); toast('回测重建已启动'); setTimeout(refreshStats, 3000); } catch (e) { toast('启动失败'); } } /* 定时报告 */ async function sendReport(kind) { const btn = event.target; btn.disabled = true; try { const r = await api('/api/report/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ kind }) }); toast(r.msg || '已启动'); setTimeout(loadReportLog, 60000); setTimeout(loadReportLog, 150000); } catch (e) { toast('启动失败:' + e.message); } btn.disabled = false; } /* 定时报告 · 静默期 */ async function loadReportQuiet() { try { const d = await api('/api/settings'); const q = (d.quiet && d.quiet.report) || {}; $('#reportQuietEnabled').checked = !!q.enabled; $('#reportQuietRanges').value = q.ranges || ''; } catch (e) {} } async function saveReportQuiet() { try { const r = await api('/api/settings', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ quiet: { report: { enabled: $('#reportQuietEnabled').checked, ranges: $('#reportQuietRanges').value.trim() } } }) }); toast(r.msg || '已保存'); } catch (e) { toast('保存失败:' + e.message); } } async function loadReportLog() { try { const d = await api('/api/report/log'); const items = d.items || []; if (!items.length) return; $('#reportLogTb').innerHTML = items.map(r => ` ${r.sent_at} ${r.kind === 'premarket' ? '🌅 盘前' : '🌇 盘后'} ${escapeHtml(r.subject)} ${r.status === 'sent' ? '已发送' : r.status === 'quiet' ? '🌙 静默' : '失败'} ${escapeHtml(r.message || '')} `).join(''); } catch (e) {} } async function reseed() { if (!confirm('将清空全部业务数据并重新生成(含向量索引重建,需 1-3 分钟),确定继续?')) return; try { await api('/api/admin/reseed', { method: 'POST' }); toast('重灌任务已启动'); } catch (e) { toast('启动失败'); } } async function health() { $('#healthBox').innerHTML = '
检查中…
'; try { const d = await api('/api/admin/healthcheck'); $('#healthBox').innerHTML = `
${Object.entries(d).map(([k, v]) => `
${k}
${escapeHtml(v)}
`).join('')}
`; } catch (e) { $('#healthBox').innerHTML = '
检查失败
'; } } refreshStats(); loadReportLog(); loadReportQuiet();