本次更新包含: 1. 更新应用标语与隐私政策文案,调整品牌宣传语 2. 重构Feed ID解析、HTML清理工具类,提取重复逻辑 3. 新增全屏图片查看器、通用动画操作按钮组件 4. 修复电池监听空指针、快捷操作异常捕获问题 5. 优化搜索、会话列表、RSS阅读器等页面体验 6. 完善多语言支持,新增多个翻译模块 7. 移除冗余代码,统一数字格式化逻辑 8. 调整登录页面布局与交互逻辑
1147 lines
61 KiB
HTML
1147 lines
61 KiB
HTML
<!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>闲言APP — 聊天会话流设计方案 v2</title>
|
||
<style>
|
||
:root {
|
||
--primary: #6C63FF;
|
||
--primary-light: #8B83FF;
|
||
--accent: #6C63FF;
|
||
--accent-light: #8B83FF;
|
||
--bg: #F2F2F7;
|
||
--bg-card: #FFFFFF;
|
||
--bg-secondary: #E5E5EA;
|
||
--bg-elevated: #FFFFFF;
|
||
--text: #1C1C1E;
|
||
--text-secondary: #8E8E93;
|
||
--text-hint: #AEAEB2;
|
||
--border: rgba(60,60,67,0.08);
|
||
--radius-sm: 8px;
|
||
--radius-md: 12px;
|
||
--radius-lg: 16px;
|
||
--radius-xl: 22px;
|
||
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
|
||
--shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1);
|
||
--shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1);
|
||
--safe-bottom: 34px;
|
||
--font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', sans-serif;
|
||
}
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body {
|
||
font-family: var(--font-family);
|
||
background: #1a1a2e;
|
||
display: flex; justify-content: center; align-items: flex-start;
|
||
min-height: 100vh; padding: 20px; gap: 40px; flex-wrap: wrap;
|
||
}
|
||
.page-header { width: 100%; text-align: center; padding: 20px 0 10px; }
|
||
.page-header h1 { font-size: 28px; color: #fff; font-weight: 700; }
|
||
.page-header p { font-size: 14px; color: rgba(255,255,255,0.5); margin-top: 6px; }
|
||
.tab-bar { width: 100%; display: flex; justify-content: center; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
|
||
.tab-btn {
|
||
padding: 8px 18px; border-radius: 20px; border: 1px solid rgba(255,255,255,0.15);
|
||
background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.6); font-size: 13px;
|
||
cursor: pointer; transition: all 0.25s; font-family: var(--font-family);
|
||
}
|
||
.tab-btn:hover { background: rgba(255,255,255,0.1); }
|
||
.tab-btn.active { background: var(--primary); color: #fff; border-color: var(--primary); box-shadow: 0 2px 12px rgba(108,99,255,0.4); }
|
||
.phone-frame {
|
||
width: 390px; height: 844px; border-radius: 44px; overflow: hidden;
|
||
position: relative; background: var(--bg);
|
||
box-shadow: 0 0 0 8px #2a2a4a, 0 20px 60px rgba(0,0,0,0.5);
|
||
display: none; flex-direction: column;
|
||
}
|
||
.phone-frame.active { display: flex; flex-direction: column; }
|
||
.phone-notch {
|
||
position: absolute; top: 0; left: 50%; transform: translateX(-50%);
|
||
width: 126px; height: 34px; background: #000; border-radius: 0 0 20px 20px; z-index: 100;
|
||
}
|
||
.phone-status-bar {
|
||
height: 54px; display: flex; align-items: flex-end; justify-content: space-between;
|
||
padding: 0 28px 6px; font-size: 14px; font-weight: 600; color: var(--text);
|
||
background: transparent; z-index: 50; flex-shrink: 0;
|
||
}
|
||
.nav-bar {
|
||
height: 52px; display: flex; align-items: center; padding: 0 16px;
|
||
background: rgba(242,242,247,0.85); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
|
||
border-bottom: 0.5px solid var(--border); flex-shrink: 0; z-index: 40;
|
||
}
|
||
.nav-bar .back { font-size: 20px; color: var(--primary); cursor: pointer; padding: 4px; }
|
||
.nav-bar .title { flex: 1; text-align: center; font-size: 17px; font-weight: 600; color: var(--text); }
|
||
.nav-bar .action { font-size: 20px; color: var(--primary); cursor: pointer; padding: 4px; }
|
||
.chat-area { flex: 1; overflow-y: auto; padding: 8px 14px; -webkit-overflow-scrolling: touch; }
|
||
.chat-area::-webkit-scrollbar { display: none; }
|
||
.time-divider { text-align: center; padding: 12px 0 8px; font-size: 12px; color: var(--text-hint); }
|
||
.time-divider span { background: rgba(120,120,128,0.08); padding: 3px 10px; border-radius: 10px; font-size: 11px; }
|
||
.msg-row { display: flex; margin-bottom: 2px; gap: 8px; }
|
||
.msg-row.right { justify-content: flex-end; }
|
||
.msg-row.left { justify-content: flex-start; }
|
||
.msg-avatar {
|
||
width: 36px; height: 36px; border-radius: 10px; flex-shrink: 0;
|
||
display: flex; align-items: center; justify-content: center; font-size: 18px;
|
||
}
|
||
.msg-avatar.ai { background: linear-gradient(135deg, #6C63FF, #4ECDC4); }
|
||
.msg-avatar.user { background: rgba(108,99,255,0.12); }
|
||
.msg-avatar.imported { background: rgba(255,149,0,0.12); }
|
||
.msg-time-top { font-size: 11px; color: var(--text-hint); margin-bottom: 3px; padding: 0 4px; }
|
||
.msg-row.right .msg-time-top { text-align: right; }
|
||
.msg-row.left .msg-time-top { text-align: left; }
|
||
.msg-bubble { max-width: 72%; padding: 10px 14px; font-size: 15px; line-height: 1.55; word-break: break-word; position: relative; }
|
||
.msg-bubble.user-bubble {
|
||
background: linear-gradient(135deg, var(--primary), var(--primary-light));
|
||
color: #fff; border-radius: 18px 18px 4px 18px;
|
||
}
|
||
.msg-bubble.ai-bubble {
|
||
background: var(--bg-card); color: var(--text); border-radius: 18px 18px 18px 4px; box-shadow: var(--shadow-sm);
|
||
}
|
||
.msg-category-tag { display: inline-block; font-size: 10px; padding: 1px 6px; border-radius: 6px; margin-top: 4px; }
|
||
.msg-category-tag.love { background: rgba(240,147,251,0.15); color: #f093fb; }
|
||
.msg-category-tag.nature { background: rgba(67,233,123,0.15); color: #2bc766; }
|
||
.msg-category-tag.motivate { background: rgba(255,107,107,0.15); color: #FF6B6B; }
|
||
.msg-category-tag.hot { background: rgba(108,99,255,0.15); color: #6C63FF; }
|
||
.msg-category-tag.literature { background: rgba(102,126,234,0.15); color: #667eea; }
|
||
.msg-category-tag.movie { background: rgba(250,112,154,0.15); color: #fa709a; }
|
||
.msg-meta-outer {
|
||
font-size: 10px; color: var(--text-hint); line-height: 1.6; padding: 2px 4px 4px;
|
||
margin-bottom: 8px;
|
||
}
|
||
.msg-row.right .msg-meta-outer { text-align: right; }
|
||
.msg-row.left .msg-meta-outer { text-align: left; }
|
||
.msg-meta-outer .meta-item { display: inline-flex; align-items: center; gap: 2px; margin-right: 6px; }
|
||
.msg-meta-outer .meta-link { color: var(--primary); cursor: pointer; text-decoration: underline; }
|
||
.msg-meta-outer .meta-reserved { color: var(--text-hint); opacity: 0.5; font-style: italic; }
|
||
.msg-meta-outer .meta-read { color: #34C759; font-weight: 600; }
|
||
.category-bar {
|
||
display: flex; gap: 6px; padding: 6px 14px; overflow-x: auto;
|
||
flex-shrink: 0; -webkit-overflow-scrolling: touch; align-items: center;
|
||
}
|
||
.category-bar::-webkit-scrollbar { display: none; }
|
||
.cat-chip {
|
||
white-space: nowrap; padding: 6px 14px; border-radius: 20px; font-size: 13px;
|
||
background: var(--bg-card); color: var(--text-secondary); cursor: pointer;
|
||
border: 1px solid transparent; transition: all 0.2s; flex-shrink: 0;
|
||
}
|
||
.cat-chip.active { background: rgba(108,99,255,0.12); color: var(--primary); border-color: rgba(108,99,255,0.25); font-weight: 600; }
|
||
.cat-expand-btn {
|
||
white-space: nowrap; padding: 6px 12px; border-radius: 20px; font-size: 13px;
|
||
background: var(--bg-card); color: var(--text-secondary); cursor: pointer;
|
||
border: 1px solid var(--border); transition: all 0.2s; flex-shrink: 0;
|
||
display: flex; align-items: center; gap: 2px; font-weight: 500;
|
||
}
|
||
.cat-expand-btn.expanded { background: rgba(108,99,255,0.08); color: var(--primary); border-color: rgba(108,99,255,0.2); }
|
||
.cat-hidden { display: none; }
|
||
.cat-hidden.show { display: inline-block; }
|
||
.input-area { flex-shrink: 0; background: var(--bg-card); border-top: 0.5px solid var(--border); padding: 8px 12px 6px; }
|
||
.input-row { display: flex; align-items: flex-end; gap: 8px; }
|
||
.input-box {
|
||
flex: 1; background: var(--bg-secondary); border-radius: 20px; padding: 8px 14px;
|
||
font-size: 15px; color: var(--text); outline: none; border: none; resize: none;
|
||
min-height: 36px; max-height: 100px; line-height: 1.4; font-family: var(--font-family);
|
||
}
|
||
.input-box::placeholder { color: var(--text-hint); }
|
||
.send-btn {
|
||
width: 36px; height: 36px; border-radius: 50%; border: none;
|
||
display: flex; align-items: center; justify-content: center;
|
||
cursor: pointer; transition: all 0.2s; flex-shrink: 0;
|
||
}
|
||
.send-btn.empty { background: var(--bg-secondary); color: var(--text-hint); }
|
||
.send-btn.has-content { background: linear-gradient(135deg, var(--primary), var(--primary-light)); color: #fff; box-shadow: 0 2px 8px rgba(108,99,255,0.35); }
|
||
.bottom-actions { display: flex; gap: 4px; padding: 6px 4px 2px; justify-content: space-around; }
|
||
.bottom-action {
|
||
display: flex; flex-direction: column; align-items: center; gap: 2px;
|
||
cursor: pointer; padding: 4px 8px; border-radius: 10px; transition: all 0.2s;
|
||
border: none; background: transparent; font-family: var(--font-family);
|
||
}
|
||
.bottom-action:hover { background: rgba(108,99,255,0.06); }
|
||
.bottom-action .icon { font-size: 20px; }
|
||
.bottom-action .label { font-size: 10px; color: var(--text-secondary); }
|
||
.bottom-action.active .label { color: var(--primary); font-weight: 600; }
|
||
.draft-bar {
|
||
display: flex; align-items: center; gap: 6px; padding: 4px 12px;
|
||
background: rgba(108,99,255,0.06); border-radius: 8px; margin: 0 12px 4px;
|
||
}
|
||
.draft-bar .draft-icon { font-size: 14px; }
|
||
.draft-bar .draft-text { flex: 1; font-size: 12px; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.draft-bar .draft-close { font-size: 14px; color: var(--text-hint); cursor: pointer; }
|
||
.safe-area-bottom { height: var(--safe-bottom); background: var(--bg-card); flex-shrink: 0; }
|
||
.session-list { flex: 1; overflow-y: auto; padding: 0 0 100px; }
|
||
.session-list::-webkit-scrollbar { display: none; }
|
||
.session-item {
|
||
display: flex; align-items: center; padding: 12px 16px; gap: 12px;
|
||
cursor: pointer; transition: background 0.15s;
|
||
}
|
||
.session-item:hover { background: rgba(120,120,128,0.04); }
|
||
.session-item:active { background: rgba(120,120,128,0.08); }
|
||
.session-avatar {
|
||
width: 50px; height: 50px; border-radius: 12px;
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 24px; flex-shrink: 0; position: relative;
|
||
}
|
||
.session-avatar .badge {
|
||
position: absolute; right: -4px; top: -4px; min-width: 18px; height: 18px;
|
||
background: #FF3B30; color: #fff; font-size: 11px; font-weight: 700;
|
||
border-radius: 9px; display: flex; align-items: center; justify-content: center; padding: 0 4px;
|
||
}
|
||
.session-info { flex: 1; min-width: 0; }
|
||
.session-name { font-size: 16px; font-weight: 600; color: var(--text); display: flex; align-items: center; gap: 4px; }
|
||
.session-name .pin-icon { font-size: 11px; color: var(--primary); }
|
||
.session-name .tag { font-size: 10px; padding: 1px 5px; border-radius: 4px; background: rgba(255,59,48,0.1); color: #FF3B30; font-weight: 700; }
|
||
.session-desc { font-size: 13px; color: var(--text-hint); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.session-right { text-align: right; flex-shrink: 0; }
|
||
.session-time { font-size: 12px; color: var(--text-hint); }
|
||
.session-arrow { font-size: 12px; color: rgba(174,174,178,0.4); margin-top: 4px; }
|
||
.draft-tag {
|
||
display: inline-flex; align-items: center; gap: 3px; font-size: 10px;
|
||
padding: 1px 6px; border-radius: 4px; background: rgba(108,99,255,0.1);
|
||
color: var(--primary); margin-top: 3px;
|
||
}
|
||
.search-bar {
|
||
margin: 0 16px 8px; padding: 8px 12px; background: var(--bg-secondary);
|
||
border-radius: 10px; display: flex; align-items: center; gap: 6px;
|
||
}
|
||
.search-bar .search-icon { font-size: 14px; color: var(--text-hint); }
|
||
.search-bar .search-text { font-size: 15px; color: var(--text-hint); }
|
||
.section-header {
|
||
padding: 12px 16px 4px; font-size: 13px; font-weight: 600;
|
||
color: var(--text-secondary); display: flex; align-items: center; gap: 4px;
|
||
}
|
||
.section-header .count { font-size: 12px; color: var(--text-hint); font-weight: 400; }
|
||
.settings-scroll { flex: 1; overflow-y: auto; }
|
||
.settings-scroll::-webkit-scrollbar { display: none; }
|
||
.settings-section { margin: 16px 16px 0; background: var(--bg-card); border-radius: var(--radius-lg); overflow: hidden; }
|
||
.settings-section-title { padding: 16px 16px 6px; font-size: 13px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; }
|
||
.settings-item {
|
||
display: flex; align-items: center; padding: 12px 16px; gap: 12px;
|
||
cursor: pointer; transition: background 0.15s; border-bottom: 0.5px solid var(--border);
|
||
}
|
||
.settings-item:last-child { border-bottom: none; }
|
||
.settings-item:hover { background: rgba(120,120,128,0.04); }
|
||
.settings-item .item-icon { font-size: 20px; width: 30px; text-align: center; }
|
||
.settings-item .item-label { flex: 1; font-size: 15px; color: var(--text); }
|
||
.settings-item .item-value { font-size: 14px; color: var(--text-hint); }
|
||
.settings-item .item-arrow { font-size: 13px; color: rgba(174,174,178,0.5); }
|
||
.toggle-switch {
|
||
width: 51px; height: 31px; border-radius: 16px; background: var(--bg-secondary);
|
||
position: relative; cursor: pointer; transition: background 0.25s;
|
||
}
|
||
.toggle-switch.on { background: #34C759; }
|
||
.toggle-switch .knob {
|
||
width: 27px; height: 27px; border-radius: 50%; background: #fff;
|
||
position: absolute; top: 2px; left: 2px; transition: transform 0.25s;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.15);
|
||
}
|
||
.toggle-switch.on .knob { transform: translateX(20px); }
|
||
.ip-modal {
|
||
display: none; position: absolute; top: 0; left: 0; right: 0; bottom: 0;
|
||
background: rgba(0,0,0,0.4); z-index: 200; align-items: center; justify-content: center;
|
||
}
|
||
.ip-modal.show { display: flex; }
|
||
.ip-card { width: 320px; background: var(--bg-card); border-radius: var(--radius-xl); padding: 20px; box-shadow: var(--shadow-lg); }
|
||
.ip-card h3 { font-size: 17px; font-weight: 600; color: var(--text); margin-bottom: 12px; }
|
||
.ip-row { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 0.5px solid var(--border); font-size: 14px; }
|
||
.ip-row:last-child { border-bottom: none; }
|
||
.ip-row .ip-label { color: var(--text-secondary); }
|
||
.ip-row .ip-value { color: var(--text); font-weight: 500; }
|
||
.ip-close {
|
||
margin-top: 16px; width: 100%; padding: 10px; border-radius: 12px;
|
||
background: var(--bg-secondary); border: none; font-size: 16px;
|
||
color: var(--primary); font-weight: 600; cursor: pointer; font-family: var(--font-family);
|
||
}
|
||
.edit-modal {
|
||
display: none; position: absolute; top: 0; left: 0; right: 0; bottom: 0;
|
||
background: rgba(0,0,0,0.4); z-index: 200; align-items: flex-end; justify-content: center;
|
||
}
|
||
.edit-modal.show { display: flex; }
|
||
.edit-sheet {
|
||
width: 100%; background: var(--bg-card); border-radius: 16px 16px 0 0;
|
||
padding: 16px 16px calc(16px + var(--safe-bottom));
|
||
}
|
||
.edit-sheet .handle { width: 36px; height: 4px; background: var(--text-hint); border-radius: 2px; margin: 0 auto 16px; opacity: 0.3; }
|
||
.edit-sheet h3 { font-size: 17px; font-weight: 600; color: var(--text); margin-bottom: 12px; }
|
||
.edit-textarea {
|
||
width: 100%; min-height: 80px; padding: 12px; border-radius: 12px;
|
||
background: var(--bg-secondary); border: none; font-size: 15px;
|
||
color: var(--text); resize: none; outline: none; font-family: var(--font-family);
|
||
}
|
||
.edit-actions { display: flex; gap: 10px; margin-top: 12px; }
|
||
.edit-actions button { flex: 1; padding: 12px; border-radius: 12px; font-size: 16px; font-weight: 600; cursor: pointer; border: none; font-family: var(--font-family); }
|
||
.edit-actions .cancel-btn { background: var(--bg-secondary); color: var(--primary); }
|
||
.edit-actions .save-btn { background: var(--primary); color: #fff; }
|
||
.emoji-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-bottom: 14px; }
|
||
.emoji-option {
|
||
width: 44px; height: 44px; border-radius: 10px; background: var(--bg-secondary);
|
||
display: flex; align-items: center; justify-content: center; font-size: 22px;
|
||
cursor: pointer; border: 2px solid transparent; transition: all 0.15s;
|
||
}
|
||
.emoji-option:hover { background: rgba(108,99,255,0.1); }
|
||
.emoji-option.selected { border-color: var(--primary); background: rgba(108,99,255,0.1); }
|
||
.add-input {
|
||
width: 100%; padding: 10px 14px; border-radius: 10px; background: var(--bg-secondary);
|
||
border: none; font-size: 15px; color: var(--text); outline: none; margin-bottom: 10px; font-family: var(--font-family);
|
||
}
|
||
.add-input::placeholder { color: var(--text-hint); }
|
||
.add-actions { display: flex; gap: 10px; }
|
||
.add-actions button { flex: 1; padding: 12px; border-radius: 12px; font-size: 16px; font-weight: 600; cursor: pointer; border: none; font-family: var(--font-family); }
|
||
.add-actions .cancel-btn { background: var(--bg-secondary); color: var(--primary); }
|
||
.add-actions .confirm-btn { background: var(--primary); color: #fff; }
|
||
.bg-preview {
|
||
width: 100%; height: 120px; border-radius: 12px;
|
||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||
display: flex; align-items: center; justify-content: center;
|
||
color: rgba(255,255,255,0.7); font-size: 14px; margin-bottom: 10px;
|
||
position: relative; overflow: hidden;
|
||
}
|
||
.bg-preview::after {
|
||
content: '点击更换背景图'; position: absolute; bottom: 8px; right: 10px;
|
||
font-size: 11px; background: rgba(0,0,0,0.3); padding: 2px 8px;
|
||
border-radius: 6px; color: #fff;
|
||
}
|
||
.category-manage { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 0; }
|
||
.category-manage .cat-item {
|
||
display: flex; align-items: center; gap: 4px; padding: 6px 10px;
|
||
border-radius: 16px; background: var(--bg-secondary); font-size: 13px; color: var(--text);
|
||
cursor: pointer; transition: background 0.15s;
|
||
}
|
||
.category-manage .cat-item:hover { background: rgba(108,99,255,0.08); }
|
||
.category-manage .cat-item .cat-edit { font-size: 11px; color: var(--primary); cursor: pointer; margin-left: 2px; }
|
||
.category-manage .cat-item .cat-remove { font-size: 12px; color: var(--text-hint); cursor: pointer; }
|
||
.category-manage .cat-add {
|
||
padding: 6px 10px; border-radius: 16px; background: rgba(108,99,255,0.08);
|
||
color: var(--primary); font-size: 13px; cursor: pointer; border: 1px dashed rgba(108,99,255,0.3);
|
||
}
|
||
.cat-edit-input {
|
||
width: 60px; padding: 2px 6px; border-radius: 6px; border: 1px solid var(--primary);
|
||
background: var(--bg-card); font-size: 12px; color: var(--text); outline: none;
|
||
font-family: var(--font-family);
|
||
}
|
||
.context-menu {
|
||
display: none; position: absolute; background: var(--bg-card); border-radius: 14px;
|
||
box-shadow: 0 8px 30px rgba(0,0,0,0.2); padding: 4px 0; z-index: 150; min-width: 180px;
|
||
}
|
||
.context-menu.show { display: block; }
|
||
.context-menu-item {
|
||
padding: 10px 16px; font-size: 15px; color: var(--text); cursor: pointer;
|
||
display: flex; align-items: center; gap: 8px;
|
||
}
|
||
.context-menu-item:hover { background: rgba(120,120,128,0.08); }
|
||
.context-menu-item.danger { color: #FF3B30; }
|
||
.context-menu-divider { height: 0.5px; background: var(--border); margin: 4px 0; }
|
||
.theme-toggle {
|
||
position: fixed; bottom: 20px; right: 20px; width: 48px; height: 48px;
|
||
border-radius: 50%; background: var(--primary); color: #fff; border: none;
|
||
font-size: 22px; cursor: pointer; box-shadow: 0 4px 12px rgba(108,99,255,0.4);
|
||
z-index: 999; display: flex; align-items: center; justify-content: center;
|
||
}
|
||
.design-notes {
|
||
width: 390px; background: rgba(255,255,255,0.04); border-radius: 16px;
|
||
padding: 20px; color: rgba(255,255,255,0.8); font-size: 13px; line-height: 1.7;
|
||
max-height: 844px; overflow-y: auto;
|
||
}
|
||
.design-notes::-webkit-scrollbar { width: 4px; }
|
||
.design-notes::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 2px; }
|
||
.design-notes h2 { font-size: 18px; color: #fff; margin-bottom: 12px; }
|
||
.design-notes h3 { font-size: 15px; color: #8B83FF; margin: 16px 0 8px; }
|
||
.design-notes ul { padding-left: 16px; }
|
||
.design-notes li { margin-bottom: 4px; }
|
||
.design-notes .highlight { color: #8B83FF; font-weight: 600; }
|
||
.design-notes .tag {
|
||
display: inline-block; padding: 1px 6px; border-radius: 4px;
|
||
background: rgba(108,99,255,0.2); color: #8B83FF; font-size: 11px; margin: 0 2px;
|
||
}
|
||
body.dark-mode { --bg: #000000; --bg-card: #1C1C1E; --bg-secondary: #2C2C2E; --bg-elevated: #2C2C2E; --text: #FFFFFF; --text-secondary: #98989D; --text-hint: #636366; --border: rgba(84,84,88,0.34); }
|
||
body.dark-mode .phone-frame { background: #000; }
|
||
body.dark-mode .nav-bar { background: rgba(0,0,0,0.85); }
|
||
body.dark-mode .msg-bubble.ai-bubble { background: #1C1C1E; }
|
||
body.dark-mode .msg-avatar.user { background: rgba(108,99,255,0.2); }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="page-header">
|
||
<h1>💬 聊天会话流 · 设计方案 v2</h1>
|
||
<p>闲言APP v4.21.0 · 2026-05-08 · 参考QQ对话框 · 支持动态主题</p>
|
||
</div>
|
||
|
||
<div class="tab-bar">
|
||
<button class="tab-btn active" onclick="switchView('chat')">💬 聊天页面</button>
|
||
<button class="tab-btn" onclick="switchView('inspiration')">✨ 灵感页面</button>
|
||
<button class="tab-btn" onclick="switchView('settings')">⚙️ 聊天设置</button>
|
||
<button class="tab-btn" onclick="switchView('add-session')">➕ 新增会话</button>
|
||
</div>
|
||
|
||
<!-- ============ 聊天页面 ============ -->
|
||
<div class="phone-frame active" id="view-chat">
|
||
<div class="phone-notch"></div>
|
||
<div class="phone-status-bar"><span>9:41</span><span>●●● ●● ◗</span></div>
|
||
<div class="nav-bar">
|
||
<span class="back" onclick="switchView('inspiration')">‹</span>
|
||
<span class="title">💬 会话流</span>
|
||
<span class="action" onclick="switchView('settings')">⚙️</span>
|
||
</div>
|
||
<div class="category-bar" id="categoryBar">
|
||
<span class="cat-expand-btn" id="catExpandBtn" onclick="toggleCategoryExpand()">📋 全部 ▸</span>
|
||
<span class="cat-chip active cat-hidden" onclick="selectCat(this)">🔥 热门</span>
|
||
<span class="cat-chip cat-hidden" onclick="selectCat(this)">爱情</span>
|
||
<span class="cat-chip cat-hidden" onclick="selectCat(this)">🌿 自然</span>
|
||
<span class="cat-chip cat-hidden" onclick="selectCat(this)">💪 励志</span>
|
||
<span class="cat-chip cat-hidden" onclick="selectCat(this)">📖 文学</span>
|
||
<span class="cat-chip cat-hidden" onclick="selectCat(this)">🎬 影视</span>
|
||
</div>
|
||
<div class="chat-area" id="chatArea">
|
||
<div class="time-divider"><span>今天 上午 9:30</span></div>
|
||
|
||
<div class="msg-row right" oncontextmenu="showContextMenu(event, this)">
|
||
<div>
|
||
<div class="msg-time-top">上午 9:30</div>
|
||
<div class="msg-bubble user-bubble">推荐一句励志的句子</div>
|
||
<div class="msg-meta-outer">
|
||
<span class="meta-item">📱 iPhone 17 Pro</span>
|
||
<span class="meta-item">📍 <span class="meta-link" onclick="showIpModal(event)">上海</span></span>
|
||
<span class="meta-item">🏷️ 励志</span>
|
||
<span class="meta-item">💾 本地</span>
|
||
<span class="meta-item">🕐 09:30</span>
|
||
<span class="meta-item meta-reserved">[ext_1] [ext_2]</span>
|
||
</div>
|
||
</div>
|
||
<div class="msg-avatar user">😊</div>
|
||
</div>
|
||
|
||
<div class="msg-row left" oncontextmenu="showContextMenu(event, this)">
|
||
<div class="msg-avatar ai">💪</div>
|
||
<div>
|
||
<div class="msg-time-top">上午 10:15</div>
|
||
<div class="msg-bubble ai-bubble" style="background:linear-gradient(135deg,#FF6B6B,#FFB74D);color:#fff;">
|
||
不管前方的路有多苦,只要走的方向正确,都比站在原地更接近幸福。
|
||
<div style="margin-top:6px;font-size:13px;color:rgba(255,255,255,0.75);">—— 宫崎骏</div>
|
||
<span class="msg-category-tag motivate">💪 励志</span>
|
||
</div>
|
||
<div class="msg-meta-outer">
|
||
<span class="meta-item">📱 Server</span>
|
||
<span class="meta-item">📍 <span class="meta-link" onclick="showIpModal(event)">深圳</span></span>
|
||
<span class="meta-item">🏷️ 励志</span>
|
||
<span class="meta-item">☁️ 云端</span>
|
||
<span class="meta-item">🕐 10:15</span>
|
||
<span class="meta-item meta-read">👁 已阅 3</span>
|
||
<span class="meta-item meta-reserved">[ext_1]</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="time-divider"><span>下午 2:30</span></div>
|
||
|
||
<div class="msg-row right" oncontextmenu="showContextMenu(event, this)">
|
||
<div>
|
||
<div class="msg-time-top">下午 2:30</div>
|
||
<div class="msg-bubble user-bubble">今天天气真好,来一句关于自然的</div>
|
||
<div class="msg-meta-outer">
|
||
<span class="meta-item">📱 iPhone 17 Pro</span>
|
||
<span class="meta-item">📍 <span class="meta-link" onclick="showIpModal(event)">上海</span></span>
|
||
<span class="meta-item">🏷️ 自然</span>
|
||
<span class="meta-item">💾 本地</span>
|
||
<span class="meta-item">🕐 14:30</span>
|
||
<span class="meta-item meta-reserved">[ext_1] [ext_2]</span>
|
||
</div>
|
||
</div>
|
||
<div class="msg-avatar user">😊</div>
|
||
</div>
|
||
|
||
<div class="msg-row left" oncontextmenu="showContextMenu(event, this)">
|
||
<div class="msg-avatar ai">🌿</div>
|
||
<div>
|
||
<div class="msg-time-top">下午 2:30</div>
|
||
<div class="msg-bubble ai-bubble" style="background:linear-gradient(135deg,#43e97b,#38f9d7);color:#fff;">
|
||
采菊东篱下,悠然见南山。
|
||
<div style="margin-top:6px;font-size:13px;color:rgba(255,255,255,0.75);">—— 陶渊明</div>
|
||
<span class="msg-category-tag nature">🌿 自然</span>
|
||
</div>
|
||
<div class="msg-meta-outer">
|
||
<span class="meta-item">📱 Server</span>
|
||
<span class="meta-item">📍 <span class="meta-link" onclick="showIpModal(event)">深圳</span></span>
|
||
<span class="meta-item">🏷️ 自然</span>
|
||
<span class="meta-item">☁️ 云端</span>
|
||
<span class="meta-item">🕐 14:30</span>
|
||
<span class="meta-item meta-read">👁 已阅 1</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="time-divider"><span>下午 5:42</span></div>
|
||
|
||
<div class="msg-row left" oncontextmenu="showContextMenu(event, this)">
|
||
<div class="msg-avatar imported">📱</div>
|
||
<div>
|
||
<div class="msg-time-top">下午 5:42 · 来自iPad</div>
|
||
<div class="msg-bubble ai-bubble">
|
||
人生如逆旅,我亦是行人。
|
||
<div style="margin-top:6px;font-size:13px;color:var(--text-secondary);">—— 苏轼《临江仙》</div>
|
||
<span class="msg-category-tag literature">📖 文学</span>
|
||
</div>
|
||
<div class="msg-meta-outer">
|
||
<span class="meta-item">📱 iPad Pro</span>
|
||
<span class="meta-item">📍 <span class="meta-link" onclick="showIpModal(event)">广州</span></span>
|
||
<span class="meta-item">🏷️ 文学</span>
|
||
<span class="meta-item">📥 导入</span>
|
||
<span class="meta-item">🕐 17:42</span>
|
||
<span class="meta-item meta-read">👁 已阅 5</span>
|
||
<span class="meta-item meta-reserved">[ext_1] [ext_2] [ext_3]</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="msg-row right" oncontextmenu="showContextMenu(event, this)">
|
||
<div>
|
||
<div class="msg-time-top">下午 6:10</div>
|
||
<div class="msg-bubble user-bubble">收藏了!这句太美了 ✨</div>
|
||
<div class="msg-meta-outer">
|
||
<span class="meta-item">📱 iPhone 17 Pro</span>
|
||
<span class="meta-item">📍 <span class="meta-link" onclick="showIpModal(event)">上海</span></span>
|
||
<span class="meta-item">🏷️ 文学</span>
|
||
<span class="meta-item">💾 本地</span>
|
||
<span class="meta-item">🕐 18:10</span>
|
||
<span class="meta-item meta-reserved">[ext_1]</span>
|
||
</div>
|
||
</div>
|
||
<div class="msg-avatar user">😊</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="draft-bar" id="draftBar" style="display:none;">
|
||
<span class="draft-icon">📝</span>
|
||
<span class="draft-text" id="draftText"></span>
|
||
<span class="draft-close" onclick="clearDraft()">✕</span>
|
||
</div>
|
||
<div class="input-area">
|
||
<div class="input-row">
|
||
<textarea class="input-box" id="inputBox" placeholder="说点什么..." rows="1" oninput="onInputChange()" onkeydown="onInputKeydown(event)"></textarea>
|
||
<button class="send-btn empty" id="sendBtn" onclick="sendMessage()">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg>
|
||
</button>
|
||
</div>
|
||
<div class="bottom-actions">
|
||
<button class="bottom-action" onclick="selectBottomCat(this, '🔥')"><span class="icon">🔥</span><span class="label">热门</span></button>
|
||
<button class="bottom-action" onclick="selectBottomCat(this, '💕')"><span class="icon">💕</span><span class="label">爱情</span></button>
|
||
<button class="bottom-action" onclick="selectBottomCat(this, '🌿')"><span class="icon">🌿</span><span class="label">自然</span></button>
|
||
<button class="bottom-action" onclick="selectBottomCat(this, '💪')"><span class="icon">💪</span><span class="label">励志</span></button>
|
||
<button class="bottom-action" onclick="selectBottomCat(this, '📖')"><span class="icon">📖</span><span class="label">文学</span></button>
|
||
<button class="bottom-action" onclick="selectBottomCat(this, '🎬')"><span class="icon">🎬</span><span class="label">影视</span></button>
|
||
</div>
|
||
</div>
|
||
<div class="safe-area-bottom"></div>
|
||
|
||
<div class="ip-modal" id="ipModal" onclick="hideIpModal(event)">
|
||
<div class="ip-card" onclick="event.stopPropagation()">
|
||
<h3>🌐 IP地址查询</h3>
|
||
<div class="ip-row"><span class="ip-label">IP地址</span><span class="ip-value">223.104.xx.xx</span></div>
|
||
<div class="ip-row"><span class="ip-label">归属地</span><span class="ip-value">上海市</span></div>
|
||
<div class="ip-row"><span class="ip-label">运营商</span><span class="ip-value">中国移动</span></div>
|
||
<div class="ip-row"><span class="ip-label">经纬度</span><span class="ip-value">31.23, 121.47</span></div>
|
||
<div class="ip-row"><span class="ip-label">查询时间</span><span class="ip-value">2026-05-08 18:10</span></div>
|
||
<div class="ip-row"><span class="ip-label">缓存状态</span><span class="ip-value" style="color:#34C759;">✓ 已缓存本地</span></div>
|
||
<button class="ip-close" onclick="hideIpModal(event)">关闭</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="edit-modal" id="editModal" onclick="hideEditModal(event)">
|
||
<div class="edit-sheet" onclick="event.stopPropagation()">
|
||
<div class="handle"></div>
|
||
<h3>✏️ 编辑消息</h3>
|
||
<textarea class="edit-textarea" id="editTextarea">推荐一句励志的句子</textarea>
|
||
<div class="edit-actions">
|
||
<button class="cancel-btn" onclick="hideEditModal(event)">取消</button>
|
||
<button class="save-btn" onclick="saveEdit()">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="context-menu" id="contextMenu">
|
||
<div class="context-menu-item" onclick="editMessage()">✏️ 编辑</div>
|
||
<div class="context-menu-item" onclick="copyMessage()">📋 复制</div>
|
||
<div class="context-menu-item" onclick="forwardMessage()">↗️ 转发</div>
|
||
<div class="context-menu-item" onclick="markAsRead()">👁 已阅 <span id="readCount" style="color:#34C759;font-weight:600;margin-left:4px;">0</span></div>
|
||
<div class="context-menu-divider"></div>
|
||
<div class="context-menu-item danger" onclick="deleteMessage()">🗑️ 删除</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============ 灵感页面 ============ -->
|
||
<div class="phone-frame" id="view-inspiration">
|
||
<div class="phone-notch"></div>
|
||
<div class="phone-status-bar"><span>9:41</span><span>●●● ●● ◗</span></div>
|
||
<div style="padding:12px 16px 0;display:flex;align-items:center;">
|
||
<span style="font-size:28px;font-weight:700;color:var(--text);">✨ 灵感</span>
|
||
<span style="flex:1;"></span>
|
||
<span style="width:36px;height:36px;border-radius:10px;background:var(--bg-secondary);display:flex;align-items:center;justify-content:center;font-size:16px;">🔧</span>
|
||
</div>
|
||
<div class="search-bar"><span class="search-icon">🔍</span><span class="search-text">搜索会话</span></div>
|
||
<div class="session-list">
|
||
<div class="section-header">📌 置顶 <span class="count">1</span></div>
|
||
<div class="session-item" onclick="switchView('chat')">
|
||
<div class="session-avatar" style="background:rgba(108,99,255,0.12);">💬<div class="badge">3</div></div>
|
||
<div class="session-info">
|
||
<div class="session-name">会话流 <span class="pin-icon">📌</span></div>
|
||
<div class="session-desc">收藏了!这句太美了 ✨</div>
|
||
<div class="draft-tag">📝 草稿: 今天心情不太好,想看一些...</div>
|
||
</div>
|
||
<div class="session-right"><div class="session-time" style="color:var(--primary);font-weight:600;">18:10</div><div class="session-arrow">›</div></div>
|
||
</div>
|
||
<div style="margin:4px 16px;height:0.5px;background:var(--border);"></div>
|
||
<div class="section-header">💬 对话 <span class="count">5</span></div>
|
||
<div class="session-item">
|
||
<div class="session-avatar" style="background:rgba(255,149,0,0.12);">🔍</div>
|
||
<div class="session-info"><div class="session-name">发现 <span class="tag">HOT</span></div><div class="session-desc">热门句子 · 分类浏览 · 每日推荐</div></div>
|
||
<div class="session-right"><div class="session-time">昨天</div><div class="session-arrow">›</div></div>
|
||
</div>
|
||
<div class="session-item">
|
||
<div class="session-avatar" style="background:rgba(52,199,89,0.12);">👣</div>
|
||
<div class="session-info"><div class="session-name">足迹</div><div class="session-desc">浏览 · 点赞 · 收藏 · 稍后读 · 笔记</div></div>
|
||
<div class="session-right"><div class="session-time">3天前</div><div class="session-arrow">›</div></div>
|
||
</div>
|
||
<div class="session-item">
|
||
<div class="session-avatar" style="background:rgba(255,59,48,0.12);">💕</div>
|
||
<div class="session-info"><div class="session-name">爱情语录</div><div class="session-desc">山有木兮木有枝,心悦君兮君不知</div><div class="draft-tag">📝 草稿: 求一句浪漫的...</div></div>
|
||
<div class="session-right"><div class="session-time">2小时前</div><div class="session-arrow">›</div></div>
|
||
</div>
|
||
<div class="session-item">
|
||
<div class="session-avatar" style="background:rgba(102,126,234,0.12);">📖</div>
|
||
<div class="session-info"><div class="session-name">读书笔记</div><div class="session-desc">今天读了《人间失格》第3章...</div></div>
|
||
<div class="session-right"><div class="session-time">5小时前</div><div class="session-arrow">›</div></div>
|
||
</div>
|
||
<div class="session-item">
|
||
<div class="session-avatar" style="background:rgba(250,112,154,0.12);">🎬</div>
|
||
<div class="session-info"><div class="session-name">影视台词</div><div class="session-desc">希望是件美好的事 —— 肖申克的救赎</div></div>
|
||
<div class="session-right"><div class="session-time">昨天</div><div class="session-arrow">›</div></div>
|
||
</div>
|
||
<div style="text-align:center;padding:20px;font-size:12px;color:var(--text-hint);">⬆️ 下拉打开工具中心</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============ 聊天设置页面 ============ -->
|
||
<div class="phone-frame" id="view-settings">
|
||
<div class="phone-notch"></div>
|
||
<div class="phone-status-bar"><span>9:41</span><span>●●● ●● ◗</span></div>
|
||
<div class="nav-bar">
|
||
<span class="back" onclick="switchView('chat')">‹</span>
|
||
<span class="title">⚙️ 聊天设置</span>
|
||
<span class="action"></span>
|
||
</div>
|
||
<div class="settings-scroll">
|
||
<div class="settings-section">
|
||
<div class="settings-item">
|
||
<div class="item-icon">💬</div>
|
||
<div class="item-label"><div style="font-weight:600;">会话流</div><div style="font-size:12px;color:var(--text-hint);margin-top:2px;">当前对话 · 7条消息</div></div>
|
||
<span class="item-arrow">›</span>
|
||
</div>
|
||
</div>
|
||
<div class="settings-section">
|
||
<div class="settings-section-title">🎨 外观</div>
|
||
<div class="settings-item" style="flex-direction:column;align-items:stretch;">
|
||
<div style="font-size:15px;color:var(--text);margin-bottom:8px;">聊天背景</div>
|
||
<div class="bg-preview">当前背景预览</div>
|
||
<div style="display:flex;gap:8px;">
|
||
<div style="flex:1;padding:8px;border-radius:10px;background:var(--bg-secondary);text-align:center;font-size:13px;color:var(--text-secondary);cursor:pointer;">📷 相册</div>
|
||
<div style="flex:1;padding:8px;border-radius:10px;background:var(--bg-secondary);text-align:center;font-size:13px;color:var(--text-secondary);cursor:pointer;">🎨 纯色</div>
|
||
<div style="flex:1;padding:8px;border-radius:10px;background:var(--bg-secondary);text-align:center;font-size:13px;color:var(--text-secondary);cursor:pointer;">🖼️ 预设</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="settings-section">
|
||
<div class="settings-section-title">💬 消息</div>
|
||
<div class="settings-item"><div class="item-icon">📝</div><div class="item-label">消息备注</div><span class="item-value">已开启</span><span class="item-arrow">›</span></div>
|
||
<div class="settings-item"><div class="item-icon">📍</div><div class="item-label">显示地址信息</div><div class="toggle-switch on" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
<div class="settings-item"><div class="item-icon">📱</div><div class="item-label">显示设备型号</div><div class="toggle-switch on" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
<div class="settings-item"><div class="item-icon">🏷️</div><div class="item-label">显示分类标签</div><div class="toggle-switch on" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
<div class="settings-item"><div class="item-icon">🕐</div><div class="item-label">显示时间戳</div><div class="toggle-switch on" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
<div class="settings-item"><div class="item-icon">☁️</div><div class="item-label">显示本地/云端</div><div class="toggle-switch" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
<div class="settings-item"><div class="item-icon">👁</div><div class="item-label">显示已阅次数</div><div class="toggle-switch on" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
<div class="settings-item"><div class="item-icon">🔧</div><div class="item-label">显示保留扩展字段</div><div class="toggle-switch" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
</div>
|
||
<div class="settings-section">
|
||
<div class="settings-section-title">🏷️ 分类管理</div>
|
||
<div class="settings-item" style="flex-direction:column;align-items:stretch;">
|
||
<div style="font-size:12px;color:var(--text-hint);margin-bottom:8px;">点击 ✎ 编辑分类名称</div>
|
||
<div class="category-manage">
|
||
<span class="cat-item" onclick="editCatName(this)">🔥 <span class="cat-name">热门</span> <span class="cat-edit">✎</span> <span class="cat-remove">✕</span></span>
|
||
<span class="cat-item" onclick="editCatName(this)"><span class="cat-name">爱情</span> <span class="cat-edit">✎</span> <span class="cat-remove">✕</span></span>
|
||
<span class="cat-item" onclick="editCatName(this)">🌿 <span class="cat-name">自然</span> <span class="cat-edit">✎</span> <span class="cat-remove">✕</span></span>
|
||
<span class="cat-item" onclick="editCatName(this)">💪 <span class="cat-name">励志</span> <span class="cat-edit">✎</span> <span class="cat-remove">✕</span></span>
|
||
<span class="cat-item" onclick="editCatName(this)">📖 <span class="cat-name">文学</span> <span class="cat-edit">✎</span> <span class="cat-remove">✕</span></span>
|
||
<span class="cat-item" onclick="editCatName(this)">🎬 <span class="cat-name">影视</span> <span class="cat-edit">✎</span> <span class="cat-remove">✕</span></span>
|
||
<span class="cat-add">+ 添加分类</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="settings-section">
|
||
<div class="settings-section-title">💾 数据</div>
|
||
<div class="settings-item"><div class="item-icon">📤</div><div class="item-label">导出聊天记录</div><span class="item-arrow">›</span></div>
|
||
<div class="settings-item"><div class="item-icon">📥</div><div class="item-label">导入聊天记录</div><span class="item-arrow">›</span></div>
|
||
<div class="settings-item"><div class="item-icon">↗️</div><div class="item-label">分享聊天记录</div><span class="item-arrow">›</span></div>
|
||
<div class="settings-item"><div class="item-icon">🔄</div><div class="item-label">同步设置</div><span class="item-value">仅本地</span><span class="item-arrow">›</span></div>
|
||
</div>
|
||
<div class="settings-section">
|
||
<div class="settings-section-title">📋 会话管理</div>
|
||
<div class="settings-item" onclick="switchView('add-session')"><div class="item-icon">➕</div><div class="item-label" style="color:var(--primary);">新增会话流</div><span class="item-arrow">›</span></div>
|
||
<div class="settings-item"><div class="item-icon">📌</div><div class="item-label">置顶当前会话</div><div class="toggle-switch" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
<div class="settings-item"><div class="item-icon">🔕</div><div class="item-label">消息免打扰</div><div class="toggle-switch" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
<div class="settings-item"><div class="item-icon">🗑️</div><div class="item-label" style="color:#FF3B30;">清空聊天记录</div><span class="item-arrow">›</span></div>
|
||
<div class="settings-item"><div class="item-icon">♻️</div><div class="item-label">回收站</div><span class="item-value">2条</span><span class="item-arrow">›</span></div>
|
||
</div>
|
||
<div class="settings-section" style="margin-bottom:20px;">
|
||
<div class="settings-section-title">🔧 扩展字段(保留)</div>
|
||
<div class="settings-item" style="flex-direction:column;align-items:stretch;gap:6px;">
|
||
<div style="font-size:12px;color:var(--text-hint);line-height:1.6;">
|
||
以下字段仅对当前对话框生效,后续扩展到其他对话框:<br>
|
||
• <span style="color:var(--primary);">session_id</span> — 会话唯一标识<br>
|
||
• <span style="color:var(--primary);">bg_image</span> — 背景图路径<br>
|
||
• <span style="color:var(--primary);">show_meta</span> — 元信息显示配置<br>
|
||
• <span style="color:var(--primary);">categories</span> — 自定义分类列表<br>
|
||
• <span style="color:var(--primary);">sync_mode</span> — 同步模式(local/cloud/both)<br>
|
||
• <span style="color:var(--primary);">read_count</span> — 已阅次数<br>
|
||
• <span style="color:var(--primary);">ext_1~ext_5</span> — 消息扩展字段(保留查询)<br>
|
||
• <span style="color:var(--primary);">reserved_1~5</span> — 预留扩展字段
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============ 新增会话页面 ============ -->
|
||
<div class="phone-frame" id="view-add-session">
|
||
<div class="phone-notch"></div>
|
||
<div class="phone-status-bar"><span>9:41</span><span>●●● ●● ◗</span></div>
|
||
<div class="nav-bar">
|
||
<span class="back" onclick="switchView('settings')">‹</span>
|
||
<span class="title">➕ 新增会话流</span>
|
||
<span class="action"></span>
|
||
</div>
|
||
<div class="settings-scroll" style="padding:16px;">
|
||
<div style="background:var(--bg-card);border-radius:var(--radius-lg);padding:16px;margin-bottom:16px;">
|
||
<div style="font-size:15px;font-weight:600;color:var(--text);margin-bottom:12px;">选择图标</div>
|
||
<div class="emoji-grid">
|
||
<div class="emoji-option selected" onclick="selectEmoji(this)">💬</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">💕</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🌿</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">💪</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">📖</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🎬</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🎵</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🎨</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">📝</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🧘</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🌟</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🎯</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">📚</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🏠</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">💡</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🔮</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">☕</div>
|
||
<div class="emoji-option" onclick="selectEmoji(this)">🌈</div>
|
||
</div>
|
||
</div>
|
||
<div style="background:var(--bg-card);border-radius:var(--radius-lg);padding:16px;margin-bottom:16px;">
|
||
<div style="font-size:15px;font-weight:600;color:var(--text);margin-bottom:10px;">会话名称</div>
|
||
<input class="add-input" placeholder="输入会话名称,如:爱情语录">
|
||
</div>
|
||
<div style="background:var(--bg-card);border-radius:var(--radius-lg);padding:16px;margin-bottom:16px;">
|
||
<div style="font-size:15px;font-weight:600;color:var(--text);margin-bottom:10px;">初始分类</div>
|
||
<div class="category-manage">
|
||
<span class="cat-item" onclick="editCatName(this)">🔥 <span class="cat-name">热门</span> <span class="cat-edit">✎</span> <span class="cat-remove">✕</span></span>
|
||
<span class="cat-item" onclick="editCatName(this)"><span class="cat-name">爱情</span> <span class="cat-edit">✎</span> <span class="cat-remove">✕</span></span>
|
||
<span class="cat-add">+ 添加</span>
|
||
</div>
|
||
</div>
|
||
<div style="background:var(--bg-card);border-radius:var(--radius-lg);padding:16px;margin-bottom:16px;">
|
||
<div style="font-size:15px;font-weight:600;color:var(--text);margin-bottom:10px;">会话描述</div>
|
||
<input class="add-input" placeholder="简短描述,如:收集浪漫爱情句子">
|
||
</div>
|
||
<div style="background:var(--bg-card);border-radius:var(--radius-lg);padding:16px;margin-bottom:24px;">
|
||
<div style="font-size:15px;font-weight:600;color:var(--text);margin-bottom:10px;">高级选项</div>
|
||
<div class="settings-item" style="padding:8px 0;"><div class="item-label" style="font-size:14px;">允许AI推送</div><div class="toggle-switch on" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
<div class="settings-item" style="padding:8px 0;border-bottom:none;"><div class="item-label" style="font-size:14px;">同步到云端</div><div class="toggle-switch" onclick="toggleSwitch(this)"><div class="knob"></div></div></div>
|
||
</div>
|
||
<div class="add-actions" style="margin:0;">
|
||
<button class="cancel-btn" onclick="switchView('settings')">取消</button>
|
||
<button class="confirm-btn" onclick="createSession()">创建会话</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============ 设计说明 ============ -->
|
||
<div class="design-notes">
|
||
<h2>📋 设计说明 v2</h2>
|
||
<h3>1. 聊天页面布局</h3>
|
||
<ul>
|
||
<li>参考 <span class="highlight">QQ对话框</span> 风格,底部输入框+发送按钮</li>
|
||
<li>最底部是 <span class="highlight">分类快捷按钮</span>,点击后作为消息分类标签</li>
|
||
<li>右上角 <span class="highlight">⚙️ 设置</span> 进入聊天设置页面</li>
|
||
<li>发送按钮 <span class="tag">双色</span>:无内容=灰色,有内容=主题色渐变</li>
|
||
<li>📋 全部按钮 <span class="highlight">默认收起</span>,点击展开分类列表</li>
|
||
</ul>
|
||
<h3>2. 消息显示规则</h3>
|
||
<ul>
|
||
<li>用户消息在 <span class="highlight">右边</span>,AI/导入消息在 <span class="highlight">左边</span></li>
|
||
<li>每条消息上方显示 <span class="highlight">时间</span>(上午/下午 + 时间)</li>
|
||
<li>时间间隔 >5分钟 显示 <span class="tag">时间分割线</span></li>
|
||
<li>消息下方小字 <span class="highlight">在气泡外下方</span> 显示</li>
|
||
<li>小字字段:<span class="tag">设备型号</span> <span class="tag">地址</span> <span class="tag">分类</span> <span class="tag">本地/云端</span> <span class="tag">时间</span> <span class="tag">已阅次数</span></li>
|
||
<li><span class="tag">ext_1~ext_5</span> 保留扩展字段,后续扩展开发</li>
|
||
<li>地址可点击 → <span class="highlight">IP查询弹窗</span>(调API后缓存本地)</li>
|
||
<li>消息 <span class="highlight">长按</span> → 弹出菜单(编辑/复制/转发/已阅/删除)</li>
|
||
<li><span class="highlight">已阅</span>:点一次已阅+1,显示已阅次数</li>
|
||
</ul>
|
||
<h3>3. 导入消息识别</h3>
|
||
<ul>
|
||
<li>从其他设备导入/发送/接收的消息 → <span class="highlight">左边显示</span></li>
|
||
<li>头像显示来源设备图标(📱 iPad等)</li>
|
||
<li>meta标记为 <span class="tag">📥 导入</span></li>
|
||
</ul>
|
||
<h3>4. 聊天设置</h3>
|
||
<ul>
|
||
<li><span class="highlight">公开设置</span>,仅对当前对话框生效</li>
|
||
<li>可设置:背景图、导出/导入/分享、消息备注、同步、分类管理</li>
|
||
<li>新增 <span class="tag">♻️ 回收站</span>:已删除消息可恢复</li>
|
||
<li>分类管理支持 <span class="highlight">编辑分类名称</span>(点击✎编辑)</li>
|
||
<li><span class="tag">保留字段</span>:session_id, bg_image, show_meta, categories, sync_mode, read_count, ext_1~5, reserved_1~5</li>
|
||
<li>新增会话流 → 在灵感页面显示</li>
|
||
</ul>
|
||
<h3>5. 草稿功能</h3>
|
||
<ul>
|
||
<li>输入框内容未发送 → 自动保存为 <span class="highlight">草稿</span></li>
|
||
<li>灵感页面会话行显示 <span class="tag">📝 草稿</span> 标签+内容预览</li>
|
||
<li>返回聊天页时自动恢复草稿</li>
|
||
</ul>
|
||
<h3>6. 动态主题</h3>
|
||
<ul>
|
||
<li>所有颜色使用 <span class="highlight">CSS变量</span>,支持一键切换深色模式</li>
|
||
<li>消息气泡渐变色跟随分类主题</li>
|
||
<li>点击右下角 🌙 按钮切换深色模式</li>
|
||
</ul>
|
||
<h3>7. 异步处理</h3>
|
||
<ul>
|
||
<li>发送消息后,<span class="highlight">IP查询、设备信息、分类标记</span> 异步进行</li>
|
||
<li>先显示消息,meta信息逐步填充</li>
|
||
<li>IP查询结果 <span class="tag">缓存本地</span>,避免重复请求</li>
|
||
</ul>
|
||
<h3>8. 需要的库</h3>
|
||
<ul>
|
||
<li><span class="tag">已有</span> dio, hive, shared_preferences, uuid, intl, device_info_plus</li>
|
||
<li><span class="tag">已有</span> flutter_slidable, share_plus, gal, archive, crypto</li>
|
||
<li><span class="tag">已有</span> connectivity_plus, path_provider, json_annotation, pull_down_button</li>
|
||
<li><span class="tag">无需新增</span> 现有库可覆盖所有功能</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<button class="theme-toggle" onclick="toggleTheme()" title="切换深色模式">🌙</button>
|
||
|
||
<script>
|
||
let selectedBottomCat = null;
|
||
let isDark = false;
|
||
let isCategoryExpanded = false;
|
||
let readCounter = 0;
|
||
|
||
function switchView(view) {
|
||
document.querySelectorAll('.phone-frame').forEach(f => f.classList.remove('active'));
|
||
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||
const el = document.getElementById('view-' + view);
|
||
if (el) el.classList.add('active');
|
||
const btns = document.querySelectorAll('.tab-btn');
|
||
const map = { chat: 0, inspiration: 1, settings: 2, 'add-session': 3 };
|
||
if (map[view] !== undefined && btns[map[view]]) btns[map[view]].classList.add('active');
|
||
hideContextMenu();
|
||
}
|
||
|
||
function toggleCategoryExpand() {
|
||
isCategoryExpanded = !isCategoryExpanded;
|
||
const btn = document.getElementById('catExpandBtn');
|
||
const hiddenChips = document.querySelectorAll('.cat-hidden');
|
||
if (isCategoryExpanded) {
|
||
btn.innerHTML = '📋 全部 <span style="font-size:10px;">▾</span>';
|
||
btn.classList.add('expanded');
|
||
hiddenChips.forEach(c => c.classList.add('show'));
|
||
} else {
|
||
btn.innerHTML = '📋 全部 <span style="font-size:10px;">▸</span>';
|
||
btn.classList.remove('expanded');
|
||
hiddenChips.forEach(c => c.classList.remove('show'));
|
||
}
|
||
}
|
||
|
||
function selectCat(el) {
|
||
document.querySelectorAll('.cat-chip').forEach(c => c.classList.remove('active'));
|
||
el.classList.add('active');
|
||
}
|
||
|
||
function selectBottomCat(el, emoji) {
|
||
document.querySelectorAll('.bottom-action').forEach(b => b.classList.remove('active'));
|
||
el.classList.add('active');
|
||
selectedBottomCat = emoji;
|
||
}
|
||
|
||
function onInputChange() {
|
||
const box = document.getElementById('inputBox');
|
||
const btn = document.getElementById('sendBtn');
|
||
const hasContent = box.value.trim().length > 0;
|
||
btn.className = 'send-btn ' + (hasContent ? 'has-content' : 'empty');
|
||
box.style.height = 'auto';
|
||
box.style.height = Math.min(box.scrollHeight, 100) + 'px';
|
||
const draftBar = document.getElementById('draftBar');
|
||
const draftText = document.getElementById('draftText');
|
||
if (hasContent) {
|
||
draftBar.style.display = 'flex';
|
||
draftText.textContent = box.value.trim().substring(0, 30) + (box.value.trim().length > 30 ? '...' : '');
|
||
} else {
|
||
draftBar.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
function onInputKeydown(e) {
|
||
if (e.key === 'Enter' && !e.shiftKey) {
|
||
e.preventDefault();
|
||
sendMessage();
|
||
}
|
||
}
|
||
|
||
function sendMessage() {
|
||
const box = document.getElementById('inputBox');
|
||
const text = box.value.trim();
|
||
if (!text) return;
|
||
const chatArea = document.getElementById('chatArea');
|
||
const catLabel = selectedBottomCat ? selectedBottomCat + ' ' + getCatName(selectedBottomCat) : '未分类';
|
||
const now = new Date();
|
||
const timeStr = now.getHours() < 12 ? '上午' : '下午';
|
||
const h = now.getHours().toString().padStart(2, '0');
|
||
const m = now.getMinutes().toString().padStart(2, '0');
|
||
const msgHtml = `
|
||
<div class="msg-row right" oncontextmenu="showContextMenu(event, this)">
|
||
<div>
|
||
<div class="msg-time-top">${timeStr} ${h}:${m}</div>
|
||
<div class="msg-bubble user-bubble">${escapeHtml(text)}</div>
|
||
<div class="msg-meta-outer">
|
||
<span class="meta-item">📱 iPhone 17 Pro</span>
|
||
<span class="meta-item">📍 <span class="meta-link" onclick="showIpModal(event)">上海</span></span>
|
||
<span class="meta-item">🏷️ ${catLabel}</span>
|
||
<span class="meta-item">💾 本地</span>
|
||
<span class="meta-item">🕐 ${h}:${m}</span>
|
||
<span class="meta-item meta-reserved">[ext_1] [ext_2]</span>
|
||
</div>
|
||
</div>
|
||
<div class="msg-avatar user">😊</div>
|
||
</div>`;
|
||
chatArea.insertAdjacentHTML('beforeend', msgHtml);
|
||
box.value = '';
|
||
box.style.height = 'auto';
|
||
onInputChange();
|
||
chatArea.scrollTop = chatArea.scrollHeight;
|
||
setTimeout(() => {
|
||
const aiReplies = [
|
||
{ text: '生活不止眼前的苟且,还有诗和远方。', author: '高晓松', cat: '📖 文学', gradient: 'linear-gradient(135deg,#667eea,#764ba2)' },
|
||
{ text: '世界上只有一种英雄主义,就是在认清生活的真相后依然热爱生活。', author: '罗曼·罗兰', cat: '💪 励志', gradient: 'linear-gradient(135deg,#FF6B6B,#FFB74D)' },
|
||
{ text: '人生若只如初见,何事秋风悲画扇。', author: '纳兰性德', cat: '爱情', gradient: 'linear-gradient(135deg,#f093fb,#f5576c)' },
|
||
{ text: '采得百花成蜜后,为谁辛苦为谁甜。', author: '罗隐', cat: '🌿 自然', gradient: 'linear-gradient(135deg,#43e97b,#38f9d7)' },
|
||
];
|
||
const reply = aiReplies[Math.floor(Math.random() * aiReplies.length)];
|
||
const replyTime = new Date();
|
||
const rh = replyTime.getHours().toString().padStart(2, '0');
|
||
const rm = replyTime.getMinutes().toString().padStart(2, '0');
|
||
const rtStr = replyTime.getHours() < 12 ? '上午' : '下午';
|
||
const aiHtml = `
|
||
<div class="msg-row left" oncontextmenu="showContextMenu(event, this)">
|
||
<div class="msg-avatar ai">✨</div>
|
||
<div>
|
||
<div class="msg-time-top">${rtStr} ${rh}:${rm}</div>
|
||
<div class="msg-bubble ai-bubble" style="background:${reply.gradient};color:#fff;">
|
||
${reply.text}
|
||
<div style="margin-top:6px;font-size:13px;color:rgba(255,255,255,0.75);">—— ${reply.author}</div>
|
||
<span class="msg-category-tag">${reply.cat}</span>
|
||
</div>
|
||
<div class="msg-meta-outer">
|
||
<span class="meta-item">📱 Server</span>
|
||
<span class="meta-item">📍 <span class="meta-link" onclick="showIpModal(event)">深圳</span></span>
|
||
<span class="meta-item">🏷️ ${reply.cat}</span>
|
||
<span class="meta-item">☁️ 云端</span>
|
||
<span class="meta-item">🕐 ${rh}:${rm}</span>
|
||
<span class="meta-item meta-read">👁 已阅 0</span>
|
||
<span class="meta-item meta-reserved">[ext_1]</span>
|
||
</div>
|
||
</div>
|
||
</div>`;
|
||
chatArea.insertAdjacentHTML('beforeend', aiHtml);
|
||
chatArea.scrollTop = chatArea.scrollHeight;
|
||
}, 800);
|
||
}
|
||
|
||
function getCatName(emoji) {
|
||
const map = { '🔥': '热门', '💕': '爱情', '🌿': '自然', '💪': '励志', '📖': '文学', '🎬': '影视' };
|
||
return map[emoji] || '未分类';
|
||
}
|
||
|
||
function escapeHtml(text) {
|
||
const div = document.createElement('div');
|
||
div.textContent = text;
|
||
return div.innerHTML;
|
||
}
|
||
|
||
function showContextMenu(e, row) {
|
||
e.preventDefault();
|
||
const menu = document.getElementById('contextMenu');
|
||
const msgBubble = row.querySelector('.msg-bubble');
|
||
if (msgBubble) {
|
||
readCounter = parseInt(msgBubble.closest('.msg-row').querySelector('.meta-read')?.textContent?.replace(/[^0-9]/g, '') || '0');
|
||
document.getElementById('readCount').textContent = readCounter;
|
||
}
|
||
menu.style.left = Math.min(e.offsetX || 100, 200) + 'px';
|
||
menu.style.top = (e.offsetY || 50) + 'px';
|
||
menu.classList.add('show');
|
||
menu._targetRow = row;
|
||
}
|
||
|
||
function hideContextMenu() {
|
||
const menu = document.getElementById('contextMenu');
|
||
if (menu) menu.classList.remove('show');
|
||
}
|
||
|
||
function editMessage() {
|
||
const menu = document.getElementById('contextMenu');
|
||
const row = menu._targetRow;
|
||
if (!row) return;
|
||
const bubble = row.querySelector('.msg-bubble');
|
||
if (!bubble) return;
|
||
const editModal = document.getElementById('editModal');
|
||
const editTextarea = document.getElementById('editTextarea');
|
||
editTextarea.value = bubble.textContent.trim();
|
||
editModal.classList.add('show');
|
||
editModal._targetBubble = bubble;
|
||
hideContextMenu();
|
||
}
|
||
|
||
function copyMessage() {
|
||
const menu = document.getElementById('contextMenu');
|
||
const row = menu._targetRow;
|
||
if (!row) return;
|
||
const bubble = row.querySelector('.msg-bubble');
|
||
if (!bubble) return;
|
||
navigator.clipboard?.writeText(bubble.textContent.trim());
|
||
hideContextMenu();
|
||
}
|
||
|
||
function forwardMessage() {
|
||
hideContextMenu();
|
||
alert('↗️ 转发功能 — 选择目标会话');
|
||
}
|
||
|
||
function markAsRead() {
|
||
const menu = document.getElementById('contextMenu');
|
||
const row = menu._targetRow;
|
||
if (!row) return;
|
||
readCounter++;
|
||
document.getElementById('readCount').textContent = readCounter;
|
||
const metaRead = row.querySelector('.meta-read');
|
||
if (metaRead) {
|
||
metaRead.textContent = '👁 已阅 ' + readCounter;
|
||
} else {
|
||
const metaOuter = row.querySelector('.msg-meta-outer');
|
||
if (metaOuter) {
|
||
const span = document.createElement('span');
|
||
span.className = 'meta-item meta-read';
|
||
span.textContent = '👁 已阅 ' + readCounter;
|
||
metaOuter.insertBefore(span, metaOuter.querySelector('.meta-reserved'));
|
||
}
|
||
}
|
||
hideContextMenu();
|
||
}
|
||
|
||
function deleteMessage() {
|
||
const menu = document.getElementById('contextMenu');
|
||
const row = menu._targetRow;
|
||
if (!row) return;
|
||
row.style.transition = 'all 0.3s';
|
||
row.style.opacity = '0';
|
||
row.style.transform = 'translateX(100px)';
|
||
setTimeout(() => row.remove(), 300);
|
||
hideContextMenu();
|
||
}
|
||
|
||
function saveEdit() {
|
||
const editModal = document.getElementById('editModal');
|
||
const bubble = editModal._targetBubble;
|
||
const editTextarea = document.getElementById('editTextarea');
|
||
if (bubble && editTextarea.value.trim()) {
|
||
bubble.textContent = editTextarea.value.trim();
|
||
}
|
||
editModal.classList.remove('show');
|
||
}
|
||
|
||
function hideEditModal(e) {
|
||
if (e.target === document.getElementById('editModal') || e.target.classList.contains('cancel-btn')) {
|
||
document.getElementById('editModal').classList.remove('show');
|
||
}
|
||
}
|
||
|
||
function showIpModal(e) {
|
||
e.stopPropagation();
|
||
document.getElementById('ipModal').classList.add('show');
|
||
}
|
||
|
||
function hideIpModal(e) {
|
||
if (e.target === document.getElementById('ipModal') || e.target.classList.contains('ip-close')) {
|
||
document.getElementById('ipModal').classList.remove('show');
|
||
}
|
||
}
|
||
|
||
function toggleSwitch(el) {
|
||
el.classList.toggle('on');
|
||
}
|
||
|
||
function clearDraft() {
|
||
const box = document.getElementById('inputBox');
|
||
box.value = '';
|
||
onInputChange();
|
||
}
|
||
|
||
function toggleTheme() {
|
||
isDark = !isDark;
|
||
document.body.classList.toggle('dark-mode', isDark);
|
||
document.querySelector('.theme-toggle').textContent = isDark ? '☀️' : '🌙';
|
||
}
|
||
|
||
function editCatName(el) {
|
||
const nameEl = el.querySelector('.cat-name');
|
||
if (!nameEl) return;
|
||
if (el.querySelector('.cat-edit-input')) return;
|
||
const currentName = nameEl.textContent;
|
||
const input = document.createElement('input');
|
||
input.className = 'cat-edit-input';
|
||
input.value = currentName;
|
||
nameEl.replaceWith(input);
|
||
input.focus();
|
||
input.select();
|
||
const finish = () => {
|
||
const newName = input.value.trim() || currentName;
|
||
const newNameEl = document.createElement('span');
|
||
newNameEl.className = 'cat-name';
|
||
newNameEl.textContent = newName;
|
||
input.replaceWith(newNameEl);
|
||
};
|
||
input.addEventListener('blur', finish);
|
||
input.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Enter') { e.preventDefault(); finish(); }
|
||
if (e.key === 'Escape') { input.value = currentName; finish(); }
|
||
});
|
||
}
|
||
|
||
function selectEmoji(el) {
|
||
document.querySelectorAll('.emoji-option').forEach(e => e.classList.remove('selected'));
|
||
el.classList.add('selected');
|
||
}
|
||
|
||
function createSession() {
|
||
alert('✅ 会话创建成功!将在灵感页面显示新会话');
|
||
switchView('inspiration');
|
||
}
|
||
|
||
document.addEventListener('click', (e) => {
|
||
const menu = document.getElementById('contextMenu');
|
||
if (menu && !menu.contains(e.target)) hideContextMenu();
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |