Files
2026-05-09 13:08:33 +00:00

3098 lines
131 KiB
HTML
Raw Permalink 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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="金融日报 — 北美华人投资者专属每日金融简报,由 Claude AI + Web Search 自动生成,每日两次更新">
<meta property="og:title" content="金融日报 | Financial Daily">
<meta property="og:description" content="北美华人投资者专属:全球指数·市场要闻·宏观数据·财报追踪·经济日历,每日自动更新">
<meta property="og:type" content="website">
<meta name="keywords" content="金融日报,北美投资,美股,A股,港股,宏观经济,财报,经济日历">
<meta name="theme-color" content="#070b14">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="金融日报">
<link rel="manifest" href="manifest.json">
<title>金融日报 | Financial Daily — 北美华人投资者日报</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
/* =========================================================
RESET & BASE
========================================================= */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #070b14;
--card: #0d1526;
--card-hover: #111e35;
--border: #1a2a4a;
--border-light:#243c66;
--accent: #00d4aa;
--accent-dim: #00a884;
--up: #00e676;
--down: #ff5252;
--neutral: #4fc3f7;
--warn: #ffb300;
--text: #e2e8f0;
--muted: #8899aa;
--dimmed: #4a5568;
--mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
--sans: 'Inter', system-ui, -apple-system, sans-serif;
--radius: 8px;
--radius-lg: 12px;
--shadow: 0 4px 24px rgba(0,0,0,0.4);
}
html { font-size: 14px; scroll-behavior: smooth; }
body {
font-family: var(--sans);
background: var(--bg);
color: var(--text);
min-height: 100vh;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
a { color: var(--accent); text-decoration: none; }
a:hover { color: #33e0be; text-decoration: underline; }
/* =========================================================
LAYOUT
========================================================= */
.container {
max-width: 1440px;
margin: 0 auto;
padding: 0 20px;
}
/* =========================================================
HEADER
========================================================= */
.site-header {
background: linear-gradient(180deg, #06091200 0%, var(--bg) 100%),
linear-gradient(135deg, #0a0f1e 0%, #0d1526 50%, #060b16 100%);
border-bottom: 1px solid var(--border);
padding: 20px 0 16px;
position: sticky;
top: 0;
z-index: 100;
backdrop-filter: blur(12px);
}
.header-inner {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
}
.logo-block {
display: flex;
align-items: baseline;
gap: 12px;
}
.site-title {
font-size: 1.6rem;
font-weight: 700;
letter-spacing: -0.02em;
background: linear-gradient(135deg, var(--accent) 0%, #4fc3f7 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.site-subtitle {
font-size: 0.75rem;
color: var(--muted);
font-family: var(--mono);
letter-spacing: 0.05em;
}
.header-meta {
display: flex;
align-items: center;
gap: 20px;
font-size: 0.8rem;
}
.header-date {
color: var(--muted);
font-family: var(--mono);
font-size: 0.75rem;
}
.header-badge {
display: flex;
align-items: center;
gap: 6px;
background: rgba(0, 212, 170, 0.08);
border: 1px solid rgba(0, 212, 170, 0.2);
border-radius: 20px;
padding: 4px 12px;
font-size: 0.7rem;
color: var(--accent);
letter-spacing: 0.03em;
}
.pulse-dot {
width: 6px;
height: 6px;
background: var(--accent);
border-radius: 50%;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.4; transform: scale(0.8); }
}
.header-nav a {
color: var(--muted);
font-size: 0.75rem;
padding: 4px 10px;
border: 1px solid var(--border);
border-radius: var(--radius);
transition: all 0.2s;
}
.header-nav a:hover {
color: var(--accent);
border-color: var(--accent);
text-decoration: none;
background: rgba(0,212,170,0.05);
}
/* =========================================================
SECTION LABELS
========================================================= */
.section-label {
display: flex;
align-items: center;
gap: 10px;
font-size: 0.65rem;
font-family: var(--mono);
font-weight: 600;
letter-spacing: 0.12em;
color: var(--muted);
text-transform: uppercase;
margin-bottom: 14px;
}
.section-label::before {
content: '';
display: block;
width: 3px;
height: 14px;
background: var(--accent);
border-radius: 2px;
}
.section-label::after {
content: '';
flex: 1;
height: 1px;
background: var(--border);
}
/* =========================================================
TICKER / INDICES STRIP
========================================================= */
.indices-section {
background: var(--card);
border-bottom: 1px solid var(--border);
padding: 16px 0;
overflow: hidden;
}
.indices-scroll-wrapper {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
}
.indices-scroll-wrapper::-webkit-scrollbar { display: none; }
.indices-track {
display: flex;
gap: 8px;
padding: 0 20px;
min-width: max-content;
}
.ticker-card {
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 12px 16px;
min-width: 130px;
cursor: default;
transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
position: relative;
overflow: hidden;
}
.ticker-card::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 2px;
border-radius: var(--radius) var(--radius) 0 0;
}
.ticker-card.up::before { background: var(--up); }
.ticker-card.down::before { background: var(--down); }
.ticker-card.neutral::before { background: var(--neutral); }
.ticker-card:hover {
transform: translateY(-2px);
border-color: var(--border-light);
box-shadow: var(--shadow);
}
.ticker-name {
font-size: 0.65rem;
color: var(--muted);
letter-spacing: 0.06em;
text-transform: uppercase;
margin-bottom: 4px;
}
.ticker-value {
font-family: var(--mono);
font-size: 1.05rem;
font-weight: 600;
color: var(--text);
letter-spacing: -0.01em;
margin-bottom: 4px;
}
.ticker-change {
display: inline-flex;
align-items: center;
gap: 3px;
font-family: var(--mono);
font-size: 0.72rem;
font-weight: 500;
padding: 2px 7px;
border-radius: 4px;
}
.ticker-change.up { color: var(--up); background: rgba(0,230,118,0.1); }
.ticker-change.down { color: var(--down); background: rgba(255,82,82,0.1); }
.ticker-change.neutral { color: var(--neutral); background: rgba(79,195,247,0.1); }
/* =========================================================
MAIN LAYOUT
========================================================= */
.main-content {
padding: 24px 0;
}
.two-col {
display: grid;
grid-template-columns: 60fr 40fr;
gap: 20px;
margin-bottom: 24px;
}
@media (max-width: 960px) {
.two-col { grid-template-columns: 1fr; }
}
/* =========================================================
CARDS
========================================================= */
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 20px;
transition: border-color 0.2s;
}
.card:hover { border-color: var(--border-light); }
/* =========================================================
LEADER CARDS
========================================================= */
.leaders-section { margin-bottom: 20px; }
.leader-card {
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 16px;
margin-bottom: 12px;
transition: all 0.2s;
position: relative;
}
.leader-card:hover {
border-color: var(--border-light);
transform: translateX(2px);
box-shadow: -3px 0 0 var(--accent);
}
.leader-header {
display: flex;
align-items: flex-start;
gap: 12px;
margin-bottom: 10px;
}
.leader-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-family: var(--mono);
font-size: 0.75rem;
font-weight: 700;
flex-shrink: 0;
border: 2px solid var(--border-light);
}
.leader-avatar.wb { background: rgba(255,179,0,0.12); color: var(--warn); border-color: rgba(255,179,0,0.3); }
.leader-avatar.rd { background: rgba(0,212,170,0.12); color: var(--accent); border-color: rgba(0,212,170,0.3); }
.leader-avatar.jd { background: rgba(79,195,247,0.12); color: var(--neutral); border-color: rgba(79,195,247,0.3); }
.leader-avatar.jp { background: rgba(255,82,82,0.12); color: var(--down); border-color: rgba(255,82,82,0.3); }
.leader-avatar.default { background: rgba(136,153,170,0.12); color: var(--muted); border-color: rgba(136,153,170,0.3); }
.leader-meta { flex: 1; }
.leader-name {
font-weight: 600;
font-size: 0.88rem;
color: var(--text);
}
.leader-role {
font-size: 0.7rem;
color: var(--muted);
margin-top: 1px;
}
.leader-date {
font-family: var(--mono);
font-size: 0.65rem;
color: var(--dimmed);
flex-shrink: 0;
}
.leader-quote {
font-style: italic;
font-size: 0.82rem;
color: var(--accent);
border-left: 2px solid var(--accent);
padding-left: 10px;
margin-bottom: 8px;
line-height: 1.5;
}
.leader-body {
font-size: 0.8rem;
color: var(--muted);
line-height: 1.65;
margin-bottom: 8px;
}
.tags {
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.tag {
font-size: 0.62rem;
font-family: var(--mono);
color: var(--neutral);
background: rgba(79,195,247,0.08);
border: 1px solid rgba(79,195,247,0.2);
border-radius: 3px;
padding: 2px 7px;
letter-spacing: 0.03em;
}
/* =========================================================
CENTRAL BANKS
========================================================= */
.cb-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
@media (max-width: 600px) {
.cb-grid { grid-template-columns: 1fr; }
}
.cb-card {
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 14px;
transition: all 0.2s;
}
.cb-card:hover { border-color: var(--border-light); box-shadow: var(--shadow); }
.cb-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 8px;
}
.cb-name {
font-weight: 600;
font-size: 0.85rem;
}
.cb-name-en {
font-size: 0.65rem;
color: var(--muted);
margin-top: 1px;
}
.bias-badge {
font-size: 0.6rem;
font-family: var(--mono);
font-weight: 600;
padding: 2px 8px;
border-radius: 3px;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.bias-badge.hawkish { background: rgba(255,82,82,0.12); color: var(--down); border: 1px solid rgba(255,82,82,0.25); }
.bias-badge.dovish { background: rgba(0,230,118,0.12); color: var(--up); border: 1px solid rgba(0,230,118,0.25); }
.bias-badge.neutral { background: rgba(136,153,170,0.12); color: var(--muted); border: 1px solid rgba(136,153,170,0.25); }
.cb-rate {
font-family: var(--mono);
font-size: 1.3rem;
font-weight: 700;
color: var(--accent);
margin-bottom: 4px;
}
.cb-action {
font-size: 0.75rem;
color: var(--muted);
margin-bottom: 6px;
line-height: 1.4;
}
.cb-next {
font-family: var(--mono);
font-size: 0.65rem;
color: var(--dimmed);
}
.cb-note {
font-size: 0.72rem;
color: var(--muted);
margin-top: 6px;
line-height: 1.5;
border-top: 1px solid var(--border);
padding-top: 6px;
}
/* =========================================================
NEWS
========================================================= */
.news-section { margin-bottom: 20px; }
.news-item {
border-left: 3px solid var(--border);
padding: 12px 14px;
margin-bottom: 10px;
background: var(--bg);
border-radius: 0 var(--radius) var(--radius) 0;
transition: all 0.2s;
}
.news-item:hover { border-left-width: 4px; transform: translateX(2px); }
.news-item.breaking { border-left-color: var(--down); }
.news-item.major { border-left-color: var(--warn); }
.news-item.normal { border-left-color: var(--neutral); }
.news-title {
font-weight: 600;
font-size: 0.85rem;
color: var(--text);
margin-bottom: 5px;
line-height: 1.4;
}
.news-title a { color: var(--text); }
.news-title a:hover { color: var(--accent); text-decoration: none; }
.news-body {
font-size: 0.78rem;
color: var(--muted);
line-height: 1.6;
margin-bottom: 7px;
}
.news-footer {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 6px;
}
.importance-badge {
font-size: 0.58rem;
font-family: var(--mono);
font-weight: 600;
padding: 1px 7px;
border-radius: 3px;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.importance-badge.breaking { background: rgba(255,82,82,0.15); color: var(--down); border: 1px solid rgba(255,82,82,0.3); }
.importance-badge.major { background: rgba(255,179,0,0.12); color: var(--warn); border: 1px solid rgba(255,179,0,0.25); }
.importance-badge.normal { background: rgba(79,195,247,0.08); color: var(--neutral); border: 1px solid rgba(79,195,247,0.2); }
/* =========================================================
MACRO
========================================================= */
.macro-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
@media (max-width: 480px) {
.macro-grid { grid-template-columns: 1fr; }
}
.macro-card {
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 12px 14px;
transition: all 0.2s;
}
.macro-card:hover { border-color: var(--border-light); }
.macro-indicator {
font-size: 0.65rem;
font-family: var(--mono);
color: var(--muted);
letter-spacing: 0.06em;
margin-bottom: 4px;
text-transform: uppercase;
}
.macro-value {
font-family: var(--mono);
font-size: 1.45rem;
font-weight: 700;
color: var(--text);
line-height: 1.1;
margin-bottom: 4px;
}
.macro-prev {
display: flex;
align-items: center;
gap: 5px;
font-family: var(--mono);
font-size: 0.7rem;
color: var(--muted);
margin-bottom: 5px;
}
.macro-prev .arrow { font-size: 0.8rem; }
.macro-prev .arrow.up { color: var(--up); }
.macro-prev .arrow.down { color: var(--down); }
.macro-desc {
font-size: 0.72rem;
color: var(--dimmed);
line-height: 1.4;
}
/* =========================================================
EARNINGS
========================================================= */
.earnings-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
@media (max-width: 800px) { .earnings-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .earnings-grid { grid-template-columns: 1fr; } }
.earnings-card {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 14px;
position: relative;
overflow: hidden;
transition: all 0.2s;
}
.earnings-card::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 3px;
}
.earnings-card.beat::before { background: linear-gradient(90deg, var(--up), transparent); }
.earnings-card.miss::before { background: linear-gradient(90deg, var(--down), transparent); }
.earnings-card.pending::before { background: linear-gradient(90deg, var(--muted), transparent); }
.earnings-card:hover { border-color: var(--border-light); transform: translateY(-2px); box-shadow: var(--shadow); }
.earnings-ticker {
font-family: var(--mono);
font-size: 1rem;
font-weight: 700;
color: var(--accent);
margin-bottom: 1px;
}
.earnings-company {
font-size: 0.75rem;
color: var(--muted);
margin-bottom: 10px;
}
.earnings-eps {
display: flex;
gap: 10px;
margin-bottom: 6px;
flex-wrap: wrap;
}
.eps-item {
flex: 1;
min-width: 60px;
}
.eps-label {
font-size: 0.6rem;
color: var(--dimmed);
font-family: var(--mono);
letter-spacing: 0.05em;
margin-bottom: 2px;
}
.eps-value {
font-family: var(--mono);
font-size: 0.9rem;
font-weight: 600;
}
.eps-value.actual.beat { color: var(--up); }
.eps-value.actual.miss { color: var(--down); }
.eps-value.est { color: var(--muted); }
.earnings-beat-badge {
display: inline-block;
font-size: 0.6rem;
font-family: var(--mono);
font-weight: 700;
padding: 1px 8px;
border-radius: 3px;
margin-bottom: 6px;
letter-spacing: 0.06em;
}
.earnings-beat-badge.beat { background: rgba(0,230,118,0.12); color: var(--up); border: 1px solid rgba(0,230,118,0.3); }
.earnings-beat-badge.miss { background: rgba(255,82,82,0.12); color: var(--down); border: 1px solid rgba(255,82,82,0.3); }
.earnings-beat-badge.pending { background: rgba(136,153,170,0.1); color: var(--muted); border: 1px solid rgba(136,153,170,0.2); }
.earnings-revenue {
font-size: 0.75rem;
color: var(--muted);
margin-bottom: 5px;
}
.earnings-revenue span { font-family: var(--mono); color: var(--text); font-size: 0.8rem; }
.earnings-highlight {
font-size: 0.72rem;
color: var(--dimmed);
line-height: 1.4;
border-top: 1px solid var(--border);
padding-top: 6px;
margin-top: 4px;
}
/* =========================================================
SECTORS
========================================================= */
.sectors-list { display: flex; flex-direction: column; gap: 8px; }
.sector-row {
display: grid;
grid-template-columns: 120px 50px 1fr 80px;
align-items: center;
gap: 12px;
padding: 10px 14px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius);
transition: all 0.2s;
}
.sector-row:hover { border-color: var(--border-light); }
@media (max-width: 560px) {
.sector-row { grid-template-columns: 1fr 60px; }
.sector-etf, .sector-bar-wrap { display: none; }
}
.sector-name { font-size: 0.82rem; font-weight: 500; }
.sector-name-en { font-size: 0.65rem; color: var(--muted); }
.sector-etf {
font-family: var(--mono);
font-size: 0.7rem;
color: var(--muted);
background: rgba(255,255,255,0.04);
border: 1px solid var(--border);
border-radius: 3px;
padding: 2px 6px;
text-align: center;
}
.sector-bar-wrap {
background: rgba(255,255,255,0.04);
border-radius: 3px;
height: 8px;
overflow: hidden;
}
.sector-bar {
height: 100%;
border-radius: 3px;
transition: width 0.8s ease;
}
.sector-bar.up { background: linear-gradient(90deg, var(--up), rgba(0,230,118,0.4)); }
.sector-bar.down { background: linear-gradient(90deg, var(--down), rgba(255,82,82,0.4)); }
.sector-pct {
font-family: var(--mono);
font-size: 0.82rem;
font-weight: 600;
text-align: right;
}
.sector-pct.up { color: var(--up); }
.sector-pct.down { color: var(--down); }
.sector-note {
font-size: 0.68rem;
color: var(--dimmed);
}
/* =========================================================
FOOTER
========================================================= */
.site-footer {
border-top: 1px solid var(--border);
padding: 20px 0;
margin-top: 20px;
}
.footer-inner {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 10px;
font-size: 0.72rem;
color: var(--dimmed);
}
.footer-inner a { color: var(--dimmed); }
.footer-inner a:hover { color: var(--accent); }
/* =========================================================
SECTION SPACING
========================================================= */
.section-block { margin-bottom: 24px; }
/* =========================================================
SCROLLBAR
========================================================= */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--border-light); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent-dim); }
/* =========================================================
LOADING SKELETON
========================================================= */
@keyframes shimmer {
0% { background-position: -1000px 0; }
100% { background-position: 1000px 0; }
}
.skeleton {
background: linear-gradient(90deg, var(--border) 25%, var(--border-light) 50%, var(--border) 75%);
background-size: 1000px 100%;
animation: shimmer 2s infinite;
border-radius: 4px;
}
/* =========================================================
UTILITIES
========================================================= */
.mt-0 { margin-top: 0; }
.mb-16 { margin-bottom: 16px; }
.text-up { color: var(--up); }
.text-down { color: var(--down); }
.text-muted { color: var(--muted); }
.font-mono { font-family: var(--mono); }
.text-sm { font-size: 0.75rem; }
/* =========================================================
SUMMARY / DAILY THESIS
========================================================= */
.summary-section {
padding: 14px 0;
border-bottom: 1px solid var(--border);
}
.summary-card {
background: linear-gradient(135deg, rgba(0,212,170,0.05) 0%, rgba(79,195,247,0.03) 100%);
border: 1px solid rgba(0,212,170,0.18);
border-radius: var(--radius-lg);
padding: 18px 22px;
display: flex;
align-items: flex-start;
gap: 16px;
}
.summary-icon { font-size: 1.5rem; flex-shrink: 0; padding-top: 3px; }
.summary-content { flex: 1; }
.summary-label {
font-size: 0.6rem; font-family: var(--mono); color: var(--accent);
letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 6px;
}
.summary-headline {
font-size: 1.05rem; font-weight: 700; color: var(--text);
line-height: 1.45; margin-bottom: 8px;
}
.summary-context {
font-size: 0.8rem; color: var(--muted); line-height: 1.65; margin-bottom: 10px;
}
.summary-meta { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.sentiment-badge {
font-size: 0.62rem; font-family: var(--mono); font-weight: 600;
padding: 3px 10px; border-radius: 4px; letter-spacing: 0.06em; text-transform: uppercase;
}
.sentiment-badge.bullish { background:rgba(0,230,118,0.1); color:var(--up); border:1px solid rgba(0,230,118,0.25); }
.sentiment-badge.bearish { background:rgba(255,82,82,0.1); color:var(--down); border:1px solid rgba(255,82,82,0.25); }
.sentiment-badge.neutral { background:rgba(79,195,247,0.08); color:var(--neutral); border:1px solid rgba(79,195,247,0.2); }
.vix-display { font-family: var(--mono); font-size: 0.72rem; color: var(--muted); }
.vix-display span { color: var(--warn); font-weight: 600; }
/* =========================================================
ECONOMIC CALENDAR
========================================================= */
.calendar-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 10px;
}
.cal-item {
background: var(--bg); border: 1px solid var(--border);
border-radius: var(--radius); padding: 12px 14px;
display: flex; gap: 12px; align-items: flex-start;
transition: all 0.2s; border-left-width: 3px;
}
.cal-item:hover { border-color: var(--border-light); }
.cal-item.high { border-left-color: var(--down); }
.cal-item.medium { border-left-color: var(--warn); }
.cal-item.low { border-left-color: var(--neutral); }
.cal-date { font-family: var(--mono); font-size: 0.65rem; color: var(--muted); min-width: 58px; line-height: 1.5; }
.cal-event { font-size: 0.8rem; color: var(--text); font-weight: 500; margin-bottom: 4px; }
.cal-values { font-family: var(--mono); font-size: 0.67rem; color: var(--muted); }
.cal-values span { color: var(--neutral); }
/* =========================================================
EMAIL SUBSCRIBE
========================================================= */
.subscribe-bar {
background: linear-gradient(90deg, rgba(0,212,170,0.05), rgba(79,195,247,0.03));
border: 1px solid rgba(0,212,170,0.15);
border-radius: var(--radius-lg);
padding: 16px 24px;
display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
margin-top: 8px; margin-bottom: 20px;
}
.subscribe-text { flex: 1; min-width: 200px; }
.subscribe-text strong { color: var(--accent); font-size: 0.9rem; }
.subscribe-text p { font-size: 0.73rem; color: var(--muted); margin-top: 3px; }
.subscribe-form { display: flex; gap: 8px; flex-wrap: wrap; }
.subscribe-form input {
background: var(--bg); border: 1px solid var(--border);
border-radius: var(--radius); padding: 8px 14px;
color: var(--text); font-size: 0.8rem; width: 200px;
outline: none; transition: border-color 0.2s;
}
.subscribe-form input:focus { border-color: var(--accent); }
.subscribe-form button {
background: var(--accent); color: #07111e;
border: none; border-radius: var(--radius); padding: 8px 18px;
font-size: 0.8rem; font-weight: 600; cursor: pointer; transition: all 0.2s;
}
.subscribe-form button:hover { background: #33e0be; }
/* =========================================================
SIMPLE / ADVANCED MODE TOGGLE
========================================================= */
.mode-btn {
display: flex; align-items: center; gap: 6px;
background: rgba(79,195,247,0.08); border: 1px solid rgba(79,195,247,0.25);
border-radius: 20px; padding: 5px 14px; cursor: pointer;
font-size: 0.72rem; color: var(--neutral); font-family: var(--sans);
transition: all 0.2s; white-space: nowrap;
}
.mode-btn:hover { background: rgba(79,195,247,0.15); border-color: var(--neutral); }
.mode-icon { font-size: 0.85rem; }
/* SIMPLE MODE: hide advanced sections */
body.simple-mode .col-left,
body.simple-mode .macro-section,
body.simple-mode .earnings-wrap,
body.simple-mode .sectors-wrap,
body.simple-mode .calendar-wrap,
body.simple-mode .subscribe-bar { display: none !important; }
body.simple-mode .two-col { grid-template-columns: 1fr !important; }
body.simple-mode .news-item:not(.featured) { display: none !important; }
body.simple-mode .macro-section { display: none !important; }
body.simple-mode .section-jumps { display: none !important; }
body.simple-mode .personal-section { margin-top: 8px; }
/* tldr: only visible in simple mode */
.news-tldr { display: none; }
body.simple-mode .news-tldr { display: block; }
.news-tldr {
background: rgba(0,212,170,0.06);
border-left: 2px solid var(--accent);
border-radius: 0 var(--radius) var(--radius) 0;
padding: 7px 12px;
margin: 6px 0 8px;
font-size: 0.75rem;
color: var(--text);
line-height: 1.5;
}
.tldr-label {
display: inline-block;
font-size: 0.6rem;
font-family: var(--mono);
color: var(--accent);
font-weight: 600;
letter-spacing: 0.05em;
margin-right: 6px;
text-transform: uppercase;
}
/* Simple mode: larger headline, cleaner feel */
body.simple-mode .summary-headline { font-size: 1.2rem; }
body.simple-mode .news-item.featured { margin-bottom: 14px; }
body.simple-mode .col-right { width: 100%; }
/* Mode banner shown in simple mode */
.simple-banner {
display: none;
background: rgba(0,212,170,0.06);
border: 1px solid rgba(0,212,170,0.15);
border-radius: var(--radius);
padding: 10px 16px;
font-size: 0.75rem;
color: var(--muted);
text-align: center;
margin-bottom: 14px;
}
body.simple-mode .simple-banner { display: block; }
.simple-banner a { color: var(--accent); cursor: pointer; }
/* =========================================================
PERSONAL DASHBOARD
========================================================= */
.personal-section { margin-bottom: 20px; }
.personal-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:14px; flex-wrap:wrap; gap:8px; }
.personal-privacy { font-size:0.62rem; color:var(--dimmed); font-family:var(--mono); }
.ptabs { display:flex; gap:6px; margin-bottom:16px; }
.ptab {
background:var(--bg); border:1px solid var(--border);
border-radius:6px; padding:6px 18px;
color:var(--muted); font-size:0.78rem; cursor:pointer;
transition:all 0.2s; font-family:var(--sans);
}
.ptab.active { background:rgba(0,212,170,0.1); border-color:var(--accent); color:var(--accent); }
.p-empty { color:var(--dimmed); font-size:0.78rem; padding:24px 0; text-align:center; }
.add-row { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:14px; }
.add-row input {
background:var(--bg); border:1px solid var(--border);
border-radius:var(--radius); padding:7px 12px;
color:var(--text); font-size:0.78rem; flex:1; min-width:100px;
outline:none; transition:border-color 0.2s; font-family:var(--mono);
}
.add-row input:focus { border-color:var(--accent); }
.add-row button {
background:var(--accent); color:#07111e;
border:none; border-radius:var(--radius); padding:7px 16px;
font-size:0.78rem; font-weight:600; cursor:pointer;
transition:all 0.2s; white-space:nowrap;
}
.add-row button:hover { background:#33e0be; }
/* Watchlist */
.wl-list { display:grid; grid-template-columns:repeat(auto-fill, minmax(200px,1fr)); gap:10px; }
.wl-card {
background:var(--bg); border:1px solid var(--border);
border-radius:var(--radius); padding:14px;
transition:all 0.2s; position:relative;
}
.wl-card:hover { border-color:var(--border-light); transform:translateY(-1px); box-shadow:var(--shadow); }
.wl-card-top { display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:10px; }
.wl-sym { font-family:var(--mono); font-size:0.85rem; font-weight:700; color:var(--text); }
.wl-alias { font-size:0.65rem; color:var(--muted); margin-top:2px; }
.wl-rm { background:none; border:none; color:var(--dimmed); font-size:1.1rem; cursor:pointer; padding:0; line-height:1; transition:color 0.15s; }
.wl-rm:hover { color:var(--down); }
.wl-price-block { display:flex; align-items:baseline; gap:6px; flex-wrap:wrap; }
.wl-price { font-family:var(--mono); font-size:1.1rem; font-weight:700; color:var(--text); }
.wl-cur { font-size:0.6rem; color:var(--muted); font-family:var(--mono); }
.wl-loading { font-size:0.72rem; color:var(--dimmed); }
.wl-prev { font-size:0.62rem; color:var(--dimmed); font-family:var(--mono); margin-top:3px; }
/* Portfolio */
.pf-summary {
display:flex; gap:0; margin-bottom:14px;
background:rgba(0,212,170,0.04); border:1px solid rgba(0,212,170,0.15);
border-radius:var(--radius); overflow:hidden;
}
.pf-sum-item {
flex:1; padding:12px 16px; text-align:center;
border-right:1px solid rgba(0,212,170,0.1); font-size:0.7rem;
color:var(--muted);
}
.pf-sum-item:last-child { border-right:none; }
.pf-sum-item span {
display:block; font-family:var(--mono); font-size:1rem;
font-weight:700; color:var(--text); margin-top:4px;
}
.pf-pnl-pos { color:var(--up) !important; }
.pf-pnl-neg { color:var(--down) !important; }
.pf-list { display:grid; grid-template-columns:repeat(auto-fill, minmax(240px,1fr)); gap:10px; }
.pf-card {
background:var(--bg); border:1px solid var(--border);
border-radius:var(--radius); padding:14px;
transition:all 0.2s;
}
.pf-card:hover { border-color:var(--border-light); }
.pf-card-top { display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; }
.pf-sym { font-family:var(--mono); font-size:0.9rem; font-weight:700; color:var(--text); }
.pf-meta { font-size:0.7rem; color:var(--muted); margin-bottom:8px; line-height:1.7; }
.pf-pnl-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:6px; border-top:1px solid var(--border); padding-top:8px; }
.pf-cur-price { font-family:var(--mono); font-size:0.85rem; font-weight:600; color:var(--text); }
.pf-gain { font-family:var(--mono); font-size:0.8rem; font-weight:600; }
.pf-gain.pos { color:var(--up); }
.pf-gain.neg { color:var(--down); }
.sub-btn {
display:inline-flex; align-items:center; gap:6px;
padding:7px 16px; border-radius:var(--radius);
font-size:0.78rem; font-weight:600; cursor:pointer;
text-decoration:none; transition:all 0.2s; border:none;
}
.rss-btn { background:rgba(255,130,0,0.12); color:#ff8200; border:1px solid rgba(255,130,0,0.3); }
.rss-btn:hover { background:rgba(255,130,0,0.22); text-decoration:none; color:#ff8200; }
.copy-btn { background:rgba(79,195,247,0.1); color:var(--neutral); border:1px solid rgba(79,195,247,0.25); }
.copy-btn:hover { background:rgba(79,195,247,0.2); text-decoration:none; color:var(--neutral); }
/* ── Section jump nav ─────────────────────────────────── */
.section-jumps {
display: flex; gap: 4px; flex-wrap: wrap;
}
.section-jumps a {
font-size: 0.68rem; font-family: var(--mono);
color: var(--dimmed); padding: 3px 9px;
border: 1px solid var(--border); border-radius: 4px;
transition: all 0.2s; text-decoration: none;
letter-spacing: 0.02em;
}
.section-jumps a:hover {
color: var(--accent); border-color: rgba(0,212,170,0.4);
background: rgba(0,212,170,0.06); text-decoration: none;
}
/* ── Macro card color by direction ────────────────────── */
.macro-card.dir-up { border-left: 3px solid var(--up); }
.macro-card.dir-down { border-left: 3px solid var(--down); }
.macro-card.dir-neutral { border-left: 3px solid var(--dimmed); }
.macro-value-up { color: var(--up) !important; }
.macro-value-down { color: var(--down) !important; }
/* ── VIX/term tooltip ──────────────────────────────────── */
.fin-term {
border-bottom: 1px dashed var(--dimmed);
cursor: help; position: relative;
}
.fin-term::after {
content: attr(data-tip);
position: absolute; bottom: 120%; left: 50%;
transform: translateX(-50%);
background: #1a2a4a; color: var(--text);
font-size: 0.65rem; line-height: 1.4;
padding: 5px 9px; border-radius: 5px;
white-space: nowrap; pointer-events: none;
opacity: 0; transition: opacity 0.2s;
border: 1px solid var(--border-light);
z-index: 999;
}
.fin-term:hover::after { opacity: 1; }
/* ── Summary headline larger ───────────────────────────── */
.summary-headline { font-size: 1.15rem !important; }
/* ── Personal section compact when at top ─────────────── */
#sec-my.section-block { margin-top: 0; margin-bottom: 16px; }
/* live data age warning */
.data-stale { border-color: rgba(255,179,0,0.35) !important; }
/* ── Reading progress bar ──────────────────────────────────── */
#reading-progress {
position: fixed; top: 0; left: 0; height: 3px; width: 0%;
background: linear-gradient(90deg, var(--accent) 0%, #4fc3f7 100%);
z-index: 9999; transition: width 0.1s linear;
box-shadow: 0 0 8px rgba(0,212,170,0.6);
}
/* ── Sticky section jump nav ───────────────────────────── */
.jump-nav {
position: sticky; top: 0; z-index: 90;
background: rgba(7,11,20,0.94); backdrop-filter: blur(14px);
border-bottom: 1px solid var(--border);
padding: 7px 20px; display: flex; gap: 6px;
flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
}
.jump-nav::-webkit-scrollbar { display: none; }
.jump-nav a {
font-size: 0.67rem; font-family: var(--mono);
color: var(--muted); padding: 4px 10px;
border: 1px solid var(--border); border-radius: 20px;
white-space: nowrap; text-decoration: none;
transition: all 0.18s; flex-shrink: 0;
}
.jump-nav a:hover, .jump-nav a.active {
color: var(--accent); border-color: rgba(0,212,170,0.5);
background: rgba(0,212,170,0.08); text-decoration: none;
}
/* ── Floating action cluster ───────────────────────────── */
.fab-cluster {
position: fixed; bottom: 28px; right: 24px;
display: flex; flex-direction: column; gap: 10px;
z-index: 500;
}
.fab {
width: 44px; height: 44px; border-radius: 50%;
border: 1px solid var(--border-light);
background: var(--card); color: var(--muted);
display: flex; align-items: center; justify-content: center;
cursor: pointer; font-size: 1.1rem;
box-shadow: 0 4px 16px rgba(0,0,0,0.5);
transition: all 0.2s;
}
.fab:hover { background: var(--card-hover); color: var(--accent); border-color: rgba(0,212,170,0.5); transform: scale(1.08); }
#fab-top { opacity: 0; pointer-events: none; transition: opacity 0.3s; }
#fab-top.visible { opacity: 1; pointer-events: auto; }
/* ── Subscribe strip (inline, after summary) ───────────────── */
.subscribe-strip {
background: linear-gradient(135deg, rgba(0,212,170,0.06) 0%, rgba(79,195,247,0.04) 100%);
border: 1px solid rgba(0,212,170,0.2);
border-radius: var(--radius-lg); padding: 14px 18px;
display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
margin-bottom: 16px;
}
.subscribe-strip-icon { font-size: 1.3rem; flex-shrink: 0; }
.subscribe-strip-body { flex: 1; min-width: 160px; }
.subscribe-strip-body strong { display: block; color: var(--accent); font-size: 0.86rem; margin-bottom: 2px; }
.subscribe-strip-body span { font-size: 0.73rem; color: var(--muted); }
.subscribe-strip-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.btn-sub-email {
padding: 6px 12px; border-radius: 6px; border: none;
background: var(--accent); color: #000; font-size: 0.76rem;
font-weight: 600; cursor: pointer; white-space: nowrap;
}
.btn-sub-email:hover { background: #33e0be; }
.btn-sub-tg {
padding: 6px 12px; border-radius: 6px;
background: linear-gradient(135deg,#229ED9,#1a8bbf);
color: #fff; font-size: 0.76rem; font-weight: 600;
text-decoration: none; white-space: nowrap; display: flex; align-items: center; gap: 5px;
}
.btn-sub-tg:hover { opacity: 0.9; text-decoration: none; color: #fff; }
/* ── Section anchor scroll offset (for sticky jump nav) ── */
.sec-anchor { scroll-margin-top: 90px; }
/* ── Share toast ──────────────────────────────────────────── */
#share-toast {
position: fixed; bottom: 84px; right: 24px;
background: var(--card); border: 1px solid var(--border-light);
color: var(--text); font-size: 0.78rem; padding: 8px 14px;
border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.4);
opacity: 0; pointer-events: none; transition: opacity 0.3s;
z-index: 501;
}
#share-toast.show { opacity: 1; }
/* ── Mobile tweaks ────────────────────────────────────────── */
@media (max-width: 768px) {
.two-col { grid-template-columns: 1fr !important; }
.fab-cluster { bottom: 20px; right: 16px; }
.subscribe-strip { flex-direction: column; align-items: flex-start; }
.jump-nav { padding: 6px 12px; }
}
/* ── Profile Bar ──────────────────────────────────────────── */
.profile-bar { display:flex; align-items:center; gap:8px; margin-bottom:12px; flex-wrap:wrap; padding:8px 12px; background:var(--bg); border-radius:var(--radius); border:1px solid var(--border); }
.profile-label { font-size:0.72rem; color:var(--muted); white-space:nowrap; }
#profile-select { background:var(--card); color:var(--text); border:1px solid var(--border); border-radius:4px; padding:3px 8px; font-size:0.78rem; cursor:pointer; }
.profile-bar button { font-size:0.72rem; padding:3px 10px; background:var(--card); color:var(--accent); border:1px solid var(--border); border-radius:4px; cursor:pointer; white-space:nowrap; }
.profile-bar button:hover { background:var(--card-hover); }
/* ── Investment Simulator ────────────────────────────────── */
.sim-section { display:flex; flex-direction:column; gap:14px; }
.sim-label { font-size:0.7rem; color:var(--muted); font-weight:600; text-transform:uppercase; letter-spacing:0.06em; margin-bottom:5px; }
.sim-capital-row { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.sim-capital-row input[type=number] { width:140px; }
#sim-currency { background:var(--card); color:var(--text); border:1px solid var(--border); border-radius:4px; padding:4px 8px; font-size:0.82rem; }
.sim-add-row { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
.sim-pct-total { font-size:0.78rem; color:var(--muted); }
.sim-pct-total.over { color:var(--down); font-weight:600; }
.sim-assets-table { width:100%; border-collapse:collapse; font-size:0.78rem; }
.sim-assets-table th { text-align:left; color:var(--muted); font-weight:500; padding:4px 6px; border-bottom:1px solid var(--border); }
.sim-assets-table td { padding:5px 6px; border-bottom:1px solid var(--border); color:var(--text); vertical-align:middle; }
.sim-alloc-bar { height:16px; border-radius:6px; overflow:hidden; display:flex; background:var(--border); margin:4px 0; }
.sim-alloc-seg { height:100%; transition:width 0.3s ease; min-width:2px; }
.sim-horizon-row { display:flex; gap:5px; flex-wrap:wrap; align-items:center; margin-top:8px; }
.sim-horizon-row > span { font-size:0.72rem; color:var(--muted); }
.sim-hbtn { padding:3px 10px; background:var(--card); color:var(--muted); border:1px solid var(--border); border-radius:4px; font-size:0.73rem; cursor:pointer; transition:all 0.15s; }
.sim-hbtn.active { background:var(--accent); color:#000; border-color:var(--accent); font-weight:600; }
.sim-hbtn:hover:not(.active) { background:var(--card-hover); color:var(--text); }
.sim-scenario-row { display:flex; gap:14px; flex-wrap:wrap; align-items:center; }
.sim-scenario-row label { font-size:0.78rem; color:var(--muted); display:flex; align-items:center; gap:5px; }
.sim-scenario-row input[type=number] { width:62px; background:var(--card); color:var(--text); border:1px solid var(--border); border-radius:4px; padding:3px 6px; font-size:0.78rem; text-align:right; }
.sim-returns-table { width:100%; border-collapse:collapse; font-size:0.78rem; }
.sim-returns-table th { text-align:right; color:var(--muted); font-weight:500; padding:4px 6px; border-bottom:1px solid var(--border); }
.sim-returns-table th:first-child { text-align:left; }
.sim-returns-table td { padding:5px 6px; text-align:right; border-bottom:1px solid var(--border); color:var(--text); vertical-align:top; line-height:1.4; }
.sim-returns-table td:first-child { text-align:left; }
.sim-returns-table tr.total-row > td { font-weight:600; border-top:2px solid var(--border-light); background:rgba(0,212,170,0.04); }
.sim-ret-pos { color:var(--up); }
.sim-ret-neg { color:var(--down); }
.sim-actions { display:flex; gap:8px; padding-top:4px; }
.sim-btn { padding:6px 16px; border-radius:var(--radius); font-size:0.78rem; cursor:pointer; border:1px solid var(--border); }
.sim-btn-secondary { background:var(--card); color:var(--muted); }
.sim-btn:hover { opacity:0.8; }
</style>
</head>
<body>
<div id="reading-progress"></div>
<!-- =========================================================
HEADER
========================================================= -->
<header class="site-header">
<div class="container">
<div class="header-inner">
<div class="logo-block">
<span class="site-title">金融日报</span>
<span style="font-size:0.72rem;color:var(--muted);font-family:var(--mono);letter-spacing:0.05em;align-self:flex-end;padding-bottom:2px;">Financial Daily</span>
</div>
<div class="header-meta">
<span class="header-date" id="current-date">Loading...</span>
<div class="header-badge">
<span class="pulse-dot"></span>
由 Claude AI 自动生成
</div>
<nav class="header-nav">
<a href="../index.html">📁 归档</a>
<a href="../feed.xml" style="color:var(--muted);">RSS</a>
</nav>
</div>
</div>
</div>
</header>
<!-- Sticky section jump nav -->
<nav class="jump-nav" id="jump-nav">
<a href="#sec-summary">📊 大势</a>
<a href="#sec-news">📰 要闻</a>
<a href="#sec-leaders">👔 领袖</a>
<a href="#sec-macro">📈 宏观</a>
<a href="#sec-earnings">💼 财报</a>
<a href="#sec-sectors">🏭 行业</a>
<a href="#sec-banks">🏦 央行</a>
<a href="#sec-calendar">📅 日历</a>
<a href="#sec-my">⭐ 工作台</a>
</nav>
<!-- =========================================================
INDICES SECTION
========================================================= -->
<section class="indices-section">
<div class="indices-scroll-wrapper">
<div class="indices-track">
<!-- INDICES:START -->
<div class="ticker-card up">
<div class="ticker-name">标普500</div>
<div class="ticker-value">7,398.93</div>
<div class="ticker-change up">▲ +0.84%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">纳斯达克</div>
<div class="ticker-value">26,247.08</div>
<div class="ticker-change up">▲ +1.71%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">道琼斯</div>
<div class="ticker-value">49,609.16</div>
<div class="ticker-change up">▲ +0.02%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">罗素2000</div>
<div class="ticker-value">2,861.21</div>
<div class="ticker-change up">▲ +0.76%</div>
</div>
<div class="ticker-card neutral">
<div class="ticker-name">上证综指</div>
<div class="ticker-value">4,179.95</div>
<div class="ticker-change neutral"> -0.00%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">恒生指数</div>
<div class="ticker-value">26,626.28</div>
<div class="ticker-change up">▲ +1.57%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">日经225</div>
<div class="ticker-value">62,713.65</div>
<div class="ticker-change down">▼ -0.19%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">德国DAX</div>
<div class="ticker-value">24,338.63</div>
<div class="ticker-change down">▼ -1.32%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">黄金现货</div>
<div class="ticker-value">4,724.00</div>
<div class="ticker-change up">▲ +0.32%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">WTI原油</div>
<div class="ticker-value">94.81</div>
<div class="ticker-change down">▼ -0.27%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">比特币</div>
<div class="ticker-value">79,743.28</div>
<div class="ticker-change down">▼ -1.58%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">美元指数</div>
<div class="ticker-value">97.91</div>
<div class="ticker-change down">▼ -0.16%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">离岸人民币</div>
<div class="ticker-value">6.93</div>
<div class="ticker-change up">▲ -0.29%</div>
</div>
<!-- INDICES:END -->
</div>
</div>
</section>
<!-- =========================================================
DAILY SUMMARY / MARKET THESIS
========================================================= -->
<section class="summary-section sec-anchor" id="sec-summary">
<div class="container">
<!-- SUMMARY:START -->
<div class="summary-card">
<div class="summary-icon">📊</div>
<div class="summary-content">
<div class="summary-label">今日大势 · Daily Market Thesis</div>
<div class="summary-headline">科技股领涨标普创历史新高,市场无视中东冲突聚焦AI财报</div>
<div class="summary-context">尽管美伊冲突持续,美股三大指数本周全线收涨,标普500和纳斯达克连续六周上涨创2024年以来最长涨幅。强劲就业数据(4月新增11.5万就业远超预期6.5万)叠加AI基础设施需求旺盛推动科技板块飙升,AMD、英伟达等芯片股带动纳指周涨4.5%。对北美华人投资者而言,当前需关注:①原油价格虽高企但市场已消化伊朗风险,②新任美联储主席Kevin Warsh可能改变通胀计量方式为降息铺路,③特朗普5月14-15日访华峰会将聚焦伊朗问题,贸易谈判或推后。</div>
<div class="summary-meta">
<span class="sentiment-badge bullish">看多 · Bullish</span>
<span class="vix-display">VIX 恐慌指数: <span>17.18</span></span>
</div>
</div>
</div>
<!-- SUMMARY:END -->
</div>
</section>
<!-- Inline subscribe strip — above the fold -->
<div class="container" style="padding-top:12px;padding-bottom:4px;">
<div class="subscribe-strip" id="subscribe-strip">
<div class="subscribe-strip-icon">📬</div>
<div class="subscribe-strip-body">
<strong>订阅每日金融早报 — 免费</strong>
<span>每个交易日自动更新,开盘前 + 收盘后各一次</span>
</div>
<div class="subscribe-strip-actions">
<form action="https://buttondown.email/api/emails/embed-subscribe/yangbai0110" method="post" target="_blank" style="display:flex;gap:6px;">
<input type="email" name="email" placeholder="your@email.com" required
style="padding:6px 10px;border-radius:6px;border:1px solid var(--border-light);background:rgba(255,255,255,0.05);color:var(--text);font-size:0.76rem;width:158px;outline:none;" />
<button type="submit" class="btn-sub-email">📧 邮件订阅</button>
</form>
<a href="https://t.me/GGmanm_bot?start=subscribe" target="_blank" class="btn-sub-tg">
<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.894 8.221-1.97 9.28c-.145.658-.537.818-1.084.508l-3-2.21-1.447 1.394c-.16.16-.295.295-.605.295l.213-3.053 5.56-5.023c.242-.213-.054-.333-.373-.12L7.44 13.55l-2.955-.924c-.643-.204-.657-.643.136-.953l11.566-4.461c.537-.194 1.006.131.707.009z"/></svg>
Telegram
</a>
<button onclick="document.getElementById('subscribe-strip').style.display='none';localStorage.setItem('fd_sub_dismissed','1');"
style="background:none;border:none;color:var(--dimmed);cursor:pointer;font-size:1.1rem;line-height:1;padding:2px 4px;" title="关闭">×</button>
</div>
</div>
</div>
<!-- =========================================================
PERSONAL DASHBOARD — Watchlist + Portfolio
========================================================= -->
<div class="section-block personal-section sec-anchor" id="sec-my">
<div class="card">
<div class="profile-bar">
<span class="profile-label">👤 用户:</span>
<select id="profile-select" onchange="profileSwitch()"></select>
<button onclick="profileNew()"> 新建</button>
<button onclick="profileDelete()">删除</button>
</div>
<div class="personal-header">
<div class="section-label">⭐ 我的工作台 · My Dashboard</div>
<span class="personal-privacy">🔒 数据存本地 · 不上传服务器</span>
</div>
<div class="ptabs">
<button class="ptab active" id="ptab-wl" onclick="switchTab(event,'wl')">📋 自选股</button>
<button class="ptab" id="ptab-pf" onclick="switchTab(event,'pf')">💼 持仓盈亏</button>
<button class="ptab" id="ptab-sim" onclick="switchTab(event,'sim')">📊 模拟器</button>
</div>
<div id="panel-wl">
<div class="add-row">
<input id="wl-sym" placeholder="代码,如 AAPL / 000001.SS / BTC-USD" />
<input id="wl-name" placeholder="备注名(可选)" />
<button onclick="wlAdd()"> 添加</button>
</div>
<div id="wl-empty" class="p-empty">还没有自选股,输入代码开始追踪 →</div>
<div id="wl-list" class="wl-list"></div>
</div>
<div id="panel-pf" style="display:none">
<div class="add-row">
<input id="pf-sym" placeholder="代码,如 AAPL / TSLA" />
<input id="pf-shares" type="number" min="0.0001" step="0.0001" placeholder="数量" />
<input id="pf-cost" type="number" min="0" step="0.01" placeholder="买入均价 ($)" />
<button onclick="pfAdd()"> 添加持仓</button>
</div>
<div id="pf-empty" class="p-empty">还没有持仓记录,输入持仓开始计算浮盈浮亏 →</div>
<div id="pf-summary" class="pf-summary" style="display:none">
<div class="pf-sum-item">总成本<span id="sum-cost"></span></div>
<div class="pf-sum-item">总市值<span id="sum-value"></span></div>
<div class="pf-sum-item">总盈亏<span id="sum-pnl"></span></div>
<div class="pf-sum-item">盈亏率<span id="sum-pct"></span></div>
</div>
<div id="pf-list" class="pf-list"></div>
</div>
<div id="panel-sim" style="display:none">
<div class="sim-section">
<div>
<div class="sim-label">总投资金额</div>
<div class="sim-capital-row">
<input type="number" id="sim-capital" min="0" step="100" value="10000" oninput="simUpdate()" />
<select id="sim-currency" onchange="simUpdate()">
<option value="USD">USD $</option>
<option value="CAD">CAD $</option>
<option value="CNY">CNY ¥</option>
</select>
</div>
</div>
<div>
<div class="sim-label">资产配置</div>
<div class="sim-add-row">
<input id="sim-sym" placeholder="代码,如 AAPL" style="width:100px" />
<input id="sim-alias" placeholder="备注名" style="width:85px" />
<input type="number" id="sim-pct" placeholder="分配%" min="0" max="100" step="1" style="width:65px" />
<input type="number" id="sim-entry" placeholder="买入价(选填)" min="0" step="0.01" style="width:110px" />
<button onclick="simAddAsset()"> 添加</button>
<span style="font-size:0.68rem;color:var(--dimmed)">不填则自动记录当前价</span>
</div>
<div id="sim-pct-total" class="sim-pct-total" style="margin-top:4px">已分配:0%</div>
</div>
<div id="sim-alloc-bar" class="sim-alloc-bar" style="display:none"></div>
<div id="sim-assets-wrap" style="display:none">
<table class="sim-assets-table">
<thead><tr><th>代码</th><th>备注</th><th>分配%</th><th>投入金额</th><th>买入价</th><th>操作</th></tr></thead>
<tbody id="sim-assets-tbody"></tbody>
</table>
</div>
<div id="sim-scenario-section" style="display:none">
<div class="sim-label">收益情景(年化%</div>
<div class="sim-scenario-row">
<label>😨 悲观 <input type="number" id="sim-bear" value="-20" step="1" oninput="simUpdate()" /></label>
<label>📊 中性 <input type="number" id="sim-base" value="8" step="1" oninput="simUpdate()" /></label>
<label>🚀 乐观 <input type="number" id="sim-bull" value="25" step="1" oninput="simUpdate()" /></label>
</div>
<div class="sim-horizon-row">
<span>时间跨度:</span>
<button class="sim-hbtn" data-h="1m" onclick="simSetHorizon(this,'1m')">1月</button>
<button class="sim-hbtn" data-h="3m" onclick="simSetHorizon(this,'3m')">3月</button>
<button class="sim-hbtn" data-h="6m" onclick="simSetHorizon(this,'6m')">6月</button>
<button class="sim-hbtn active" data-h="1y" onclick="simSetHorizon(this,'1y')">1年</button>
<button class="sim-hbtn" data-h="3y" onclick="simSetHorizon(this,'3y')">3年</button>
<button class="sim-hbtn" data-h="5y" onclick="simSetHorizon(this,'5y')">5年</button>
</div>
</div>
<div id="sim-returns-wrap" style="display:none">
<div class="sim-label">预期收益预测</div>
<table class="sim-returns-table">
<thead>
<tr>
<th style="text-align:left">资产</th>
<th>投入</th>
<th>📈 实际</th>
<th>😨 悲观</th>
<th>📊 中性</th>
<th>🚀 乐观</th>
</tr>
</thead>
<tbody id="sim-returns-tbody"></tbody>
</table>
</div>
<div class="sim-actions">
<button class="sim-btn sim-btn-secondary" onclick="simReset()">🗑 重置</button>
</div>
</div>
</div>
</div>
</div>
<!-- =========================================================
MAIN CONTENT
========================================================= -->
<main class="main-content">
<div class="container">
<!-- TWO-COLUMN LAYOUT -->
<div class="two-col">
<!-- LEFT COLUMN (60%) -->
<div class="left-col">
<!-- LEADERS SECTION -->
<div class="section-block leaders-section sec-anchor" id="sec-leaders">
<div class="card">
<div class="section-label">市场领袖观点 · Market Leaders</div>
<!-- LEADERS:START -->
<div class="leader-card">
<div class="leader-header">
<div class="leader-avatar jd">JD</div>
<div class="leader-meta">
<div class="leader-name">杰米·戴蒙 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Jamie Dimon</span></div>
<div class="leader-role">摩根大通CEO</div>
</div>
<div class="leader-date">4月11日</div>
</div>
<div class="leader-quote">"利率就像万有引力,影响几乎所有资产价格"</div>
<div class="leader-body">戴蒙在4月股东信中重申巴菲特26年前的警告,强调当前通胀环境下利率上升风险。他警告通胀可能成为'派对上的臭鼬',导致利率高于市场预期,从而压低股票估值。戴蒙还预测黄金可能轻松涨至每盎司1万美元,并警告信贷衰退可能比预期更严重。</div>
<div class="tags"><span class="tag">#利率</span><span class="tag">#通胀</span><span class="tag">#美股</span></div>
</div>
<div class="leader-card">
<div class="leader-header">
<div class="leader-avatar default">KW</div>
<div class="leader-meta">
<div class="leader-name">凯文·沃什 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Kevin Warsh</span></div>
<div class="leader-role">美联储候任主席</div>
</div>
<div class="leader-date">4月21日</div>
</div>
<div class="leader-quote">"AI将让几乎所有东西变得更便宜"</div>
<div class="leader-body">特朗普提名的新任美联储主席沃什在4月参议院听证会上表示,希望改用'修剪平均值'衡量通胀,该指标当前显示通胀为2.3%(低于核心PCE的3.0%)。他强调AI驱动的生产率提升将带来通缩效应,为降息提供理论依据。市场预期他可能在6月首次主持FOMC会议时释放鸽派信号。</div>
<div class="tags"><span class="tag">#美联储</span><span class="tag">#通胀</span><span class="tag">#AI</span></div>
</div>
<div class="leader-card">
<div class="leader-header">
<div class="leader-avatar rd">RD</div>
<div class="leader-meta">
<div class="leader-name">雷·达利欧 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Ray Dalio</span></div>
<div class="leader-role">桥水基金创始人</div>
</div>
<div class="leader-date">2025年</div>
</div>
<div class="leader-quote">"人们的投资组合中黄金配置通常不足"</div>
<div class="leader-body">达利欧警告美国国债问题'即将到来且极其重要',预测美国终将不得不出售全球不愿购买的债务。他强调在动荡时期黄金是有效的多元化工具。去年黄金价格已飙升40%以上,但达利欧认为黄金仍有上涨空间,特别是在央行持续购金和美元储备多元化背景下。</div>
<div class="tags"><span class="tag">#黄金</span><span class="tag">#国债</span><span class="tag">#风险对冲</span></div>
</div>
<div class="leader-card">
<div class="leader-header">
<div class="leader-avatar wb">WB</div>
<div class="leader-meta">
<div class="leader-name">沃伦·巴菲特 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Warren Buffett</span></div>
<div class="leader-role">伯克希尔哈撒韦前CEO</div>
</div>
<div class="leader-date">5月1日</div>
</div>
<div class="leader-quote">"对普通人来说,最好的投资是标普500指数基金"</div>
<div class="leader-body">在5月1日伯克希尔年度股东大会上,巴菲特表示控制政府收支问题'永远无法完全解决',并警告这一问题曾重创许多文明。他重申长期看好美国股市,但强调利率对资产估值的引力作用。巴菲特还对国债激增表示担忧,呼应了戴蒙和达利欧的警告。</div>
<div class="tags"><span class="tag">#价值投资</span><span class="tag">#国债</span><span class="tag">#美股</span></div>
</div>
<div class="leader-card">
<div class="leader-header">
<div class="leader-avatar jp">JP</div>
<div class="leader-meta">
<div class="leader-name">杰罗姆·鲍威尔 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Jerome Powell</span></div>
<div class="leader-role">美联储现任主席</div>
</div>
<div class="leader-date">4月30日</div>
</div>
<div class="leader-quote">"是时候就财政可持续性展开成人对话了"</div>
<div class="leader-body">鲍威尔在4月30日最后一次主持FOMC会议(8-4分裂投票创1992年以来最大分歧),强调伊朗战争导致的油价上涨压力可能持续,但尚未改变长期通胀预期。他表示2026年通胀预期中值为2.7%,市场现预期全年利率不变甚至可能加息。鲍威尔将于5月15日卸任主席但继续担任理事,引发政府批评。</div>
<div class="tags"><span class="tag">#美联储</span><span class="tag">#利率</span><span class="tag">#通胀</span></div>
</div>
<!-- LEADERS:END -->
</div>
</div>
<!-- CENTRAL BANKS SECTION -->
<div class="section-block sec-anchor" id="sec-banks">
<div class="card">
<div class="section-label">央行动态 · Central Banks</div>
<!-- CENTRAL_BANKS:START -->
<div class="cb-grid">
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">美联储</div>
<div class="cb-name-en">Federal Reserve</div>
</div>
<span class="bias-badge hawkish">Hawkish</span>
</div>
<div class="cb-rate">3.50-3.75%</div>
<div class="cb-action">4月30日投票8-4维持利率3.50-3.75%</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-17</span></div>
<div class="cb-note">鲍威尔最后一次会议创1992年以来最大分歧,新主席沃什5月15日上任可能改变通胀衡量方式为降息铺路</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">欧洲央行</div>
<div class="cb-name-en">European Central Bank</div>
</div>
<span class="bias-badge neutral">Neutral</span>
</div>
<div class="cb-rate">3.00%</div>
<div class="cb-action">维持利率不变</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-05</span></div>
<div class="cb-note">欧元区通胀压力缓解,但伊朗战争能源成本上升带来不确定性</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">中国人民银行</div>
<div class="cb-name-en">People's Bank of China</div>
</div>
<span class="bias-badge neutral">Neutral</span>
</div>
<div class="cb-rate">1年期LPR 3.45%</div>
<div class="cb-action">维持LPR利率稳定</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-05-20</span></div>
<div class="cb-note">房地产风险缓解,通缩风险下降,核心CPI企稳,汽油价格因伊朗冲突上涨11%后实施价格上限</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">日本银行</div>
<div class="cb-name-en">Bank of Japan</div>
</div>
<span class="bias-badge hawkish">Hawkish</span>
</div>
<div class="cb-rate">0.25%</div>
<div class="cb-action">2026年首家加息的主要央行</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-13</span></div>
<div class="cb-note">通胀持续高于3%,首相高市早苗财政刺激计划推动,年底前预期再加息1-2次至4.2%</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">澳洲联储</div>
<div class="cb-name-en">Reserve Bank of Australia</div>
</div>
<span class="bias-badge hawkish">Hawkish</span>
</div>
<div class="cb-rate">4.35%</div>
<div class="cb-action">2026年首家加息并表示愿意进一步收紧</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-03</span></div>
<div class="cb-note">核心通胀持续高于3%,劳动力市场紧张,大宗商品价格强劲,澳元年初至今对美元升值6.2%</div>
</div>
</div>
<!-- CENTRAL_BANKS:END -->
</div>
</div>
</div><!-- /left-col -->
<!-- RIGHT COLUMN (40%) -->
<div class="right-col">
<!-- NEWS SECTION -->
<div class="section-block news-section sec-anchor" id="sec-news">
<div class="card">
<div class="section-label">市场要闻 · Market News</div>
<!-- NEWS:START -->
<div class="news-item breaking featured">
<div class="news-title"><a href="https://www.cnbc.com/2026/05/08/iran-focus-at-trump-xi-summit-may-delay-progress-on-tariffs-rare-earths.html" target="_blank" rel="noopener">美伊冲突主导特朗普访华议程,贸易谈判或推迟</a></div>
<div class="news-body">特朗普将于5月14-15日访问中国,这是2017年以来首次美国总统访华。财政部长贝森特已确认伊朗问题将成为核心议题。中国本周首次接待伊朗外长,引发和平协议希望推动油价下跌和股市上涨。但分析指出,伊朗问题占据主导地位意味着关税和稀土出口限制等商业议题进展可能有限。特朗普此前威胁若中国向伊朗提供武器将加征50%关税。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>中美峰会将聚焦伊朗而非贸易,关税谈判短期难有突破,持有中概股投资者需耐心等待</div>
<div class="news-footer">
<span class="importance-badge breaking">BREAKING</span>
<div class="tags"><span class="tag">#中美关系</span><span class="tag">#伊朗</span><span class="tag">#贸易</span></div>
</div>
</div>
<div class="news-item breaking featured">
<div class="news-title"><a href="https://www.cnbc.com/2026/05/07/stock-market-today-live-updates.html" target="_blank" rel="noopener">强劲就业数据推动美股创新高,市场消化加息预期</a></div>
<div class="news-body">美国4月新增就业11.5万人,远超预期的6.5万人,失业率维持4.3%。这是连续第二个月就业增长超预期,巩固了鹰派美联储官员的立场。但市场选择聚焦科技财报和AI增长前景,标普500周五收涨0.84%至7,398.93创历史新高,纳指周涨4.5%标志连续六周上涨。密歇根大学消费者信心指数降至48.2的历史新低,凸显高油价压力。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>就业强劲但市场更关注AI,科技股ETF持有者短期受益,但需警惕通胀数据意外</div>
<div class="news-footer">
<span class="importance-badge breaking">BREAKING</span>
<div class="tags"><span class="tag">#就业</span><span class="tag">#美股</span><span class="tag">#科技</span></div>
</div>
</div>
<div class="news-item high featured">
<div class="news-title">AMD Q1财报大超预期,AI芯片需求引爆股价飙升18%</div>
<div class="news-body">AMD公布Q1营收103亿美元(增长38%)和每股收益1.37美元(非GAAP),均超预期。数据中心营收58亿美元(增长57%),CEO苏姿丰表示AI推理和代理AI推动CPU和加速器需求激增。公司预测Q2营收112亿美元(增长46%),并宣布首个机架级系统Helios与MI450系列GPU。芯片行业面临全球内存短缺和伊朗战争供应链挑战。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>AMD证明AI繁荣惠及多家芯片商,半导体ETF和科技基金持有者可能继续受益</div>
<div class="news-footer">
<span class="importance-badge high">HIGH</span>
<div class="tags"><span class="tag">#AMD</span><span class="tag">#AI</span><span class="tag">#财报</span></div>
</div>
</div>
<div class="news-item high">
<div class="news-title">苹果与英特尔达成芯片制造协议,推动美国本土化</div>
<div class="news-body">苹果成为英特尔代工业务最新客户,加入微软、亚马逊和特斯拉阵营。英特尔18A制程节点已投入量产,公司预计2027年代工业务盈亏平衡。此举标志苹果从台积电部分转向美国本土制造,符合'国内制造'战略。美国政府此前对英特尔注资89亿美元(占股9.9%),英伟达随后追加50亿美元股权投资。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>半导体供应链向美国转移加速,英特尔股票可能受益,但台积电面临客户流失风险</div>
<div class="news-footer">
<span class="importance-badge high">HIGH</span>
<div class="tags"><span class="tag">#苹果</span><span class="tag">#英特尔</span><span class="tag">#芯片</span></div>
</div>
</div>
<div class="news-item high">
<div class="news-title">中国无视美国制裁继续从伊朗进口石油,贸易战升级</div>
<div class="news-body">中国政府指示炼油厂继续从伊朗进口原油,无视特朗普的25%关税威胁和霍尔木兹海峡封锁。中国国防部长警告美国不要干涉中伊双边关系,强调霍尔木兹海峡对中国航运保持开放。中国2025年从伊朗进口99.6亿美元,主要是机械、电气、汽车零部件等合法商品。中国已限制钨出口(占全球80%产量),价格3月暴涨50%。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>中美在能源和关键矿产领域对抗加剧,持有能源股和大宗商品基金可能继续受益</div>
<div class="news-footer">
<span class="importance-badge high">HIGH</span>
<div class="tags"><span class="tag">#中美关系</span><span class="tag">#能源</span><span class="tag">#关税</span></div>
</div>
</div>
<div class="news-item medium">
<div class="news-title">标普500各行业板块涨跌互现,科技领涨能源滞后</div>
<div class="news-body">5月8日收盘,科技板块(XLK)大涨超3%创近期最佳表现,AI芯片需求持续驱动。能源板块自伊朗战争以来跑赢大盘但本周回调,原油从100美元高位回落。金融、材料和工业板块受益于资本支出增长。医疗保健因运营效率改善表现稳健。通讯服务估值过高和AI支出担忧加剧。11个行业板块中9个周五上涨。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>板块轮动明显,科技和工业最强,能源获利回吐,行业ETF投资者可考虑再平衡</div>
<div class="news-footer">
<span class="importance-badge medium">MEDIUM</span>
<div class="tags"><span class="tag">#板块</span><span class="tag">#科技</span><span class="tag">#能源</span></div>
</div>
</div>
<div class="news-item high">
<div class="news-title">下周CPI报告或显示通胀升至3.7%,降息预期进一步推迟</div>
<div class="news-body">根据路透调查,4月CPI同比预计升至3.7%(为2023年9月以来最高),核心PPI预计飙升至5.0%(为2023年1月以来最高)。克利夫兰联储预测CPI将在4月达3.6%、5月达3.9%。高油价是主要推手,伊朗冲突使汽油价格超过每加仑4美元。沃什主张的修剪平均通胀指标当前为2.3%,可能为降息提供依据。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>通胀压力重燃,降息预期推迟至9月甚至2027年,债券投资者需警惕收益率上行风险</div>
<div class="news-footer">
<span class="importance-badge high">HIGH</span>
<div class="tags"><span class="tag">#通胀</span><span class="tag">#CPI</span><span class="tag">#美联储</span></div>
</div>
</div>
<!-- NEWS:END -->
</div>
</div>
<!-- MACRO SECTION -->
<div class="section-block sec-anchor" id="sec-macro">
<div class="card">
<div class="section-label">宏观指标 · Macro Data</div>
<!-- MACRO:START -->
<div class="macro-grid">
<div class="macro-card dir-down">
<div class="macro-indicator">非农就业人数(4月)</div>
<div class="macro-value macro-value-down">+115,000</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: +178,000</div>
<div class="macro-desc">远超预期的65,000,连续第二月超预期增长,失业率维持4.3%,劳动力市场韧性支持鹰派政策</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">CPI同比(3月)</div>
<div class="macro-value macro-value-down">3.3%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 3.2%</div>
<div class="macro-desc">能源价格飙升推动通胀反弹,高于预期,4月CPI预计进一步升至3.7%</div>
</div>
<div class="macro-card dir-down">
<div class="macro-indicator">核心PCE(2月)</div>
<div class="macro-value macro-value-up">3.0%</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: 3.1%</div>
<div class="macro-desc">美联储首选通胀指标小幅下降,但仍远高于2%目标</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">初请失业金(5月2日当周)</div>
<div class="macro-value macro-value-up">200,000</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 190,000</div>
<div class="macro-desc">略高于预期的206,000,四周平均值降至203,250,劳动力市场保持紧张</div>
</div>
<div class="macro-card dir-down">
<div class="macro-indicator">生产率增长(Q1)</div>
<div class="macro-value macro-value-down">+0.8%</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: +1.6%</div>
<div class="macro-desc">从Q4的1.6%放缓,单位劳动力成本增长2.3%超预期的1.6%</div>
</div>
<div class="macro-card dir-down">
<div class="macro-indicator">密歇根消费者信心(5月初)</div>
<div class="macro-value macro-value-down">48.2</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: 50.0</div>
<div class="macro-desc">创历史新低,较4月下降3.2%,高油价严重打击消费者情绪</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">WTI原油均价(Q1)</div>
<div class="macro-value macro-value-up">$72.67</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: $71.38</div>
<div class="macro-desc">同比仅增1.8%,但3月底伊朗战争爆发后飙升至101美元,Q1末达峰值</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">美国10年期国债收益率</div>
<div class="macro-value macro-value-up">4.38%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 4.30%</div>
<div class="macro-desc">从2月初的4.0%升至3月底的4.44%,反映通胀担忧和财政赤字压力</div>
</div>
</div>
<!-- MACRO:END -->
</div>
</div>
</div><!-- /right-col -->
</div><!-- /two-col -->
<!-- EARNINGS WRAP -->
========================================================= -->
<div class="section-block earnings-wrap sec-anchor" id="sec-earnings">
<div class="card">
<div class="section-label">财报追踪 · Earnings Tracker</div>
<!-- EARNINGS:START -->
<div class="earnings-grid">
<div class="earnings-card beat">
<div class="earnings-ticker">AMD</div>
<div class="earnings-company">AMD</div>
<span class="earnings-beat-badge beat">BEAT ✓</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual beat">$1.37</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$1.29</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>$10.25B</span></div>
<div class="earnings-highlight">数据中心营收增长57%至58亿美元,预测Q2营收112亿美元(增46%),股价暴涨18%</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">PLTR</div>
<div class="earnings-company">Palantir</div>
<span class="earnings-beat-badge beat">BEAT ✓</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual beat">$营收超预期5.8%</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$N/A</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>具体金额未披露</span></div>
<div class="earnings-highlight">AIP人工智能平台需求强劲无法满足,但美国商业营收略低于预期1.3%,Rule of 40得分升至145</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">ARM</div>
<div class="earnings-company">Arm Holdings</div>
<span class="earnings-beat-badge beat">BEAT ✓</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual beat">$超预期</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$N/A</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>具体金额未披露</span></div>
<div class="earnings-highlight">财报后股价初涨后跌7%,CEO警告智能手机市场因内存芯片短缺将转为负增长</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">AKAM</div>
<div class="earnings-company">Akamai</div>
<span class="earnings-beat-badge beat">BEAT ✓</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual beat">$超预期</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$N/A</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>具体金额未披露</span></div>
<div class="earnings-highlight">Q1财报喜忧参半但上调全年展望,股价暴涨28.5%</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">TSM</div>
<div class="earnings-company">台积电</div>
<span class="earnings-beat-badge pending">UPCOMING</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$N/A</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-05-08</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>NT$410.73B ($13.08B)</span></div>
<div class="earnings-highlight">4月营收环比降1.1%但同比增17.5%,面临苹果等客户转向英特尔代工压力</div>
</div>
<div class="earnings-card miss">
<div class="earnings-ticker">未上市</div>
<div class="earnings-company">CoreWeave</div>
<span class="earnings-beat-badge miss">MISS ✗</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual miss">$-$1.12</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$-$0.92</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>$2.1B (Q1)</span></div>
<div class="earnings-highlight">AI云计算公司Q2营收指引24.5-26亿美元低于预期26.9亿,资本支出上调至310-350亿美元,盘前跌7%</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">MCD</div>
<div class="earnings-company">McDonald's</div>
<span class="earnings-beat-badge beat">BEAT ✓</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual beat">$$2.83</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$$2.74</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>$6.52B</span></div>
<div class="earnings-highlight">Q1财报全面超预期,股价涨3%</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">DDOG</div>
<div class="earnings-company">Datadog</div>
<span class="earnings-beat-badge beat">BEAT ✓</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual beat">$$0.60</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$$0.51</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>Q2指引10.7-10.8亿</span></div>
<div class="earnings-highlight">软件监控公司大幅超预期,Q2指引高于市场预期9.939亿,股价飙升28%</div>
</div>
</div>
<!-- EARNINGS:END -->
</div>
</div>
<!-- SECTORS WRAP -->
========================================================= -->
<div class="section-block sec-anchor" id="sec-sectors">
<div class="card">
<div class="section-label">板块表现 · Sector Performance</div>
<!-- SECTORS:START -->
<div class="sectors-list">
<div class="sector-row">
<div><div class="sector-name">信息科技</div><div class="sector-name-en">Information Technology</div></div>
<div class="sector-etf">XLK</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:100%"></div></div>
<div class="sector-pct up">+3.00%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">通讯服务</div><div class="sector-name-en">Communication Services</div></div>
<div class="sector-etf">XLC</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:55%"></div></div>
<div class="sector-pct up">+1.50%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">非必需消费</div><div class="sector-name-en">Consumer Discretionary</div></div>
<div class="sector-etf">XLY</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:46%"></div></div>
<div class="sector-pct up">+1.20%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">工业</div><div class="sector-name-en">Industrials</div></div>
<div class="sector-etf">XLI</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:37%"></div></div>
<div class="sector-pct up">+0.90%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">金融</div><div class="sector-name-en">Financials</div></div>
<div class="sector-etf">XLF</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:34%"></div></div>
<div class="sector-pct up">+0.80%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">材料</div><div class="sector-name-en">Materials</div></div>
<div class="sector-etf">XLB</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:70%"></div></div>
<div class="sector-pct up">+2.00%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">医疗保健</div><div class="sector-name-en">Health Care</div></div>
<div class="sector-etf">XLV</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:28%"></div></div>
<div class="sector-pct up">+0.60%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">能源</div><div class="sector-name-en">Energy</div></div>
<div class="sector-etf">XLE</div>
<div class="sector-bar-wrap"><div class="sector-bar down" style="width:64%"></div></div>
<div class="sector-pct down">-1.80%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">房地产</div><div class="sector-name-en">Real Estate</div></div>
<div class="sector-etf">XLRE</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:25%"></div></div>
<div class="sector-pct up">+0.50%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">公用事业</div><div class="sector-name-en">Utilities</div></div>
<div class="sector-etf">XLU</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:22%"></div></div>
<div class="sector-pct up">+0.40%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">必需消费</div><div class="sector-name-en">Consumer Staples</div></div>
<div class="sector-etf">XLP</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:19%"></div></div>
<div class="sector-pct up">+0.30%</div>
</div>
</div>
<!-- SECTORS:END -->
</div>
<!-- =========================================================
MARKET CHARTS — TradingView Market Overview
========================================================= -->
<div class="section-block">
<div class="card" style="padding:16px 20px;">
<div class="section-label">📈 行情图表 · Live Charts</div>
<div class="tradingview-widget-container">
<div class="tradingview-widget-container__widget"></div>
<script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-market-overview.js" async>
{
"colorTheme": "dark",
"dateRange": "1D",
"showChart": true,
"locale": "zh_CN",
"isTransparent": true,
"showSymbolLogo": true,
"showFloatingTooltip": false,
"width": "100%",
"height": "480",
"tabs": [
{
"title": "🇺🇸 美股",
"symbols": [
{"s":"FOREXCOM:SPXUSD","d":"S&P 500"},
{"s":"FOREXCOM:NSXUSD","d":"Nasdaq 100"},
{"s":"FOREXCOM:DJI","d":"道琼斯"},
{"s":"CBOE:VIX","d":"VIX 恐慌指数"},
{"s":"TVC:US10Y","d":"美10年债"}
],
"originalTitle": "US"
},
{
"title": "🇨🇳 中国",
"symbols": [
{"s":"SSE:000001","d":"上证指数"},
{"s":"SZSE:399006","d":"创业板指"},
{"s":"HKEX:HSI","d":"恒生指数"},
{"s":"FX:USDCNH","d":"离岸人民币"},
{"s":"HKEX:2318","d":"中国平安"}
],
"originalTitle": "China"
},
{
"title": "🛢️ 大宗",
"symbols": [
{"s":"TVC:GOLD","d":"黄金"},
{"s":"NYMEX:CL1!","d":"原油 WTI"},
{"s":"COMEX:SI1!","d":"白银"},
{"s":"TVC:DXY","d":"美元指数"}
],
"originalTitle": "Commodities"
},
{
"title": "₿ 加密",
"symbols": [
{"s":"BINANCE:BTCUSDT","d":"Bitcoin"},
{"s":"BINANCE:ETHUSDT","d":"Ethereum"},
{"s":"BINANCE:SOLUSDT","d":"Solana"}
],
"originalTitle": "Crypto"
}
]
}
</script>
</div>
</div>
</div>
<!-- =========================================================
ECONOMIC CALENDAR (FULL WIDTH)
========================================================= -->
<div class="section-block calendar-wrap sec-anchor" id="sec-calendar">
<div class="card">
<div class="section-label">本周日程 · Economic Calendar</div>
<!-- TradingView Economic Calendar: real-time, always accurate -->
<div class="tradingview-widget-container">
<div class="tradingview-widget-container__widget"></div>
<script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-events.js" async>
{
"colorTheme": "dark",
"isTransparent": true,
"width": "100%",
"height": "420",
"locale": "zh_CN",
"importanceFilter": "0,1",
"currencyFilter": "USD,EUR,JPY,GBP,CNY,AUD,CAD"
}
</script>
</div>
<!-- Claude AI 解读:本周重点事件分析(可折叠) -->
<details style="margin-top:14px;">
<summary style="color:var(--muted);font-size:0.72rem;cursor:pointer;user-select:none;padding:6px 0;">
💬 AI 解读:本周重点事件 ▾
</summary>
<div style="margin-top:10px;">
<!-- CALENDAR:START -->
<div class="calendar-grid">
<div class="cal-item medium">
<div class="cal-date">周一 5/12<br><span style="font-size:0.6rem;color:var(--dimmed)">6:00 AM ET</span></div>
<div>
<div class="cal-event">NFIB小企业乐观指数</div>
<div class="cal-values">预期: <span>4月数据</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周二 5/13<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">CPI消费者物价指数</div>
<div class="cal-values">预期: <span>3.7% (同比)</span> &nbsp;&middot;&nbsp; 前值: 3.3%</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周二 5/13<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">PPI生产者物价指数</div>
<div class="cal-values">预期: <span>5.0% (同比)</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周三 5/14<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">零售销售</div>
<div class="cal-values">预期: <span>4月数据</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周三 5/14<br><span style="font-size:0.6rem;color:var(--dimmed)">全天</span></div>
<div>
<div class="cal-event">特朗普访华峰会第一天</div>
<div class="cal-values">预期: <span>聚焦伊朗和平谈判</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周四 5/15<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">帝国制造业指数</div>
<div class="cal-values">预期: <span>5月数据</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周四 5/15<br><span style="font-size:0.6rem;color:var(--dimmed)">全天</span></div>
<div>
<div class="cal-event">特朗普访华峰会第二天/沃什正式就任美联储主席</div>
<div class="cal-values">预期: <span>鲍威尔卸任但留任理事</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周五 5/16<br><span style="font-size:0.6rem;color:var(--dimmed)">9:15 AM ET</span></div>
<div>
<div class="cal-event">工业产出</div>
<div class="cal-values">预期: <span>4月数据</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周五 5/16<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">初请失业金人数</div>
<div class="cal-values">预期: <span>5月9日当周</span> &nbsp;&middot;&nbsp; 前值: 200,000</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周三 5/21<br><span style="font-size:0.6rem;color:var(--dimmed)">2:00 PM ET</span></div>
<div>
<div class="cal-event">FOMC会议纪要</div>
<div class="cal-values">预期: <span>4月29-30日会议</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
</div>
<!-- CALENDAR:END -->
</div>
</details>
</div>
</div>
<!-- SUBSCRIBE -->
<div class="subscribe-bar">
<div class="subscribe-text">
<strong>📬 订阅每日金融早报</strong>
<p>每个交易日自动更新,开盘前 + 收盘后各一次</p>
</div>
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;">
<!-- Email subscription (Buttondown) -->
<form action="https://buttondown.email/api/emails/embed-subscribe/yangbai0110" method="post" target="_blank"
style="display:flex;gap:6px;align-items:center;flex-wrap:wrap;">
<input type="email" name="email" placeholder="your@email.com" required
style="padding:6px 10px;border-radius:6px;border:1px solid var(--border-light);background:var(--card);color:var(--text);font-size:0.78rem;width:180px;outline:none;" />
<button type="submit"
style="padding:6px 12px;border-radius:6px;background:var(--accent);color:#000;border:none;font-size:0.78rem;font-weight:600;cursor:pointer;white-space:nowrap;">
📧 邮件订阅
</button>
</form>
<!-- Telegram -->
<a href="https://t.me/GGmanm_bot?start=subscribe" target="_blank" class="sub-btn" style="background:linear-gradient(135deg,#229ED9,#1a8bbf);color:#fff;display:flex;align-items:center;gap:6px;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" style="flex-shrink:0"><path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.894 8.221-1.97 9.28c-.145.658-.537.818-1.084.508l-3-2.21-1.447 1.394c-.16.16-.295.295-.605.295l.213-3.053 5.56-5.023c.242-.213-.054-.333-.373-.12L7.44 13.55l-2.955-.924c-.643-.204-.657-.643.136-.953l11.566-4.461c.537-.194 1.006.131.707.009z"/></svg>
Telegram 早报
</a>
<!-- RSS -->
<a href="../feed.xml" target="_blank" class="sub-btn rss-btn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" style="flex-shrink:0"><circle cx="6.18" cy="17.82" r="2.18"/><path d="M4 4.44v2.83c7.03 0 12.73 5.7 12.73 12.73h2.83c0-8.59-6.97-15.56-15.56-15.56zm0 5.66v2.83c3.9 0 7.07 3.17 7.07 7.07h2.83c0-5.47-4.43-9.9-9.9-9.9z"/></svg>
RSS
</a>
<a href="https://yang1bai.github.io/finance-daily-site/feed.xml" id="copy-rss" onclick="copyRSS(event)" class="sub-btn copy-btn">📋 复制</a>
<span id="subscriber-count" style="font-size:0.7rem;color:var(--dimmed);"></span>
</div>
</div>
</div><!-- /container -->
</main>
<!-- =========================================================
FOOTER
========================================================= -->
<footer class="site-footer">
<div class="container">
<div class="footer-inner">
<span>© 2025 金融日报 · Financial Daily &nbsp;|&nbsp; Powered by <a href="https://www.anthropic.com" target="_blank">Claude AI</a></span>
<span>内容由AI自动生成,仅供参考,不构成投资建议</span>
<a href="../feed.xml">RSS Feed</a>
</div>
<div style="display:flex;gap:24px;justify-content:center;margin-top:12px;font-size:0.75rem;color:var(--muted);">
<span>👁 访客 <strong id="footer-visitors" style="color:var(--accent)"></strong></span>
<span>📄 浏览 <strong id="footer-pageviews" style="color:var(--accent)"></strong></span>
</div>
</div>
</footer>
<script>
// Set current date
(function() {
const el = document.getElementById('current-date');
if (!el) return;
const now = new Date();
const opts = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'short' };
el.textContent = now.toLocaleDateString('zh-CN', opts);
})();
// Data age indicator
(function() {
const metaEl = document.querySelector('meta[name="last-updated"]');
if (!metaEl) return;
const updated = new Date(metaEl.content);
const ageH = (Date.now() - updated) / 3600000;
const badge = document.querySelector('.header-badge');
if (!badge) return;
const ageMin = Math.round(ageH * 60);
const ageStr = ageH < 1 ? ageMin + '分钟前更新' : Math.round(ageH) + '小时前更新';
badge.title = ageStr;
if (ageH > 14) badge.classList.add('data-stale');
})();
// Simple / Advanced mode toggle
(function() {
const btn = document.getElementById('mode-btn');
if (!btn) return;
const stored = localStorage.getItem('fd-mode') || 'advanced';
applyMode(stored);
btn.addEventListener('click', function() {
const isSimple = document.body.classList.contains('simple-mode');
const next = isSimple ? 'advanced' : 'simple';
localStorage.setItem('fd-mode', next);
applyMode(next);
});
function applyMode(mode) {
const label = btn.querySelector('.mode-label');
const icon = btn.querySelector('.mode-icon');
if (mode === 'simple') {
document.body.classList.add('simple-mode');
label.textContent = '专业模式';
icon.textContent = '📊';
} else {
document.body.classList.remove('simple-mode');
label.textContent = '新手模式';
icon.textContent = '📖';
}
}
})();
// Live quotes from data/quotes.json (populated by live-quotes workflow)
(function() {
fetch('data/quotes.json?' + Date.now())
.then(r => r.ok ? r.json() : null)
.then(data => {
if (!data || !data.quotes) return;
const track = document.querySelector('.indices-track');
if (!track) return;
data.quotes.forEach(q => {
track.querySelectorAll('.ticker-card').forEach(card => {
const nameEl = card.querySelector('.ticker-name');
if (nameEl && nameEl.textContent.trim() === q.name) {
card.className = 'ticker-card ' + q.direction;
card.querySelector('.ticker-value').textContent = q.value;
const chgEl = card.querySelector('.ticker-change');
const arrow = q.direction === 'up' ? '▲' : '▼';
chgEl.textContent = arrow + ' ' + q.change_pct;
chgEl.className = 'ticker-change ' + q.direction;
}
});
});
// Show live badge
const badge = document.querySelector('.header-badge');
if (badge) {
const updated = new Date(data.updated);
const mins = Math.round((Date.now() - updated) / 60000);
badge.title = '行情数据: ' + (mins < 60 ? mins + '分钟前' : Math.round(mins/60) + '小时前');
badge.classList.remove('data-stale');
}
})
.catch(() => {});
})();
// Auto-tooltip for financial jargon
const FIN_TERMS = {
'VIX': 'VIX = 标普期权隐含波动率,越高越恐慌',
'PCE': 'PCE = 个人消费支出物价指数,美联储首选通胀指标',
'NFP': 'NFP = 非农就业人数,衡量美国就业市场健康度',
'CPI': 'CPI = 消费者物价指数,最常见通胀衡量指标',
'PMI': 'PMI > 50 = 经济扩张;PMI < 50 = 经济收缩',
'QE': 'QE = 量化宽松,央行购买债券向市场注入流动性',
'鹰派': '鹰派 = 倾向加息/收紧货币政策,对抗通胀',
'鸽派': '鸽派 = 倾向降息/宽松货币政策,刺激经济',
'EPS': 'EPS = 每股收益,公司盈利能力的核心指标',
'DXY': 'DXY = 美元指数,衡量美元对六大货币的强弱',
};
document.addEventListener('DOMContentLoaded', function() {
const walker = document.createTreeWalker(
document.querySelector('.macro-section') || document.body,
NodeFilter.SHOW_TEXT
);
// Only apply to macro + news sections to avoid performance issues
['macro-section','news-section','cb-grid'].forEach(cls => {
const sec = document.querySelector('.' + cls);
if (!sec) return;
Object.entries(FIN_TERMS).forEach(([term, tip]) => {
sec.querySelectorAll('.macro-indicator, .cb-action, .news-body').forEach(el => {
if (el.innerHTML.includes(term) && !el.innerHTML.includes('fin-term')) {
el.innerHTML = el.innerHTML.replace(
new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g,'\\$&') + ')', 'g'),
`<span class="fin-term" data-tip="${tip}">$1</span>`
);
}
});
});
});
});
function copyRSS(e) {
e.preventDefault();
const url = 'https://yang1bai.github.io/finance-daily-site/feed.xml';
navigator.clipboard.writeText(url).then(() => {
const btn = document.getElementById('copy-rss');
btn.textContent = '✅ 已复制';
setTimeout(() => { btn.textContent = '📋 复制链接'; }, 2000);
}).catch(() => {
prompt('RSS 链接:', url);
});
}
// ═══════════════════════════════════════════════════════════
// PERSONAL DASHBOARD — Watchlist + Portfolio
// ═══════════════════════════════════════════════════════════
// ── Multi-user Profiles ──────────────────────────────────────
function profileLoad() {
return JSON.parse(localStorage.getItem('fd-profiles-v1') || 'null') || [{ id: 'default', name: '默认用户' }];
}
function profileSave(list) { localStorage.setItem('fd-profiles-v1', JSON.stringify(list)); }
function profileActive() { return localStorage.getItem('fd-active-profile-v1') || 'default'; }
function profileSetActive(id) { localStorage.setItem('fd-active-profile-v1', id); }
function profileRenderSelect() {
const list = profileLoad();
const active = profileActive();
const sel = document.getElementById('profile-select');
if (!sel) return;
sel.innerHTML = list.map(p => `<option value="${p.id}" ${p.id === active ? 'selected' : ''}>${p.name}</option>`).join('');
}
function profileSwitch() {
const sel = document.getElementById('profile-select');
if (!sel) return;
profileSetActive(sel.value);
wlRender(); pfRender(); simRender();
}
function profileNew() {
const name = prompt('输入用户名:', '用户' + (profileLoad().length + 1));
if (!name || !name.trim()) return;
const id = 'user_' + Date.now();
const list = profileLoad();
list.push({ id, name: name.trim() });
profileSave(list);
profileSetActive(id);
profileRenderSelect();
wlRender(); pfRender(); simRender();
}
function profileDelete() {
const list = profileLoad();
if (list.length <= 1) { alert('至少保留一个用户'); return; }
const active = profileActive();
const idx = list.findIndex(p => p.id === active);
if (idx === -1) return;
if (!confirm(`确认删除用户"${list[idx].name}"的所有数据?`)) return;
['watchlist-v1','portfolio-v1','sim-v1'].forEach(k => {
localStorage.removeItem(`fd-${active}-${k}`);
});
list.splice(idx, 1);
profileSave(list);
profileSetActive(list[0].id);
profileRenderSelect();
wlRender(); pfRender(); simRender();
}
// ── Dynamic localStorage keys ──────────────────────────
function lsWL() { return `fd-${profileActive()}-watchlist-v1`; }
function lsPF() { return `fd-${profileActive()}-portfolio-v1`; }
function lsSIM() { return `fd-${profileActive()}-sim-v1`; }
const priceCache = {};
function wlLoad() { return JSON.parse(localStorage.getItem(lsWL()) || '[]'); }
function wlSave(d) { localStorage.setItem(lsWL(), JSON.stringify(d)); }
function pfLoad() { return JSON.parse(localStorage.getItem(lsPF()) || '[]'); }
function pfSave(d) { localStorage.setItem(lsPF(), JSON.stringify(d)); }
function switchTab(e, tab) {
['wl','pf','sim'].forEach(t => {
document.getElementById('panel-' + t).style.display = t === tab ? 'block' : 'none';
document.getElementById('ptab-' + t).classList.toggle('active', t === tab);
});
}
// ── Price fetching (Yahoo Finance → CORS proxy fallback) ───
function toYahooSym(raw) {
if (!raw.includes(':')) return raw;
const [exch, ticker] = raw.split(':');
const map = { SSE:'', SZSE:'', HKEX:'.HK', TSX:'.TO', LSE:'.L', FWB:'.DE' };
if (exch === 'SSE') return ticker + '.SS';
if (exch === 'SZSE') return ticker + '.SZ';
return ticker + (map[exch] || '');
}
async function fetchPrice(rawSym) {
const key = rawSym;
if (priceCache[key] && Date.now() - priceCache[key].ts < 300000) return priceCache[key];
const ySym = toYahooSym(rawSym);
const yUrl = `https://query1.finance.yahoo.com/v8/finance/chart/${encodeURIComponent(ySym)}?range=1d&interval=1m&includePrePost=false`;
const proxies = [
yUrl,
`https://corsproxy.io/?${encodeURIComponent(yUrl)}`,
`https://api.allorigins.win/get?url=${encodeURIComponent(yUrl)}`
];
for (const url of proxies) {
try {
const resp = await fetch(url, { signal: AbortSignal.timeout(7000) });
if (!resp.ok) continue;
let json = await resp.json();
// allorigins wraps in {contents: '...'}
if (json.contents) json = JSON.parse(json.contents);
const result = json.chart?.result?.[0];
if (!result) continue;
const meta = result.meta;
const price = meta.regularMarketPrice;
const prev = meta.chartPreviousClose || meta.previousClose || price;
const chgPct = prev ? (price - prev) / prev * 100 : 0;
const chgAbs = price - prev;
const info = { price, prev, chgPct, chgAbs, currency: meta.currency || 'USD', ts: Date.now() };
priceCache[key] = info;
return info;
} catch(e) {}
}
return null;
}
function fmtNum(n, dec=2) {
return n.toLocaleString('en-US', { minimumFractionDigits: dec, maximumFractionDigits: dec });
}
// ── Watchlist ───────────────────────────────────────────────
function wlAdd() {
const sym = (document.getElementById('wl-sym').value || '').trim().toUpperCase();
const name = (document.getElementById('wl-name').value || '').trim();
if (!sym) return;
const list = wlLoad();
if (list.find(i => i.symbol === sym)) { alert('已在自选列表'); return; }
list.push({ symbol: sym, alias: name });
wlSave(list);
document.getElementById('wl-sym').value = '';
document.getElementById('wl-name').value = '';
wlRender();
}
function wlRemove(sym) {
wlSave(wlLoad().filter(i => i.symbol !== sym));
wlRender();
}
function wlRender() {
const list = wlLoad();
const grid = document.getElementById('wl-list');
const empty = document.getElementById('wl-empty');
if (!list.length) { empty.style.display = 'block'; grid.innerHTML = ''; return; }
empty.style.display = 'none';
grid.innerHTML = list.map(item => {
const id = 'wlp-' + item.symbol.replace(/[^a-z0-9]/gi, '_');
return `<div class="wl-card">
<div class="wl-card-top">
<div>
<div class="wl-sym">${item.symbol}</div>
${item.alias ? `<div class="wl-alias">${item.alias}</div>` : ''}
</div>
<button class="wl-rm" onclick="wlRemove('${item.symbol.replace(/'/g,"\'")}')">×</button>
</div>
<div id="${id}"><span class="wl-loading">加载中…</span></div>
</div>`;
}).join('');
list.forEach(item => {
const id = 'wlp-' + item.symbol.replace(/[^a-z0-9]/gi, '_');
fetchPrice(item.symbol).then(info => {
const el = document.getElementById(id);
if (!el) return;
if (!info) { el.innerHTML = '<span class="wl-loading">获取失败</span>'; return; }
const dir = info.chgPct >= 0 ? 'up' : 'down';
const arrow = info.chgPct >= 0 ? '▲' : '▼';
el.innerHTML = `
<div class="wl-price-block">
<span class="wl-cur">${info.currency}</span>
<span class="wl-price">${fmtNum(info.price)}</span>
<span class="ticker-change ${dir}" style="font-size:0.72rem;">${arrow} ${Math.abs(info.chgPct).toFixed(2)}%</span>
</div>
<div class="wl-prev">昨收 ${fmtNum(info.prev)}</div>
`;
});
});
}
// ── Portfolio ───────────────────────────────────────────────
function pfAdd() {
const sym = (document.getElementById('pf-sym').value || '').trim().toUpperCase();
const shares = parseFloat(document.getElementById('pf-shares').value);
const cost = parseFloat(document.getElementById('pf-cost').value);
if (!sym || !shares || !cost || isNaN(shares) || isNaN(cost)) {
alert('请完整填写代码、数量和买入均价');
return;
}
const list = pfLoad();
list.push({ symbol: sym, shares, costBasis: cost, addedAt: Date.now() });
pfSave(list);
['pf-sym','pf-shares','pf-cost'].forEach(id => document.getElementById(id).value = '');
pfRender();
}
function pfRemove(idx) {
const list = pfLoad(); list.splice(idx, 1); pfSave(list); pfRender();
}
function pfRender() {
const list = pfLoad();
const grid = document.getElementById('pf-list');
const empty = document.getElementById('pf-empty');
const sumEl = document.getElementById('pf-summary');
if (!list.length) { empty.style.display='block'; grid.innerHTML=''; sumEl.style.display='none'; return; }
empty.style.display = 'none';
sumEl.style.display = 'flex';
const totalCost = list.reduce((s, i) => s + i.shares * i.costBasis, 0);
document.getElementById('sum-cost').textContent = '$' + fmtNum(totalCost);
grid.innerHTML = list.map((item, idx) => {
const id = 'pfp-' + idx;
const itemCost = item.shares * item.costBasis;
return `<div class="pf-card">
<div class="pf-card-top">
<span class="pf-sym">${item.symbol}</span>
<button class="wl-rm" onclick="pfRemove(${idx})">×</button>
</div>
<div class="pf-meta">
${fmtNum(item.shares, 4)} 股 &nbsp;×&nbsp; $${fmtNum(item.costBasis)} 成本<br>
持仓成本 <strong>$${fmtNum(itemCost)}</strong>
</div>
<div class="pf-pnl-row" id="${id}"><span class="wl-loading">计算盈亏中…</span></div>
</div>`;
}).join('');
let fetchedCount = 0, totalValue = 0;
list.forEach((item, idx) => {
fetchPrice(item.symbol).then(info => {
fetchedCount++;
const el = document.getElementById('pfp-' + idx);
if (!el) return;
if (!info) { el.innerHTML = '<span class="wl-loading">价格获取失败</span>'; return; }
const curVal = item.shares * info.price;
const pnlAbs = curVal - item.shares * item.costBasis;
const pnlPct = pnlAbs / (item.shares * item.costBasis) * 100;
const dir = pnlAbs >= 0 ? 'pos' : 'neg';
const sign = pnlAbs >= 0 ? '+' : '';
totalValue += curVal;
el.innerHTML = `
<span class="pf-cur-price">${info.currency} ${fmtNum(info.price)}</span>
<span class="pf-gain ${dir}">${sign}$${fmtNum(pnlAbs)} (${sign}${pnlPct.toFixed(2)}%)</span>
`;
if (fetchedCount === list.length) {
document.getElementById('sum-value').textContent = '$' + fmtNum(totalValue);
const totPnl = totalValue - totalCost;
const totPct = totPnl / totalCost * 100;
const sign2 = totPnl >= 0 ? '+' : '';
const cls = totPnl >= 0 ? 'pf-pnl-pos' : 'pf-pnl-neg';
document.getElementById('sum-pnl').innerHTML = `<span class="${cls}">${sign2}$${fmtNum(totPnl)}</span>`;
document.getElementById('sum-pct').innerHTML = `<span class="${cls}">${sign2}${totPct.toFixed(2)}%</span>`;
}
});
});
}
// ── Investment Simulator ─────────────────────────────────
function simLoad() {
return JSON.parse(localStorage.getItem(lsSIM()) || 'null') || {
capital: 10000, currency: 'USD',
assets: [],
scenarios: { bear: -20, base: 8, bull: 25 },
horizon: '1y'
};
}
function simSave(d) { localStorage.setItem(lsSIM(), JSON.stringify(d)); }
function simRender() {
const d = simLoad();
const capEl = document.getElementById('sim-capital');
const curEl = document.getElementById('sim-currency');
const bearEl = document.getElementById('sim-bear');
const baseEl = document.getElementById('sim-base');
const bullEl = document.getElementById('sim-bull');
if (capEl) capEl.value = d.capital;
if (curEl) curEl.value = d.currency;
if (bearEl) bearEl.value = d.scenarios.bear;
if (baseEl) baseEl.value = d.scenarios.base;
if (bullEl) bullEl.value = d.scenarios.bull;
document.querySelectorAll('.sim-hbtn').forEach(b => {
b.classList.toggle('active', b.dataset.h === d.horizon);
});
simRenderAssets(d);
simCalcReturns(d);
}
function simRenderAssets(d) {
const capital = parseFloat(d.capital) || 0;
const totalPct = d.assets.reduce((s, a) => s + (parseFloat(a.pct)||0), 0);
const pctEl = document.getElementById('sim-pct-total');
if (pctEl) {
pctEl.textContent = `已分配:${totalPct.toFixed(1)}%`;
pctEl.className = 'sim-pct-total' + (totalPct > 100 ? ' over' : '');
}
if (!d.assets.length) {
['sim-assets-wrap','sim-alloc-bar','sim-scenario-section','sim-returns-wrap'].forEach(id => {
const el = document.getElementById(id);
if (el) el.style.display = 'none';
});
return;
}
['sim-assets-wrap','sim-scenario-section','sim-returns-wrap'].forEach(id => {
const el = document.getElementById(id);
if (el) el.style.display = 'block';
});
const bar = document.getElementById('sim-alloc-bar');
if (bar) {
bar.style.display = 'flex';
bar.innerHTML = d.assets.map((a, i) => {
const w = Math.min(parseFloat(a.pct)||0, 100);
return `<div class="sim-alloc-seg" title="${a.symbol} ${a.pct}%" style="width:${w}%;background:hsl(${i*47},65%,50%);"></div>`;
}).join('');
}
const tbody = document.getElementById('sim-assets-tbody');
if (tbody) {
const cur = d.currency === 'CNY' ? '¥' : '$';
tbody.innerHTML = d.assets.map((a, idx) => {
const invest = capital * (parseFloat(a.pct)||0) / 100;
return `<tr>
<td><strong>${a.symbol}</strong></td>
<td>${a.alias || '—'}</td>
<td><input type="number" min="0" max="100" step="1" value="${a.pct}" onchange="simUpdatePct(${idx},this.value)" style="width:55px;background:transparent;border:1px solid var(--border);color:var(--text);border-radius:3px;padding:2px 5px;" /></td>
<td>${cur}${fmtNum(invest)}</td>
<td style="font-size:0.72rem;color:var(--dimmed)">${a.entryPrice ? cur + fmtNum(a.entryPrice) : '—'}</td>
<td><button class="wl-rm" onclick="simRemoveAsset(${idx})">×</button></td>
</tr>`;
}).join('');
}
}
async function simCalcReturns(d) {
const tbody = document.getElementById('sim-returns-tbody');
if (!tbody || !d.assets.length) return;
const capital = parseFloat(d.capital) || 0;
const horizonMap = { '1m': 1/12, '3m': 0.25, '6m': 0.5, '1y': 1, '3y': 3, '5y': 5 };
const years = horizonMap[d.horizon] || 1;
const bear = parseFloat(d.scenarios.bear) / 100;
const base = parseFloat(d.scenarios.base) / 100;
const bull = parseFloat(d.scenarios.bull) / 100;
const cur = d.currency === 'CNY' ? '¥' : '$';
function calcProfit(invest, rate, yrs) { return invest * Math.pow(1 + rate, yrs) - invest; }
function sCell(v, invest) {
const p = invest ? (v / invest * 100).toFixed(1) : '0.0';
const sign = v >= 0 ? '+' : '';
const cls = v >= 0 ? 'sim-ret-pos' : 'sim-ret-neg';
return `<span class="${cls}">${sign}${cur}${fmtNum(Math.abs(v))}<br><small>${sign}${p}%</small></span>`;
}
let totBear = 0, totBase = 0, totBull = 0, totInvest = 0;
// Render scenario columns immediately
tbody.innerHTML = d.assets.map(a => {
const invest = capital * (parseFloat(a.pct)||0) / 100;
const pb = calcProfit(invest, bear, years);
const pn = calcProfit(invest, base, years);
const pu = calcProfit(invest, bull, years);
totBear += pb; totBase += pn; totBull += pu; totInvest += invest;
const rid = 'simreal-' + a.symbol.replace(/[^a-z0-9]/gi,'_');
const realCell = a.entryPrice
? `<td id="${rid}"><span style="color:var(--dimmed);font-size:0.72rem">拉取中…</span></td>`
: `<td style="color:var(--dimmed);font-size:0.72rem">无买入价</td>`;
return `<tr>
<td><strong>${a.symbol}</strong>${a.alias ? `<br><small style="color:var(--muted)">${a.alias}</small>` : ''}</td>
<td>${cur}${fmtNum(invest)}</td>
${realCell}
<td>${sCell(pb, invest)}</td>
<td>${sCell(pn, invest)}</td>
<td>${sCell(pu, invest)}</td>
</tr>`;
}).join('');
tbody.innerHTML += `<tr class="total-row">
<td>合计</td>
<td>${cur}${fmtNum(totInvest)}</td>
<td id="simreal-total">—</td>
<td>${sCell(totBear, totInvest)}</td>
<td>${sCell(totBase, totInvest)}</td>
<td>${sCell(totBull, totInvest)}</td>
</tr>`;
// Async: fetch live prices for real P&L column
const realResults = new Array(d.assets.length).fill(null);
let fetched = 0;
d.assets.forEach(async (a, idx) => {
if (!a.entryPrice) { fetched++; return; }
const rid = 'simreal-' + a.symbol.replace(/[^a-z0-9]/gi,'_');
const el = document.getElementById(rid);
const info = await fetchPrice(a.symbol).catch(() => null);
fetched++;
if (!el) return;
if (!info) { el.innerHTML = '<span style="color:var(--dimmed);font-size:0.72rem">获取失败</span>'; return; }
const invest = capital * (parseFloat(a.pct)||0) / 100;
const realPnl = invest * (info.price - a.entryPrice) / a.entryPrice;
realResults[idx] = realPnl;
el.innerHTML = sCell(realPnl, invest);
// Update total row when all fetched
if (fetched === d.assets.length) {
const totEl = document.getElementById('simreal-total');
if (totEl) {
const validResults = realResults.filter(r => r !== null);
if (validResults.length) {
const totReal = validResults.reduce((s,v) => s+v, 0);
totEl.innerHTML = sCell(totReal, totInvest);
}
}
}
});
}
function simUpdate() {
const d = simLoad();
d.capital = parseFloat(document.getElementById('sim-capital').value) || 10000;
d.currency = document.getElementById('sim-currency').value;
d.scenarios.bear = parseFloat(document.getElementById('sim-bear').value) || -20;
d.scenarios.base = parseFloat(document.getElementById('sim-base').value) || 8;
d.scenarios.bull = parseFloat(document.getElementById('sim-bull').value) || 25;
simSave(d);
simRenderAssets(d);
simCalcReturns(d);
}
function simSetHorizon(btn, h) {
const d = simLoad();
d.horizon = h;
simSave(d);
document.querySelectorAll('.sim-hbtn').forEach(b => b.classList.toggle('active', b.dataset.h === h));
simCalcReturns(d);
}
async function simAddAsset() {
const sym = (document.getElementById('sim-sym').value || '').trim().toUpperCase();
const alias = (document.getElementById('sim-alias').value || '').trim();
const pct = parseFloat(document.getElementById('sim-pct').value) || 0;
const manualEntry = parseFloat(document.getElementById('sim-entry').value) || null;
if (!sym) return;
const d = simLoad();
if (d.assets.find(a => a.symbol === sym)) { alert('该资产已在列表中'); return; }
let entryPrice = manualEntry;
if (!entryPrice) {
const btn = document.querySelector('#panel-sim .sim-add-row button');
if (btn) { btn.textContent = '抓取中…'; btn.disabled = true; }
const info = await fetchPrice(sym).catch(() => null);
if (btn) { btn.textContent = ' 添加'; btn.disabled = false; }
entryPrice = info ? info.price : null;
if (!entryPrice) { alert(`无法获取 ${sym} 当前价格,请手动填入买入价`); return; }
}
d.assets.push({ symbol: sym, alias, pct, entryPrice, entryDate: new Date().toISOString().slice(0,10) });
simSave(d);
document.getElementById('sim-sym').value = '';
document.getElementById('sim-alias').value = '';
document.getElementById('sim-pct').value = '';
document.getElementById('sim-entry').value = '';
simRender();
}
function simRemoveAsset(idx) {
const d = simLoad();
d.assets.splice(idx, 1);
simSave(d);
simRender();
}
function simUpdatePct(idx, val) {
const d = simLoad();
d.assets[idx].pct = parseFloat(val) || 0;
simSave(d);
simRenderAssets(d);
simCalcReturns(d);
}
function simReset() {
if (!confirm('确认重置模拟器数据?')) return;
localStorage.removeItem(lsSIM());
simRender();
}
// Init personal dashboard on load
document.addEventListener('DOMContentLoaded', function() {
profileRenderSelect();
wlRender();
pfRender();
simRender();
// Enter key triggers add
document.getElementById('wl-name').addEventListener('keydown', e => { if(e.key==='Enter') wlAdd(); });
document.getElementById('pf-cost').addEventListener('keydown', e => { if(e.key==='Enter') pfAdd(); });
});
// ── Reading progress bar ──────────────────────────────────────────────────────────
(function() {
const bar = document.getElementById('reading-progress');
if (!bar) return;
window.addEventListener('scroll', function() {
const scrolled = window.scrollY;
const total = document.documentElement.scrollHeight - window.innerHeight;
bar.style.width = (total > 0 ? (scrolled / total * 100) : 0) + '%';
}, { passive: true });
})();
// ── Back-to-top FAB visibility ───────────────────────────────────────────────────
(function() {
const btn = document.getElementById('fab-top');
if (!btn) return;
window.addEventListener('scroll', function() {
btn.classList.toggle('visible', window.scrollY > 400);
}, { passive: true });
})();
// ── Share / copy URL ────────────────────────────────────────────────────────────
function shareOrCopy() {
const url = window.location.href;
const toast = document.getElementById('share-toast');
if (navigator.share) {
navigator.share({ title: '金融日报 | Financial Daily', url });
} else {
navigator.clipboard.writeText(url).then(function() {
toast.classList.add('show');
setTimeout(function() { toast.classList.remove('show'); }, 2000);
});
}
}
// ── Jump nav active highlight on scroll ────────────────────────────────────────
(function() {
const sections = document.querySelectorAll('.sec-anchor[id]');
const links = document.querySelectorAll('.jump-nav a');
if (!sections.length || !links.length) return;
const obs = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
links.forEach(function(l) { l.classList.remove('active'); });
const a = document.querySelector('.jump-nav a[href="#' + entry.target.id + '"]');
if (a) a.classList.add('active');
}
});
}, { rootMargin: '-20% 0px -70% 0px' });
sections.forEach(function(s) { obs.observe(s); });
})();
// ── Dismiss subscribe strip if already dismissed ────────────────────────────
(function() {
if (localStorage.getItem('fd_sub_dismissed')) {
var el = document.getElementById('subscribe-strip');
if (el) el.style.display = 'none';
}
})();
// ── Subscriber count (Telegram) ───────────────────────────────────────
(function loadSubCount() {
const el = document.getElementById('subscriber-count');
if (!el) return;
fetch('data/investment-subscribers.json')
.then(r => r.json())
.then(d => {
const count = Object.values(d.subscribers || {}).filter(s => s.active).length;
if (count > 0) el.textContent = `📱 ${count} 人已订阅Telegram早报`;
})
.catch(() => {});
})();
// ── Visitor counter (Cloudflare Worker + KV) ──────────────────────────
document.addEventListener('DOMContentLoaded', function () {
const WORKER = 'https://finance-daily-counter.yangbai0110.workers.dev';
const LS_KEY = 'fd_visited';
const visEl = document.getElementById('footer-visitors');
const pvEl = document.getElementById('footer-pageviews');
function fmt(n) { return Number(n).toLocaleString('en-US'); }
function animate(el, target) {
if (!el) return;
if (target === 0) { el.textContent = '0'; return; }
const dur = 900; let t0 = null;
const step = ts => {
if (!t0) t0 = ts;
const p = Math.min((ts - t0) / dur, 1);
el.textContent = fmt(Math.round((1 - Math.pow(1 - p, 3)) * target));
if (p < 1) requestAnimationFrame(step);
};
requestAnimationFrame(step);
}
const isNew = !localStorage.getItem(LS_KEY);
fetch(WORKER + (isNew ? '?newVisitor=1' : '?newVisitor=0'))
.then(r => r.json())
.then(data => {
localStorage.setItem(LS_KEY, '1');
animate(visEl, data.visitors || 0);
animate(pvEl, data.pageViews || 0);
})
.catch(() => {
if (visEl) visEl.textContent = '--';
if (pvEl) pvEl.textContent = '--';
});
});
</script>
<!-- Floating action cluster -->
<div class="fab-cluster">
<button class="fab" id="fab-share" title="分享此页" onclick="shareOrCopy()">🔗</button>
<button class="fab" id="fab-top" title="回到顶部" onclick="window.scrollTo({top:0,behavior:'smooth'})"></button>
</div>
<div id="share-toast">✅ 链接已复制</div>
</body>
</html>