Files
xianyan/docs/preview/widescreen-dashboard.html
Developer 5a49d20c8a chore: 完成项目品牌域名批量替换与功能迭代
本次提交包含多项核心更新:
1. 全量替换项目内所有xianyan.app域名变更为s2ss.com,包含配置文件、路由、隐私政策等
2. 重构图表库从fl_chart迁移至syncfusion_flutter_charts,优化图表渲染效果
3. 新增宽屏分屏布局支持,包含右侧面板注册表与可拖拽分割线
4. 完善触觉反馈服务与认证感知Mixin,修复多处内存泄漏问题
5. 合并勋章墙与金币记录入口至成就中心,简化个人中心导航
6. 新增收藏与时间线数据合并导入功能
7. 修复多处UI样式问题,统一主题颜色使用规范
8. 新增日历同步与跨平台触觉反馈依赖库
9. 修复BotToast初始化流程,避免路由切换时的弹窗崩溃
2026-05-29 10:06:55 +08:00

714 lines
20 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=1440">
<title>闲言 - 概览仪表盘</title>
<style>
:root {
--primary: #007AFF;
--primary-light: rgba(0,122,255,0.12);
--secondary: #5856D6;
--background: #FAFAFA;
--surface: #FFFFFF;
--surface-secondary: #F2F2F7;
--text: #1C1C1E;
--text-secondary: #8E8E93;
--text-tertiary: #AEAEB2;
--separator: rgba(60,60,67,0.12);
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--space-1: 4px;
--space-2: 8px;
--space-3: 16px;
--space-4: 24px;
--space-5: 32px;
--font-family: -apple-system, system-ui, 'SF Pro Display', 'Segoe UI', sans-serif;
--nav-width: 72px;
--glass-bg: rgba(255,255,255,0.72);
--glass-blur: 20px;
--card-bg: rgba(255,255,255,0.8);
--red: #FF3B30;
--orange: #FF9500;
--green: #34C759;
--teal: #5AC8FA;
}
[data-theme="dark"] {
--background: #1A1A2E;
--surface: #16213E;
--surface-secondary: #0F3460;
--text: #F5F5F7;
--text-secondary: #98989D;
--text-tertiary: #636366;
--separator: rgba(84,84,88,0.65);
--glass-bg: rgba(30,30,50,0.72);
--card-bg: rgba(30,30,50,0.8);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: var(--font-family);
background: var(--background);
color: var(--text);
height: 100vh;
overflow: hidden;
transition: background 0.3s, color 0.3s;
}
.app-shell { display: flex; height: 100vh; width: 100%; }
.nav-sidebar {
width: var(--nav-width);
min-width: var(--nav-width);
background: var(--glass-bg);
backdrop-filter: blur(var(--glass-blur));
-webkit-backdrop-filter: blur(var(--glass-blur));
border-right: 1px solid var(--separator);
display: flex;
flex-direction: column;
align-items: center;
padding: var(--space-4) 0;
gap: var(--space-2);
z-index: 10;
}
.nav-logo {
width: 40px; height: 40px;
border-radius: var(--radius-lg);
background: linear-gradient(135deg, var(--primary), var(--secondary));
display: flex; align-items: center; justify-content: center;
font-size: 20px; color: #fff;
margin-bottom: var(--space-4);
box-shadow: var(--shadow-md);
}
.nav-item {
width: 48px; height: 48px;
border-radius: var(--radius-lg);
display: flex; flex-direction: column; align-items: center; justify-content: center;
cursor: pointer; transition: all 0.2s ease;
font-size: 10px; color: var(--text-secondary); gap: 2px;
text-decoration: none; position: relative;
}
.nav-item .nav-icon { font-size: 22px; line-height: 1; }
.nav-item .nav-label { font-size: 9px; font-weight: 500; }
.nav-item:hover { background: var(--primary-light); color: var(--primary); }
.nav-spacer { flex: 1; }
.nav-theme-btn {
width: 40px; height: 40px; border-radius: 50%;
border: none; background: var(--surface-secondary);
color: var(--text); font-size: 18px; cursor: pointer;
display: flex; align-items: center; justify-content: center;
transition: all 0.2s;
}
.nav-theme-btn:hover { background: var(--primary-light); }
.main-content {
flex: 1;
overflow-y: auto;
padding: var(--space-5);
}
.dashboard-header {
margin-bottom: var(--space-5);
}
.greeting {
font-size: 32px;
font-weight: 700;
letter-spacing: -0.5px;
margin-bottom: var(--space-1);
}
.greeting-sub {
font-size: 15px;
color: var(--text-secondary);
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--space-3);
margin-bottom: var(--space-5);
}
.stat-card {
background: var(--card-bg);
backdrop-filter: blur(10px);
border-radius: var(--radius-xl);
padding: var(--space-4);
border: 1px solid var(--separator);
transition: transform 0.2s, box-shadow 0.2s;
position: relative;
overflow: hidden;
}
.stat-card:hover {
transform: translateY(-3px);
box-shadow: var(--shadow-lg);
}
.stat-card::after {
content: '';
position: absolute;
top: -20px; right: -20px;
width: 80px; height: 80px;
border-radius: 50%;
opacity: 0.06;
}
.stat-card:nth-child(1)::after { background: var(--primary); }
.stat-card:nth-child(2)::after { background: var(--red); }
.stat-card:nth-child(3)::after { background: var(--orange); }
.stat-card:nth-child(4)::after { background: var(--green); }
.stat-icon {
width: 44px; height: 44px;
border-radius: var(--radius-lg);
display: flex; align-items: center; justify-content: center;
font-size: 22px; margin-bottom: var(--space-3);
}
.stat-value {
font-size: 28px; font-weight: 700;
letter-spacing: -0.5px;
}
.stat-label {
font-size: 13px; color: var(--text-secondary);
margin-top: var(--space-1);
}
.stat-trend {
font-size: 12px; color: var(--green);
margin-top: var(--space-1);
display: flex; align-items: center; gap: 4px;
}
.section {
margin-bottom: var(--space-5);
}
.section-header {
display: flex; align-items: center; justify-content: space-between;
margin-bottom: var(--space-3);
}
.section-title {
font-size: 20px; font-weight: 700;
}
.section-action {
font-size: 14px; color: var(--primary);
cursor: pointer; text-decoration: none;
}
.today-recommend {
background: linear-gradient(135deg, var(--primary), var(--secondary));
border-radius: var(--radius-xl);
padding: var(--space-5);
color: #fff;
position: relative;
overflow: hidden;
margin-bottom: var(--space-5);
}
.today-recommend::before {
content: '';
position: absolute;
top: -40px; right: -40px;
width: 160px; height: 160px;
border-radius: 50%;
background: rgba(255,255,255,0.1);
}
.today-recommend::after {
content: '';
position: absolute;
bottom: -30px; left: -30px;
width: 120px; height: 120px;
border-radius: 50%;
background: rgba(255,255,255,0.06);
}
.recommend-badge {
display: inline-flex; align-items: center; gap: 4px;
padding: 4px 12px; border-radius: 20px;
background: rgba(255,255,255,0.2);
font-size: 12px; font-weight: 600;
margin-bottom: var(--space-3);
}
.recommend-sentence {
font-size: 22px; font-weight: 500;
line-height: 1.6;
margin-bottom: var(--space-3);
position: relative;
z-index: 1;
}
.recommend-author {
font-size: 14px; opacity: 0.8;
position: relative; z-index: 1;
}
.recommend-actions {
display: flex; gap: var(--space-2);
margin-top: var(--space-4);
position: relative; z-index: 1;
}
.recommend-btn {
padding: var(--space-2) var(--space-4);
border-radius: 20px;
border: none;
font-size: 14px; font-weight: 600;
cursor: pointer;
font-family: var(--font-family);
transition: all 0.2s;
}
.recommend-btn.primary {
background: #fff; color: var(--primary);
}
.recommend-btn.primary:hover { opacity: 0.9; }
.recommend-btn.ghost {
background: rgba(255,255,255,0.2); color: #fff;
}
.recommend-btn.ghost:hover { background: rgba(255,255,255,0.3); }
.quick-actions-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: var(--space-3);
}
.quick-action-card {
background: var(--card-bg);
backdrop-filter: blur(10px);
border-radius: var(--radius-xl);
padding: var(--space-4);
border: 1px solid var(--separator);
display: flex; flex-direction: column; align-items: center;
gap: var(--space-2);
cursor: pointer;
transition: all 0.2s;
}
.quick-action-card:hover {
transform: translateY(-3px);
box-shadow: var(--shadow-lg);
background: var(--primary-light);
}
.quick-action-icon {
width: 48px; height: 48px;
border-radius: var(--radius-lg);
display: flex; align-items: center; justify-content: center;
font-size: 24px;
}
.quick-action-label {
font-size: 13px; font-weight: 500;
color: var(--text-secondary);
}
.recent-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-3);
}
.recent-card {
background: var(--card-bg);
backdrop-filter: blur(10px);
border-radius: var(--radius-xl);
padding: var(--space-4);
border: 1px solid var(--separator);
cursor: pointer;
transition: all 0.2s;
}
.recent-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.recent-card-header {
display: flex; align-items: center; gap: var(--space-2);
margin-bottom: var(--space-3);
}
.recent-card-avatar {
width: 32px; height: 32px;
border-radius: 50%;
display: flex; align-items: center; justify-content: center;
font-size: 16px; color: #fff;
}
.recent-card-author { font-size: 13px; font-weight: 600; }
.recent-card-time { font-size: 11px; color: var(--text-tertiary); margin-left: auto; }
.recent-card-text {
font-size: 14px; line-height: 1.6;
color: var(--text);
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.recent-card-footer {
display: flex; gap: var(--space-3);
margin-top: var(--space-2);
font-size: 12px; color: var(--text-secondary);
}
.chart-section {
background: var(--card-bg);
backdrop-filter: blur(10px);
border-radius: var(--radius-xl);
padding: var(--space-4);
border: 1px solid var(--separator);
}
.chart-header {
display: flex; align-items: center; justify-content: space-between;
margin-bottom: var(--space-4);
}
.chart-title { font-size: 16px; font-weight: 600; }
.chart-tabs {
display: flex; gap: var(--space-1);
background: var(--surface-secondary);
border-radius: var(--radius-lg);
padding: 2px;
}
.chart-tab {
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-md);
font-size: 12px; font-weight: 500;
cursor: pointer; border: none;
background: transparent; color: var(--text-secondary);
font-family: var(--font-family);
transition: all 0.2s;
}
.chart-tab.active {
background: var(--surface);
color: var(--text);
box-shadow: var(--shadow-sm);
}
.bar-chart {
display: flex; align-items: flex-end;
gap: var(--space-2);
height: 160px;
padding-top: var(--space-3);
}
.bar-item {
flex: 1;
display: flex; flex-direction: column;
align-items: center; gap: var(--space-1);
}
.bar {
width: 100%;
max-width: 40px;
border-radius: var(--radius-sm) var(--radius-sm) 0 0;
background: var(--primary);
transition: height 0.5s ease;
position: relative;
min-height: 4px;
}
.bar:hover { opacity: 0.8; }
.bar-label {
font-size: 11px; color: var(--text-tertiary);
}
.bar-value {
font-size: 10px; color: var(--text-secondary);
font-weight: 600;
}
.activity-heatmap {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 4px;
margin-top: var(--space-3);
}
.heatmap-cell {
aspect-ratio: 1;
border-radius: var(--radius-sm);
background: var(--surface-secondary);
transition: all 0.2s;
cursor: pointer;
position: relative;
}
.heatmap-cell:hover { transform: scale(1.2); }
.heatmap-cell.level-1 { background: rgba(0,122,255,0.2); }
.heatmap-cell.level-2 { background: rgba(0,122,255,0.4); }
.heatmap-cell.level-3 { background: rgba(0,122,255,0.6); }
.heatmap-cell.level-4 { background: rgba(0,122,255,0.8); }
.heatmap-labels {
display: flex; justify-content: space-between;
margin-top: var(--space-1);
font-size: 10px; color: var(--text-tertiary);
}
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--text-tertiary); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-secondary); }
</style>
</head>
<body data-theme="light">
<div class="app-shell">
<nav class="nav-sidebar">
<div class="nav-logo">💬</div>
<a class="nav-item" href="widescreen-home.html" title="闲言">
<span class="nav-icon">💬</span>
<span class="nav-label">闲言</span>
</a>
<a class="nav-item" href="widescreen-discover.html" title="发现">
<span class="nav-icon">🧭</span>
<span class="nav-label">发现</span>
</a>
<a class="nav-item" href="widescreen-profile.html" title="我的">
<span class="nav-icon">👤</span>
<span class="nav-label">我的</span>
</a>
<div class="nav-spacer"></div>
<button class="nav-theme-btn" onclick="toggleTheme()" title="切换主题">🌙</button>
</nav>
<div class="main-content">
<div class="dashboard-header">
<div class="greeting">☀️ 早上好,诗意栖居</div>
<div class="greeting-sub">今天是 2026年5月29日 星期五 · 让文字点亮你的一天</div>
</div>
<div class="today-recommend">
<div class="recommend-badge">🌟 今日推荐</div>
<div class="recommend-sentence">人生如逆旅,我亦是行人。在这漫长的旅途中,愿你我都能找到属于自己的诗意与远方。</div>
<div class="recommend-author">—— 苏轼《临江仙·送钱穆父》</div>
<div class="recommend-actions">
<button class="recommend-btn primary">❤️ 喜欢</button>
<button class="recommend-btn ghost">📖 深度解读</button>
<button class="recommend-btn ghost">🔗 分享</button>
</div>
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon" style="background:var(--primary-light)">📖</div>
<div class="stat-value">1,286</div>
<div class="stat-label">总阅读量</div>
<div class="stat-trend">↑ 12% 较上周</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background:rgba(255,59,48,0.1)">❤️</div>
<div class="stat-value">456</div>
<div class="stat-label">获赞总数</div>
<div class="stat-trend">↑ 8% 较上周</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background:rgba(255,149,0,0.1)"></div>
<div class="stat-value">128</div>
<div class="stat-label">收藏句子</div>
<div class="stat-trend">↑ 5 本周新增</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background:rgba(52,199,89,0.1)">✍️</div>
<div class="stat-value">56</div>
<div class="stat-label">原创句子</div>
<div class="stat-trend">↑ 3 本周新增</div>
</div>
</div>
<div class="section">
<div class="section-header">
<div class="section-title">⚡ 快捷操作</div>
</div>
<div class="quick-actions-grid">
<div class="quick-action-card">
<div class="quick-action-icon" style="background:rgba(0,122,255,0.1)">✍️</div>
<span class="quick-action-label">写句子</span>
</div>
<div class="quick-action-card">
<div class="quick-action-icon" style="background:rgba(255,149,0,0.1)"></div>
<span class="quick-action-label">我的收藏</span>
</div>
<div class="quick-action-card">
<div class="quick-action-icon" style="background:rgba(90,200,250,0.1)">🕐</div>
<span class="quick-action-label">浏览历史</span>
</div>
<div class="quick-action-card">
<div class="quick-action-icon" style="background:rgba(88,86,214,0.1)">📖</div>
<span class="quick-action-label">稍后阅读</span>
</div>
<div class="quick-action-card">
<div class="quick-action-icon" style="background:rgba(255,45,85,0.1)">🤖</div>
<span class="quick-action-label">AI 助手</span>
</div>
</div>
</div>
<div class="section">
<div class="section-header">
<div class="section-title">🕐 最近浏览</div>
<a class="section-action" href="#">查看全部 </a>
</div>
<div class="recent-grid">
<div class="recent-card">
<div class="recent-card-header">
<div class="recent-card-avatar" style="background:linear-gradient(135deg,#007AFF,#5856D6)">🌙</div>
<span class="recent-card-author">李白</span>
<span class="recent-card-time">3分钟前</span>
</div>
<div class="recent-card-text">长风破浪会有时,直挂云帆济沧海。人生不如意十之八九,但那又如何?</div>
<div class="recent-card-footer">
<span>❤️ 2.3k</span>
<span>💬 186</span>
</div>
</div>
<div class="recent-card">
<div class="recent-card-header">
<div class="recent-card-avatar" style="background:linear-gradient(135deg,#FF9500,#FF3B30)">🍂</div>
<span class="recent-card-author">苏轼</span>
<span class="recent-card-time">15分钟前</span>
</div>
<div class="recent-card-text">竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生。回首向来萧瑟处,归去,也无风雨也无晴。</div>
<div class="recent-card-footer">
<span>❤️ 1.8k</span>
<span>💬 92</span>
</div>
</div>
<div class="recent-card">
<div class="recent-card-header">
<div class="recent-card-avatar" style="background:linear-gradient(135deg,#34C759,#007AFF)">🌿</div>
<span class="recent-card-author">王维</span>
<span class="recent-card-time">1小时前</span>
</div>
<div class="recent-card-text">行到水穷处,坐看云起时。世间万物皆有定数,不必强求。</div>
<div class="recent-card-footer">
<span>❤️ 956</span>
<span>💬 45</span>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header">
<div class="section-title">📊 数据统计</div>
</div>
<div class="chart-section">
<div class="chart-header">
<div class="chart-title">本周阅读量</div>
<div class="chart-tabs">
<button class="chart-tab active"></button>
<button class="chart-tab"></button>
<button class="chart-tab"></button>
</div>
</div>
<div class="bar-chart" id="barChart">
<div class="bar-item">
<div class="bar-value">42</div>
<div class="bar" style="height:42%"></div>
<div class="bar-label">周一</div>
</div>
<div class="bar-item">
<div class="bar-value">68</div>
<div class="bar" style="height:68%"></div>
<div class="bar-label">周二</div>
</div>
<div class="bar-item">
<div class="bar-value">55</div>
<div class="bar" style="height:55%"></div>
<div class="bar-label">周三</div>
</div>
<div class="bar-item">
<div class="bar-value">82</div>
<div class="bar" style="height:82%"></div>
<div class="bar-label">周四</div>
</div>
<div class="bar-item">
<div class="bar-value">91</div>
<div class="bar" style="height:91%"></div>
<div class="bar-label">周五</div>
</div>
<div class="bar-item">
<div class="bar-value">76</div>
<div class="bar" style="height:76%"></div>
<div class="bar-label">周六</div>
</div>
<div class="bar-item">
<div class="bar-value">63</div>
<div class="bar" style="height:63%"></div>
<div class="bar-label">周日</div>
</div>
</div>
<div style="margin-top:32px">
<div class="chart-title" style="margin-bottom:12px">活跃度热力图</div>
<div class="activity-heatmap" id="heatmap"></div>
<div class="heatmap-labels">
<span>4周前</span>
<span>3周前</span>
<span>2周前</span>
<span>上周</span>
<span>本周</span>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function toggleTheme() {
const body = document.body;
const btn = document.querySelector('.nav-theme-btn');
if (body.dataset.theme === 'light') {
body.dataset.theme = 'dark';
btn.textContent = '☀️';
} else {
body.dataset.theme = 'light';
btn.textContent = '🌙';
}
}
const heatmap = document.getElementById('heatmap');
const levels = [0, 0, 1, 0, 2, 1, 0, 0, 1, 3, 2, 1, 0, 0, 1, 2, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1];
for (let i = 0; i < 28; i++) {
const cell = document.createElement('div');
cell.className = 'heatmap-cell' + (levels[i] ? ` level-${levels[i]}` : '');
cell.title = `${levels[i]} 次互动`;
heatmap.appendChild(cell);
}
document.querySelectorAll('.chart-tab').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('.chart-tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
});
});
</script>
</body>
</html>