Files
deerflow-code/facebook-style-data-display.html
T

832 lines
48 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">
<title>数据广场 DataFeed · 仿 Facebook 风格数据展示</title>
<style>
:root{
--fb-blue:#1877f2; --fb-blue-dark:#166fe5; --bg:#f0f2f5;
--card:#fff; --text:#1c1e21; --sub:#65676b; --weak:#8a8d91;
--divider:#e4e6eb; --hover:#f0f2f5; --hover2:#e4e6eb;
--green:#31a24c; --red:#e41e3f; --yellow:#f7b928;
--shadow:0 1px 2px rgba(0,0,0,.2);
}
*{box-sizing:border-box;margin:0;padding:0}
html{scrollbar-gutter:stable}
body{
background:var(--bg);color:var(--text);
font-family:"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",Helvetica,Arial,sans-serif;
font-size:15px;-webkit-font-smoothing:antialiased;
}
a{color:inherit;text-decoration:none}
button{font-family:inherit}
/* ============ 顶部导航(Facebook 蓝条) ============ */
.topbar{
position:fixed;top:0;left:0;right:0;height:56px;z-index:100;
background:var(--fb-blue);display:flex;align-items:center;justify-content:space-between;
padding:0 16px;gap:8px;
}
.tb-left{display:flex;align-items:center;gap:10px;flex:1;min-width:0}
.logo{
width:40px;height:40px;border-radius:50%;flex:none;
background:#fff;color:var(--fb-blue);font-size:22px;font-weight:800;
display:grid;place-items:center;cursor:pointer;
}
.search{position:relative}
.search svg{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--sub);pointer-events:none}
.search input{
width:250px;max-width:44vw;height:40px;border:none;border-radius:20px;outline:none;
background:rgba(255,255,255,.96);padding:0 14px 0 38px;font-size:15px;color:var(--text);
}
.search input::placeholder{color:var(--weak)}
.tb-center{display:flex;gap:4px;flex:none}
.tb-nav{
width:48px;height:48px;border-radius:10px;display:grid;place-items:center;
color:#dfe9fb;position:relative;cursor:pointer;
}
.tb-nav svg{width:26px;height:26px}
.tb-nav:hover,.tb-nav.active{background:rgba(255,255,255,.18);color:#fff}
.tb-right{display:flex;align-items:center;gap:8px;flex:1;justify-content:flex-end}
.icon-btn{
width:40px;height:40px;border-radius:50%;position:relative;flex:none;
background:rgba(255,255,255,.18);display:grid;place-items:center;color:#fff;cursor:pointer;
}
.icon-btn:hover{background:rgba(255,255,255,.28)}
.icon-btn svg{width:22px;height:22px}
.badge{
position:absolute;top:-3px;right:-3px;min-width:18px;height:18px;padding:0 4px;
border-radius:9px;background:var(--red);color:#fff;font-size:11px;font-weight:700;
display:grid;place-items:center;border:2px solid var(--fb-blue);
}
.me{
width:40px;height:40px;border-radius:50%;border:none;flex:none;cursor:pointer;
background:linear-gradient(135deg,#42a5f5,#0d47a1);color:#fff;font-weight:600;font-size:15px;
}
/* ============ 三栏布局 ============ */
.layout{
max-width:1284px;margin:0 auto;display:grid;gap:16px;
grid-template-columns:280px minmax(0,680px) 300px;
padding:72px 12px 40px;align-items:start;
}
.side{position:sticky;top:72px;max-height:calc(100vh - 88px);overflow-y:auto;padding:4px 2px}
.side::-webkit-scrollbar{width:8px}
.side::-webkit-scrollbar-thumb{background:#cfd2d6;border-radius:4px}
.side::-webkit-scrollbar-thumb:hover{background:#b6b9be}
/* ---- 左栏 ---- */
.profile-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;cursor:pointer}
.profile-row:hover{background:var(--hover)}
.profile-row b{font-size:15px}
.profile-row .sub{font-size:12.5px;color:var(--sub)}
.menu{margin-top:4px}
.mi{
display:flex;align-items:center;gap:12px;padding:7px 10px;border-radius:8px;
font-weight:600;font-size:15px;cursor:pointer;user-select:none;
}
.mi:hover{background:var(--hover)}
.mi .ic{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;color:var(--fb-blue);flex:none}
.mi .ic svg{width:22px;height:22px}
.mi .cnt{
margin-left:auto;background:#d8dadf;color:var(--text);font-size:12px;font-weight:700;
border-radius:10px;padding:1px 8px;
}
.sq{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;font-size:18px;flex:none}
.sq-blue{background:#e7f3ff}.sq-green{background:#e6f7ea}.sq-orange{background:#fff3d6}.sq-purple{background:#f0e9ff}
.hr{border:none;border-top:1px solid var(--divider);margin:10px 12px}
.side-title{font-weight:700;color:var(--weak);font-size:17px;padding:6px 12px 2px}
.side-foot{font-size:12px;color:var(--weak);padding:12px 12px 4px;line-height:1.7}
/* ---- 通用卡片 / 头像 ---- */
.card{background:var(--card);border-radius:8px;box-shadow:var(--shadow)}
.avatar{
width:40px;height:40px;border-radius:50%;display:grid;place-items:center;
color:#fff;font-weight:600;font-size:15px;flex:none;cursor:pointer;
}
.avatar.sm{width:32px;height:32px;font-size:13px}
.av-blue{background:linear-gradient(135deg,#1877f2,#0c56c0)}
.av-green{background:linear-gradient(135deg,#45bd62,#1a7a3a)}
.av-orange{background:linear-gradient(135deg,#f7a325,#d97b06)}
.av-purple{background:linear-gradient(135deg,#8b5cf6,#5b21b6)}
.av-teal{background:linear-gradient(135deg,#14b8a6,#0f766e)}
.sub{color:var(--sub)}
/* ---- 发布器 ---- */
.composer{padding:12px 16px 10px;margin-bottom:16px}
.composer-top{display:flex;gap:10px;align-items:center}
.composer-top input{
flex:1;height:42px;border-radius:21px;border:none;outline:none;
background:var(--hover);padding:0 16px;font-size:15px;color:var(--text);transition:box-shadow .15s,background .15s;
}
.composer-top input:focus{background:#fff;box-shadow:inset 0 0 0 2px var(--fb-blue)}
.composer-actions{display:flex;border-top:1px solid var(--divider);margin-top:10px;padding-top:6px}
.ca{
flex:1;display:flex;align-items:center;justify-content:center;gap:8px;
padding:9px 4px;border-radius:8px;font-weight:600;font-size:14.5px;color:var(--sub);
cursor:pointer;user-select:none;background:none;border:none;
}
.ca:hover{background:var(--hover)}
.ca svg{width:22px;height:22px}
.ca.c-blue{color:var(--fb-blue)}.ca.c-green{color:var(--green)}.ca.c-orange{color:#f0940a}
/* ---- 数据专题(Stories) ---- */
.stories{display:flex;gap:8px;overflow-x:auto;padding:12px;margin-bottom:16px;scrollbar-width:none}
.stories::-webkit-scrollbar{display:none}
.story{
flex:0 0 110px;height:190px;border-radius:14px;position:relative;overflow:hidden;
cursor:pointer;color:#fff;display:flex;flex-direction:column;justify-content:flex-end;
padding:10px;transition:transform .15s;
}
.story:hover{transform:scale(1.02)}
.story .big{position:absolute;top:44px;left:0;right:0;text-align:center;font-size:40px}
.story .av{position:absolute;top:8px;left:8px;width:30px;height:30px;border-radius:50%;border:2px solid rgba(255,255,255,.9)}
.story .nm{font-size:12.5px;font-weight:700;text-shadow:0 1px 3px rgba(0,0,0,.45);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.story.create{background:#fff;align-items:center;justify-content:flex-start;color:var(--text);padding-top:14px}
.story.create:hover{background:var(--hover)}
.story.create .plus{
width:44px;height:44px;border-radius:50%;background:var(--fb-blue);color:#fff;
display:grid;place-items:center;font-size:26px;font-weight:300;margin-bottom:8px;
}
.story.create span{font-size:13px;font-weight:600}
/* ---- 帖子(数据卡片) ---- */
.post{margin-bottom:16px}
.post-hd{display:flex;align-items:center;gap:10px;padding:12px 16px 0}
.post-hd .meta{min-width:0;flex:1}
.post-hd .meta b{font-size:15px;cursor:pointer}
.post-hd .meta b:hover{text-decoration:underline}
.post-hd .meta .sub{font-size:13px;display:flex;align-items:center;gap:4px}
.post-hd .more{color:var(--sub);cursor:pointer;padding:4px 8px;border-radius:50%;font-weight:700}
.post-hd .more:hover{background:var(--hover)}
.post-txt{padding:10px 16px 12px;line-height:1.55;font-size:15px}
.post-txt a{color:var(--fb-blue);font-weight:600}
.chart-wrap{padding:0 16px}
.chart-head{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;padding:0 16px 6px}
.chart-title{font-size:15px;font-weight:700}
.legend{display:flex;gap:14px;font-size:13px;color:var(--sub);align-items:center;flex-wrap:wrap}
.dot{width:10px;height:10px;border-radius:3px;display:inline-block;margin-right:5px;vertical-align:-1px}
.pills{display:flex;gap:6px}
.pill{
border:none;cursor:pointer;padding:4px 14px;border-radius:20px;
background:var(--hover);color:var(--sub);font-size:13px;font-weight:600;
}
.pill.active{background:#e7f3ff;color:var(--fb-blue)}
.summary{font-size:13px;color:var(--sub);padding:6px 16px 4px}
/* KPI 四宫格 */
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;padding:2px 16px 14px}
.kpi{background:#f7f8fa;border:1px solid var(--divider);border-radius:10px;padding:10px 12px}
.kpi .lab{font-size:12.5px;color:var(--sub);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kpi .num{font-size:20px;font-weight:800;letter-spacing:-.3px;margin:3px 0 2px;white-space:nowrap}
.delta{font-size:12px;font-weight:700;display:inline-flex;align-items:center;gap:2px}
.up{color:var(--green)}.down{color:var(--red)}
.spark{width:100%;height:26px;display:block;margin-top:4px}
/* 柱状图 */
.bars{display:flex;align-items:flex-end;gap:14px;height:175px;padding:0 6px;margin-top:4px}
.bcol{flex:1;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:6px}
.bval{font-size:12px;font-weight:700;color:var(--sub)}
.bar{
width:100%;max-width:44px;border-radius:6px 6px 2px 2px;cursor:pointer;
background:linear-gradient(180deg,#4b95f5,#1877f2);transition:filter .15s;
}
.bar:hover{filter:brightness(1.12)}
.bar.top{background:linear-gradient(180deg,#1877f2,#0a4bb3)}
.bname{font-size:12px;color:var(--sub);white-space:nowrap}
/* 环形图 + 图例 */
.split{display:grid;grid-template-columns:210px 1fr;gap:8px;align-items:center;padding:2px 16px 14px}
.donut{width:180px;height:180px;margin:0 auto;display:block}
.lg-row{display:flex;align-items:center;gap:10px;padding:7px 0;font-size:14px;border-bottom:1px dashed #f0f2f5}
.lg-row:last-child{border-bottom:none}
.lg-row .nm{flex:1}
.lg-row .v{font-weight:700}
.lg-row .pc{color:var(--sub);font-size:13px;width:44px;text-align:right}
/* 表格 */
.tbl-wrap{overflow-x:auto}
.tbl{width:100%;border-collapse:collapse;font-size:14px;min-width:440px}
.tbl th{
text-align:left;font-size:13px;font-weight:600;color:var(--sub);
padding:8px 16px;border-bottom:1px solid var(--divider);white-space:nowrap;
}
.tbl td{padding:10px 16px;border-bottom:1px solid #f0f2f5;white-space:nowrap}
.tbl tr:last-child td{border-bottom:none}
.tbl tbody tr:hover{background:#f7f9fc}
.rank{width:22px;height:22px;border-radius:6px;display:grid;place-items:center;font-size:12px;font-weight:800;color:#fff}
.r1{background:#f7b928}.r2{background:#aeb3ba}.r3{background:#d08a4e}.rx{background:#e4e6eb;color:var(--sub)}
/* 互动条 */
.post-stats{display:flex;align-items:center;justify-content:space-between;padding:10px 16px 6px;color:var(--sub);font-size:14.5px}
.react{
width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:0 0 0 1px var(--divider);
display:inline-grid;place-items:center;font-size:12px;margin-right:5px;vertical-align:-4px;
}
.actions{display:flex;border-top:1px solid var(--divider);padding:4px 6px}
.act{
flex:1;display:flex;align-items:center;justify-content:center;gap:8px;
padding:9px 4px;border-radius:8px;color:var(--sub);font-weight:600;font-size:14.5px;
cursor:pointer;user-select:none;background:none;border:none;
}
.act:hover{background:var(--hover)}
.act svg{width:20px;height:20px}
.act.liked{color:var(--fb-blue)}
/* 评论 */
.comments{padding:2px 16px 14px}
.cmt-more{color:var(--sub);font-size:14px;font-weight:600;padding:4px 0 8px;cursor:pointer}
.cmt-more:hover{text-decoration:underline}
.cmt{display:flex;gap:8px;margin-bottom:10px}
.cmt-bubble{background:var(--hover);border-radius:18px;padding:8px 13px;font-size:14px;line-height:1.45;max-width:100%}
.cmt-name{font-weight:700;font-size:13px;display:block;margin-bottom:1px}
.cmt-meta{font-size:12.5px;color:var(--sub);padding:3px 13px 0;display:flex;gap:8px}
.cmt-meta a{cursor:pointer}
.cmt-meta a:hover{text-decoration:underline;color:var(--text)}
.cmt-input{display:flex;gap:8px;align-items:center;margin-top:4px}
.cmt-input input{
flex:1;height:38px;border-radius:19px;border:none;outline:none;background:var(--hover);
padding:0 14px;font-size:14px;
}
.cmt-input input:focus{background:#fff;box-shadow:inset 0 0 0 2px var(--fb-blue)}
/* ---- 右栏 ---- */
.rc{padding:14px 12px;margin-bottom:16px}
.rc h4{font-size:16.5px;font-weight:700;color:var(--weak);margin:0 4px 8px;letter-spacing:.2px}
.rc-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;cursor:pointer}
.rc-item:hover{background:var(--hover)}
.rc-item .tt{font-size:14px;font-weight:600;line-height:1.3}
.rc-item .dd{font-size:12.5px;color:var(--sub)}
.rc-thumb{
width:96px;height:66px;border-radius:8px;flex:none;display:grid;place-items:center;
font-size:26px;color:#fff;
}
.rc-status{width:9px;height:9px;border-radius:50%;flex:none}
.on{background:var(--green)}.off{background:#bcc0c4}.pulse{background:var(--green);animation:pu 1.4s infinite}
@keyframes pu{0%{box-shadow:0 0 0 0 rgba(49,162,76,.5)}70%{box-shadow:0 0 0 7px rgba(49,162,76,0)}100%{box-shadow:0 0 0 0 rgba(49,162,76,0)}}
.rc-row{display:flex;align-items:center;gap:10px;padding:7px 10px;border-radius:8px;cursor:pointer}
.rc-row:hover{background:var(--hover)}
.rc-row b{font-size:14.5px;font-weight:600}
.rc-row .sub{font-size:12.5px}
.rc-row .tail{margin-left:auto;font-size:12.5px;color:var(--sub);white-space:nowrap}
/* 空结果 / Toast */
.noresult{display:none;text-align:center;color:var(--sub);padding:40px 0;font-size:15px}
.toast{
position:fixed;left:50%;bottom:28px;transform:translateX(-50%) translateY(90px);
background:#1c1e21;color:#fff;padding:11px 22px;border-radius:10px;font-size:14px;
opacity:0;transition:all .25s;z-index:300;pointer-events:none;box-shadow:0 4px 14px rgba(0,0,0,.3);
}
.toast.show{transform:translateX(-50%);opacity:1}
/* ---- 响应式 ---- */
@media (max-width:1160px){
.layout{grid-template-columns:240px minmax(0,1fr)}
.side-r{display:none}
}
@media (max-width:920px){
.layout{grid-template-columns:minmax(0,1fr);padding-top:64px}
.side-l{display:none}
.tb-center{display:none}
}
@media (max-width:600px){
.kpis{grid-template-columns:repeat(2,1fr)}
.split{grid-template-columns:1fr}
.stories{padding:10px}
.composer-actions .ca span{display:none}
}
</style>
</head>
<body>
<!-- ================= 顶部导航 ================= -->
<header class="topbar">
<div class="tb-left">
<a class="logo" title="DataFeed 数据广场">数</a>
<div class="search">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><circle cx="11" cy="11" r="7"/><line x1="16.5" y1="16.5" x2="21" y2="21"/></svg>
<input id="globalSearch" type="text" placeholder="搜索数据、指标、报表…" autocomplete="off">
</div>
</div>
<nav class="tb-center">
<a class="tb-nav active" title="首页"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3.1 3 10.2V21h6.2v-6h5.6v6H21V10.2z"/></svg></a>
<a class="tb-nav" title="实时看板"><svg viewBox="0 0 24 24" fill="currentColor"><rect x="2.3" y="5" width="19.4" height="14" rx="4" fill="none" stroke="currentColor" stroke-width="2"/><path d="M10 9.1v5.8L15.4 12z"/></svg></a>
<a class="tb-nav" title="数据集市"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 4h3l2.5 11a1.6 1.6 0 0 0 1.6 1.3h8.2a1.6 1.6 0 0 0 1.6-1.3L21 8H6.2"/><circle cx="10" cy="20" r="1.5" fill="currentColor"/><circle cx="17.2" cy="20" r="1.5" fill="currentColor"/></svg></a>
<a class="tb-nav" title="数据小组"><svg viewBox="0 0 24 24" fill="currentColor"><circle cx="9" cy="8.6" r="3.3"/><path d="M3 19.2c.5-3.1 3-4.9 6-4.9s5.5 1.8 6 4.9z"/><circle cx="16.9" cy="7.8" r="2.5"/><path d="M15.6 13.7c2.7.2 4.8 1.9 5.3 4.5h-4.4a7 7 0 0 0-.9-4.5z"/></svg></a>
</nav>
<div class="tb-right">
<a class="icon-btn" title="功能菜单"><svg viewBox="0 0 24 24" fill="currentColor"><circle cx="6" cy="6" r="1.9"/><circle cx="12" cy="6" r="1.9"/><circle cx="18" cy="6" r="1.9"/><circle cx="6" cy="12" r="1.9"/><circle cx="12" cy="12" r="1.9"/><circle cx="18" cy="12" r="1.9"/><circle cx="6" cy="18" r="1.9"/><circle cx="12" cy="18" r="1.9"/><circle cx="18" cy="18" r="1.9"/></svg></a>
<a class="icon-btn" title="消息"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3C6.7 3 2.5 6.8 2.5 11.4c0 2.6 1.4 5 3.6 6.6L5.2 22l4.2-2.1c.8.2 1.7.3 2.6.3 5.3 0 9.5-3.8 9.5-8.5S17.3 3 12 3z"/></svg><span class="badge">3</span></a>
<a class="icon-btn" title="通知"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3a5.8 5.8 0 0 0-5.8 5.8v3.6L4.6 15a1 1 0 0 0 .9 1.5h13a1 1 0 0 0 .9-1.5l-1.6-2.6V8.8A5.8 5.8 0 0 0 12 3z"/><path d="M9.8 19a2.3 2.3 0 0 0 4.4 0z"/></svg><span class="badge">5</span></a>
<button class="me" title="张分析 · 数据分析师">张</button>
</div>
</header>
<main class="layout">
<!-- ================= 左栏 ================= -->
<aside class="side side-l">
<div class="profile-row">
<div class="avatar av-blue">张</div>
<div><b>张分析</b><div class="sub">数据分析师 · 增长中心</div></div>
</div>
<nav class="menu">
<a class="mi"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3.5" y="3.5" width="7.5" height="7.5" rx="2"/><rect x="13" y="3.5" width="7.5" height="7.5" rx="2"/><rect x="3.5" y="13" width="7.5" height="7.5" rx="2"/><rect x="13" y="13" width="7.5" height="7.5" rx="2"/></svg></span>数据概览</a>
<a class="mi"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 13h3.2l2-5.2 3.5 9 2.2-7 1.5 3.2H21"/></svg></span>实时监控<span class="cnt">3</span></a>
<a class="mi"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"><path d="M6 2.5h8L19 8v13.5H6z"/><path d="M14 2.5V8h5M9 12.5h7M9 16h7"/></svg></span>报表中心</a>
<a class="mi"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><ellipse cx="12" cy="5.5" rx="7.5" ry="3"/><path d="M4.5 5.5v13c0 1.7 3.4 3 7.5 3s7.5-1.3 7.5-3v-13"/><path d="M4.5 12c0 1.7 3.4 3 7.5 3s7.5-1.3 7.5-3"/></svg></span>数据源管理</a>
<a class="mi"><span class="ic"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.8l2.6 5.6 6.1.7-4.5 4.2 1.2 6-5.4-3-5.4 3 1.2-6L3.3 9.1l6.1-.7z"/></svg></span>我的收藏</a>
<a class="mi"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4.5 6.5h15M9.5 6V4.2A1.2 1.2 0 0 1 10.7 3h2.6a1.2 1.2 0 0 1 1.2 1.2V6"/><path d="M7 6.5l.8 13a1.5 1.5 0 0 0 1.5 1.4h5.4a1.5 1.5 0 0 0 1.5-1.4l.8-13"/></svg></span>回收站</a>
</nav>
<hr class="hr">
<div class="side-title">快捷方式</div>
<nav class="menu">
<a class="mi"><span class="sq sq-blue">🛒</span>电商大促</a>
<a class="mi"><span class="sq sq-green">📈</span>用户增长</a>
<a class="mi"><span class="sq sq-orange">📣</span>营销投放</a>
<a class="mi"><span class="sq sq-purple">🎧</span>客服质量</a>
</nav>
<hr class="hr">
<div class="side-title">我的小组</div>
<nav class="menu">
<a class="mi"><span class="sq sq-blue">👥</span>增长数据组</a>
<a class="mi"><span class="sq sq-green">🧪</span>实验平台组</a>
</nav>
<div class="side-foot">隐私 · 条款 · 广告 · Cookie<br>DataFeed © 2026 · 仿 Facebook 风格演示页</div>
</aside>
<!-- ================= 中间信息流 ================= -->
<section class="feed">
<!-- 发布器(顶部搜索/筛选) -->
<div class="card composer">
<div class="composer-top">
<div class="avatar av-blue">张</div>
<input id="feedFilter" type="text" placeholder="筛选下方数据卡片,如:趋势 / 渠道 / 排行 / KPI…" autocomplete="off">
</div>
<div class="composer-actions">
<button class="ca c-blue" data-toast="演示页面:实时看板未接入"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2.3" y="5" width="19.4" height="14" rx="4"/><path d="M10 9.1v5.8L15.4 12z" fill="currentColor" stroke="none"/></svg><span>实时看板</span></button>
<button class="ca c-green" data-toast="演示页面:导入报表未接入"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="6.5" width="18" height="13.5" rx="3"/><circle cx="12" cy="13" r="3.6"/><path d="M8 6.5 9.3 4h5.4L16 6.5"/></svg><span>导入报表</span></button>
<button class="ca c-orange" data-toast="演示页面:智能分析未接入"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="8.5"/><circle cx="9" cy="10" r="1.1" fill="currentColor" stroke="none"/><circle cx="15" cy="10" r="1.1" fill="currentColor" stroke="none"/><path d="M8.5 14.5c1 1.2 2.1 1.8 3.5 1.8s2.5-.6 3.5-1.8"/></svg><span>智能分析</span></button>
</div>
</div>
<!-- 数据专题(Stories) -->
<div class="card stories" id="stories">
<div class="story create"><div class="plus">+</div><span>创建专题</span></div>
<div class="story" style="background:linear-gradient(165deg,#166fe5,#0a3d91)"><span class="av avatar av-orange">促</span><div class="big">🛒</div><div class="nm">双 11 作战室</div></div>
<div class="story" style="background:linear-gradient(165deg,#f7b928,#dd7d0a)"><span class="av avatar av-blue">渠</span><div class="big">📣</div><div class="nm">渠道复盘</div></div>
<div class="story" style="background:linear-gradient(165deg,#45bd62,#177a37)"><span class="av avatar av-green">像</span><div class="big">👥</div><div class="nm">用户画像</div></div>
<div class="story" style="background:linear-gradient(165deg,#fa383e,#a80f26)"><span class="av avatar av-teal">留</span><div class="big">📈</div><div class="nm">留存专题</div></div>
<div class="story" style="background:linear-gradient(165deg,#8b5cf6,#4c1d95)"><span class="av avatar av-purple">实</span><div class="big">🧪</div><div class="nm">A/B 实验</div></div>
</div>
<!-- 卡片 1:今日核心指标 KPI -->
<article class="card post" data-key="kpi 核心指标 概览 活跃用户 注册 订单 gmv dashboard">
<div class="post-hd">
<div class="avatar av-blue">数</div>
<div class="meta">
<b>数据中心</b>
<div class="sub">12 分钟前 · <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor"><path d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm-1 5h2v6h-2zm0 8h2v2h-2z" opacity=".9"/><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm0 18.2c-4.5 0-8.2-3.7-8.2-8.2S7.5 3.8 12 3.8 20.2 7.5 20.2 12 16.5 20.2 12 20.2z"/></svg> 公开</div>
</div>
<span class="more">···</span>
</div>
<div class="post-txt">📊 <b>今日核心指标速览</b>(截至今日 16:00):活跃与 GMV 延续双位数增长,订单量小幅回落,详见 <a>#每日简报</a></div>
<div class="kpis">
<div class="kpi">
<div class="lab">今日活跃用户</div>
<div class="num">42.8 万</div>
<span class="delta up">▲ 12.5%</span>
<svg class="spark" viewBox="0 0 100 28" preserveAspectRatio="none"><polyline points="0,22 14,19 28,21 42,15 56,17 70,11 84,13 100,6" fill="none" stroke="#31a24c" stroke-width="2"/></svg>
</div>
<div class="kpi">
<div class="lab">新增注册</div>
<div class="num">8,642</div>
<span class="delta up">▲ 3.2%</span>
<svg class="spark" viewBox="0 0 100 28" preserveAspectRatio="none"><polyline points="0,20 14,21 28,16 42,17 56,14 70,15 84,9 100,7" fill="none" stroke="#31a24c" stroke-width="2"/></svg>
</div>
<div class="kpi">
<div class="lab">订单量</div>
<div class="num">15,237</div>
<span class="delta down">▼ 2.4%</span>
<svg class="spark" viewBox="0 0 100 28" preserveAspectRatio="none"><polyline points="0,8 14,12 28,10 42,15 56,14 70,18 84,17 100,21" fill="none" stroke="#e41e3f" stroke-width="2"/></svg>
</div>
<div class="kpi">
<div class="lab">GMV(成交总额)</div>
<div class="num">¥382.6 万</div>
<span class="delta up">▲ 8.1%</span>
<svg class="spark" viewBox="0 0 100 28" preserveAspectRatio="none"><polyline points="0,18 14,20 28,16 42,17 56,12 70,14 84,8 100,4" fill="none" stroke="#31a24c" stroke-width="2"/></svg>
</div>
</div>
<div class="post-stats">
<div><span class="react">👍</span><span class="like-num" data-count="1286">1,286</span></div>
<div><span class="cmt-num" data-count="86">86 条评论</span> · <span>42 次分享</span></div>
</div>
<div class="actions">
<button class="act act-like"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M8.5 21H5.2a1.2 1.2 0 0 1-1.2-1.2v-8.6c0-.7.5-1.2 1.2-1.2h3.3zM9.7 10.2 13 3.5c1.4.2 2.2 1.2 2.2 2.7V9h4.4c1.3 0 2.2 1.1 1.9 2.3l-1.5 6.7c-.3 1.2-1.1 3-2.5 3H9.7z"/></svg>赞</button>
<button class="act act-comment"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3C6.5 3 2 6.9 2 11.7c0 2.8 1.4 5.3 3.7 7L5 22l4.3-2c.9.2 1.8.4 2.7.4 5.5 0 10-3.9 10-8.7S17.5 3 12 3z"/></svg>评论</button>
<button class="act act-share"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M13.5 4.5 21 11l-7.5 6.5v-3.9C8 13.7 5.2 15.6 3.5 19.5c.2-6.7 4-10.5 10-11.4z"/></svg>分享</button>
</div>
<div class="comments">
<div class="cmt-more">查看全部 <span class="cmt-total">86</span> 条评论</div>
<div class="cmt">
<div class="avatar av-orange sm">王</div>
<div>
<div class="cmt-bubble"><span class="cmt-name">运营小王</span>GMV 涨势不错,双 11 前继续冲 🚀</div>
<div class="cmt-meta"><a>赞</a><a>回复</a><span>42 分钟前</span></div>
</div>
</div>
<div class="cmt">
<div class="avatar av-blue sm">数</div>
<div>
<div class="cmt-bubble"><span class="cmt-name">数据中心</span>回复<span style="color:var(--fb-blue);font-weight:600">@运营小王</span>:建议同步关注订单量下滑,可能是支付成功率波动</div>
<div class="cmt-meta"><a>赞</a><a>回复</a><span>35 分钟前</span></div>
</div>
</div>
<div class="cmt-input">
<div class="avatar av-blue sm">张</div>
<input type="text" placeholder="撰写评论…(回车发送)">
</div>
</div>
</article>
<!-- 卡片 2:流量趋势折线图 -->
<article class="card post" data-key="趋势 流量 访问 折线 7天 30天 trend">
<div class="post-hd">
<div class="avatar av-green">增</div>
<div class="meta">
<b>增长分析组</b>
<div class="sub">1 小时前 · 内部可见</div>
</div>
<span class="more">···</span>
</div>
<div class="post-txt">📈 <b>平台访问量趋势</b>:今日访问创近期新高,较昨日同期 +22%,大促预热流量开始释放 <a>#流量监控</a></div>
<div class="chart-head">
<div class="legend">
<span><span class="dot" style="background:#1877f2"></span>今日</span>
<span><span class="dot" style="background:#b6bcc4"></span>昨日</span>
</div>
<div class="pills">
<button class="pill active" data-range="7">近 7 天</button>
<button class="pill" data-range="30">近 30 天</button>
</div>
</div>
<div class="chart-wrap">
<svg id="trendSvg" viewBox="0 0 640 264" style="width:100%;height:auto;display:block"></svg>
</div>
<div class="summary" id="trendSummary">单位:万次访问</div>
<div class="post-stats">
<div><span class="react">👍</span><span class="like-num" data-count="642">642</span></div>
<div><span>38 条评论</span> · <span>17 次分享</span></div>
</div>
<div class="actions">
<button class="act act-like"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M8.5 21H5.2a1.2 1.2 0 0 1-1.2-1.2v-8.6c0-.7.5-1.2 1.2-1.2h3.3zM9.7 10.2 13 3.5c1.4.2 2.2 1.2 2.2 2.7V9h4.4c1.3 0 2.2 1.1 1.9 2.3l-1.5 6.7c-.3 1.2-1.1 3-2.5 3H9.7z"/></svg>赞</button>
<button class="act act-comment"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3C6.5 3 2 6.9 2 11.7c0 2.8 1.4 5.3 3.7 7L5 22l4.3-2c.9.2 1.8.4 2.7.4 5.5 0 10-3.9 10-8.7S17.5 3 12 3z"/></svg>评论</button>
<button class="act act-share"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M13.5 4.5 21 11l-7.5 6.5v-3.9C8 13.7 5.2 15.6 3.5 19.5c.2-6.7 4-10.5 10-11.4z"/></svg>分享</button>
</div>
</article>
<!-- 卡片 3:渠道转化率柱状图 -->
<article class="card post" data-key="渠道 转化率 柱状 对比 营销 channel bar">
<div class="post-hd">
<div class="avatar av-orange">营</div>
<div class="meta">
<b>营销实验室</b>
<div class="sub">3 小时前 · 公开</div>
</div>
<span class="more">···</span>
</div>
<div class="post-txt">🎯 <b>各渠道转化率对比</b>(本周 vs 上周):付费广告转化率升至 6.2% 领跑各渠道,邮件营销持续垫底,建议调整预算配比 <a>#渠道分析</a></div>
<div class="chart-head"><div class="chart-title">转化率(%)· 本周</div><div class="legend"><span>最深色为本周最优渠道</span></div></div>
<div class="chart-wrap" style="padding-bottom:14px">
<div class="bars">
<div class="bcol"><span class="bval">4.8</span><div class="bar" style="height:62%" title="自然搜索 4.8%"></div><span class="bname">自然搜索</span></div>
<div class="bcol"><span class="bval">6.2</span><div class="bar top" style="height:80%" title="付费广告 6.2%"></div><span class="bname">付费广告</span></div>
<div class="bcol"><span class="bval">3.9</span><div class="bar" style="height:50%" title="社交媒体 3.9%"></div><span class="bname">社交媒体</span></div>
<div class="bcol"><span class="bval">5.5</span><div class="bar" style="height:71%" title="直接访问 5.5%"></div><span class="bname">直接访问</span></div>
<div class="bcol"><span class="bval">2.1</span><div class="bar" style="height:27%" title="邮件营销 2.1%"></div><span class="bname">邮件营销</span></div>
<div class="bcol"><span class="bval">3.4</span><div class="bar" style="height:44%" title="联盟推广 3.4%"></div><span class="bname">联盟推广</span></div>
</div>
</div>
<div class="post-stats">
<div><span class="react">👍</span><span class="like-num" data-count="318">318</span></div>
<div><span>21 条评论</span> · <span>9 次分享</span></div>
</div>
<div class="actions">
<button class="act act-like"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M8.5 21H5.2a1.2 1.2 0 0 1-1.2-1.2v-8.6c0-.7.5-1.2 1.2-1.2h3.3zM9.7 10.2 13 3.5c1.4.2 2.2 1.2 2.2 2.7V9h4.4c1.3 0 2.2 1.1 1.9 2.3l-1.5 6.7c-.3 1.2-1.1 3-2.5 3H9.7z"/></svg>赞</button>
<button class="act act-comment"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3C6.5 3 2 6.9 2 11.7c0 2.8 1.4 5.3 3.7 7L5 22l4.3-2c.9.2 1.8.4 2.7.4 5.5 0 10-3.9 10-8.7S17.5 3 12 3z"/></svg>评论</button>
<button class="act act-share"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M13.5 4.5 21 11l-7.5 6.5v-3.9C8 13.7 5.2 15.6 3.5 19.5c.2-6.7 4-10.5 10-11.4z"/></svg>分享</button>
</div>
</article>
<!-- 卡片 4:访问来源占比(环形图) -->
<article class="card post" data-key="来源 分布 占比 环形 donut 用户画像">
<div class="post-hd">
<div class="avatar av-teal">像</div>
<div class="meta">
<b>用户画像中心</b>
<div class="sub">5 小时前 · 公开</div>
</div>
<span class="more">···</span>
</div>
<div class="post-txt">🍩 <b>今日访问来源分布</b>:付费广告占比升至 31%(+4pt),自然流量份额被稀释,SEO 侧需要关注 <a>#来源分析</a></div>
<div class="chart-head"><div class="chart-title">访问来源占比 · 今日</div></div>
<div class="split">
<svg class="donut" viewBox="0 0 160 160">
<g transform="rotate(-90 80 80)">
<circle cx="80" cy="80" r="60" fill="none" stroke="#f0f2f5" stroke-width="26"/>
<circle cx="80" cy="80" r="60" fill="none" stroke="#1877f2" stroke-width="26" stroke-dasharray="155.3 377" stroke-dashoffset="0"/>
<circle cx="80" cy="80" r="60" fill="none" stroke="#45bd62" stroke-width="26" stroke-dasharray="113.9 377" stroke-dashoffset="-158.3"/>
<circle cx="80" cy="80" r="60" fill="none" stroke="#f7b928" stroke-width="26" stroke-dasharray="64.9 377" stroke-dashoffset="-275.2"/>
<circle cx="80" cy="80" r="60" fill="none" stroke="#fa383e" stroke-width="26" stroke-dasharray="30.9 377" stroke-dashoffset="-343.1"/>
</g>
<text x="80" y="76" text-anchor="middle" font-size="19" font-weight="700" fill="#1c1e21">128.4万</text>
<text x="80" y="96" text-anchor="middle" font-size="12" fill="#65676b">总访问量</text>
</svg>
<div>
<div class="lg-row"><span class="dot" style="background:#1877f2"></span><span class="nm">自然流量</span><span class="v">53.9 万</span><span class="pc">42%</span></div>
<div class="lg-row"><span class="dot" style="background:#45bd62"></span><span class="nm">付费广告</span><span class="v">39.8 万</span><span class="pc">31%</span></div>
<div class="lg-row"><span class="dot" style="background:#f7b928"></span><span class="nm">社交媒体</span><span class="v">23.1 万</span><span class="pc">18%</span></div>
<div class="lg-row"><span class="dot" style="background:#fa383e"></span><span class="nm">直接访问</span><span class="v">11.6 万</span><span class="pc">9%</span></div>
</div>
</div>
<div class="post-stats">
<div><span class="react">👍</span><span class="like-num" data-count="205">205</span></div>
<div><span>12 条评论</span> · <span>6 次分享</span></div>
</div>
<div class="actions">
<button class="act act-like"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M8.5 21H5.2a1.2 1.2 0 0 1-1.2-1.2v-8.6c0-.7.5-1.2 1.2-1.2h3.3zM9.7 10.2 13 3.5c1.4.2 2.2 1.2 2.2 2.7V9h4.4c1.3 0 2.2 1.1 1.9 2.3l-1.5 6.7c-.3 1.2-1.1 3-2.5 3H9.7z"/></svg>赞</button>
<button class="act act-comment"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3C6.5 3 2 6.9 2 11.7c0 2.8 1.4 5.3 3.7 7L5 22l4.3-2c.9.2 1.8.4 2.7.4 5.5 0 10-3.9 10-8.7S17.5 3 12 3z"/></svg>评论</button>
<button class="act act-share"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M13.5 4.5 21 11l-7.5 6.5v-3.9C8 13.7 5.2 15.6 3.5 19.5c.2-6.7 4-10.5 10-11.4z"/></svg>分享</button>
</div>
</article>
<!-- 卡片 5:热销商品 TOP5 -->
<article class="card post" data-key="商品 排行 榜单 top 销量 销售额 电商 rank table">
<div class="post-hd">
<div class="avatar av-purple">电</div>
<div class="meta">
<b>电商运营组</b>
<div class="sub">8 小时前 · 公开</div>
</div>
<span class="more">···</span>
</div>
<div class="post-txt">🏆 <b>今日热销商品 TOP5</b>:降噪耳机 Pro 稳居榜首,便携榨汁机环比 +24.8% 增速最快 <a>#电商日报</a></div>
<div class="tbl-wrap" style="padding-bottom:8px">
<table class="tbl">
<thead><tr><th>#</th><th>商品</th><th>销量</th><th>销售额</th><th>环比</th></tr></thead>
<tbody>
<tr><td><span class="rank r1">1</span></td><td><b>无线降噪耳机 Pro</b></td><td>3,286 件</td><td>¥482.6 万</td><td class="up" style="color:var(--green);font-weight:700">▲ 18.2%</td></tr>
<tr><td><span class="rank r2">2</span></td><td><b>智能手表 S6</b></td><td>2,941 件</td><td>¥398.2 万</td><td style="color:var(--green);font-weight:700">▲ 9.6%</td></tr>
<tr><td><span class="rank r3">3</span></td><td><b>便携榨汁机</b></td><td>2,733 件</td><td>¥96.3 万</td><td style="color:var(--green);font-weight:700">▲ 24.8%</td></tr>
<tr><td><span class="rank rx">4</span></td><td><b>机械键盘 K87</b></td><td>2,158 件</td><td>¥172.9 万</td><td style="color:var(--red);font-weight:700">▼ 3.1%</td></tr>
<tr><td><span class="rank rx">5</span></td><td><b>桌面升降支架</b></td><td>1,986 件</td><td>¥119.5 万</td><td style="color:var(--green);font-weight:700">▲ 5.4%</td></tr>
</tbody>
</table>
</div>
<div class="post-stats">
<div><span class="react">❤️</span><span class="like-num" data-count="521">521</span></div>
<div><span>45 条评论</span> · <span>28 次分享</span></div>
</div>
<div class="actions">
<button class="act act-like"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M8.5 21H5.2a1.2 1.2 0 0 1-1.2-1.2v-8.6c0-.7.5-1.2 1.2-1.2h3.3zM9.7 10.2 13 3.5c1.4.2 2.2 1.2 2.2 2.7V9h4.4c1.3 0 2.2 1.1 1.9 2.3l-1.5 6.7c-.3 1.2-1.1 3-2.5 3H9.7z"/></svg>赞</button>
<button class="act act-comment"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3C6.5 3 2 6.9 2 11.7c0 2.8 1.4 5.3 3.7 7L5 22l4.3-2c.9.2 1.8.4 2.7.4 5.5 0 10-3.9 10-8.7S17.5 3 12 3z"/></svg>评论</button>
<button class="act act-share"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M13.5 4.5 21 11l-7.5 6.5v-3.9C8 13.7 5.2 15.6 3.5 19.5c.2-6.7 4-10.5 10-11.4z"/></svg>分享</button>
</div>
</article>
<div class="noresult card" id="noResult" style="padding:40px 0">🔍 没有匹配的数据卡片,换个关键词试试(如:趋势 / 渠道 / 排行)</div>
</section>
<!-- ================= 右栏 ================= -->
<aside class="side side-r">
<div class="card rc">
<h4>推荐看板</h4>
<div class="rc-item">
<div class="rc-thumb" style="background:linear-gradient(140deg,#166fe5,#0a3d91)">🛒</div>
<div><div class="tt">双 11 作战室</div><div class="dd">datafeed.cn/board/d11</div></div>
</div>
<div class="rc-item">
<div class="rc-thumb" style="background:linear-gradient(140deg,#f7b928,#dd7d0a)">📣</div>
<div><div class="tt">渠道 ROI 分析</div><div class="dd">datafeed.cn/board/roi</div></div>
</div>
</div>
<div class="card rc">
<h4>数据更新计划</h4>
<div class="rc-row"><span class="rc-status on"></span><div><b>T+1 销售宽表</b><div class="sub">每日 02:00 · 已完成</div></div><span class="tail">2h 前</span></div>
<div class="rc-row"><span class="rc-status on"></span><div><b>用户标签计算</b><div class="sub">每日 03:30 · 已完成</div></div><span class="tail">40m 前</span></div>
<div class="rc-row"><span class="rc-status pulse"></span><div><b>实时埋点流</b><div class="sub">持续写入 · 运行中</div></div><span class="tail" style="color:var(--green);font-weight:700">正常</span></div>
<div class="rc-row"><span class="rc-status off"></span><div><b>周报快照</b><div class="sub">每周一 09:00 · 待执行</div></div><span class="tail">2d 后</span></div>
</div>
<div class="card rc">
<h4>值班分析师</h4>
<div class="rc-row"><div class="avatar sm av-green">李</div><div><b>李雷</b><div class="sub">主值班 · 增长数据</div></div></div>
<div class="rc-row"><div class="avatar sm av-blue">韩</div><div><b>韩梅梅</b><div class="sub">副值班 · 电商数据</div></div></div>
<div class="rc-row"><div class="avatar sm av-orange">陈</div><div><b>陈晨</b><div class="sub">渠道数据 · 离线</div></div></div>
</div>
<div class="card rc">
<h4>你的小组</h4>
<div class="rc-row"><div class="avatar sm av-blue">增</div><div><b>增长数据组</b><div class="sub">12 位成员 · 3 条新动态</div></div></div>
<div class="rc-row"><div class="avatar sm av-green">实</div><div><b>实验平台组</b><div class="sub">8 位成员 · 1 条新动态</div></div></div>
</div>
</aside>
</main>
<div class="toast" id="toast"></div>
<script>
/* ================= 折线图(平滑曲线,Catmull-Rom → 贝塞尔) ================= */
const SVGNS = 'http://www.w3.org/2000/svg';
const PAD = {l:44, r:628, t:16, b:222}; // 640 x 264 绘图区
function smoothPath(pts){
if(pts.length < 2) return '';
let d = `M ${pts[0][0].toFixed(1)} ${pts[0][1].toFixed(1)}`;
for(let i = 0; i < pts.length - 1; i++){
const p0 = pts[Math.max(0, i-1)], p1 = pts[i], p2 = pts[i+1], p3 = pts[Math.min(pts.length-1, i+2)];
const c1x = p1[0] + (p2[0]-p0[0])/6, c1y = p1[1] + (p2[1]-p0[1])/6;
const c2x = p2[0] - (p3[0]-p1[0])/6, c2y = p2[1] - (p3[1]-p1[1])/6;
d += ` C ${c1x.toFixed(1)} ${c1y.toFixed(1)}, ${c2x.toFixed(1)} ${c2y.toFixed(1)}, ${p2[0].toFixed(1)} ${p2[1].toFixed(1)}`;
}
return d;
}
function gen30(){ // 近 30 天(确定性伪随机,演示用)
const labels=[], today=[], yest=[];
for(let i = 29; i >= 0; i--){
const d = new Date(2026, 9, 25 - i);
labels.push(`${d.getMonth()+1}/${d.getDate()}`);
const v = 55 + 16*Math.sin(i/3.4) + 9*Math.cos(i/1.7) + (i%7===6 ? 9 : 0) - (i%7===0 ? 5 : 0);
today.push(Math.round(v*10)/10);
yest.push(Math.round((v - 6 + 4*Math.cos(i/2.2))*10)/10);
}
return {labels, today, yesterday:yest};
}
const DATASETS = {
'7': {labels:['10/19','10/20','10/21','10/22','10/23','10/24','10/25'],
today:[52.4,61.2,58.6,73.1,66.4,81.2,88.5],
yesterday:[48.9,55.3,60.2,64.5,59.1,70.6,72.3]},
'30': gen30()
};
function el(name, attrs){
const n = document.createElementNS(SVGNS, name);
for(const k in attrs) n.setAttribute(k, attrs[k]);
return n;
}
function buildTrend(range){
const ds = DATASETS[range];
const svg = document.getElementById('trendSvg');
svg.innerHTML = '';
const peak = Math.max(...ds.today, ...ds.yesterday);
const step = Math.max(10, Math.ceil(peak/4/5)*5);
const maxT = step*4;
const n = ds.today.length;
const X = i => PAD.l + (PAD.r-PAD.l)*i/(n-1);
const Y = v => PAD.b - (v/maxT)*(PAD.b-PAD.t);
// 渐变
const defs = el('defs');
const grad = el('linearGradient', {id:'gBlue', x1:0, y1:0, x2:0, y2:1});
grad.appendChild(el('stop', {offset:'0%', 'stop-color':'#1877f2', 'stop-opacity':.22}));
grad.appendChild(el('stop', {offset:'100%', 'stop-color':'#1877f2', 'stop-opacity':0}));
defs.appendChild(grad); svg.appendChild(defs);
// 网格 + Y 轴刻度
for(let i = 0; i <= 4; i++){
const v = step*i, y = Y(v);
svg.appendChild(el('line', {x1:PAD.l, x2:PAD.r, y1:y, y2:y, stroke:'#e4e6eb', 'stroke-dasharray': i? '3 5' : '0'}));
const t = el('text', {x:PAD.l-8, y:y+4, 'text-anchor':'end', 'font-size':11, fill:'#8a8d91'});
t.textContent = v; svg.appendChild(t);
}
const pt = arr => arr.map((v,i)=>[X(i), Y(v)]);
const pToday = pt(ds.today), pYest = pt(ds.yesterday);
// 面积(今日)
const area = smoothPath(pToday) + ` L ${pToday[n-1][0]} ${PAD.b} L ${pToday[0][0]} ${PAD.b} Z`;
svg.appendChild(el('path', {d:area, fill:'url(#gBlue)'}));
// 昨日(灰虚线)
svg.appendChild(el('path', {d:smoothPath(pYest), fill:'none', stroke:'#b6bcc4', 'stroke-width':2, 'stroke-dasharray':'5 6'}));
// 今日(蓝)
svg.appendChild(el('path', {d:smoothPath(pToday), fill:'none', stroke:'#1877f2', 'stroke-width':3, 'stroke-linecap':'round'}));
// 端点
svg.appendChild(el('circle', {cx:pToday[n-1][0], cy:pToday[n-1][1], r:4.5, fill:'#1877f2', stroke:'#fff', 'stroke-width':2}));
// X 轴标签 & 悬停提示
const labelStep = Math.max(1, Math.ceil(n/7));
for(let i = 0; i < n; i++){
if(n <= 8){
svg.appendChild(el('circle', {cx:X(i), cy:Y(ds.today[i]), r:2.6, fill:'#1877f2'}));
}
const hit = el('circle', {cx:X(i), cy:Y(ds.today[i]), r:11, fill:'transparent', style:'cursor:pointer'});
const ti = el('title'); ti.textContent = `${ds.labels[i]} · 今日 ${ds.today[i]} 万 / 昨日 ${ds.yesterday[i]} 万`;
hit.appendChild(ti); svg.appendChild(hit);
if(i % labelStep === 0 || i === n-1){
const t = el('text', {x:X(i), y:244, 'text-anchor':'middle', 'font-size':11, fill:'#8a8d91'});
t.textContent = ds.labels[i]; svg.appendChild(t);
}
}
const mx = Math.max(...ds.today), mn = Math.min(...ds.today);
const avg = (ds.today.reduce((a,b)=>a+b,0)/n).toFixed(1);
document.getElementById('trendSummary').textContent =
`单位:万次访问 · 峰值 ${mx} 万 · 谷值 ${mn} 万 · 均值 ${avg} 万`;
}
buildTrend('7');
document.querySelectorAll('.pill[data-range]').forEach(p => {
p.addEventListener('click', () => {
document.querySelectorAll('.pill[data-range]').forEach(x => x.classList.remove('active'));
p.classList.add('active');
buildTrend(p.dataset.range);
});
});
/* ================= 点赞 ================= */
document.querySelectorAll('.act-like').forEach(btn => {
btn.addEventListener('click', () => {
const post = btn.closest('.post');
const num = post.querySelector('.like-num');
const on = btn.classList.toggle('liked');
num.dataset.count = +num.dataset.count + (on ? 1 : -1);
const c = +num.dataset.count;
num.textContent = c >= 1000 ? (c/1000).toFixed(1).replace(/\.0$/,'') + 'k' : c.toLocaleString('zh-CN');
});
});
/* ================= 评论(回车发送) ================= */
const cmtInput = document.querySelector('.cmt-input input');
cmtInput.addEventListener('keydown', e => {
if(e.key !== 'Enter' || !e.target.value.trim()) return;
const post = e.target.closest('.post');
const wrap = e.target.closest('.comments');
const txt = e.target.value.trim();
e.target.value = '';
const div = document.createElement('div');
div.className = 'cmt';
div.innerHTML = `<div class="avatar av-blue sm">张</div>
<div><div class="cmt-bubble"><span class="cmt-name">张分析</span>${txt.replace(/</g,'&lt;')}</div>
<div class="cmt-meta"><a>赞</a><a>回复</a><span>刚刚</span></div></div>`;
wrap.insertBefore(div, e.target.closest('.cmt-input'));
const cn = post.querySelector('.cmt-num'), total = post.querySelector('.cmt-total');
cn.dataset.count = +cn.dataset.count + 1;
cn.textContent = cn.dataset.count + ' 条评论';
total.textContent = cn.dataset.count;
});
document.querySelectorAll('.act-comment').forEach(btn => {
btn.addEventListener('click', () => {
const input = btn.closest('.post').querySelector('.cmt-input input');
if(input){ input.focus(); } else { showToast('该卡片暂未开放评论(演示)'); }
});
});
/* ================= 分享 / 演示按钮 Toast ================= */
const toast = document.getElementById('toast');
let toastTimer;
function showToast(msg){
toast.textContent = msg;
toast.classList.add('show');
clearTimeout(toastTimer);
toastTimer = setTimeout(() => toast.classList.remove('show'), 1800);
}
document.querySelectorAll('.act-share').forEach(b => b.addEventListener('click', () => showToast('看板链接已复制(演示)')));
document.querySelectorAll('[data-toast]').forEach(b => b.addEventListener('click', () => showToast(b.dataset.toast)));
document.querySelectorAll('.story').forEach(s => s.addEventListener('click', () => showToast('演示页面:数据专题未接入')));
/* ================= 搜索 / 筛选(顶栏 + 发布器共用) ================= */
function filterPosts(q){
q = q.trim().toLowerCase();
let visible = 0;
document.querySelectorAll('.feed .post').forEach(p => {
const hit = !q || (p.dataset.key + ' ' + p.textContent).toLowerCase().includes(q);
p.style.display = hit ? '' : 'none';
if(hit) visible++;
});
document.getElementById('noResult').style.display = visible ? 'none' : 'block';
}
['globalSearch','feedFilter'].forEach(id => {
document.getElementById(id).addEventListener('input', e => {
filterPosts(e.target.value);
if(id === 'globalSearch'){ const f = document.getElementById('feedFilter'); if(f.value !== e.target.value) f.value = e.target.value; }
else { const g = document.getElementById('globalSearch'); if(g.value !== e.target.value) g.value = e.target.value; }
});
});
/* ================= 顶部导航高亮 ================= */
document.querySelectorAll('.tb-nav').forEach(n => {
n.addEventListener('click', () => {
document.querySelectorAll('.tb-nav').forEach(x => x.classList.remove('active'));
n.classList.add('active');
});
});
</script>
</body>
</html>