Files
xianyan/docs/mockups/leisure_settings.html
Developer 355191aaf6 feat(leisure): 新增闲情逸致模块与多项功能优化
本次提交完成多项核心更新:
1. 新增闲情逸致功能模块,包含时间线、收藏标注、季节主题等基础框架
2. 替换hive为社区维护的hive_ce包,修复依赖兼容问题
3. 统一替换"开发中"提示为"当前设备不支持",优化用户提示文案
4. 新增多项功能开关与特性标志,统一管理不可用功能提示
5. 完善用户账户洞察系统,新增头像审核中状态检测
6. 优化TTS语音朗读服务,修复Android端引擎初始化问题
7. 重构知识图谱缩放手势逻辑,解决缩放不跟手问题
8. 新增精灵头像组件,替换默认聊天头像样式
9. 新增外部链接跳转确认弹窗,提升使用安全性
10. 升级后端API接口,新增签到配置获取与补签积分规则动态读取
11. 完善多语言翻译覆盖率限制,非中文语言仅显示最高50%进度
12. 新增HTTP缓存拦截器,优化网络请求性能
13. 新增恢复出厂设置选项,完善数据管理功能

同时修复了多处代码细节问题:简化字符串拼接、优化布局代码、移除多余代码等。
2026-05-27 08:06:54 +08:00

