本次更新涵盖多个功能模块的优化与新增: 1. 新增Wi-Fi直连配对方式与协作画布模块 2. 完成设备管理重命名API与前端适配 3. 优化日签卡片空数据保护与UI细节 4. 新增剪贴板工具与每日运势会话 5. 修复应用锁恢复、语音消息录制等已知问题 6. 完善文件传输统计与配对逻辑 7. 更新安卓权限配置与iOS隐私描述 8. 新增自动化测试脚本与文档 9. 清理旧版审计报告与测试文件
1484 lines
61 KiB
HTML
1484 lines
61 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN" data-theme="dark" data-style="ancient">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>每日运势 - 交互式设计预览</title>
|
|
<style>
|
|
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;600;700;900&family=Noto+Sans+SC:wght@300;400;500;700&display=swap');
|
|
|
|
:root {
|
|
--primary: #C41E3A;
|
|
--primary-light: #E8475D;
|
|
--primary-dark: #8B1528;
|
|
--gold: #D4A843;
|
|
--gold-light: #F0D68A;
|
|
--gold-dark: #A07C2E;
|
|
--radius-sm: 8px;
|
|
--radius-md: 14px;
|
|
--radius-lg: 20px;
|
|
--font-serif: 'Noto Serif SC', serif;
|
|
--font-sans: 'Noto Sans SC', sans-serif;
|
|
--transition: 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
[data-theme="dark"] {
|
|
--bg: #0D0D0D;
|
|
--bg-elevated: #141414;
|
|
--bg-card: #1A1A1A;
|
|
--bg-card-light: #252525;
|
|
--bg-input: #1E1E1E;
|
|
--text: #F5F0E8;
|
|
--text-secondary: #9A9590;
|
|
--text-dim: #5A5550;
|
|
--border: #2A2A2A;
|
|
--border-light: #333;
|
|
--shadow-card: 0 4px 24px rgba(0,0,0,0.4);
|
|
--divider: rgba(255,255,255,0.06);
|
|
--overlay: rgba(0,0,0,0.6);
|
|
}
|
|
|
|
[data-theme="light"] {
|
|
--bg: #F2F2F7;
|
|
--bg-elevated: #FFFFFF;
|
|
--bg-card: #FFFFFF;
|
|
--bg-card-light: #F9F9FB;
|
|
--bg-input: #F2F2F7;
|
|
--text: #1C1C1E;
|
|
--text-secondary: #636366;
|
|
--text-dim: #AEAEB2;
|
|
--border: #E5E5EA;
|
|
--border-light: #D1D1D6;
|
|
--shadow-card: 0 2px 16px rgba(0,0,0,0.08);
|
|
--divider: rgba(0,0,0,0.05);
|
|
--overlay: rgba(0,0,0,0.3);
|
|
}
|
|
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font-family: var(--font-sans);
|
|
min-height: 100vh;
|
|
transition: background var(--transition), color var(--transition);
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
.app-shell {
|
|
max-width: 480px;
|
|
margin: 0 auto;
|
|
min-height: 100vh;
|
|
position: relative;
|
|
}
|
|
|
|
.nav-bar {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 100;
|
|
background: var(--bg-elevated);
|
|
backdrop-filter: blur(20px);
|
|
-webkit-backdrop-filter: blur(20px);
|
|
border-bottom: 1px solid var(--border);
|
|
transition: background var(--transition);
|
|
}
|
|
.nav-bar-inner {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 12px 16px;
|
|
}
|
|
.nav-title {
|
|
font-size: 17px;
|
|
font-weight: 600;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.nav-actions {
|
|
display: flex;
|
|
gap: 4px;
|
|
}
|
|
.nav-btn {
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 50%;
|
|
border: none;
|
|
background: var(--bg-card-light);
|
|
color: var(--text);
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.2s;
|
|
}
|
|
.nav-btn:hover { background: var(--border-light); }
|
|
.nav-btn svg { width: 18px; height: 18px; }
|
|
|
|
.nav-tabs {
|
|
display: flex;
|
|
padding: 0 16px 10px;
|
|
gap: 2px;
|
|
}
|
|
.nav-tab {
|
|
flex: 1;
|
|
padding: 7px 0;
|
|
border-radius: 8px;
|
|
border: none;
|
|
background: transparent;
|
|
color: var(--text-dim);
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.25s;
|
|
font-family: var(--font-sans);
|
|
}
|
|
.nav-tab.active {
|
|
background: var(--primary);
|
|
color: #fff;
|
|
}
|
|
|
|
.section { display: none; padding: 16px; }
|
|
.section.active { display: block; }
|
|
|
|
/* ====== SVG Icon System ====== */
|
|
.icon {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 20px;
|
|
height: 20px;
|
|
flex-shrink: 0;
|
|
}
|
|
.icon svg { width: 100%; height: 100%; fill: currentColor; }
|
|
.icon-sm { width: 16px; height: 16px; }
|
|
.icon-lg { width: 24px; height: 24px; }
|
|
.icon-xl { width: 32px; height: 32px; }
|
|
|
|
/* ====== Timeline ====== */
|
|
.timeline { padding: 4px 0; }
|
|
|
|
.tl-item {
|
|
margin-bottom: 12px;
|
|
border-radius: var(--radius-lg);
|
|
overflow: hidden;
|
|
transition: all var(--transition);
|
|
}
|
|
.tl-item:last-child { margin-bottom: 0; }
|
|
|
|
.tl-summary {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 14px 16px;
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-lg);
|
|
cursor: pointer;
|
|
transition: all 0.25s;
|
|
user-select: none;
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
.tl-item.expanded .tl-summary {
|
|
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
|
|
border-bottom-color: transparent;
|
|
background: var(--bg-card-light);
|
|
}
|
|
.tl-summary:active { transform: scale(0.985); }
|
|
|
|
.tl-dot {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
font-size: 18px;
|
|
position: relative;
|
|
}
|
|
.tl-dot.today {
|
|
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
|
|
box-shadow: 0 2px 10px rgba(196,30,58,0.35);
|
|
}
|
|
.tl-dot.past {
|
|
background: var(--bg-input);
|
|
}
|
|
|
|
.tl-info { flex: 1; min-width: 0; }
|
|
.tl-date-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-bottom: 3px;
|
|
}
|
|
.tl-date { font-size: 14px; font-weight: 600; color: var(--text); }
|
|
.tl-level-badge {
|
|
padding: 2px 10px;
|
|
border-radius: 10px;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
}
|
|
.tl-level-badge.daji { background: rgba(212,168,67,0.15); color: var(--gold); }
|
|
.tl-level-badge.zhongji { background: rgba(76,175,80,0.12); color: #66BB6A; }
|
|
.tl-level-badge.ji { background: rgba(66,165,245,0.12); color: #42A5F5; }
|
|
.tl-level-badge.xiaoji { background: rgba(171,71,188,0.12); color: #AB47BC; }
|
|
.tl-level-badge.moji { background: rgba(255,167,38,0.12); color: #FFA726; }
|
|
|
|
.tl-preview {
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
.tl-dims-row {
|
|
display: flex;
|
|
gap: 4px;
|
|
margin-top: 6px;
|
|
flex-wrap: wrap;
|
|
}
|
|
.tl-dim-chip {
|
|
padding: 1px 7px;
|
|
border-radius: 6px;
|
|
font-size: 10px;
|
|
background: var(--divider);
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.tl-chevron {
|
|
color: var(--text-dim);
|
|
transition: transform 0.3s;
|
|
}
|
|
.tl-item.expanded .tl-chevron { transform: rotate(180deg); }
|
|
|
|
.tl-detail {
|
|
max-height: 0;
|
|
overflow: hidden;
|
|
transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
border-top: none;
|
|
border-radius: 0 0 var(--radius-lg) var(--radius-lg);
|
|
}
|
|
.tl-item.expanded .tl-detail {
|
|
max-height: 2000px;
|
|
}
|
|
.tl-detail-inner {
|
|
padding: 16px;
|
|
}
|
|
|
|
.tl-actions {
|
|
display: flex;
|
|
gap: 8px;
|
|
padding: 12px 16px;
|
|
border-top: 1px solid var(--divider);
|
|
}
|
|
.action-btn {
|
|
padding: 8px 16px;
|
|
border-radius: 20px;
|
|
border: 1px solid var(--border);
|
|
background: transparent;
|
|
color: var(--text-secondary);
|
|
font-size: 13px;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
font-family: var(--font-sans);
|
|
}
|
|
.action-btn:hover { border-color: var(--primary); color: var(--primary-light); }
|
|
.action-btn.primary {
|
|
background: var(--primary);
|
|
border-color: var(--primary);
|
|
color: #fff;
|
|
}
|
|
.action-btn.primary:hover { background: var(--primary-dark); }
|
|
.action-btn:active { transform: scale(0.96); }
|
|
.action-btn svg { width: 14px; height: 14px; }
|
|
|
|
/* ====== Fortune Card Styles ====== */
|
|
.fortune-card {
|
|
border-radius: var(--radius-lg);
|
|
overflow: hidden;
|
|
transition: all var(--transition);
|
|
}
|
|
|
|
/* --- Ancient Style --- */
|
|
[data-style="ancient"] .fortune-card {
|
|
background: linear-gradient(160deg, #1C1008, #2A1810, #1C1008);
|
|
border: 1px solid rgba(212,168,67,0.2);
|
|
box-shadow: var(--shadow-card);
|
|
padding: 24px 20px;
|
|
position: relative;
|
|
}
|
|
[data-theme="light"][data-style="ancient"] .fortune-card {
|
|
background: linear-gradient(160deg, #FFF8E7, #FFF3D6, #FFF8E7);
|
|
border-color: rgba(160,124,46,0.2);
|
|
}
|
|
[data-style="ancient"] .fortune-card::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0; left: 0; right: 0; bottom: 0;
|
|
background: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none'%3E%3Cg fill='%23D4A843' fill-opacity='0.03'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
|
|
pointer-events: none;
|
|
}
|
|
|
|
.fc-ornament {
|
|
text-align: center;
|
|
font-size: 11px;
|
|
color: var(--gold-dark);
|
|
letter-spacing: 8px;
|
|
margin-bottom: 14px;
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
}
|
|
.fc-ornament::before, .fc-ornament::after {
|
|
content: '';
|
|
flex: 1;
|
|
max-width: 60px;
|
|
height: 1px;
|
|
background: linear-gradient(90deg, transparent, var(--gold-dark), transparent);
|
|
}
|
|
|
|
.fc-level { text-align: center; }
|
|
.fc-level-char {
|
|
font-family: var(--font-serif);
|
|
font-size: 64px;
|
|
font-weight: 900;
|
|
background: linear-gradient(180deg, var(--gold-light), var(--gold), var(--gold-dark));
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
line-height: 1.1;
|
|
filter: drop-shadow(0 2px 6px rgba(212,168,67,0.25));
|
|
}
|
|
.fc-level-sub {
|
|
font-family: var(--font-serif);
|
|
font-size: 14px;
|
|
color: var(--gold);
|
|
margin-top: 2px;
|
|
letter-spacing: 4px;
|
|
}
|
|
.fc-level-score {
|
|
font-size: 12px;
|
|
color: var(--gold-dark);
|
|
margin-top: 6px;
|
|
}
|
|
|
|
.fc-sign {
|
|
text-align: center;
|
|
font-family: var(--font-serif);
|
|
font-size: 14px;
|
|
color: var(--gold-light);
|
|
line-height: 1.9;
|
|
margin: 16px 0;
|
|
padding: 12px;
|
|
border-top: 1px solid rgba(212,168,67,0.12);
|
|
border-bottom: 1px solid rgba(212,168,67,0.12);
|
|
}
|
|
|
|
.fc-dims {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 8px;
|
|
margin-top: 14px;
|
|
}
|
|
.fc-dim {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 8px 10px;
|
|
background: rgba(212,168,67,0.05);
|
|
border-radius: var(--radius-sm);
|
|
border: 1px solid rgba(212,168,67,0.08);
|
|
}
|
|
.fc-dim-icon { width: 18px; height: 18px; flex-shrink: 0; }
|
|
.fc-dim-icon svg { width: 100%; height: 100%; }
|
|
.fc-dim-info { flex: 1; }
|
|
.fc-dim-name { font-size: 10px; color: var(--text-dim); }
|
|
.fc-dim-val { font-size: 12px; color: var(--gold); font-weight: 500; }
|
|
.fc-dim-bar {
|
|
width: 100%;
|
|
height: 3px;
|
|
background: rgba(212,168,67,0.12);
|
|
border-radius: 2px;
|
|
margin-top: 3px;
|
|
overflow: hidden;
|
|
}
|
|
.fc-dim-bar-fill {
|
|
height: 100%;
|
|
border-radius: 2px;
|
|
background: linear-gradient(90deg, var(--gold-dark), var(--gold));
|
|
transition: width 0.8s ease;
|
|
}
|
|
|
|
.fc-lucky {
|
|
display: flex;
|
|
justify-content: space-around;
|
|
margin-top: 14px;
|
|
padding-top: 14px;
|
|
border-top: 1px solid rgba(212,168,67,0.08);
|
|
}
|
|
.fc-lucky-item { text-align: center; }
|
|
.fc-lucky-label { font-size: 10px; color: var(--text-dim); margin-bottom: 3px; }
|
|
.fc-lucky-value { font-size: 12px; color: var(--gold-light); font-weight: 500; }
|
|
|
|
.fc-yiji {
|
|
display: flex;
|
|
gap: 10px;
|
|
margin-top: 14px;
|
|
}
|
|
.fc-yi, .fc-ji {
|
|
flex: 1;
|
|
padding: 8px 10px;
|
|
border-radius: var(--radius-sm);
|
|
font-size: 11px;
|
|
}
|
|
.fc-yi { background: rgba(76,175,80,0.06); border: 1px solid rgba(76,175,80,0.1); }
|
|
.fc-ji { background: rgba(244,67,54,0.06); border: 1px solid rgba(244,67,54,0.1); }
|
|
.fc-yj-label { font-weight: 600; margin-bottom: 4px; display: flex; align-items: center; gap: 4px; }
|
|
.fc-yi .fc-yj-label { color: #4CAF50; }
|
|
.fc-ji .fc-yj-label { color: #F44336; }
|
|
.fc-yj-label svg { width: 12px; height: 12px; }
|
|
.fc-yj-tags { display: flex; flex-wrap: wrap; gap: 3px; }
|
|
.fc-yj-tag { padding: 1px 7px; border-radius: 4px; font-size: 10px; }
|
|
.fc-yi .fc-yj-tag { background: rgba(76,175,80,0.1); color: #81C784; }
|
|
.fc-ji .fc-yj-tag { background: rgba(244,67,54,0.1); color: #EF9A9A; }
|
|
|
|
.fc-date {
|
|
text-align: center;
|
|
font-size: 10px;
|
|
color: var(--text-dim);
|
|
margin-top: 12px;
|
|
letter-spacing: 1px;
|
|
}
|
|
|
|
/* --- WeChat Style --- */
|
|
[data-style="wechat"] .fortune-card {
|
|
background: linear-gradient(160deg, #1A2332, #1E2D3D, #1A2332);
|
|
border: 1px solid rgba(100,180,255,0.1);
|
|
box-shadow: var(--shadow-card);
|
|
padding: 20px;
|
|
}
|
|
[data-theme="light"][data-style="wechat"] .fortune-card {
|
|
background: linear-gradient(160deg, #E3F2FD, #BBDEFB, #E3F2FD);
|
|
border-color: rgba(66,165,245,0.15);
|
|
}
|
|
|
|
[data-style="wechat"] .fc-level-char {
|
|
font-size: 48px;
|
|
-webkit-text-fill-color: #42A5F5;
|
|
background: none;
|
|
filter: none;
|
|
}
|
|
[data-style="wechat"] .fc-level-sub { color: #64B5F6; }
|
|
[data-style="wechat"] .fc-level-score { color: #546E7A; }
|
|
|
|
[data-style="wechat"] .fc-sign {
|
|
color: #90CAF9;
|
|
border-color: rgba(66,165,245,0.12);
|
|
}
|
|
[data-style="wechat"] .fc-dim {
|
|
background: rgba(66,165,245,0.05);
|
|
border-color: rgba(66,165,245,0.08);
|
|
}
|
|
[data-style="wechat"] .fc-dim-val { color: #64B5F6; }
|
|
[data-style="wechat"] .fc-dim-bar { background: rgba(66,165,245,0.1); }
|
|
[data-style="wechat"] .fc-dim-bar-fill { background: linear-gradient(90deg, #1565C0, #42A5F5); }
|
|
[data-style="wechat"] .fc-lucky { border-color: rgba(66,165,245,0.08); }
|
|
[data-style="wechat"] .fc-lucky-value { color: #90CAF9; }
|
|
[data-style="wechat"] .fc-ornament { color: #546E7A; }
|
|
[data-style="wechat"] .fc-ornament::before,
|
|
[data-style="wechat"] .fc-ornament::after { background: linear-gradient(90deg, transparent, #546E7A, transparent); }
|
|
|
|
/* --- Apple Style --- */
|
|
[data-style="apple"] .fortune-card {
|
|
background: #FFFFFF;
|
|
border: 1px solid #E5E5EA;
|
|
box-shadow: var(--shadow-card);
|
|
padding: 20px;
|
|
color: #1C1C1E;
|
|
}
|
|
[data-theme="dark"][data-style="apple"] .fortune-card {
|
|
background: #1C1C1E;
|
|
border-color: #38383A;
|
|
color: #F5F0E8;
|
|
}
|
|
|
|
[data-style="apple"] .fc-level-char {
|
|
font-size: 48px;
|
|
-webkit-text-fill-color: #FF375F;
|
|
background: none;
|
|
filter: none;
|
|
}
|
|
[data-style="apple"] .fc-level-sub { color: #8E8E93; }
|
|
[data-style="apple"] .fc-level-score { color: #AEAEB2; }
|
|
[data-style="apple"] .fc-sign {
|
|
color: #636366;
|
|
border-color: #E5E5EA;
|
|
}
|
|
[data-style="apple"] .fc-dim {
|
|
background: #F2F2F7;
|
|
border-color: transparent;
|
|
}
|
|
[data-theme="dark"][data-style="apple"] .fc-dim { background: #2C2C2E; }
|
|
[data-style="apple"] .fc-dim-val { color: #1C1C1E; }
|
|
[data-theme="dark"][data-style="apple"] .fc-dim-val { color: #F5F0E8; }
|
|
[data-style="apple"] .fc-dim-bar { background: rgba(0,0,0,0.06); }
|
|
[data-theme="dark"][data-style="apple"] .fc-dim-bar { background: rgba(255,255,255,0.08); }
|
|
[data-style="apple"] .fc-dim-bar-fill { background: #FF375F; }
|
|
[data-style="apple"] .fc-lucky { border-color: #E5E5EA; }
|
|
[data-theme="dark"][data-style="apple"] .fc-lucky { border-color: #38383A; }
|
|
[data-style="apple"] .fc-lucky-value { color: #1C1C1E; font-weight: 600; }
|
|
[data-theme="dark"][data-style="apple"] .fc-lucky-value { color: #F5F0E8; }
|
|
[data-style="apple"] .fc-lucky-label { color: #8E8E93; }
|
|
[data-style="apple"] .fc-yi { background: rgba(52,199,89,0.06); border-color: rgba(52,199,89,0.1); }
|
|
[data-style="apple"] .fc-ji { background: rgba(255,59,48,0.06); border-color: rgba(255,59,48,0.1); }
|
|
[data-style="apple"] .fc-yi .fc-yj-tag { background: rgba(52,199,89,0.1); color: #34C759; border-radius: 10px; }
|
|
[data-style="apple"] .fc-ji .fc-yj-tag { background: rgba(255,59,48,0.1); color: #FF3B30; border-radius: 10px; }
|
|
[data-style="apple"] .fc-ornament { color: #AEAEB2; }
|
|
[data-style="apple"] .fc-ornament::before,
|
|
[data-style="apple"] .fc-ornament::after { background: linear-gradient(90deg, transparent, #AEAEB2, transparent); }
|
|
[data-style="apple"] .fc-date { color: #AEAEB2; }
|
|
|
|
/* ====== Settings Page ====== */
|
|
.settings-panel {
|
|
background: var(--bg-card);
|
|
border-radius: var(--radius-lg);
|
|
border: 1px solid var(--border);
|
|
overflow: hidden;
|
|
transition: background var(--transition), border-color var(--transition);
|
|
}
|
|
.settings-group {
|
|
padding: 14px 16px;
|
|
border-bottom: 1px solid var(--divider);
|
|
}
|
|
.settings-group:last-child { border-bottom: none; }
|
|
.sg-title {
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
margin-bottom: 10px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
font-weight: 500;
|
|
}
|
|
.s-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 9px 0;
|
|
}
|
|
.s-row:not(:last-child) { border-bottom: 1px solid var(--divider); }
|
|
.s-label { font-size: 14px; color: var(--text); display: flex; align-items: center; gap: 8px; }
|
|
.s-label svg { width: 18px; height: 18px; color: var(--text-secondary); }
|
|
.s-desc { font-size: 11px; color: var(--text-dim); margin-top: 1px; }
|
|
|
|
.ios-toggle {
|
|
width: 44px;
|
|
height: 26px;
|
|
border-radius: 13px;
|
|
background: #39393D;
|
|
position: relative;
|
|
cursor: pointer;
|
|
transition: background 0.3s;
|
|
flex-shrink: 0;
|
|
}
|
|
.ios-toggle.on { background: #34C759; }
|
|
.ios-toggle::after {
|
|
content: '';
|
|
position: absolute;
|
|
width: 22px;
|
|
height: 22px;
|
|
border-radius: 50%;
|
|
background: #fff;
|
|
top: 2px;
|
|
left: 2px;
|
|
transition: transform 0.3s;
|
|
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
|
}
|
|
.ios-toggle.on::after { transform: translateX(18px); }
|
|
|
|
.style-selector {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
.style-opt {
|
|
flex: 1;
|
|
padding: 10px 6px;
|
|
border-radius: var(--radius-md);
|
|
border: 2px solid var(--border);
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: all 0.25s;
|
|
background: transparent;
|
|
}
|
|
.style-opt.active {
|
|
border-color: var(--primary);
|
|
background: rgba(196,30,58,0.06);
|
|
}
|
|
.style-opt .so-icon { font-size: 22px; margin-bottom: 3px; }
|
|
.style-opt .so-name { font-size: 11px; color: var(--text-secondary); }
|
|
.style-opt.active .so-name { color: var(--primary-light); font-weight: 500; }
|
|
|
|
.chip-group { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
.chip {
|
|
padding: 6px 14px;
|
|
border-radius: 16px;
|
|
border: 1px solid var(--border);
|
|
background: transparent;
|
|
color: var(--text-secondary);
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
font-family: var(--font-sans);
|
|
}
|
|
.chip.active {
|
|
border-color: var(--primary);
|
|
background: rgba(196,30,58,0.08);
|
|
color: var(--primary-light);
|
|
}
|
|
|
|
.s-nav {
|
|
font-size: 13px;
|
|
color: var(--primary-light);
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 2px;
|
|
}
|
|
.s-nav svg { width: 14px; height: 14px; }
|
|
|
|
/* ====== Session Page ====== */
|
|
.session-list {
|
|
background: var(--bg-card);
|
|
border-radius: var(--radius-lg);
|
|
border: 1px solid var(--border);
|
|
overflow: hidden;
|
|
transition: all var(--transition);
|
|
}
|
|
.session-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 13px 16px;
|
|
border-bottom: 1px solid var(--divider);
|
|
cursor: pointer;
|
|
transition: background 0.15s;
|
|
}
|
|
.session-item:hover { background: var(--divider); }
|
|
.session-item:last-child { border-bottom: none; }
|
|
.sv-avatar {
|
|
width: 44px;
|
|
height: 44px;
|
|
border-radius: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 20px;
|
|
flex-shrink: 0;
|
|
}
|
|
.sv-avatar.fortune { background: rgba(196,30,58,0.1); }
|
|
.sv-avatar.discover { background: rgba(66,165,245,0.1); }
|
|
.sv-avatar.footprint { background: rgba(76,175,80,0.1); }
|
|
.sv-info { flex: 1; min-width: 0; }
|
|
.sv-name { font-size: 15px; font-weight: 500; color: var(--text); }
|
|
.sv-sub { font-size: 12px; color: var(--text-dim); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.sv-meta { text-align: right; flex-shrink: 0; }
|
|
.sv-time { font-size: 11px; color: var(--text-dim); }
|
|
.sv-badge {
|
|
display: inline-block;
|
|
min-width: 16px;
|
|
height: 16px;
|
|
border-radius: 8px;
|
|
background: var(--primary);
|
|
color: #fff;
|
|
font-size: 10px;
|
|
line-height: 16px;
|
|
text-align: center;
|
|
margin-top: 3px;
|
|
padding: 0 4px;
|
|
}
|
|
|
|
.push-mock {
|
|
background: var(--bg-card);
|
|
backdrop-filter: blur(20px);
|
|
border-radius: 16px;
|
|
padding: 12px 14px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-top: 16px;
|
|
border: 1px solid var(--border);
|
|
box-shadow: var(--shadow-card);
|
|
}
|
|
.push-icon {
|
|
width: 34px;
|
|
height: 34px;
|
|
border-radius: 8px;
|
|
background: var(--primary);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 16px;
|
|
flex-shrink: 0;
|
|
}
|
|
.push-body { flex: 1; }
|
|
.push-title { font-size: 13px; font-weight: 600; color: var(--text); }
|
|
.push-text { font-size: 12px; color: var(--text-secondary); margin-top: 1px; }
|
|
.push-time { font-size: 11px; color: var(--text-dim); flex-shrink: 0; }
|
|
|
|
/* ====== API Section ====== */
|
|
.api-card {
|
|
padding: 12px 14px;
|
|
background: var(--bg-card);
|
|
border-radius: var(--radius-md);
|
|
border: 1px solid var(--border);
|
|
margin-bottom: 8px;
|
|
transition: all var(--transition);
|
|
}
|
|
.api-method {
|
|
display: inline-block;
|
|
padding: 1px 7px;
|
|
border-radius: 4px;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
margin-right: 6px;
|
|
}
|
|
.api-method.get { background: #1B5E20; color: #4CAF50; }
|
|
.api-method.post { background: #E65100; color: #FF9800; }
|
|
.api-path { font-size: 13px; color: var(--text); font-family: 'SF Mono', monospace; }
|
|
.api-desc { font-size: 11px; color: var(--text-dim); margin-top: 4px; }
|
|
|
|
.data-block {
|
|
background: #0D1117;
|
|
border-radius: var(--radius-md);
|
|
padding: 14px;
|
|
font-family: 'SF Mono', 'Fira Code', monospace;
|
|
font-size: 11px;
|
|
line-height: 1.6;
|
|
overflow-x: auto;
|
|
border: 1px solid #21262D;
|
|
margin-top: 10px;
|
|
}
|
|
.dk { color: #79C0FF; }
|
|
.ds { color: #A5D6FF; }
|
|
.dn { color: #F2CC60; }
|
|
.db { color: #FF7B72; }
|
|
.dc { color: #8B949E; }
|
|
|
|
.section-title {
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
color: var(--text);
|
|
margin-bottom: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.section-title svg { width: 20px; height: 20px; color: var(--primary-light); }
|
|
.section-desc {
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
margin-bottom: 16px;
|
|
}
|
|
.card-gap { margin-top: 16px; }
|
|
|
|
/* Theme indicator */
|
|
.theme-indicator {
|
|
position: fixed;
|
|
bottom: 20px;
|
|
right: 20px;
|
|
display: flex;
|
|
gap: 8px;
|
|
z-index: 200;
|
|
}
|
|
.theme-fab {
|
|
width: 44px;
|
|
height: 44px;
|
|
border-radius: 50%;
|
|
border: 2px solid var(--border);
|
|
background: var(--bg-card);
|
|
color: var(--text);
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 2px 12px rgba(0,0,0,0.3);
|
|
transition: all 0.25s;
|
|
font-size: 18px;
|
|
}
|
|
.theme-fab:hover { transform: scale(1.1); }
|
|
.theme-fab:active { transform: scale(0.95); }
|
|
|
|
/* Sort indicator */
|
|
.sort-indicator {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
font-size: 11px;
|
|
color: var(--text-dim);
|
|
padding: 8px 0;
|
|
}
|
|
.sort-indicator svg { width: 12px; height: 12px; }
|
|
|
|
/* Animations */
|
|
@keyframes slideUp {
|
|
from { opacity: 0; transform: translateY(12px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
.anim-in { animation: slideUp 0.35s ease both; }
|
|
.anim-in:nth-child(2) { animation-delay: 0.06s; }
|
|
.anim-in:nth-child(3) { animation-delay: 0.12s; }
|
|
.anim-in:nth-child(4) { animation-delay: 0.18s; }
|
|
.anim-in:nth-child(5) { animation-delay: 0.24s; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="app-shell">
|
|
<div class="nav-bar">
|
|
<div class="nav-bar-inner">
|
|
<div class="nav-title">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a15 15 0 0 1 4 10 15 15 0 0 1-4 10 15 15 0 0 1-4-10A15 15 0 0 1 12 2z"/><line x1="2" y1="12" x2="22" y2="12"/></svg>
|
|
每日运势
|
|
</div>
|
|
<div class="nav-actions">
|
|
<button class="nav-btn" title="切换主题" onclick="toggleTheme()">
|
|
<svg class="theme-icon-dark" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
|
<svg class="theme-icon-light" style="display:none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
|
|
</button>
|
|
<button class="nav-btn" title="设置" onclick="switchSection('settings')">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="nav-tabs">
|
|
<button class="nav-tab active" onclick="switchSection('timeline',this)">时间线</button>
|
|
<button class="nav-tab" onclick="switchSection('cards',this)">卡片样式</button>
|
|
<button class="nav-tab" onclick="switchSection('settings',this)">设置</button>
|
|
<button class="nav-tab" onclick="switchSection('session',this)">会话入口</button>
|
|
<button class="nav-tab" onclick="switchSection('api',this)">API</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ====== Timeline Section (Main) ====== -->
|
|
<div class="section active" id="sec-timeline">
|
|
<div class="sort-indicator">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
|
|
最新在上面 · <span style="color:var(--primary-light);cursor:pointer" onclick="switchSection('settings',null)">可在设置中更改</span>
|
|
</div>
|
|
|
|
<div class="timeline" id="timeline-container">
|
|
<!-- Today - Expanded by default -->
|
|
<div class="tl-item expanded anim-in" data-date="2026-05-13" data-is-today="true">
|
|
<div class="tl-summary" onclick="toggleTimeline(this)">
|
|
<div class="tl-dot today">🔮</div>
|
|
<div class="tl-info">
|
|
<div class="tl-date-row">
|
|
<span class="tl-date">今天 · 5月13日</span>
|
|
<span class="tl-level-badge daji">大吉</span>
|
|
</div>
|
|
<div class="tl-preview">鹏程万里风正举,一帆风顺向天涯…</div>
|
|
<div class="tl-dims-row">
|
|
<span class="tl-dim-chip">❤️ 中吉</span>
|
|
<span class="tl-dim-chip">💼 吉</span>
|
|
<span class="tl-dim-chip">💰 小吉</span>
|
|
<span class="tl-dim-chip">💪 大吉</span>
|
|
</div>
|
|
</div>
|
|
<div class="tl-chevron icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
|
|
</div>
|
|
</div>
|
|
<div class="tl-detail">
|
|
<div class="tl-detail-inner">
|
|
<div class="fortune-card" id="fortune-card-today"></div>
|
|
</div>
|
|
<div class="tl-actions">
|
|
<button class="action-btn primary" onclick="event.stopPropagation()">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>
|
|
换一签
|
|
</button>
|
|
<button class="action-btn" onclick="event.stopPropagation()">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
编辑
|
|
</button>
|
|
<button class="action-btn" onclick="event.stopPropagation()">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg>
|
|
分享
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Yesterday -->
|
|
<div class="tl-item anim-in" data-date="2026-05-12">
|
|
<div class="tl-summary" onclick="toggleTimeline(this)">
|
|
<div class="tl-dot past">📜</div>
|
|
<div class="tl-info">
|
|
<div class="tl-date-row">
|
|
<span class="tl-date">昨天 · 5月12日</span>
|
|
<span class="tl-level-badge zhongji">中吉</span>
|
|
</div>
|
|
<div class="tl-preview">春风化雨润无声,静待花开自有情…</div>
|
|
<div class="tl-dims-row">
|
|
<span class="tl-dim-chip">❤️ 吉</span>
|
|
<span class="tl-dim-chip">💼 小吉</span>
|
|
<span class="tl-dim-chip">💰 中吉</span>
|
|
</div>
|
|
</div>
|
|
<div class="tl-chevron icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
|
|
</div>
|
|
</div>
|
|
<div class="tl-detail">
|
|
<div class="tl-detail-inner">
|
|
<div class="fortune-card" id="fortune-card-yesterday"></div>
|
|
</div>
|
|
<div class="tl-actions">
|
|
<button class="action-btn" style="opacity:0.5;cursor:default" onclick="event.stopPropagation()">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
|
已锁定
|
|
</button>
|
|
<button class="action-btn" onclick="event.stopPropagation()">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
编辑
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Day before yesterday -->
|
|
<div class="tl-item anim-in" data-date="2026-05-11">
|
|
<div class="tl-summary" onclick="toggleTimeline(this)">
|
|
<div class="tl-dot past">📜</div>
|
|
<div class="tl-info">
|
|
<div class="tl-date-row">
|
|
<span class="tl-date">前天 · 5月11日</span>
|
|
<span class="tl-level-badge ji">吉</span>
|
|
</div>
|
|
<div class="tl-preview">山高水远路漫漫,行到尽头是坦途…</div>
|
|
<div class="tl-dims-row">
|
|
<span class="tl-dim-chip">❤️ 末吉</span>
|
|
<span class="tl-dim-chip">💼 中吉</span>
|
|
<span class="tl-dim-chip">💰 吉</span>
|
|
</div>
|
|
</div>
|
|
<div class="tl-chevron icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
|
|
</div>
|
|
</div>
|
|
<div class="tl-detail">
|
|
<div class="tl-detail-inner">
|
|
<div class="fortune-card" id="fortune-card-day11"></div>
|
|
</div>
|
|
<div class="tl-actions">
|
|
<button class="action-btn" style="opacity:0.5;cursor:default" onclick="event.stopPropagation()">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
|
已锁定
|
|
</button>
|
|
<button class="action-btn" onclick="event.stopPropagation()">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
编辑
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- May 10 -->
|
|
<div class="tl-item anim-in" data-date="2026-05-10">
|
|
<div class="tl-summary" onclick="toggleTimeline(this)">
|
|
<div class="tl-dot past">📜</div>
|
|
<div class="tl-info">
|
|
<div class="tl-date-row">
|
|
<span class="tl-date">5月10日</span>
|
|
<span class="tl-level-badge xiaoji">小吉</span>
|
|
</div>
|
|
<div class="tl-preview">月到中天分外明,守得云开见月明…</div>
|
|
</div>
|
|
<div class="tl-chevron icon">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
|
|
</div>
|
|
</div>
|
|
<div class="tl-detail">
|
|
<div class="tl-detail-inner">
|
|
<div class="fortune-card" id="fortune-card-day10"></div>
|
|
</div>
|
|
<div class="tl-actions">
|
|
<button class="action-btn" style="opacity:0.5;cursor:default" onclick="event.stopPropagation()">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
|
已锁定
|
|
</button>
|
|
<button class="action-btn" onclick="event.stopPropagation()">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
编辑
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ====== Card Styles Section ====== -->
|
|
<div class="section" id="sec-cards">
|
|
<div class="section-title">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
|
|
卡片样式预览
|
|
</div>
|
|
<div class="section-desc">点击下方切换风格 · 卡片跟随动态主题</div>
|
|
|
|
<div class="style-selector" style="margin-bottom:16px">
|
|
<div class="style-opt active" onclick="switchStyle('ancient',this)">🏯<div class="so-name">古风签筒</div></div>
|
|
<div class="style-opt" onclick="switchStyle('wechat',this)">📊<div class="so-name">微信运动</div></div>
|
|
<div class="style-opt" onclick="switchStyle('apple',this)">⌚<div class="so-name">Apple风</div></div>
|
|
</div>
|
|
|
|
<div class="fortune-card" id="fortune-card-preview"></div>
|
|
</div>
|
|
|
|
<!-- ====== Settings Section ====== -->
|
|
<div class="section" id="sec-settings">
|
|
<div class="section-title">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
|
运势设置
|
|
</div>
|
|
<div class="section-desc">管理显示项目 · 推送时间 · 风格切换 · 排序方式</div>
|
|
|
|
<div class="settings-panel">
|
|
<div class="settings-group">
|
|
<div class="sg-title">🎨 卡片风格</div>
|
|
<div class="style-selector">
|
|
<div class="style-opt active" onclick="switchStyle('ancient',this)">🏯<div class="so-name">古风签筒</div></div>
|
|
<div class="style-opt" onclick="switchStyle('wechat',this)">📊<div class="so-name">微信运动</div></div>
|
|
<div class="style-opt" onclick="switchStyle('apple',this)">⌚<div class="so-name">Apple风</div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<div class="sg-title">📋 显示项目</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>爱情运势</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="7" width="20" height="14" rx="2" ry="2"/><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/></svg>事业运势</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>财运</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>健康</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>学业</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>人际</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>幸运指标</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>宜忌</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>签文</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<div class="sg-title">⏰ 推送设置</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>每日推送</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div style="margin-top:8px">
|
|
<div style="font-size:11px;color:var(--text-dim);margin-bottom:6px">推送时间</div>
|
|
<div class="chip-group">
|
|
<span class="chip" onclick="selectChip(this)">06:00</span>
|
|
<span class="chip" onclick="selectChip(this)">07:00</span>
|
|
<span class="chip active" onclick="selectChip(this)">08:00</span>
|
|
<span class="chip" onclick="selectChip(this)">09:00</span>
|
|
<span class="chip" onclick="selectChip(this)">10:00</span>
|
|
</div>
|
|
</div>
|
|
<div style="margin-top:10px">
|
|
<div style="font-size:11px;color:var(--text-dim);margin-bottom:6px">推送频率</div>
|
|
<div class="chip-group">
|
|
<span class="chip active" onclick="selectChip(this)">每天1次</span>
|
|
<span class="chip" onclick="selectChip(this)">早晚各1次</span>
|
|
<span class="chip" onclick="selectChip(this)">自定义</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<div class="sg-title">🔄 排序方式</div>
|
|
<div class="s-row">
|
|
<div>
|
|
<div class="s-label">时间线排序</div>
|
|
<div class="s-desc">控制运势卡片的显示顺序</div>
|
|
</div>
|
|
</div>
|
|
<div style="margin-top:6px">
|
|
<div class="chip-group">
|
|
<span class="chip active" onclick="selectSort(this,'newest')">最新在上面</span>
|
|
<span class="chip" onclick="selectSort(this,'oldest')">最早在上面</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<div class="sg-title">🔧 扩展设置</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 2a15 15 0 0 1 4 10 15 15 0 0 1-4 10 15 15 0 0 1-4-10A15 15 0 0 1 12 2z"/></svg>星座绑定</div>
|
|
<div class="s-nav">设置 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>生日绑定</div>
|
|
<div class="s-nav">设置 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/></svg>运势提醒</div>
|
|
<div class="ios-toggle" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>60秒新闻</div>
|
|
<div class="ios-toggle" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
<div class="s-row">
|
|
<div class="s-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="17" y1="10" x2="3" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="17" y1="18" x2="3" y2="18"/></svg>每日微语</div>
|
|
<div class="ios-toggle on" onclick="this.classList.toggle('on')"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ====== Session Section ====== -->
|
|
<div class="section" id="sec-session">
|
|
<div class="section-title">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
|
|
会话流入口
|
|
</div>
|
|
<div class="section-desc">灵感页面会话列表 · 新增"每日运势"系统会话</div>
|
|
|
|
<div class="session-list">
|
|
<div class="session-item" style="background:rgba(196,30,58,0.04)">
|
|
<div class="sv-avatar fortune">🔮</div>
|
|
<div class="sv-info">
|
|
<div class="sv-name">每日运势 <span style="font-size:10px;color:var(--primary-light);margin-left:4px;padding:1px 6px;border-radius:6px;background:rgba(196,30,58,0.1)">NEW</span></div>
|
|
<div class="sv-sub">今日大吉 · 爱情中吉 · 事业吉 · 财运小吉</div>
|
|
</div>
|
|
<div class="sv-meta">
|
|
<div class="sv-time">08:00</div>
|
|
<div class="sv-badge">1</div>
|
|
</div>
|
|
</div>
|
|
<div class="session-item">
|
|
<div class="sv-avatar discover">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
|
</div>
|
|
<div class="sv-info">
|
|
<div class="sv-name">发现</div>
|
|
<div class="sv-sub">热门句子 · 分类浏览 · 每日推荐</div>
|
|
</div>
|
|
<div class="sv-meta"><div class="sv-time">昨天</div></div>
|
|
</div>
|
|
<div class="session-item">
|
|
<div class="sv-avatar footprint">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
|
|
</div>
|
|
<div class="sv-info">
|
|
<div class="sv-name">足迹</div>
|
|
<div class="sv-sub">浏览 · 点赞 · 收藏 · 稍后读 · 笔记</div>
|
|
</div>
|
|
<div class="sv-meta"><div class="sv-time">3天前</div></div>
|
|
</div>
|
|
<div class="session-item">
|
|
<div class="sv-avatar" style="background:rgba(212,168,67,0.1)">📅</div>
|
|
<div class="sv-info">
|
|
<div class="sv-name">日签卡片</div>
|
|
<div class="sv-sub">每日一句 · 样式切换 · 一键分享</div>
|
|
</div>
|
|
<div class="sv-meta"><div class="sv-time">6小时前</div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-gap"></div>
|
|
<div class="section-title" style="font-size:15px">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
|
|
推送消息示例
|
|
</div>
|
|
|
|
<div class="push-mock">
|
|
<div class="push-icon">🔮</div>
|
|
<div class="push-body">
|
|
<div class="push-title">每日运势</div>
|
|
<div class="push-text">今日大吉!爱情中吉,事业吉,财运小吉…</div>
|
|
</div>
|
|
<div class="push-time">08:00</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ====== API Section ====== -->
|
|
<div class="section" id="sec-api">
|
|
<div class="section-title">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
|
|
API 接口设计
|
|
</div>
|
|
<div class="section-desc">服务端接口 · 数据结构 · 数据库设计</div>
|
|
|
|
<div class="api-card"><span class="api-method get">GET</span><span class="api-path">/api/fortune/daily</span><div class="api-desc">获取今日运势 · hash(uid+date)确定性生成</div></div>
|
|
<div class="api-card"><span class="api-method get">GET</span><span class="api-path">/api/fortune/daily?regen=1</span><div class="api-desc">重新生成今日运势 · 换一签 · 仅今天可用</div></div>
|
|
<div class="api-card"><span class="api-method get">GET</span><span class="api-path">/api/fortune/history?uid=xxx&page=1</span><div class="api-desc">获取历史运势列表 · 分页</div></div>
|
|
<div class="api-card"><span class="api-method post">POST</span><span class="api-path">/api/fortune/config</span><div class="api-desc">更新用户运势配置 · 显示/推送/风格/排序</div></div>
|
|
<div class="api-card"><span class="api-method get">GET</span><span class="api-path">/api/fortune/themes</span><div class="api-desc">获取可用卡片风格列表</div></div>
|
|
<div class="api-card"><span class="api-method get">GET</span><span class="api-path">/api/fortune/image?uid=xxx&date=2026-05-13</span><div class="api-desc">获取运势卡片图片 · GD库生成 · CDN缓存</div></div>
|
|
<div class="api-card"><span class="api-method get">GET</span><span class="api-path">/api/fortune/60s</span><div class="api-desc">获取今日60秒新闻 · 附加到运势卡片</div></div>
|
|
|
|
<div class="card-gap"></div>
|
|
<div class="section-title" style="font-size:15px">📦 运势数据结构</div>
|
|
<div class="data-block">
|
|
<span class="dc">{</span>
|
|
<span class="dk">"date"</span>: <span class="ds">"2026-05-13"</span>,
|
|
<span class="dk">"uid"</span>: <span class="ds">"user_abc123"</span>,
|
|
<span class="dk">"fortune_level"</span>: <span class="ds">"大吉"</span>,
|
|
<span class="dk">"fortune_score"</span>: <span class="dn">92</span>,
|
|
<span class="dk">"sign_text"</span>: <span class="ds">"鹏程万里风正举..."</span>,
|
|
<span class="dk">"dimensions"</span>: <span class="dc">{</span>
|
|
<span class="dk">"love"</span>: <span class="dc">{</span> <span class="dk">"level"</span>: <span class="ds">"中吉"</span>, <span class="dk">"score"</span>: <span class="dn">78</span> <span class="dc">}</span>,
|
|
<span class="dk">"career"</span>: <span class="dc">{</span> <span class="dk">"level"</span>: <span class="ds">"吉"</span>, <span class="dk">"score"</span>: <span class="dn">85</span> <span class="dc">}</span>,
|
|
<span class="dk">"wealth"</span>: <span class="dc">{</span> <span class="dk">"level"</span>: <span class="ds">"小吉"</span>, <span class="dk">"score"</span>: <span class="dn">70</span> <span class="dc">}</span>,
|
|
<span class="dk">"health"</span>: <span class="dc">{</span> <span class="dk">"level"</span>: <span class="ds">"大吉"</span>, <span class="dk">"score"</span>: <span class="dn">95</span> <span class="dc">}</span>,
|
|
<span class="dk">"study"</span>: <span class="dc">{</span> <span class="dk">"level"</span>: <span class="ds">"末吉"</span>, <span class="dk">"score"</span>: <span class="dn">60</span> <span class="dc">}</span>,
|
|
<span class="dk">"social"</span>: <span class="dc">{</span> <span class="dk">"level"</span>: <span class="ds">"中吉"</span>, <span class="dk">"score"</span>: <span class="dn">75</span> <span class="dc">}</span>
|
|
<span class="dc">}</span>,
|
|
<span class="dk">"lucky"</span>: <span class="dc">{</span>
|
|
<span class="dk">"number"</span>: <span class="dn">7</span>, <span class="dk">"color"</span>: <span class="ds">"朱红"</span>,
|
|
<span class="dk">"direction"</span>: <span class="ds">"东南"</span>, <span class="dk">"constellation"</span>: <span class="ds">"天秤"</span>
|
|
<span class="dc">}</span>,
|
|
<span class="dk">"suitable"</span>: [<span class="ds">"求财"</span>,<span class="ds">"出行"</span>,<span class="ds">"签约"</span>],
|
|
<span class="dk">"unsuitable"</span>: [<span class="ds">"动土"</span>,<span class="ds">"嫁娶"</span>],
|
|
<span class="dk">"theme"</span>: <span class="ds">"ancient"</span>,
|
|
<span class="dk">"is_today"</span>: <span class="db">true</span>,
|
|
<span class="dk">"can_regenerate"</span>: <span class="db">true</span>,
|
|
<span class="dk">"sort_order"</span>: <span class="ds">"newest_first"</span>
|
|
<span class="dc">}</span>
|
|
</div>
|
|
|
|
<div class="card-gap"></div>
|
|
<div class="section-title" style="font-size:15px">🗄️ 数据库表</div>
|
|
<div class="data-block">
|
|
<span class="db">-- 签文数据库</span>
|
|
<span class="dk">tool_fortune_data</span> (
|
|
id, type(<span class="ds">'sign'|'yi'|'ji'|'lucky'</span>),
|
|
level, content, category, weight
|
|
)
|
|
<span class="db">-- 用户运势记录</span>
|
|
<span class="dk">tool_fortune_record</span> (
|
|
id, uid, date, fortune_level, fortune_score,
|
|
sign_text, dimensions_json, lucky_json,
|
|
suitable_json, unsuitable_json, theme,
|
|
regen_count, image_url, created_at
|
|
)
|
|
<span class="db">-- 用户运势配置</span>
|
|
<span class="dk">tool_fortune_config</span> (
|
|
id, uid, theme, show_dims_json,
|
|
push_enabled, push_time, push_freq,
|
|
sort_order, constellation, birthday,
|
|
extra_json, updated_at
|
|
)
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Floating theme toggle -->
|
|
<div class="theme-indicator">
|
|
<div class="theme-fab" title="切换主题" onclick="toggleTheme()">🌓</div>
|
|
</div>
|
|
|
|
<script>
|
|
const SVG_ICONS = {
|
|
heart: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>',
|
|
briefcase: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="7" width="20" height="14" rx="2" ry="2"/><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/></svg>',
|
|
dollar: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>',
|
|
pulse: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>',
|
|
book: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>',
|
|
users: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>',
|
|
check: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>',
|
|
x: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',
|
|
};
|
|
|
|
const fortuneData = {
|
|
today: {
|
|
level: '大吉', sub: '上上签', score: 92,
|
|
sign: '鹏程万里风正举<br>一帆风顺向天涯<br>贵人相助逢佳运<br>事事如意福无涯',
|
|
dims: [
|
|
{ icon: 'heart', name: '爱情', level: '中吉', pct: 78 },
|
|
{ icon: 'briefcase', name: '事业', level: '吉', pct: 85 },
|
|
{ icon: 'dollar', name: '财运', level: '小吉', pct: 70 },
|
|
{ icon: 'pulse', name: '健康', level: '大吉', pct: 95 },
|
|
{ icon: 'book', name: '学业', level: '末吉', pct: 60 },
|
|
{ icon: 'users', name: '人际', level: '中吉', pct: 75 },
|
|
],
|
|
lucky: [{ l: '幸运数字', v: '7' }, { l: '幸运颜色', v: '朱红' }, { l: '幸运方位', v: '东南' }, { l: '幸运星座', v: '天秤' }],
|
|
yi: ['求财', '出行', '签约'], ji: ['动土', '嫁娶'],
|
|
date: '丙午年 五月十三 · 星期二',
|
|
},
|
|
yesterday: {
|
|
level: '中吉', sub: '中上签', score: 78,
|
|
sign: '春风化雨润无声<br>静待花开自有情<br>莫道前路多坎坷<br>柳暗花明又一村',
|
|
dims: [
|
|
{ icon: 'heart', name: '爱情', level: '吉', pct: 82 },
|
|
{ icon: 'briefcase', name: '事业', level: '小吉', pct: 68 },
|
|
{ icon: 'dollar', name: '财运', level: '中吉', pct: 78 },
|
|
{ icon: 'pulse', name: '健康', level: '吉', pct: 80 },
|
|
{ icon: 'book', name: '学业', level: '末吉', pct: 55 },
|
|
{ icon: 'users', name: '人际', level: '小吉', pct: 65 },
|
|
],
|
|
lucky: [{ l: '幸运数字', v: '3' }, { l: '幸运颜色', v: '靛蓝' }, { l: '幸运方位', v: '西北' }, { l: '幸运星座', v: '双鱼' }],
|
|
yi: ['纳财', '安床'], ji: ['开市', '出行'],
|
|
date: '丙午年 五月十二 · 星期一',
|
|
},
|
|
day11: {
|
|
level: '吉', sub: '中签', score: 75,
|
|
sign: '山高水远路漫漫<br>行到尽头是坦途<br>莫愁前路无知己<br>天下谁人不识君',
|
|
dims: [
|
|
{ icon: 'heart', name: '爱情', level: '末吉', pct: 55 },
|
|
{ icon: 'briefcase', name: '事业', level: '中吉', pct: 78 },
|
|
{ icon: 'dollar', name: '财运', level: '吉', pct: 75 },
|
|
{ icon: 'pulse', name: '健康', level: '小吉', pct: 68 },
|
|
{ icon: 'book', name: '学业', level: '中吉', pct: 76 },
|
|
{ icon: 'users', name: '人际', level: '吉', pct: 80 },
|
|
],
|
|
lucky: [{ l: '幸运数字', v: '5' }, { l: '幸运颜色', v: '翠绿' }, { l: '幸运方位', v: '正南' }, { l: '幸运星座', v: '射手' }],
|
|
yi: ['祭祀', '修造'], ji: ['嫁娶', '入宅'],
|
|
date: '丙午年 五月十一 · 星期日',
|
|
},
|
|
day10: {
|
|
level: '小吉', sub: '中下签', score: 65,
|
|
sign: '月到中天分外明<br>守得云开见月明<br>但将冷眼观螃蟹<br>看你横行到几时',
|
|
dims: [
|
|
{ icon: 'heart', name: '爱情', level: '小吉', pct: 65 },
|
|
{ icon: 'briefcase', name: '事业', level: '末吉', pct: 58 },
|
|
{ icon: 'dollar', name: '财运', level: '小吉', pct: 62 },
|
|
{ icon: 'pulse', name: '健康', level: '吉', pct: 80 },
|
|
{ icon: 'book', name: '学业', level: '中吉', pct: 72 },
|
|
{ icon: 'users', name: '人际', level: '末吉', pct: 55 },
|
|
],
|
|
lucky: [{ l: '幸运数字', v: '9' }, { l: '幸运颜色', v: '琥珀' }, { l: '幸运方位', v: '东北' }, { l: '幸运星座', v: '双子' }],
|
|
yi: ['祈福', '求嗣'], ji: ['动土', '安葬'],
|
|
date: '丙午年 五月初十 · 星期六',
|
|
},
|
|
};
|
|
|
|
function buildFortuneCard(data) {
|
|
let dimsHtml = data.dims.map(d => `
|
|
<div class="fc-dim">
|
|
<div class="fc-dim-icon">${SVG_ICONS[d.icon] || ''}</div>
|
|
<div class="fc-dim-info">
|
|
<div class="fc-dim-name">${d.name}</div>
|
|
<div class="fc-dim-val">${d.level}</div>
|
|
<div class="fc-dim-bar"><div class="fc-dim-bar-fill" style="width:${d.pct}%"></div></div>
|
|
</div>
|
|
</div>`).join('');
|
|
|
|
let luckyHtml = data.lucky.map(l => `
|
|
<div class="fc-lucky-item"><div class="fc-lucky-label">${l.l}</div><div class="fc-lucky-value">${l.v}</div></div>`).join('');
|
|
|
|
let yiTags = data.yi.map(t => `<span class="fc-yj-tag">${t}</span>`).join('');
|
|
let jiTags = data.ji.map(t => `<span class="fc-yj-tag">${t}</span>`).join('');
|
|
|
|
return `
|
|
<div class="fc-ornament">✦ 签 ✦</div>
|
|
<div class="fc-level">
|
|
<div class="fc-level-char">${data.level}</div>
|
|
<div class="fc-level-sub">${data.sub}</div>
|
|
<div class="fc-level-score">综合运势 ${data.score} 分</div>
|
|
</div>
|
|
<div class="fc-sign">${data.sign}</div>
|
|
<div class="fc-dims">${dimsHtml}</div>
|
|
<div class="fc-lucky">${luckyHtml}</div>
|
|
<div class="fc-yiji">
|
|
<div class="fc-yi">
|
|
<div class="fc-yj-label">${SVG_ICONS.check} 宜</div>
|
|
<div class="fc-yj-tags">${yiTags}</div>
|
|
</div>
|
|
<div class="fc-ji">
|
|
<div class="fc-yj-label">${SVG_ICONS.x} 忌</div>
|
|
<div class="fc-yj-tags">${jiTags}</div>
|
|
</div>
|
|
</div>
|
|
<div class="fc-date">${data.date}</div>`;
|
|
}
|
|
|
|
function initCards() {
|
|
document.getElementById('fortune-card-today').innerHTML = buildFortuneCard(fortuneData.today);
|
|
document.getElementById('fortune-card-yesterday').innerHTML = buildFortuneCard(fortuneData.yesterday);
|
|
document.getElementById('fortune-card-day11').innerHTML = buildFortuneCard(fortuneData.day11);
|
|
document.getElementById('fortune-card-day10').innerHTML = buildFortuneCard(fortuneData.day10);
|
|
document.getElementById('fortune-card-preview').innerHTML = buildFortuneCard(fortuneData.today);
|
|
}
|
|
|
|
function toggleTimeline(summaryEl) {
|
|
const item = summaryEl.closest('.tl-item');
|
|
item.classList.toggle('expanded');
|
|
}
|
|
|
|
function switchSection(name, tabEl) {
|
|
document.querySelectorAll('.section').forEach(s => s.classList.remove('active'));
|
|
document.getElementById('sec-' + name).classList.add('active');
|
|
document.querySelectorAll('.nav-tab').forEach(t => t.classList.remove('active'));
|
|
if (tabEl) tabEl.classList.add('active');
|
|
else document.querySelectorAll('.nav-tab').forEach(t => { if (t.textContent.includes({'timeline':'时间线','cards':'卡片','settings':'设置','session':'会话','api':'API'}[name])) t.classList.add('active'); });
|
|
}
|
|
|
|
function toggleTheme() {
|
|
const html = document.documentElement;
|
|
const isDark = html.getAttribute('data-theme') === 'dark';
|
|
html.setAttribute('data-theme', isDark ? 'light' : 'dark');
|
|
document.querySelector('.theme-icon-dark').style.display = isDark ? 'none' : 'block';
|
|
document.querySelector('.theme-icon-light').style.display = isDark ? 'block' : 'none';
|
|
}
|
|
|
|
function switchStyle(style, el) {
|
|
document.documentElement.setAttribute('data-style', style);
|
|
document.querySelectorAll('.style-opt').forEach(o => o.classList.remove('active'));
|
|
if (el) el.classList.add('active');
|
|
else document.querySelectorAll('.style-opt').forEach(o => { if (o.querySelector('.so-name').textContent.includes({'ancient':'古风','wechat':'微信','apple':'Apple'}[style])) o.classList.add('active'); });
|
|
}
|
|
|
|
function selectChip(el) {
|
|
el.parentElement.querySelectorAll('.chip').forEach(c => c.classList.remove('active'));
|
|
el.classList.add('active');
|
|
}
|
|
|
|
function selectSort(el, order) {
|
|
el.parentElement.querySelectorAll('.chip').forEach(c => c.classList.remove('active'));
|
|
el.classList.add('active');
|
|
const container = document.getElementById('timeline-container');
|
|
const items = Array.from(container.children);
|
|
if (order === 'oldest') items.reverse();
|
|
items.forEach(item => container.appendChild(item));
|
|
const indicator = document.querySelector('.sort-indicator');
|
|
if (indicator) indicator.innerHTML = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
|
|
${order === 'newest' ? '最新在上面' : '最早在上面'} · <span style="color:var(--primary-light);cursor:pointer" onclick="switchSection('settings',null)">可在设置中更改</span>`;
|
|
}
|
|
|
|
initCards();
|
|
</script>
|
|
</body>
|
|
</html>
|