Files
finance-daily-site/index.html
T
2026-05-07 13:57:16 +00:00

3087 lines
131 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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="archive/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,365.12</div>
<div class="ticker-change up">▲ +1.46%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">纳斯达克综合指数</div>
<div class="ticker-value">25,838.94</div>
<div class="ticker-change up">▲ +2.02%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">道琼斯工业平均指数</div>
<div class="ticker-value">49,910.59</div>
<div class="ticker-change up">▲ +1.24%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">罗素2000小盘股指数</div>
<div class="ticker-value">2,886.77</div>
<div class="ticker-change up">▲ +1.47%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">上证综指</div>
<div class="ticker-value">4,180.09</div>
<div class="ticker-change up">▲ +0.48%</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 up">
<div class="ticker-name">日经225</div>
<div class="ticker-value">59,513.12</div>
<div class="ticker-change up">▲ +0.38%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">德国DAX</div>
<div class="ticker-value">24,890.28</div>
<div class="ticker-change down">▼ -0.11%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">黄金现货</div>
<div class="ticker-value">4,697.48</div>
<div class="ticker-change up">▲ +3.14%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">WTI原油</div>
<div class="ticker-value">91.73</div>
<div class="ticker-change down">▼ -3.52%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">比特币</div>
<div class="ticker-value">80,480.40</div>
<div class="ticker-change down">▼ -1.44%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">美元指数</div>
<div class="ticker-value">104.5</div>
<div class="ticker-change up">▲ +0.30%</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">美国与伊朗和平谈判取得进展,原油价格暴跌至91美元,缓解通胀担忧。标普500周三大涨1.46%创历史新高,AMD财报超预期暴涨19%引领科技股反弹。对北美华人投资者而言,当前市场情绪转向乐观,但美联储鹰派立场不变、利率维持在3.5-3.75%,需警惕估值过高风险。VIX回落至17.29显示恐慌情绪降温。</div>
<div class="summary-meta">
<span class="sentiment-badge bullish">看多 · Bullish</span>
<span class="vix-display">VIX 恐慌指数: <span>17.29</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">在2026年股东信中,戴蒙回应巴菲特26年前的警告,强调利率上升将对所有资产价格构成下行压力。他警告通胀可能成为'派对上的臭鼬',若通胀持续高企,利率将维持高位甚至继续上涨,这将迫使股票估值下调。戴蒙在里根经济论坛上表示,债券市场某个时点会'崩溃',只是不确定是6个月还是6年后发生。</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月初</div>
</div>
<div class="leader-quote">"我认为控制政府收支的问题永远无法完全解决"</div>
<div class="leader-body">在2026年股东大会上被问及DOGE能否解决债务问题时,巴菲特表达了悲观看法,称这一问题曾严重损害许多文明,美国也不例外。他在最新股东信中再次重申利率是资产定价的核心因素,这一观点在26年后仍然适用。当前美股估值高企,巴菲特建议普通投资者持有标普500指数基金。</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 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">3月</div>
</div>
<div class="leader-quote">"我们面临非常严重的供需问题"</div>
<div class="leader-body">达利欧在3月新加坡演讲中警告,美国某个时点将不得不'出售全球不愿购买的债务规模',这是'迫在眉睫'且'极其重要'的场景。他预测将看到'震撼性的发展'来处理债务问题。达利欧建议投资者增持黄金配置,认为'当坏时代来临时,黄金是非常有效的分散化工具'。</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月29日</div>
</div>
<div class="leader-quote">"我将留在理事会直到这项调查真正结束"</div>
<div class="leader-body">在4月29日的最后一次FOMC会议上,鲍威尔确认将于5月15日卸任主席,但因特朗普政府的法律攻击而决定留任理事。美联储维持利率在3.5-3.75%不变,但出现历史性的4票反对,为1992年以来最多。鲍威尔强调通胀预期已升至2.7%,降息前景恶化,市场现在甚至预期可能加息。</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">LS</div>
<div class="leader-meta">
<div class="leader-name">丽莎·苏 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Lisa Su</span></div>
<div class="leader-role">AMD CEO</div>
</div>
<div class="leader-date">5月6日</div>
</div>
<div class="leader-quote">"智能代理正在推动AI采用周期中的巨大需求"</div>
<div class="leader-body">AMD第一季度营收增长38%,数据中心业务暴涨57%至58亿美元。苏博士在CNBC采访中表示,过去90天与大客户沟通后发现,工作负载正在转向CPU密集型的智能代理应用。AMD宣布与英特尔合作开发x86 AI计算扩展,旨在将计算密度提升16倍。AMD股价今年已暴涨66%,过去一年涨幅超过200%。</div>
<div class="tags"><span class="tag">#AI</span><span class="tag">#芯片</span><span class="tag">#AMD</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.5-3.75%</div>
<div class="cb-action">维持利率3.5-3.75%不变</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-17</span></div>
<div class="cb-note">4月29日会议出现史上最大分歧,4票反对。鲍威尔5月15日卸任主席但留任理事,Kevin Warsh将接任。通胀预期升至2.7%,全年或不降息。</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">2.75%</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">ECB认为已达到'好地方',通胀接近2%且增长温和。需看到大幅负面意外才会进一步降息,预计2026年维持当前利率。</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 dovish">Dovish</span>
</div>
<div class="cb-rate">LPR 1年期3.35%</div>
<div class="cb-action">保持宽松基调</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">滚动操作</span></div>
<div class="cb-note">预计2026年降息20个基点、降准100个基点以支撑增长。近月经济放缓显示需要持续政策支持。中美贸易紧张和产能过剩调查增加不确定性。</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.75%</div>
<div class="cb-action">维持利率0.75%不变</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-13</span></div>
<div class="cb-note">4月28日会议以6-3投票维持利率,三位委员主张加息至1.0%。上调2026财年核心通胀预期至2.8%,下调GDP增长至0.5%。伊朗战争推高能源价格是主因。</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">美伊和平谈判取得突破,原油暴跌缓解通胀压力</div>
<div class="news-body">Axios报道称美国与伊朗正接近签署一份一页纸的14点谅解备忘录,以结束冲突并为核谈判建立框架。伊朗外交部向CNBC确认正在评估美方提案。受此消息影响,WTI原油暴跌4%至91美元,布伦特原油跌至97美元。霍尔木兹海峡占全球石油供应20%,其重新开放将显著降低能源成本。</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">AMD财报超预期暴涨19%,AI芯片需求持续爆发</div>
<div class="news-body">AMD第一季度EPS达84美分同比翻倍,营收同比增长38%。数据中心业务增长57%至58亿美元,CEO苏姿丰将大幅上调全年指引。不同于英伟达专注GPU,AMD在CPU领域占据领先地位,正受益于智能代理AI转向CPU密集型计算。AMD股价周三单日暴涨19%,创史上最大单日涨幅之一,带动半导体板块集体走高。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>AI芯片供应链紧张,AMD与英伟达双寡头格局确立,科技ETF持有者继续受益</div>
<div class="news-footer">
<span class="importance-badge breaking">BREAKING</span>
<div class="tags"><span class="tag">#AI</span><span class="tag">#财报</span><span class="tag">#芯片</span></div>
</div>
</div>
<div class="news-item breaking featured">
<div class="news-title">美联储出现史上最大分歧,4票反对维持利率不变</div>
<div class="news-body">4月29日FOMC会议以8-4投票维持利率在3.5-3.75%,创1992年以来最多反对票。三位官员支持维持但反对宽松倾向,一位官员(Miran)主张降息25个基点。鲍威尔强调伊朗战争导致能源价格高企,通胀预期升至2.7%。期货市场现在预期2026年全年不降息,甚至有9.1%概率加息。</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 high">
<div class="news-title">标普500盈利季创20年最强,84%公司超预期</div>
<div class="news-body">FactSet数据显示,已公布的63%标普500公司中,84%超EPS预期,为2021年二季度以来最高。盈利增长20.7%,远超5年均值7.3%。信息技术、通信服务和非必需消费品板块领涨,能源和医疗板块拖累。分析师预计Q2-Q4增长率分别为21.3%、23.0%和20.6%,全年增长21.3%。标普500远期市盈率升至20.9倍,高于5年均值19.9倍。</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">中美贸易紧张再升级,特朗普威胁对华加征50%关税</div>
<div class="news-body">CNN报道称中国准备向伊朗运送防空导弹,特朗普威胁若属实将对中国加征50%关税。5月14-15日特朗普将访华与习近平会晤,这是8年来首次。3月美国启动两项301调查针对中国产能过剩和强迫劳动。当前美国对华基准关税为30%(90天休战后),叠加既有关税后部分商品有效税率超145%。中美5月峰会成为关键节点。</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">麦当劳周四财报成焦点,消费者支出健康度受考验</div>
<div class="news-body">麦当劳将于5月7日盘前公布Q1财报,预期EPS为2.75美元增长3%,同店销售预计增长3.9%。分析师关注GLP-1减肥药对低收入客群的影响、牛肉成本上涨压力,以及伊朗冲突对消费行为的冲击。麦当劳今年累计下跌7%,而标普500上涨7%。罗斯柴尔德将评级从卖出上调至中性,认为其完成'美元菜单时代以来最全面的价值重置'。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>若麦当劳业绩疲软,暗示消费者支出降温,零售和餐饮股承压</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 medium">
<div class="news-title">最高法院推翻特朗普IEEPA关税,全球贸易格局生变</div>
<div class="news-body">2月20日最高法院裁定总统无权使用IEEPA(国际紧急经济权力法)征收关税。特朗普转向Section 301调查作为替代工具,3月启动针对16国的产能过剩调查和针对40+国的强迫劳动调查。听证会已在4-5月举行,新一轮关税可能在夏季出台。贸易律师预计这将成为特朗普重建关税筹码的主要途径。</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>贸易不确定性持续,进口商需密切关注301调查结果和排除申请窗口</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>
<!-- 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-up">
<div class="macro-indicator">CPI YoY (3月)</div>
<div class="macro-value macro-value-down">3.3%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 2.9%</div>
<div class="macro-desc">3月CPI同比上涨3.3%,环比上涨0.9%,受能源价格飙升推动。核心CPI同比2.6%保持稳定。伊朗战争推高油价是主因。</div>
</div>
<div class="macro-card dir-neutral">
<div class="macro-indicator">失业率 (3月)</div>
<div class="macro-value ">4.3%</div>
<div class="macro-prev"><span class="arrow "></span> 前值: 4.3%</div>
<div class="macro-desc">失业率保持在4.3%不变。3月新增就业17.8万人,扭转2月-13.3万的收缩(受联邦裁员影响)。劳动力市场韧性尚存。</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">初请失业金人数为20万,低于预期的20.5万。持续申领失业金人数降至176万。劳动力市场降温但未崩溃。</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">核心PCE同比3.0%,略低于1月3.1%,但仍远高于美联储2%目标。3月数据受伊朗战争影响,预计将大幅上升。</div>
</div>
<div class="macro-card dir-neutral">
<div class="macro-indicator">ISM制造业PMI (4月)</div>
<div class="macro-value ">预计公布</div>
<div class="macro-prev"><span class="arrow "></span> 前值: N/A</div>
<div class="macro-desc">4月ISM制造业PMI将于本周公布。市场关注伊朗战争对供应链和成本的冲击是否传导至制造业。</div>
</div>
<div class="macro-card dir-down">
<div class="macro-indicator">ISM服务业PMI (3月)</div>
<div class="macro-value macro-value-down">54.0</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: 56.1</div>
<div class="macro-desc">服务业PMI从56.1降至54.0,仍处于扩张区间但增速放缓。能源成本上升和消费者情绪疲软是主因。</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">GDP增长 (Q4 2025终值)</div>
<div class="macro-value macro-value-up">1.3% QoQ</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 0.3%</div>
<div class="macro-desc">2025年第四季度GDP季调环比增长1.3%,避免技术性衰退。2026年Q1增长预计放缓至0.5%,受伊朗战争拖累。</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">10年期美债收益率升至4.38%,2年期3.89%,利差扩大至49个基点。收益率曲线陡峭化反映市场预期经济放缓但通胀持续。</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">$0.84</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$0.44</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>$9.6B</span></div>
<div class="earnings-highlight">数据中心营收暴涨57%至58亿美元,CEO苏姿丰称智能代理AI推动CPU需求激增,股价单日暴涨19%创史上最大涨幅之一</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">DIS</div>
<div class="earnings-company">Walt Disney</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">新任CEO Josh D'Amaro首份财报超预期,流媒体增长强劲,主题公园表现稳健,股价周三上涨5%</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">MCD</div>
<div class="earnings-company">McDonald's</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">$2.75</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-07</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期增长3%</span></div>
<div class="earnings-highlight">市场关注同店销售增长3.9%能否实现,GLP-1减肥药对低收入客群影响、牛肉成本和伊朗冲突的消费影响是焦点</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">SMCI</div>
<div class="earnings-company">Super Micro Computer</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">AI服务器需求爆发,发布强劲Q2指引,股价周三暴涨17%,但ARM财报后警告无法满足10亿美元增量需求</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">业绩超预期但警告AGI CPU供应不足无法满足10亿美元增量需求,股价周四下跌7.3%</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">PLTR</div>
<div class="earnings-company">Palantir</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">$同比翻倍</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-05</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>AI和国防需求强劲</span></div>
<div class="earnings-highlight">分析师预期EPS同比翻倍,AI平台和政府合同增长成焦点,估值偏高容错空间有限</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">COIN</div>
<div class="earnings-company">Coinbase</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">$收入或下降</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>Q1交易量疲软</span></div>
<div class="earnings-highlight">分析师预期Q1营收下降,市场不确定性导致交易量低迷,是本周最重要的加密原生财报</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">ABNB</div>
<div class="earnings-company">Airbnb</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>关注Q2预订量</span></div>
<div class="earnings-highlight">投资者聚焦Q2夜间预订量和美国宏观经济对旅游需求的影响,消费者情绪疲软是风险</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">Technology</div></div>
<div class="sector-etf">XLK</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:70%"></div></div>
<div class="sector-pct up">+2.51%</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:58%"></div></div>
<div class="sector-pct up">+2.01%</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:47%"></div></div>
<div class="sector-pct up">+1.56%</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:78%"></div></div>
<div class="sector-pct up">+2.82%</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:100%"></div></div>
<div class="sector-pct up">+3.71%</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:33%"></div></div>
<div class="sector-pct up">+0.98%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">医疗保健</div><div class="sector-name-en">Healthcare</div></div>
<div class="sector-etf">XLV</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:25%"></div></div>
<div class="sector-pct up">+0.65%</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:13%"></div></div>
<div class="sector-pct up">+0.13%</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:53%"></div></div>
<div class="sector-pct up">+1.79%</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 down" style="width:28%"></div></div>
<div class="sector-pct down">-0.75%</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:92%"></div></div>
<div class="sector-pct down">-3.39%</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 high">
<div class="cal-date">周四 5/8<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">4月非农就业报告 (NFP)</div>
<div class="cal-values">预期: <span>49,000</span> &nbsp;&middot;&nbsp; 前值: 178,000 (3月)</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周四 5/8<br><span style="font-size:0.6rem;color:var(--dimmed)">盘后</span></div>
<div>
<div class="cal-event">Coinbase (COIN) 财报</div>
<div class="cal-values">预期: <span>Q1交易量或疲软</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周四 5/8<br><span style="font-size:0.6rem;color:var(--dimmed)">盘后</span></div>
<div>
<div class="cal-event">Airbnb (ABNB) 财报</div>
<div class="cal-values">预期: <span>关注Q2预订量</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周二 5/12<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">4月CPI报告</div>
<div class="cal-values">预期: <span>预计因油价回落而降温</span> &nbsp;&middot;&nbsp; 前值: 3.3% YoY (3月)</div>
</div>
</div>
<div class="cal-item medium">
<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">4月PPI报告</div>
<div class="cal-values">预期: <span>关注能源和运输成本</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周二 5/20<br><span style="font-size:0.6rem;color:var(--dimmed)">盘后</span></div>
<div>
<div class="cal-event">英伟达 (NVDA) Q1 FY2027财报</div>
<div class="cal-values">预期: <span>市场最关注的科技财报</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周二 5/20<br><span style="font-size:0.6rem;color:var(--dimmed)">下午2:00 PM ET</span></div>
<div>
<div class="cal-event">美联储4月FOMC会议纪要发布</div>
<div class="cal-values">预期: <span>关注鲍威尔最后会议的分歧细节</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周三 5/28<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">4月PCE物价指数</div>
<div class="cal-values">预期: <span>美联储偏好的通胀指标</span> &nbsp;&middot;&nbsp; 前值: 3.0% YoY (2月核心)</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周三 6/5<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; 前值: 维持2.75%</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周五 6/6<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">5月非农就业报告</div>
<div class="cal-values">预期: <span>Warsh时代首份就业报告</span> &nbsp;&middot;&nbsp; 前值: 待定</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周二-三 6/16-17<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>Warsh首次主持,关注点阵图</span> &nbsp;&middot;&nbsp; 前值: 3.5-3.75%</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>