715 lines
19 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>闲情逸致 — 设置页面</title>
<style>
:root {
--primary: #6C63FF;
--primary-light: #8B83FF;
--accent: #4ECDC4;
--secondary: #FF6B6B;
--success: #10B981;
--warning: #F59E0B;
--error: #EF4444;
--info: #3B82F6;
--bg-primary: #FAFAFA;
--bg-secondary: #F5F5F5;
--bg-card: #FFFFFF;
--bg-elevated: #FFFFFF;
--text-primary: #1A1A2E;
--text-secondary: #6B7280;
--text-hint: #9CA3AF;
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 24px;
--space-xl: 32px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
-webkit-font-smoothing: antialiased;
}
.phone-frame {
max-width: 430px;
margin: 0 auto;
min-height: 100vh;
background: var(--bg-primary);
}
.appbar {
position: sticky;
top: 0;
z-index: 100;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
background: rgba(250,250,250,0.78);
border-bottom: 0.5px solid rgba(0,0,0,0.08);
padding: 12px var(--space-md);
display: flex;
align-items: center;
gap: 8px;
}
.appbar-back {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--bg-secondary);
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
cursor: pointer;
border: none;
color: var(--text-primary);
}
.appbar-title {
font-size: 17px;
font-weight: 600;
}
.content {
padding: var(--space-md);
}
.section {
margin-bottom: var(--space-lg);
}
.section-title {
font-size: 13px;
font-weight: 600;
color: var(--text-hint);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: var(--space-sm);
padding-left: var(--space-md);
}
.card-group {
background: var(--bg-card);
border-radius: var(--radius-lg);
overflow: hidden;
box-shadow: var(--shadow-sm);
border: 0.5px solid rgba(0,0,0,0.04);
}
.setting-row {
padding: 14px var(--space-md);
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 0.5px solid rgba(0,0,0,0.04);
cursor: pointer;
transition: background 0.15s;
}
.setting-row:last-child {
border-bottom: none;
}
.setting-row:active {
background: rgba(0,0,0,0.03);
}
.setting-left {
display: flex;
align-items: center;
gap: 12px;
}
.setting-icon {
width: 32px;
height: 32px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
.setting-icon.purple { background: rgba(108,99,255,0.12); }
.setting-icon.teal { background: rgba(78,205,196,0.12); }
.setting-icon.orange { background: rgba(245,158,11,0.12); }
.setting-icon.blue { background: rgba(59,130,246,0.12); }
.setting-icon.red { background: rgba(239,68,68,0.12); }
.setting-icon.green { background: rgba(16,185,129,0.12); }
.setting-icon.pink { background: rgba(255,107,107,0.12); }
.setting-icon.indigo { background: rgba(99,102,241,0.12); }
.setting-label {
font-size: 15px;
font-weight: 500;
}
.setting-desc {
font-size: 12px;
color: var(--text-hint);
margin-top: 2px;
}
.setting-right {
display: flex;
align-items: center;
gap: 6px;
color: var(--text-hint);
font-size: 14px;
}
.setting-right .chevron {
font-size: 12px;
opacity: 0.4;
}
/* Choice Group (3-option selector) */
.choice-group {
padding: 10px var(--space-md);
border-bottom: 0.5px solid rgba(0,0,0,0.04);
}
.choice-group:last-child {
border-bottom: none;
}
.choice-label {
font-size: 15px;
font-weight: 500;
margin-bottom: 4px;
}
.choice-desc {
font-size: 12px;
color: var(--text-hint);
margin-bottom: 10px;
}
.choice-options {
display: flex;
gap: 8px;
}
.choice-option {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 10px 6px;
border-radius: var(--radius-lg);
background: var(--bg-secondary);
cursor: pointer;
transition: all 0.2s;
border: 1.5px solid transparent;
}
.choice-option:active {
transform: scale(0.97);
}
.choice-option.selected {
background: rgba(108,99,255,0.08);
border-color: rgba(108,99,255,0.4);
}
.choice-option-icon {
font-size: 24px;
}
.choice-option-text {
font-size: 12px;
font-weight: 500;
color: var(--text-secondary);
}
.choice-option.selected .choice-option-text {
color: var(--primary);
font-weight: 600;
}
.choice-preview {
width: 60px;
height: 40px;
border-radius: 6px;
overflow: hidden;
}
.preview-gradient {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #4ECDC4, #44B09E);
}
.preview-image {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #667eea, #764ba2);
}
.preview-minimal {
width: 100%;
height: 100%;
background: var(--bg-card);
border: 1px solid rgba(0,0,0,0.06);
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
color: var(--text-hint);
}
/* Toggle Switch */
.toggle {
width: 51px;
height: 31px;
border-radius: 16px;
background: #E5E5EA;
position: relative;
cursor: pointer;
transition: background 0.3s;
}
.toggle.active {
background: var(--primary);
}
.toggle::after {
content: '';
position: absolute;
width: 27px;
height: 27px;
border-radius: 50%;
background: white;
top: 2px;
left: 2px;
transition: transform 0.3s;
box-shadow: 0 1px 3px rgba(0,0,0,0.15);
}
.toggle.active::after {
transform: translateX(20px);
}
/* Slider */
.slider-row {
padding: 14px var(--space-md);
border-bottom: 0.5px solid rgba(0,0,0,0.04);
}
.slider-label {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
}
.slider-label span:first-child {
font-size: 15px;
font-weight: 500;
}
.slider-label span:last-child {
font-size: 13px;
color: var(--primary);
font-weight: 600;
}
input[type="range"] {
width: 100%;
height: 4px;
-webkit-appearance: none;
appearance: none;
background: var(--bg-secondary);
border-radius: 2px;
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 22px;
height: 22px;
border-radius: 50%;
background: var(--primary);
cursor: pointer;
box-shadow: 0 2px 6px rgba(108,99,255,0.3);
}
/* Submit Button */
.submit-section {
margin-top: var(--space-xl);
padding: 0 var(--space-md);
}
.submit-btn {
width: 100%;
padding: 14px;
border-radius: var(--radius-lg);
background: var(--primary);
color: white;
font-size: 16px;
font-weight: 600;
border: none;
cursor: pointer;
transition: all 0.2s;
box-shadow: 0 4px 12px rgba(108,99,255,0.3);
}
.submit-btn:active {
transform: scale(0.98);
opacity: 0.9;
}
.submit-note {
text-align: center;
font-size: 12px;
color: var(--text-hint);
margin-top: 8px;
line-height: 1.5;
}
/* Data Stats */
.data-stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
margin-bottom: var(--space-lg);
}
.stat-card {
background: var(--bg-card);
border-radius: var(--radius-lg);
padding: var(--space-md);
text-align: center;
box-shadow: var(--shadow-sm);
border: 0.5px solid rgba(0,0,0,0.04);
}
.stat-value {
font-size: 24px;
font-weight: 700;
color: var(--primary);
}
.stat-label {
font-size: 11px;
color: var(--text-hint);
margin-top: 4px;
}
/* Dark Mode */
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #1A1A2E;
--bg-secondary: #16213E;
--bg-card: #2D2D44;
--bg-elevated: #333355;
--text-primary: #E5E5E5;
--text-secondary: #9CA3AF;
--text-hint: #6B7280;
}
.appbar {
background: rgba(26,26,46,0.78);
border-bottom-color: rgba(255,255,255,0.06);
}
.toggle { background: #3A3A5C; }
}
</style>
</head>
<body>
<div class="phone-frame">
<div class="appbar">
<button class="appbar-back" onclick="window.location.href='leisure_timeline.html'"></button>
<div class="appbar-title">⚙️ 闲情逸致设置</div>
</div>
<div class="content">
<!-- Data Stats -->
<div class="data-stats">
<div class="stat-card">
<div class="stat-value">365</div>
<div class="stat-label">总节点</div>
</div>
<div class="stat-card">
<div class="stat-value">728</div>
<div class="stat-label">卡片数</div>
</div>
<div class="stat-card">
<div class="stat-value">12</div>
<div class="stat-label">已收藏</div>
</div>
</div>
<!-- Display Settings -->
<div class="section">
<div class="section-title">显示设置</div>
<div class="card-group">
<div class="setting-row">
<div class="setting-left">
<div class="setting-icon purple">📐</div>
<div>
<div class="setting-label">卡片大小</div>
<div class="setting-desc">调整时间线卡片的显示大小</div>
</div>
</div>
<div class="setting-right">
<span>标准</span>
<span class="chevron"></span>
</div>
</div>
<div class="slider-row">
<div class="slider-label">
<span>卡片圆角</span>
<span>12px</span>
</div>
<input type="range" min="0" max="24" value="12">
</div>
<div class="setting-row">
<div class="setting-left">
<div class="setting-icon teal">🎨</div>
<div>
<div class="setting-label">卡片样式</div>
<div class="setting-desc">精致卡片 / 扁平简约 / 图文卡片</div>
</div>
</div>
<div class="setting-right">
<span>精致卡片</span>
<span class="chevron"></span>
</div>
</div>
<div class="setting-row">
<div class="setting-left">
<div class="setting-icon blue">🌓</div>
<div>
<div class="setting-label">显示季节标签</div>
<div class="setting-desc">在日期节点显示季节颜色标签</div>
</div>
</div>
<div class="setting-right">
<div class="toggle active" onclick="this.classList.toggle('active')"></div>
</div>
</div>
<div class="setting-row">
<div class="setting-left">
<div class="setting-icon orange">🌅</div>
<div>
<div class="setting-label">显示日出日落</div>
<div class="setting-desc">在卡片中显示当日日出日落时间</div>
</div>
</div>
<div class="setting-right">
<div class="toggle active" onclick="this.classList.toggle('active')"></div>
</div>
</div>
<div class="setting-row">
<div class="setting-left">
<div class="setting-icon red">⚠️</div>
<div>
<div class="setting-label">风险提示</div>
<div class="setting-desc">高海拔/边境/高危地区风险标注</div>
</div>
</div>
<div class="setting-right">
<div class="toggle active" onclick="this.classList.toggle('active')"></div>
</div>
</div>
</div>
</div>
<!-- Decision Options -->
<div class="section">
<div class="section-title">决策选项</div>
<div class="card-group">
<div class="choice-group">
<div class="choice-label">📤 分享卡片样式</div>
<div class="choice-desc">选择分享时生成的卡片风格</div>
<div class="choice-options">
<div class="choice-option selected" onclick="selectChoice(this)">
<div class="choice-preview"><div class="preview-gradient"></div></div>
<span class="choice-option-text">渐变头图</span>
</div>
<div class="choice-option" onclick="selectChoice(this)">
<div class="choice-preview"><div class="preview-image"></div></div>
<span class="choice-option-text">图片卡片</span>
</div>
<div class="choice-option" onclick="selectChoice(this)">
<div class="choice-preview"><div class="preview-minimal"></div></div>
<span class="choice-option-text">极简诗意</span>
</div>
</div>
</div>
<div class="choice-group">
<div class="choice-label">📍 默认打开位置</div>
<div class="choice-desc">打开时间线时默认定位到哪个位置</div>
<div class="choice-options">
<div class="choice-option selected" onclick="selectChoice(this)">
<span class="choice-option-icon">📅</span>
<span class="choice-option-text">今日</span>
</div>
<div class="choice-option" onclick="selectChoice(this)">
<span class="choice-option-icon">📊</span>
<span class="choice-option-text">最近有数据</span>
</div>
<div class="choice-option" onclick="selectChoice(this)">
<span class="choice-option-icon">🔖</span>
<span class="choice-option-text">上次浏览</span>
</div>
</div>
</div>
<div class="choice-group">
<div class="choice-label">📐 卡片信息密度</div>
<div class="choice-desc">控制卡片中显示的信息量</div>
<div class="choice-options">
<div class="choice-option" onclick="selectChoice(this)">
<span class="choice-option-icon">压缩</span>
<span class="choice-option-text">紧凑</span>
</div>
<div class="choice-option selected" onclick="selectChoice(this)">
<span class="choice-option-icon">标准</span>
<span class="choice-option-text">标准</span>
</div>
<div class="choice-option" onclick="selectChoice(this)">
<span class="choice-option-icon">宽松</span>
<span class="choice-option-text">宽松</span>
</div>
</div>
</div>
<div class="choice-group">
<div class="choice-label">⚠️ 风险提示级别</div>
<div class="choice-desc">控制风险提示的显示范围</div>
<div class="choice-options">
<div class="choice-option" onclick="selectChoice(this)">
<span class="choice-option-icon">🔴</span>
<span class="choice-option-text">仅高危</span>
</div>
<div class="choice-option selected" onclick="selectChoice(this)">
<span class="choice-option-icon">🟡</span>
<span class="choice-option-text">全部</span>
</div>
<div class="choice-option" onclick="selectChoice(this)">
<span class="choice-option-icon"></span>
<span class="choice-option-text">关闭</span>
</div>
</div>
</div>
<div class="choice-group">
<div class="choice-label">🔄 数据更新频率</div>
<div class="choice-desc">控制时间线数据的自动更新策略</div>
<div class="choice-options">
<div class="choice-option selected" onclick="selectChoice(this)">
<span class="choice-option-icon">📲</span>
<span class="choice-option-text">每次打开</span>
</div>
<div class="choice-option" onclick="selectChoice(this)">
<span class="choice-option-icon">📅</span>
<span class="choice-option-text">每日</span>
</div>
<div class="choice-option" onclick="selectChoice(this)">
<span class="choice-option-icon"></span>
<span class="choice-option-text">手动</span>
</div>
</div>
</div>
</div>
</div>
<!-- Data Settings -->
<div class="section">
<div class="section-title">数据管理</div>
<div class="card-group">
<div class="setting-row">
<div class="setting-left">
<div class="setting-icon green">📥</div>
<div>
<div class="setting-label">更新数据</div>
<div class="setting-desc">从服务器获取最新花期/美食/景点数据</div>
</div>
</div>
<div class="setting-right">
<span class="chevron"></span>
</div>
</div>
<div class="setting-row">
<div class="setting-left">
<div class="setting-icon blue">🗑️</div>
<div>
<div class="setting-label">清除缓存</div>
<div class="setting-desc">清除已缓存的图片和临时数据</div>
</div>
</div>
<div class="setting-right">
<span>2.3 MB</span>
<span class="chevron"></span>
</div>
</div>
<div class="setting-row">
<div class="setting-left">
<div class="setting-icon purple">📤</div>
<div>
<div class="setting-label">导出数据</div>
<div class="setting-desc">导出收藏和标注数据为JSON</div>
</div>
</div>
<div class="setting-right">
<span class="chevron"></span>
</div>
</div>
<div class="setting-row">
<div class="setting-left">
<div class="setting-icon orange">📊</div>
<div>
<div class="setting-label">数据源管理</div>
<div class="setting-desc">管理花期/美食/景点的数据来源</div>
</div>
</div>
<div class="setting-right">
<span>3 个源</span>
<span class="chevron"></span>
</div>
</div>
</div>
</div>
<!-- Submit Section -->
<div class="submit-section">
<button class="submit-btn" onclick="alert('提交收录功能即将上线,敬请期待 ✨')">
📮 提交收录
</button>
<div class="submit-note">
发现好的花期/美食/景点?提交收录后经审核可加入时间线<br>
此功能后续开发,敬请期待
</div>
</div>
</div>
</div>
<script>
function selectChoice(el) {
el.parentElement.querySelectorAll('.choice-option').forEach(o => o.classList.remove('selected'));
el.classList.add('selected');
}
</script>
</body>
</html>