主要变更: 1. 重构"国学"相关模块为"经典名句",统一命名规范 2. 重命名"阅读报告"为"使用报告",调整相关文案与配置 3. 修复iOS模拟器图片缓存兼容问题,优化图表渲染逻辑 4. 新增设备活跃状态前端兜底判断,修复在线计数异常 5. 完善登录/注册流程,新增忘记密码路由与账户编辑提示 6. 优化文件传输与字体导入逻辑,废弃过时的bytes属性使用 7. 添加Spotlight全局快捷键支持,更新隐私权限与通知配置 8. 补充数据库迁移脚本与部署文档,修复后端接口兼容问题 9. 调整部分UI交互细节,优化内存占用与应用稳定性
1132 lines
40 KiB
HTML
1132 lines
40 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>闲言APP — 我的页面下拉搜索 · 方案预览</title>
|
||
<style>
|
||
/* ========== 设计令牌 ========== */
|
||
:root {
|
||
--primary: #007AFF;
|
||
--primary-light: rgba(0,122,255,0.12);
|
||
--bg: #F2F2F7;
|
||
--bg-elevated: #FFFFFF;
|
||
--bg-glass: rgba(255,255,255,0.72);
|
||
--bg-overlay: rgba(0,0,0,0.32);
|
||
--text-primary: #1C1C1E;
|
||
--text-secondary: #8E8E93;
|
||
--text-hint: #C7C7CC;
|
||
--separator: rgba(60,60,67,0.12);
|
||
--radius-sm: 8px;
|
||
--radius-md: 12px;
|
||
--radius-lg: 16px;
|
||
--radius-xl: 20px;
|
||
--shadow-search: 0 20px 60px rgba(0,0,0,0.18), 0 0 0 0.5px rgba(0,0,0,0.08);
|
||
--font-family: -apple-system, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', sans-serif;
|
||
}
|
||
|
||
/* 暗色主题 */
|
||
[data-theme="dark"] {
|
||
--primary: #0A84FF;
|
||
--primary-light: rgba(10,132,255,0.18);
|
||
--bg: #000000;
|
||
--bg-elevated: #1C1C1E;
|
||
--bg-glass: rgba(44,44,46,0.78);
|
||
--bg-overlay: rgba(0,0,0,0.52);
|
||
--text-primary: #FFFFFF;
|
||
--text-secondary: #98989D;
|
||
--text-hint: #48484A;
|
||
--separator: rgba(84,84,88,0.36);
|
||
--shadow-search: 0 20px 60px rgba(0,0,0,0.4), 0 0 0 0.5px rgba(255,255,255,0.06);
|
||
}
|
||
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
|
||
body {
|
||
font-family: var(--font-family);
|
||
background: var(--bg);
|
||
color: var(--text-primary);
|
||
min-height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
transition: background 0.3s, color 0.3s;
|
||
}
|
||
|
||
/* ========== 顶部工具栏 ========== */
|
||
.toolbar {
|
||
width: 100%;
|
||
padding: 16px 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
background: var(--bg-elevated);
|
||
border-bottom: 1px solid var(--separator);
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
backdrop-filter: blur(20px);
|
||
-webkit-backdrop-filter: blur(20px);
|
||
}
|
||
.toolbar h1 {
|
||
font-size: 17px;
|
||
font-weight: 600;
|
||
}
|
||
.toolbar-actions {
|
||
display: flex;
|
||
gap: 12px;
|
||
align-items: center;
|
||
}
|
||
.theme-toggle {
|
||
padding: 6px 14px;
|
||
border-radius: 999px;
|
||
border: 1px solid var(--separator);
|
||
background: var(--bg);
|
||
color: var(--text-primary);
|
||
font-size: 13px;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
.theme-toggle:hover {
|
||
background: var(--primary-light);
|
||
border-color: var(--primary);
|
||
}
|
||
|
||
/* ========== 方案说明 ========== */
|
||
.description {
|
||
max-width: 720px;
|
||
width: 100%;
|
||
padding: 24px;
|
||
}
|
||
.description h2 {
|
||
font-size: 22px;
|
||
font-weight: 700;
|
||
margin-bottom: 12px;
|
||
}
|
||
.description p {
|
||
font-size: 15px;
|
||
color: var(--text-secondary);
|
||
line-height: 1.6;
|
||
margin-bottom: 8px;
|
||
}
|
||
.feature-list {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||
gap: 12px;
|
||
margin: 16px 0;
|
||
}
|
||
.feature-item {
|
||
padding: 12px 16px;
|
||
background: var(--bg-elevated);
|
||
border-radius: var(--radius-md);
|
||
border: 1px solid var(--separator);
|
||
font-size: 14px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.feature-icon {
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: 6px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* ========== 手机模拟器 ========== */
|
||
.phone-container {
|
||
display: flex;
|
||
gap: 40px;
|
||
padding: 24px;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
}
|
||
.phone-wrapper {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
.phone-label {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: var(--text-secondary);
|
||
}
|
||
.phone {
|
||
width: 375px;
|
||
height: 740px;
|
||
background: var(--bg);
|
||
border-radius: 44px;
|
||
border: 3px solid var(--separator);
|
||
overflow: hidden;
|
||
position: relative;
|
||
box-shadow: 0 8px 32px rgba(0,0,0,0.12);
|
||
}
|
||
|
||
/* ========== Profile 页面内容 ========== */
|
||
.profile-page {
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow-y: auto;
|
||
position: relative;
|
||
}
|
||
.profile-header {
|
||
padding: 60px 20px 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.profile-header-icon {
|
||
width: 28px;
|
||
height: 28px;
|
||
background: var(--primary-light);
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--primary);
|
||
font-size: 14px;
|
||
}
|
||
.profile-header h1 {
|
||
font-size: 28px;
|
||
font-weight: 700;
|
||
}
|
||
.profile-header-actions {
|
||
margin-left: auto;
|
||
display: flex;
|
||
gap: 8px;
|
||
}
|
||
.header-btn {
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: 50%;
|
||
background: var(--bg-elevated);
|
||
border: 1px solid var(--separator);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
transition: all 0.2s;
|
||
}
|
||
.header-btn:hover {
|
||
background: var(--primary-light);
|
||
border-color: var(--primary);
|
||
}
|
||
.header-btn.search-btn {
|
||
background: var(--primary-light);
|
||
border-color: transparent;
|
||
color: var(--primary);
|
||
}
|
||
|
||
/* 用户卡片 */
|
||
.user-card {
|
||
margin: 0 16px 12px;
|
||
padding: 16px;
|
||
background: var(--bg-elevated);
|
||
border-radius: var(--radius-lg);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
.avatar {
|
||
width: 52px;
|
||
height: 52px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(135deg, var(--primary), #5856D6);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: white;
|
||
font-size: 22px;
|
||
font-weight: 600;
|
||
}
|
||
.user-info { flex: 1; }
|
||
.user-name { font-size: 17px; font-weight: 600; }
|
||
.user-desc { font-size: 13px; color: var(--text-secondary); margin-top: 2px; }
|
||
|
||
/* 设置组 */
|
||
.settings-group {
|
||
margin: 0 16px 12px;
|
||
background: var(--bg-elevated);
|
||
border-radius: var(--radius-lg);
|
||
overflow: hidden;
|
||
}
|
||
.settings-item {
|
||
padding: 12px 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
border-bottom: 0.5px solid var(--separator);
|
||
cursor: pointer;
|
||
transition: background 0.15s;
|
||
}
|
||
.settings-item:last-child { border-bottom: none; }
|
||
.settings-item:hover { background: var(--primary-light); }
|
||
.settings-icon {
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 7px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 15px;
|
||
color: white;
|
||
flex-shrink: 0;
|
||
}
|
||
.settings-label { flex: 1; font-size: 15px; }
|
||
.settings-chevron { color: var(--text-hint); font-size: 13px; }
|
||
|
||
/* ========== 搜索浮层 ========== */
|
||
.search-overlay {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: var(--bg-overlay);
|
||
backdrop-filter: blur(30px);
|
||
-webkit-backdrop-filter: blur(30px);
|
||
z-index: 50;
|
||
display: none;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding-top: 80px;
|
||
animation: fadeIn 0.2s ease-out;
|
||
}
|
||
.search-overlay.active { display: flex; }
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
@keyframes slideDown {
|
||
from { opacity: 0; transform: translateY(-16px) scale(0.98); }
|
||
to { opacity: 1; transform: translateY(0) scale(1); }
|
||
}
|
||
|
||
.search-container {
|
||
width: 340px;
|
||
background: var(--bg-glass);
|
||
backdrop-filter: saturate(180%) blur(40px);
|
||
-webkit-backdrop-filter: saturate(180%) blur(40px);
|
||
border-radius: var(--radius-xl);
|
||
box-shadow: var(--shadow-search);
|
||
overflow: hidden;
|
||
animation: slideDown 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
||
max-height: 560px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 搜索栏 */
|
||
.search-bar {
|
||
padding: 12px 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
border-bottom: 0.5px solid var(--separator);
|
||
}
|
||
.search-icon {
|
||
color: var(--text-secondary);
|
||
font-size: 16px;
|
||
flex-shrink: 0;
|
||
}
|
||
.search-input {
|
||
flex: 1;
|
||
border: none;
|
||
outline: none;
|
||
background: transparent;
|
||
font-size: 17px;
|
||
color: var(--text-primary);
|
||
font-family: var(--font-family);
|
||
}
|
||
.search-input::placeholder {
|
||
color: var(--text-hint);
|
||
}
|
||
.search-clear {
|
||
width: 20px;
|
||
height: 20px;
|
||
border-radius: 50%;
|
||
background: var(--text-hint);
|
||
color: white;
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 11px;
|
||
cursor: pointer;
|
||
flex-shrink: 0;
|
||
}
|
||
.search-clear.visible { display: flex; }
|
||
|
||
/* 搜索结果 */
|
||
.search-results {
|
||
overflow-y: auto;
|
||
flex: 1;
|
||
}
|
||
|
||
/* 分类标题 */
|
||
.result-category {
|
||
padding: 8px 16px 4px;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
color: var(--text-secondary);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
/* 结果项 */
|
||
.result-item {
|
||
padding: 10px 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
cursor: pointer;
|
||
transition: background 0.12s;
|
||
}
|
||
.result-item:hover, .result-item.selected {
|
||
background: var(--primary-light);
|
||
}
|
||
.result-icon {
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: var(--radius-sm);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 17px;
|
||
flex-shrink: 0;
|
||
}
|
||
.result-icon.page {
|
||
background: linear-gradient(135deg, #007AFF, #5856D6);
|
||
color: white;
|
||
}
|
||
.result-icon.feature {
|
||
background: linear-gradient(135deg, #34C759, #30D158);
|
||
color: white;
|
||
}
|
||
.result-icon.tool {
|
||
background: linear-gradient(135deg, #FF9500, #FF6B00);
|
||
color: white;
|
||
}
|
||
.result-icon.setting {
|
||
background: linear-gradient(135deg, #8E8E93, #636366);
|
||
color: white;
|
||
}
|
||
.result-icon.content {
|
||
background: linear-gradient(135deg, #AF52DE, #BF5AF2);
|
||
color: white;
|
||
}
|
||
.result-content { flex: 1; min-width: 0; }
|
||
.result-title {
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.result-title mark {
|
||
background: none;
|
||
color: var(--primary);
|
||
font-weight: 700;
|
||
}
|
||
.result-subtitle {
|
||
font-size: 12px;
|
||
color: var(--text-secondary);
|
||
margin-top: 1px;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.result-badge {
|
||
padding: 2px 8px;
|
||
border-radius: 999px;
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
flex-shrink: 0;
|
||
}
|
||
.result-badge.page { background: rgba(0,122,255,0.12); color: #007AFF; }
|
||
.result-badge.feature { background: rgba(52,199,89,0.12); color: #34C759; }
|
||
.result-badge.tool { background: rgba(255,149,0,0.12); color: #FF9500; }
|
||
.result-badge.setting { background: rgba(142,142,147,0.12); color: #8E8E93; }
|
||
.result-badge.content { background: rgba(175,82,222,0.12); color: #AF52DE; }
|
||
|
||
/* 快捷键提示 */
|
||
.shortcut-hint {
|
||
padding: 10px 16px;
|
||
border-top: 0.5px solid var(--separator);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 16px;
|
||
font-size: 12px;
|
||
color: var(--text-hint);
|
||
}
|
||
.kbd {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 2px 6px;
|
||
background: var(--bg-elevated);
|
||
border: 1px solid var(--separator);
|
||
border-radius: 4px;
|
||
font-size: 11px;
|
||
font-family: var(--font-family);
|
||
color: var(--text-secondary);
|
||
min-width: 20px;
|
||
}
|
||
|
||
/* 空状态 */
|
||
.empty-state {
|
||
padding: 40px 16px;
|
||
text-align: center;
|
||
}
|
||
.empty-icon {
|
||
font-size: 40px;
|
||
margin-bottom: 12px;
|
||
opacity: 0.4;
|
||
}
|
||
.empty-text {
|
||
font-size: 15px;
|
||
color: var(--text-secondary);
|
||
}
|
||
.empty-hint {
|
||
font-size: 13px;
|
||
color: var(--text-hint);
|
||
margin-top: 4px;
|
||
}
|
||
|
||
/* 最近搜索标签 */
|
||
.recent-tags {
|
||
padding: 8px 16px 12px;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 6px;
|
||
}
|
||
.recent-tag {
|
||
padding: 4px 10px;
|
||
background: var(--bg-elevated);
|
||
border: 1px solid var(--separator);
|
||
border-radius: 999px;
|
||
font-size: 13px;
|
||
color: var(--text-secondary);
|
||
cursor: pointer;
|
||
transition: all 0.15s;
|
||
}
|
||
.recent-tag:hover {
|
||
background: var(--primary-light);
|
||
border-color: var(--primary);
|
||
color: var(--primary);
|
||
}
|
||
|
||
/* ========== 方案对比 ========== */
|
||
.comparison {
|
||
max-width: 720px;
|
||
width: 100%;
|
||
padding: 0 24px 24px;
|
||
}
|
||
.comparison h3 {
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
margin: 24px 0 12px;
|
||
}
|
||
.comparison-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 14px;
|
||
}
|
||
.comparison-table th, .comparison-table td {
|
||
padding: 10px 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid var(--separator);
|
||
}
|
||
.comparison-table th {
|
||
font-weight: 600;
|
||
color: var(--text-secondary);
|
||
font-size: 12px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
.comparison-table td { color: var(--text-primary); }
|
||
.check { color: #34C759; }
|
||
.cross { color: #FF3B30; }
|
||
|
||
/* ========== 交互脚本 ========== */
|
||
.click-hint {
|
||
position: absolute;
|
||
bottom: 16px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
padding: 6px 14px;
|
||
background: var(--primary);
|
||
color: white;
|
||
border-radius: 999px;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
animation: pulse 2s infinite;
|
||
z-index: 10;
|
||
pointer-events: none;
|
||
}
|
||
@keyframes pulse {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.6; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body data-theme="light">
|
||
|
||
<!-- 工具栏 -->
|
||
<div class="toolbar">
|
||
<h1>🔍 闲言APP — 我的页面下拉搜索 · 方案预览</h1>
|
||
<div class="toolbar-actions">
|
||
<button class="theme-toggle" onclick="toggleTheme()">🌓 切换主题</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 方案说明 -->
|
||
<div class="description">
|
||
<h2>方案概述</h2>
|
||
<p>在「我的」页面顶部标题栏增加搜索入口,点击后弹出 macOS Spotlight 风格的搜索浮层,支持快速跳转到应用内任意页面/功能/设置。</p>
|
||
|
||
<div class="feature-list">
|
||
<div class="feature-item">
|
||
<div class="feature-icon" style="background:rgba(0,122,255,0.12);color:#007AFF;">🔍</div>
|
||
<span>实时搜索建议</span>
|
||
</div>
|
||
<div class="feature-item">
|
||
<div class="feature-icon" style="background:rgba(52,199,89,0.12);color:#34C759;">📂</div>
|
||
<span>分类结果展示</span>
|
||
</div>
|
||
<div class="feature-item">
|
||
<div class="feature-icon" style="background:rgba(255,149,0,0.12);color:#FF9500;">⌨️</div>
|
||
<span>键盘快捷键</span>
|
||
</div>
|
||
<div class="feature-item">
|
||
<div class="feature-icon" style="background:rgba(175,82,222,0.12);color:#AF52DE;">🎨</div>
|
||
<span>动态主题适配</span>
|
||
</div>
|
||
<div class="feature-item">
|
||
<div class="feature-icon" style="background:rgba(255,59,48,0.12);color:#FF3B30;">🕐</div>
|
||
<span>最近搜索记录</span>
|
||
</div>
|
||
<div class="feature-item">
|
||
<div class="feature-icon" style="background:rgba(88,86,214,0.12);color:#5856D6;">🚀</div>
|
||
<span>拼音首字母匹配</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 手机模拟器 -->
|
||
<div class="phone-container">
|
||
<!-- 状态1: 默认页面 -->
|
||
<div class="phone-wrapper">
|
||
<div class="phone-label">默认状态 — 搜索入口</div>
|
||
<div class="phone" id="phone-default">
|
||
<div class="profile-page">
|
||
<div class="profile-header">
|
||
<div class="profile-header-icon">👤</div>
|
||
<h1>我的</h1>
|
||
<div class="profile-header-actions">
|
||
<div class="header-btn search-btn" onclick="showSearch('default')">🔍</div>
|
||
<div class="header-btn">+</div>
|
||
</div>
|
||
</div>
|
||
<div class="user-card">
|
||
<div class="avatar">闲</div>
|
||
<div class="user-info">
|
||
<div class="user-name">闲言用户</div>
|
||
<div class="user-desc">Lv.6 · 积分 2,580</div>
|
||
</div>
|
||
<div style="color:var(--text-hint);font-size:13px;">›</div>
|
||
</div>
|
||
<div class="settings-group">
|
||
<div class="settings-item">
|
||
<div class="settings-icon" style="background:#FF3B30;">❤️</div>
|
||
<span class="settings-label">收藏</span>
|
||
<span class="settings-chevron">›</span>
|
||
</div>
|
||
<div class="settings-item">
|
||
<div class="settings-icon" style="background:#007AFF;">📖</div>
|
||
<span class="settings-label">阅读历史</span>
|
||
<span class="settings-chevron">›</span>
|
||
</div>
|
||
</div>
|
||
<div class="settings-group">
|
||
<div class="settings-item">
|
||
<div class="settings-icon" style="background:#5856D6;">⚙️</div>
|
||
<span class="settings-label">账号设置</span>
|
||
<span class="settings-chevron">›</span>
|
||
</div>
|
||
<div class="settings-item">
|
||
<div class="settings-icon" style="background:#FF9500;">💾</div>
|
||
<span class="settings-label">数据管理</span>
|
||
<span class="settings-chevron">›</span>
|
||
</div>
|
||
<div class="settings-item">
|
||
<div class="settings-icon" style="background:#34C759;">🌐</div>
|
||
<span class="settings-label">语言</span>
|
||
<span class="settings-chevron">›</span>
|
||
</div>
|
||
</div>
|
||
<div class="settings-group">
|
||
<div class="settings-item">
|
||
<div class="settings-icon" style="background:#8E8E93;">ℹ️</div>
|
||
<span class="settings-label">关于</span>
|
||
<span class="settings-chevron">›</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="click-hint">👆 点击搜索图标试试</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 状态2: 搜索浮层 - 初始 -->
|
||
<div class="phone-wrapper">
|
||
<div class="phone-label">搜索浮层 — 初始状态</div>
|
||
<div class="phone" id="phone-initial">
|
||
<div class="profile-page" style="filter:blur(2px);">
|
||
<div class="profile-header">
|
||
<div class="profile-header-icon">👤</div>
|
||
<h1>我的</h1>
|
||
</div>
|
||
<div class="user-card">
|
||
<div class="avatar">闲</div>
|
||
<div class="user-info">
|
||
<div class="user-name">闲言用户</div>
|
||
<div class="user-desc">Lv.6 · 积分 2,580</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="search-overlay active" onclick="hideSearch(event, 'initial')">
|
||
<div class="search-container" onclick="event.stopPropagation()">
|
||
<div class="search-bar">
|
||
<span class="search-icon">🔍</span>
|
||
<input class="search-input" type="text" placeholder="搜索页面、功能、设置…" oninput="handleSearch(this, 'initial')" id="input-initial">
|
||
<div class="search-clear" id="clear-initial" onclick="clearSearch('initial')">✕</div>
|
||
</div>
|
||
<div class="search-results" id="results-initial">
|
||
<div class="result-category">最近搜索</div>
|
||
<div class="recent-tags">
|
||
<span class="recent-tag" onclick="fillSearch('initial', '天气')">天气</span>
|
||
<span class="recent-tag" onclick="fillSearch('initial', '笔记')">笔记</span>
|
||
<span class="recent-tag" onclick="fillSearch('initial', '主题')">主题</span>
|
||
<span class="recent-tag" onclick="fillSearch('initial', '番茄钟')">番茄钟</span>
|
||
<span class="recent-tag" onclick="fillSearch('initial', '签到')">签到</span>
|
||
</div>
|
||
<div class="result-category">常用功能</div>
|
||
<div class="result-item" onclick="selectResult(this)">
|
||
<div class="result-icon page">🏠</div>
|
||
<div class="result-content">
|
||
<div class="result-title">首页</div>
|
||
<div class="result-subtitle">主页 · 每日推荐</div>
|
||
</div>
|
||
<span class="result-badge page">页面</span>
|
||
</div>
|
||
<div class="result-item" onclick="selectResult(this)">
|
||
<div class="result-icon feature">📅</div>
|
||
<div class="result-content">
|
||
<div class="result-title">每日签到</div>
|
||
<div class="result-subtitle">功能 · 获取积分奖励</div>
|
||
</div>
|
||
<span class="result-badge feature">功能</span>
|
||
</div>
|
||
<div class="result-item" onclick="selectResult(this)">
|
||
<div class="result-icon tool">⏱️</div>
|
||
<div class="result-content">
|
||
<div class="result-title">番茄钟</div>
|
||
<div class="result-subtitle">工具 · 专注计时</div>
|
||
</div>
|
||
<span class="result-badge tool">工具</span>
|
||
</div>
|
||
<div class="result-item" onclick="selectResult(this)">
|
||
<div class="result-icon setting">🎨</div>
|
||
<div class="result-content">
|
||
<div class="result-title">主题定制</div>
|
||
<div class="result-subtitle">设置 · 个性化外观</div>
|
||
</div>
|
||
<span class="result-badge setting">设置</span>
|
||
</div>
|
||
</div>
|
||
<div class="shortcut-hint">
|
||
<span><span class="kbd">↑</span><span class="kbd">↓</span> 导航</span>
|
||
<span><span class="kbd">↵</span> 打开</span>
|
||
<span><span class="kbd">esc</span> 关闭</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 状态3: 搜索浮层 - 搜索结果 -->
|
||
<div class="phone-wrapper">
|
||
<div class="phone-label">搜索浮层 — 搜索结果</div>
|
||
<div class="phone" id="phone-results">
|
||
<div class="profile-page" style="filter:blur(2px);">
|
||
<div class="profile-header">
|
||
<div class="profile-header-icon">👤</div>
|
||
<h1>我的</h1>
|
||
</div>
|
||
</div>
|
||
<div class="search-overlay active">
|
||
<div class="search-container">
|
||
<div class="search-bar">
|
||
<span class="search-icon">🔍</span>
|
||
<input class="search-input" type="text" value="主" oninput="handleSearch(this, 'results')" id="input-results">
|
||
<div class="search-clear visible" onclick="clearSearch('results')">✕</div>
|
||
</div>
|
||
<div class="search-results" id="results-results">
|
||
<div class="result-category">页面</div>
|
||
<div class="result-item selected">
|
||
<div class="result-icon page">🏠</div>
|
||
<div class="result-content">
|
||
<div class="result-title"><mark>主</mark>页</div>
|
||
<div class="result-subtitle">主导航 · 每日推荐内容</div>
|
||
</div>
|
||
<span class="result-badge page">页面</span>
|
||
</div>
|
||
<div class="result-category">功能</div>
|
||
<div class="result-item">
|
||
<div class="result-icon feature">🔑</div>
|
||
<div class="result-content">
|
||
<div class="result-title"><mark>主</mark>题定制</div>
|
||
<div class="result-subtitle">个性化 · 颜色/字体/样式</div>
|
||
</div>
|
||
<span class="result-badge feature">功能</span>
|
||
</div>
|
||
<div class="result-item">
|
||
<div class="result-icon feature">📊</div>
|
||
<div class="result-content">
|
||
<div class="result-title">数据<mark>主</mark>览</div>
|
||
<div class="result-subtitle">统计 · 来源数据分析</div>
|
||
</div>
|
||
<span class="result-badge feature">功能</span>
|
||
</div>
|
||
<div class="result-category">设置</div>
|
||
<div class="result-item">
|
||
<div class="result-icon setting">🎨</div>
|
||
<div class="result-content">
|
||
<div class="result-title"><mark>主</mark>题设置</div>
|
||
<div class="result-subtitle">外观 · 深色/浅色/跟随系统</div>
|
||
</div>
|
||
<span class="result-badge setting">设置</span>
|
||
</div>
|
||
<div class="result-category">内容</div>
|
||
<div class="result-item">
|
||
<div class="result-icon content">📝</div>
|
||
<div class="result-content">
|
||
<div class="result-title"><mark>主</mark>页编辑器</div>
|
||
<div class="result-subtitle">编辑器 · Markdown写作</div>
|
||
</div>
|
||
<span class="result-badge content">内容</span>
|
||
</div>
|
||
</div>
|
||
<div class="shortcut-hint">
|
||
<span><span class="kbd">↑</span><span class="kbd">↓</span> 导航</span>
|
||
<span><span class="kbd">↵</span> 打开</span>
|
||
<span><span class="kbd">esc</span> 关闭</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 方案对比 -->
|
||
<div class="comparison">
|
||
<h3>搜索结果分类说明</h3>
|
||
<table class="comparison-table">
|
||
<thead>
|
||
<tr>
|
||
<th>分类</th>
|
||
<th>颜色</th>
|
||
<th>包含内容</th>
|
||
<th>示例</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="result-badge page">页面</span></td>
|
||
<td>蓝色</td>
|
||
<td>主导航页面、Tab页面</td>
|
||
<td>首页、发现、我的、编辑器</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="result-badge feature">功能</span></td>
|
||
<td>绿色</td>
|
||
<td>功能模块页面</td>
|
||
<td>签到、成就、运势、天气、番茄钟</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="result-badge tool">工具</span></td>
|
||
<td>橙色</td>
|
||
<td>工具类页面</td>
|
||
<td>汉字、成语、翻译、汇率、OCR</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="result-badge setting">设置</span></td>
|
||
<td>灰色</td>
|
||
<td>设置相关页面</td>
|
||
<td>主题、语言、通用、账号、隐私</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="result-badge content">内容</span></td>
|
||
<td>紫色</td>
|
||
<td>内容浏览页面</td>
|
||
<td>收藏、历史、笔记、诗词、文章</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h3>交互设计</h3>
|
||
<table class="comparison-table">
|
||
<thead>
|
||
<tr>
|
||
<th>交互</th>
|
||
<th>触发方式</th>
|
||
<th>效果</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>打开搜索</td>
|
||
<td>点击🔍图标 / 下拉手势 / Cmd+K</td>
|
||
<td>弹出毛玻璃搜索浮层</td>
|
||
</tr>
|
||
<tr>
|
||
<td>关闭搜索</td>
|
||
<td>点击遮罩 / ESC键 / 点击清除</td>
|
||
<td>搜索浮层消失,恢复原页面</td>
|
||
</tr>
|
||
<tr>
|
||
<td>实时搜索</td>
|
||
<td>输入文字</td>
|
||
<td>按分类展示匹配结果,高亮关键词</td>
|
||
</tr>
|
||
<tr>
|
||
<td>选择结果</td>
|
||
<td>点击 / 回车</td>
|
||
<td>跳转到对应页面</td>
|
||
</tr>
|
||
<tr>
|
||
<td>键盘导航</td>
|
||
<td>↑↓ 箭头键</td>
|
||
<td>在结果列表中移动选中项</td>
|
||
</tr>
|
||
<tr>
|
||
<td>拼音匹配</td>
|
||
<td>输入拼音首字母</td>
|
||
<td>匹配中文页面名(如"qt"→"天气")</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<script>
|
||
// 搜索数据
|
||
const searchData = [
|
||
{ name: '首页', category: '页面', type: 'page', icon: '🏠', desc: '主导航 · 每日推荐内容', pinyin: 'shouye', route: '/home' },
|
||
{ name: '发现', category: '页面', type: 'page', icon: '🔭', desc: '探索 · 精选内容', pinyin: 'faxian', route: '/discover' },
|
||
{ name: '我的', category: '页面', type: 'page', icon: '👤', desc: '个人中心 · 设置', pinyin: 'wode', route: '/profile' },
|
||
{ name: '编辑器', category: '页面', type: 'page', icon: '✏️', desc: 'Markdown · 写作', pinyin: 'bianjiqi', route: '/editor' },
|
||
{ name: '搜索', category: '页面', type: 'page', icon: '🔍', desc: '全局搜索 · 内容检索', pinyin: 'sousuo', route: '/search' },
|
||
{ name: '每日签到', category: '功能', type: 'feature', icon: '📅', desc: '签到 · 获取积分奖励', pinyin: 'meiriqiandao', route: '/signin' },
|
||
{ name: '成就中心', category: '功能', type: 'feature', icon: '🏆', desc: '成就 · 勋章收集', pinyin: 'chengjiuzhongxin', route: '/achievement' },
|
||
{ name: '每日运势', category: '功能', type: 'feature', icon: '✨', desc: '运势 · 每日一卦', pinyin: 'meiriyunshi', route: '/fortune' },
|
||
{ name: '天气', category: '功能', type: 'feature', icon: '🌤️', desc: '天气 · 实时气象', pinyin: 'tianqi', route: '/weather' },
|
||
{ name: '番茄钟', category: '功能', type: 'feature', icon: '⏱️', desc: '专注 · 计时器', pinyin: 'fanqiezhong', route: '/pomodoro' },
|
||
{ name: '倒计时', category: '功能', type: 'feature', icon: '⏳', desc: '倒计时 · 纪念日', pinyin: 'daojishi', route: '/countdown' },
|
||
{ name: '节气', category: '功能', type: 'feature', icon: '🌿', desc: '二十四节气 · 农历', pinyin: 'jieqi', route: '/solar-term' },
|
||
{ name: '健康', category: '功能', type: 'feature', icon: '💊', desc: '健康 · 用药提醒', pinyin: 'jiankang', route: '/health' },
|
||
{ name: '游戏', category: '功能', type: 'feature', icon: '🎮', desc: '小游戏 · 休闲', pinyin: 'youxi', route: '/game' },
|
||
{ name: '汉字', category: '工具', type: 'tool', icon: '字', desc: '汉字查询 · 笔画', pinyin: 'hanzi', route: '/hanzi' },
|
||
{ name: '成语', category: '工具', type: 'tool', icon: '典', desc: '成语词典 · 典故', pinyin: 'chengyu', route: '/cy' },
|
||
{ name: '翻译', category: '工具', type: 'tool', icon: '🌐', desc: '多语言翻译', pinyin: 'fanyi', route: '/translate' },
|
||
{ name: '汇率', category: '工具', type: 'tool', icon: '💱', desc: '汇率换算', pinyin: 'huilv', route: '/exchange-rate' },
|
||
{ name: 'OCR', category: '工具', type: 'tool', icon: '📷', desc: '文字识别', pinyin: 'ocr', route: '/ocr' },
|
||
{ name: 'RSS', category: '工具', type: 'tool', icon: '📡', desc: 'RSS阅读器', pinyin: 'rss', route: '/rss-reader' },
|
||
{ name: '主题定制', category: '设置', type: 'setting', icon: '🎨', desc: '个性化 · 颜色/字体', pinyin: 'zhutidingzhi', route: '/settings/theme' },
|
||
{ name: '主题设置', category: '设置', type: 'setting', icon: '🌓', desc: '外观 · 深色/浅色', pinyin: 'zhutishezhi', route: '/settings/theme' },
|
||
{ name: '语言', category: '设置', type: 'setting', icon: '🌐', desc: '多语言切换', pinyin: 'yuyan', route: '/settings/language' },
|
||
{ name: '通用设置', category: '设置', type: 'setting', icon: '⚙️', desc: '通用 · 偏好设置', pinyin: 'tongyongshezhi', route: '/settings/general' },
|
||
{ name: '账号设置', category: '设置', type: 'setting', icon: '🔐', desc: '账号 · 安全', pinyin: 'zhanghaoshezhi', route: '/settings/account' },
|
||
{ name: '隐私', category: '设置', type: 'setting', icon: '🛡️', desc: '隐私 · 数据保护', pinyin: 'yinsi', route: '/settings/privacy' },
|
||
{ name: '数据管理', category: '设置', type: 'setting', icon: '💾', desc: '数据 · 导入导出', pinyin: 'shujuguanli', route: '/data-management' },
|
||
{ name: '收藏', category: '内容', type: 'content', icon: '❤️', desc: '我的收藏', pinyin: 'shoucang', route: '/favorites' },
|
||
{ name: '阅读历史', category: '内容', type: 'content', icon: '📖', desc: '浏览记录', pinyin: 'yuedulishi', route: '/history' },
|
||
{ name: '笔记', category: '内容', type: 'content', icon: '📝', desc: '我的笔记', pinyin: 'biji', route: '/notes' },
|
||
{ name: '诗词', category: '内容', type: 'content', icon: '📜', desc: '古诗词鉴赏', pinyin: 'shici', route: '/poetry' },
|
||
{ name: '文章', category: '内容', type: 'content', icon: '📄', desc: '文章阅读', pinyin: 'wenzhang', route: '/articles' },
|
||
{ name: '数据总揽', category: '功能', type: 'feature', icon: '📊', desc: '统计 · 来源分析', pinyin: 'shujuzonglan', route: '/statistics' },
|
||
{ name: '每日任务', category: '功能', type: 'feature', icon: '✅', desc: '任务 · 积分奖励', pinyin: 'meirirenwu', route: '/daily-task' },
|
||
{ name: '用户中心', category: '页面', type: 'page', icon: '👤', desc: '个人信息 · 编辑', pinyin: 'yonghuzhongxin', route: '/user-center' },
|
||
{ name: '关于', category: '设置', type: 'setting', icon: 'ℹ️', desc: '版本 · 许可证', pinyin: 'guanyu', route: '/about' },
|
||
];
|
||
|
||
function toggleTheme() {
|
||
const body = document.body;
|
||
const current = body.getAttribute('data-theme');
|
||
body.setAttribute('data-theme', current === 'dark' ? 'light' : 'dark');
|
||
}
|
||
|
||
function showSearch(phoneId) {
|
||
const phone = document.getElementById('phone-' + phoneId);
|
||
const overlay = phone.querySelector('.search-overlay');
|
||
if (overlay) {
|
||
overlay.classList.add('active');
|
||
const input = overlay.querySelector('.search-input');
|
||
if (input) setTimeout(() => input.focus(), 100);
|
||
}
|
||
}
|
||
|
||
function hideSearch(event, phoneId) {
|
||
if (event.target.classList.contains('search-overlay')) {
|
||
event.target.classList.remove('active');
|
||
}
|
||
}
|
||
|
||
function clearSearch(phoneId) {
|
||
const input = document.getElementById('input-' + phoneId);
|
||
if (input) {
|
||
input.value = '';
|
||
handleSearch(input, phoneId);
|
||
}
|
||
}
|
||
|
||
function fillSearch(phoneId, text) {
|
||
const input = document.getElementById('input-' + phoneId);
|
||
if (input) {
|
||
input.value = text;
|
||
handleSearch(input, phoneId);
|
||
input.focus();
|
||
}
|
||
}
|
||
|
||
function handleSearch(input, phoneId) {
|
||
const query = input.value.trim().toLowerCase();
|
||
const clearBtn = document.getElementById('clear-' + phoneId);
|
||
const resultsContainer = document.getElementById('results-' + phoneId);
|
||
|
||
if (clearBtn) {
|
||
clearBtn.classList.toggle('visible', query.length > 0);
|
||
}
|
||
|
||
if (!query) {
|
||
// 恢复默认状态
|
||
resultsContainer.innerHTML = `
|
||
<div class="result-category">最近搜索</div>
|
||
<div class="recent-tags">
|
||
<span class="recent-tag" onclick="fillSearch('${phoneId}', '天气')">天气</span>
|
||
<span class="recent-tag" onclick="fillSearch('${phoneId}', '笔记')">笔记</span>
|
||
<span class="recent-tag" onclick="fillSearch('${phoneId}', '主题')">主题</span>
|
||
<span class="recent-tag" onclick="fillSearch('${phoneId}', '番茄钟')">番茄钟</span>
|
||
<span class="recent-tag" onclick="fillSearch('${phoneId}', '签到')">签到</span>
|
||
</div>
|
||
<div class="result-category">常用功能</div>
|
||
<div class="result-item">
|
||
<div class="result-icon page">🏠</div>
|
||
<div class="result-content">
|
||
<div class="result-title">首页</div>
|
||
<div class="result-subtitle">主页 · 每日推荐</div>
|
||
</div>
|
||
<span class="result-badge page">页面</span>
|
||
</div>
|
||
<div class="result-item">
|
||
<div class="result-icon feature">📅</div>
|
||
<div class="result-content">
|
||
<div class="result-title">每日签到</div>
|
||
<div class="result-subtitle">功能 · 获取积分奖励</div>
|
||
</div>
|
||
<span class="result-badge feature">功能</span>
|
||
</div>
|
||
<div class="result-item">
|
||
<div class="result-icon tool">⏱️</div>
|
||
<div class="result-content">
|
||
<div class="result-title">番茄钟</div>
|
||
<div class="result-subtitle">工具 · 专注计时</div>
|
||
</div>
|
||
<span class="result-badge tool">工具</span>
|
||
</div>
|
||
<div class="result-item">
|
||
<div class="result-icon setting">🎨</div>
|
||
<div class="result-content">
|
||
<div class="result-title">主题定制</div>
|
||
<div class="result-subtitle">设置 · 个性化外观</div>
|
||
</div>
|
||
<span class="result-badge setting">设置</span>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
// 搜索匹配
|
||
const results = searchData.filter(item => {
|
||
return item.name.toLowerCase().includes(query) ||
|
||
item.pinyin.includes(query) ||
|
||
item.desc.toLowerCase().includes(query) ||
|
||
item.pinyin.split('').filter((c, i) => i === 0 || item.pinyin[i-1] === ' ').join('').includes(query);
|
||
});
|
||
|
||
if (results.length === 0) {
|
||
resultsContainer.innerHTML = `
|
||
<div class="empty-state">
|
||
<div class="empty-icon">🔍</div>
|
||
<div class="empty-text">未找到"${query}"相关结果</div>
|
||
<div class="empty-hint">试试其他关键词或拼音首字母</div>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
// 按分类分组
|
||
const grouped = {};
|
||
const categoryOrder = ['页面', '功能', '工具', '设置', '内容'];
|
||
results.forEach(item => {
|
||
if (!grouped[item.category]) grouped[item.category] = [];
|
||
grouped[item.category].push(item);
|
||
});
|
||
|
||
let html = '';
|
||
categoryOrder.forEach(cat => {
|
||
if (!grouped[cat]) return;
|
||
html += `<div class="result-category">${cat}</div>`;
|
||
grouped[cat].forEach(item => {
|
||
const highlighted = highlightText(item.name, query);
|
||
html += `
|
||
<div class="result-item" onclick="selectResult(this)">
|
||
<div class="result-icon ${item.type}">${item.icon}</div>
|
||
<div class="result-content">
|
||
<div class="result-title">${highlighted}</div>
|
||
<div class="result-subtitle">${item.desc}</div>
|
||
</div>
|
||
<span class="result-badge ${item.type}">${cat}</span>
|
||
</div>
|
||
`;
|
||
});
|
||
});
|
||
|
||
resultsContainer.innerHTML = html;
|
||
}
|
||
|
||
function highlightText(text, query) {
|
||
if (!query) return text;
|
||
const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
|
||
return text.replace(regex, '<mark>$1</mark>');
|
||
}
|
||
|
||
function selectResult(el) {
|
||
el.style.background = 'var(--primary)';
|
||
el.style.color = 'white';
|
||
el.style.borderRadius = '8px';
|
||
el.style.margin = '0 4px';
|
||
el.style.transition = 'all 0.15s';
|
||
setTimeout(() => {
|
||
el.style.background = '';
|
||
el.style.color = '';
|
||
el.style.borderRadius = '';
|
||
el.style.margin = '';
|
||
}, 300);
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|