- 重构「灵感」模块为「发现」模块,统一页面命名与文案 - 新增flutter_tts语音朗读依赖与鸿蒙Nearby配对方式 - 添加Android/iOS/鸿蒙全平台桌面小组件支持(7种类型) - 完善文件传输模块,新增画布邀请消息与删除会话功能 - 优化协作画布光标广播节流逻辑,修复已知bug - 更新应用英文名与隐私政策入口,新增翻译API抽象层 - 移除用户中心多余的加号按钮,完善空状态组件类型
1179 lines
46 KiB
HTML
1179 lines
46 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;
|
||
--secondary: #FF6B6B;
|
||
--accent: #4ECDC4;
|
||
--bgPrimary: #FAFAFA;
|
||
--bgSecondary: #F5F5F5;
|
||
--bgCard: #FFFFFF;
|
||
--bgElevated: #FFFFFF;
|
||
--textPrimary: #1A1A2E;
|
||
--textSecondary: #6B7280;
|
||
--textHint: #9CA3AF;
|
||
--textInverse: #FFFFFF;
|
||
--iconPrimary: #1A1A2E;
|
||
--iconSecondary: #6B7280;
|
||
--overlaySubtle: rgba(0,0,0,0.04);
|
||
--overlayMedium: rgba(0,0,0,0.12);
|
||
--overlayStrong: rgba(0,0,0,0.5);
|
||
--successColor: #34C759;
|
||
--errorColor: #FF3B30;
|
||
--warningColor: #FF9500;
|
||
--infoColor: #007AFF;
|
||
--destructiveColor: #FF3B30;
|
||
--glassBg: rgba(255,255,255,0.72);
|
||
--glassBorder: rgba(255,255,255,0.35);
|
||
--glassBlur: 20px;
|
||
--space-1: 4px;
|
||
--space-2: 8px;
|
||
--space-3: 16px;
|
||
--space-4: 24px;
|
||
--space-5: 32px;
|
||
--radius-sm: 4px;
|
||
--radius-md: 8px;
|
||
--radius-lg: 12px;
|
||
--radius-xl: 16px;
|
||
--radius-full: 999px;
|
||
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
||
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
|
||
--font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', system-ui, sans-serif;
|
||
}
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body {
|
||
font-family: var(--font-family);
|
||
background: #E5E5EA;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: flex-start;
|
||
min-height: 100vh;
|
||
padding: 20px;
|
||
gap: 24px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.phone-frame {
|
||
width: 390px;
|
||
height: 844px;
|
||
background: var(--bgPrimary);
|
||
border-radius: 44px;
|
||
overflow: hidden;
|
||
box-shadow: 0 25px 60px rgba(0,0,0,0.3), 0 0 0 1px rgba(0,0,0,0.08);
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex-shrink: 0;
|
||
}
|
||
.phone-frame.dark {
|
||
--bgPrimary: #1A1A2E;
|
||
--bgSecondary: #16213E;
|
||
--bgCard: #2D2D44;
|
||
--bgElevated: #333355;
|
||
--textPrimary: #E5E5E5;
|
||
--textSecondary: #9CA3AF;
|
||
--textHint: #6B7280;
|
||
--iconPrimary: #E5E5E5;
|
||
--iconSecondary: #9CA3AF;
|
||
--overlaySubtle: rgba(255,255,255,0.04);
|
||
--overlayMedium: rgba(255,255,255,0.12);
|
||
--glassBg: rgba(45,45,68,0.72);
|
||
--glassBorder: rgba(255,255,255,0.12);
|
||
}
|
||
.status-bar {
|
||
height: 54px;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
justify-content: space-between;
|
||
padding: 0 32px 8px;
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: var(--textPrimary);
|
||
flex-shrink: 0;
|
||
}
|
||
.status-bar .time { font-weight: 700; }
|
||
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 13px; }
|
||
.nav-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 4px var(--space-3) 8px;
|
||
background: var(--bgPrimary);
|
||
flex-shrink: 0;
|
||
position: relative;
|
||
z-index: 10;
|
||
}
|
||
.nav-bar .back-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
color: var(--primary);
|
||
font-size: 17px;
|
||
cursor: pointer;
|
||
background: none;
|
||
border: none;
|
||
font-family: inherit;
|
||
}
|
||
.nav-bar .title {
|
||
position: absolute;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
font-size: 17px;
|
||
font-weight: 600;
|
||
color: var(--textPrimary);
|
||
white-space: nowrap;
|
||
}
|
||
.nav-bar .actions {
|
||
display: flex;
|
||
gap: var(--space-2);
|
||
align-items: center;
|
||
}
|
||
.nav-icon-btn {
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: var(--radius-md);
|
||
border: none;
|
||
background: var(--bgSecondary);
|
||
color: var(--textSecondary);
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 18px;
|
||
transition: all 0.2s;
|
||
}
|
||
.nav-icon-btn:hover { background: var(--primary); color: white; }
|
||
.lang-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-2);
|
||
padding: var(--space-2) var(--space-3);
|
||
background: var(--bgSecondary);
|
||
flex-shrink: 0;
|
||
overflow-x: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
scrollbar-width: none;
|
||
}
|
||
.lang-bar::-webkit-scrollbar { display: none; }
|
||
.lang-chip {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
padding: 6px 14px;
|
||
border-radius: var(--radius-full);
|
||
border: 1.5px solid transparent;
|
||
background: var(--bgCard);
|
||
color: var(--textSecondary);
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||
font-family: inherit;
|
||
box-shadow: var(--shadow-sm);
|
||
}
|
||
.lang-chip:hover { border-color: var(--primary); color: var(--primary); }
|
||
.lang-chip.selected {
|
||
background: var(--primary);
|
||
color: white;
|
||
border-color: var(--primary);
|
||
box-shadow: 0 2px 8px rgba(108,99,255,0.35);
|
||
}
|
||
.lang-chip .flag { font-size: 16px; }
|
||
.lang-pair-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: var(--space-3);
|
||
padding: var(--space-2) var(--space-3);
|
||
flex-shrink: 0;
|
||
}
|
||
.lang-pair-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 6px 16px;
|
||
border-radius: var(--radius-lg);
|
||
background: var(--bgCard);
|
||
box-shadow: var(--shadow-sm);
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: var(--textPrimary);
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
.lang-pair-item:hover { box-shadow: var(--shadow-md); }
|
||
.lang-pair-item .flag { font-size: 18px; }
|
||
.lang-pair-item .detect-badge {
|
||
font-size: 10px;
|
||
padding: 2px 6px;
|
||
border-radius: var(--radius-full);
|
||
background: var(--accent);
|
||
color: white;
|
||
font-weight: 600;
|
||
}
|
||
.lang-pair-arrow { font-size: 18px; color: var(--textHint); }
|
||
.message-area {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
padding: var(--space-3);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-2);
|
||
-webkit-overflow-scrolling: touch;
|
||
}
|
||
.message-area::-webkit-scrollbar { width: 0; }
|
||
.empty-state {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: var(--space-3);
|
||
padding: var(--space-5);
|
||
}
|
||
.empty-state .icon { font-size: 64px; }
|
||
.empty-state .title { font-size: 20px; font-weight: 700; color: var(--textPrimary); }
|
||
.empty-state .subtitle { font-size: 14px; color: var(--textHint); text-align: center; line-height: 1.5; max-width: 260px; }
|
||
.msg-row {
|
||
display: flex;
|
||
gap: var(--space-2);
|
||
max-width: 85%;
|
||
animation: msgIn 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
@keyframes msgIn {
|
||
from { opacity: 0; transform: translateY(12px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
.msg-row.user { align-self: flex-end; flex-direction: row-reverse; }
|
||
.msg-row.assistant { align-self: flex-start; }
|
||
.msg-avatar {
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: var(--radius-full);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 16px;
|
||
flex-shrink: 0;
|
||
margin-top: 2px;
|
||
}
|
||
.msg-row.user .msg-avatar { background: var(--primary); color: white; }
|
||
.msg-row.assistant .msg-avatar { background: var(--accent); color: white; }
|
||
.msg-bubble {
|
||
padding: 10px 14px;
|
||
border-radius: 18px;
|
||
font-size: 15px;
|
||
line-height: 1.5;
|
||
position: relative;
|
||
word-break: break-word;
|
||
}
|
||
.msg-row.user .msg-bubble { background: var(--primary); color: white; border-bottom-right-radius: 4px; }
|
||
.msg-row.assistant .msg-bubble { background: var(--bgCard); color: var(--textPrimary); border-bottom-left-radius: 4px; box-shadow: var(--shadow-sm); }
|
||
.msg-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
margin-top: 4px;
|
||
font-size: 11px;
|
||
color: var(--textHint);
|
||
}
|
||
.msg-row.user .msg-meta { justify-content: flex-end; }
|
||
.msg-lang-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 3px;
|
||
padding: 2px 8px;
|
||
border-radius: var(--radius-full);
|
||
background: rgba(108,99,255,0.12);
|
||
color: var(--primary);
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
}
|
||
.msg-row.assistant .msg-lang-badge { background: rgba(78,205,196,0.12); color: var(--accent); }
|
||
.msg-copy-btn {
|
||
background: none;
|
||
border: none;
|
||
color: var(--textHint);
|
||
cursor: pointer;
|
||
font-size: 13px;
|
||
padding: 2px 4px;
|
||
border-radius: 4px;
|
||
transition: all 0.2s;
|
||
}
|
||
.msg-copy-btn:hover { background: var(--overlaySubtle); color: var(--primary); }
|
||
.typing-indicator { display: flex; gap: 4px; padding: 4px 0; }
|
||
.typing-indicator span {
|
||
width: 7px;
|
||
height: 7px;
|
||
border-radius: 50%;
|
||
background: var(--textHint);
|
||
animation: typing 1.4s infinite;
|
||
}
|
||
.typing-indicator span:nth-child(2) { animation-delay: 0.2s; }
|
||
.typing-indicator span:nth-child(3) { animation-delay: 0.4s; }
|
||
@keyframes typing {
|
||
0%, 60%, 100% { opacity: 0.3; transform: scale(0.8); }
|
||
30% { opacity: 1; transform: scale(1); }
|
||
}
|
||
.input-bar {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
gap: var(--space-2);
|
||
padding: var(--space-2) var(--space-3);
|
||
padding-bottom: calc(var(--space-2) + 20px);
|
||
background: var(--bgPrimary);
|
||
border-top: 0.5px solid var(--overlayMedium);
|
||
flex-shrink: 0;
|
||
}
|
||
.input-wrapper {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
background: var(--bgSecondary);
|
||
border-radius: 22px;
|
||
padding: 6px 6px 6px 16px;
|
||
min-height: 44px;
|
||
max-height: 120px;
|
||
transition: box-shadow 0.2s;
|
||
}
|
||
.input-wrapper:focus-within { box-shadow: 0 0 0 2px var(--primary); }
|
||
.input-wrapper textarea {
|
||
flex: 1;
|
||
border: none;
|
||
background: none;
|
||
font-size: 16px;
|
||
font-family: inherit;
|
||
color: var(--textPrimary);
|
||
resize: none;
|
||
outline: none;
|
||
line-height: 1.4;
|
||
max-height: 100px;
|
||
padding: 6px 0;
|
||
}
|
||
.input-wrapper textarea::placeholder { color: var(--textHint); }
|
||
.send-btn {
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: var(--radius-full);
|
||
border: none;
|
||
background: var(--primary);
|
||
color: white;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 16px;
|
||
flex-shrink: 0;
|
||
transition: all 0.2s;
|
||
box-shadow: 0 2px 8px rgba(108,99,255,0.3);
|
||
}
|
||
.send-btn:hover { transform: scale(1.08); }
|
||
.send-btn:active { transform: scale(0.95); }
|
||
.send-btn:disabled { background: var(--bgSecondary); color: var(--textHint); box-shadow: none; cursor: default; transform: none; }
|
||
.sheet-overlay {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: rgba(0,0,0,0.4);
|
||
z-index: 100;
|
||
display: none;
|
||
animation: fadeIn 0.25s;
|
||
}
|
||
.sheet-overlay.show { display: flex; }
|
||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||
.settings-sheet {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
max-height: 85%;
|
||
background: var(--bgPrimary);
|
||
border-radius: 16px 16px 0 0;
|
||
overflow: hidden;
|
||
display: none;
|
||
flex-direction: column;
|
||
animation: slideUp 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
.settings-sheet.show { display: flex; }
|
||
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
|
||
.sheet-handle { width: 36px; height: 5px; border-radius: 3px; background: var(--overlayMedium); margin: 8px auto 4px; flex-shrink: 0; }
|
||
.sheet-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: var(--space-2) var(--space-3) var(--space-3);
|
||
border-bottom: 0.5px solid var(--overlayMedium);
|
||
flex-shrink: 0;
|
||
}
|
||
.sheet-header .title { font-size: 17px; font-weight: 700; color: var(--textPrimary); }
|
||
.sheet-header .close-btn {
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: var(--radius-full);
|
||
border: none;
|
||
background: var(--bgSecondary);
|
||
color: var(--textSecondary);
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
}
|
||
.sheet-content { flex: 1; overflow-y: auto; padding: var(--space-3); }
|
||
.settings-group { margin-bottom: var(--space-4); }
|
||
.settings-group-title {
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
color: var(--textHint);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
margin-bottom: var(--space-2);
|
||
padding-left: var(--space-2);
|
||
}
|
||
.settings-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 14px var(--space-3);
|
||
background: var(--bgCard);
|
||
border-radius: var(--radius-lg);
|
||
margin-bottom: 2px;
|
||
cursor: pointer;
|
||
transition: background 0.15s;
|
||
}
|
||
.settings-item:first-of-type { border-radius: var(--radius-lg) var(--radius-lg) var(--radius-sm) var(--radius-sm); }
|
||
.settings-item:last-of-type { border-radius: var(--radius-sm) var(--radius-sm) var(--radius-lg) var(--radius-lg); }
|
||
.settings-item:only-of-type { border-radius: var(--radius-lg); }
|
||
.settings-item:hover { background: var(--bgSecondary); }
|
||
.settings-item .left { display: flex; align-items: center; gap: var(--space-3); }
|
||
.settings-item .icon-wrap {
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: var(--radius-md);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 16px;
|
||
}
|
||
.settings-item .label { font-size: 15px; font-weight: 500; color: var(--textPrimary); }
|
||
.settings-item .sublabel { font-size: 12px; color: var(--textHint); margin-top: 2px; }
|
||
.settings-item .right { display: flex; align-items: center; gap: 6px; color: var(--textHint); font-size: 14px; }
|
||
.ios-toggle {
|
||
width: 51px;
|
||
height: 31px;
|
||
border-radius: 16px;
|
||
background: #E5E5EA;
|
||
position: relative;
|
||
cursor: pointer;
|
||
transition: background 0.3s;
|
||
flex-shrink: 0;
|
||
}
|
||
.ios-toggle.on { background: var(--successColor); }
|
||
.ios-toggle .knob {
|
||
width: 27px;
|
||
height: 27px;
|
||
border-radius: 50%;
|
||
background: white;
|
||
position: absolute;
|
||
top: 2px;
|
||
left: 2px;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
.ios-toggle.on .knob { transform: translateX(20px); }
|
||
.api-list { display: flex; flex-direction: column; gap: 2px; }
|
||
.api-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-3);
|
||
padding: 12px var(--space-3);
|
||
background: var(--bgCard);
|
||
cursor: pointer;
|
||
transition: background 0.15s;
|
||
}
|
||
.api-item:first-of-type { border-radius: var(--radius-lg) var(--radius-lg) var(--radius-sm) var(--radius-sm); }
|
||
.api-item:last-of-type { border-radius: var(--radius-sm) var(--radius-sm) var(--radius-lg) var(--radius-lg); }
|
||
.api-item:hover { background: var(--bgSecondary); }
|
||
.api-item .api-icon {
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: var(--radius-md);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 18px;
|
||
flex-shrink: 0;
|
||
}
|
||
.api-item .api-info { flex: 1; }
|
||
.api-item .api-name { font-size: 15px; font-weight: 500; color: var(--textPrimary); }
|
||
.api-item .api-desc { font-size: 12px; color: var(--textHint); margin-top: 2px; }
|
||
.api-item .api-check {
|
||
width: 22px;
|
||
height: 22px;
|
||
border-radius: 50%;
|
||
border: 2px solid var(--overlayMedium);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 12px;
|
||
color: transparent;
|
||
transition: all 0.2s;
|
||
}
|
||
.api-item.selected .api-check { background: var(--primary); border-color: var(--primary); color: white; }
|
||
.api-item .api-status { font-size: 10px; padding: 2px 8px; border-radius: var(--radius-full); font-weight: 600; }
|
||
.api-status.active { background: rgba(52,199,89,0.12); color: var(--successColor); }
|
||
.api-status.slow { background: rgba(255,149,0,0.12); color: var(--warningColor); }
|
||
.discover-card {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-3);
|
||
padding: var(--space-3);
|
||
background: var(--bgCard);
|
||
border-radius: var(--radius-xl);
|
||
box-shadow: var(--shadow-sm);
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
margin: 0 var(--space-3) var(--space-2);
|
||
}
|
||
.discover-card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
|
||
.discover-card .card-icon {
|
||
width: 52px;
|
||
height: 52px;
|
||
border-radius: var(--radius-lg);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 28px;
|
||
flex-shrink: 0;
|
||
}
|
||
.discover-card .card-info { flex: 1; }
|
||
.discover-card .card-title { font-size: 16px; font-weight: 600; color: var(--textPrimary); }
|
||
.discover-card .card-desc { font-size: 13px; color: var(--textHint); margin-top: 2px; }
|
||
.discover-card .card-arrow { color: var(--textHint); font-size: 18px; }
|
||
.page-label {
|
||
text-align: center;
|
||
padding: 12px;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
color: var(--textHint);
|
||
background: var(--bgSecondary);
|
||
border-radius: 0 0 20px 20px;
|
||
}
|
||
.conversation-list-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-2);
|
||
padding: 10px var(--space-3);
|
||
background: var(--bgCard);
|
||
margin-bottom: 2px;
|
||
cursor: pointer;
|
||
transition: background 0.15s;
|
||
}
|
||
.conversation-list-item:first-of-type { border-radius: var(--radius-lg) var(--radius-lg) var(--radius-sm) var(--radius-sm); }
|
||
.conversation-list-item:last-of-type { border-radius: var(--radius-sm) var(--radius-sm) var(--radius-lg) var(--radius-lg); }
|
||
.conversation-list-item:hover { background: var(--bgSecondary); }
|
||
.conv-avatar {
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: var(--radius-full);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 16px;
|
||
flex-shrink: 0;
|
||
}
|
||
.conv-info { flex: 1; }
|
||
.conv-name { font-size: 14px; font-weight: 500; color: var(--textPrimary); }
|
||
.conv-preview { font-size: 12px; color: var(--textHint); margin-top: 1px; }
|
||
.history-count {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 20px;
|
||
height: 20px;
|
||
border-radius: 10px;
|
||
background: var(--primary);
|
||
color: white;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
padding: 0 6px;
|
||
}
|
||
.toast {
|
||
position: absolute;
|
||
top: 80px;
|
||
left: 50%;
|
||
transform: translateX(-50%) translateY(-20px);
|
||
background: var(--bgCard);
|
||
color: var(--textPrimary);
|
||
padding: 10px 20px;
|
||
border-radius: var(--radius-full);
|
||
box-shadow: var(--shadow-lg);
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
z-index: 200;
|
||
opacity: 0;
|
||
transition: all 0.3s;
|
||
pointer-events: none;
|
||
white-space: nowrap;
|
||
}
|
||
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
|
||
.detect-result {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
padding: 3px 10px;
|
||
border-radius: var(--radius-full);
|
||
background: rgba(78,205,196,0.1);
|
||
color: var(--accent);
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
margin-top: 6px;
|
||
}
|
||
.tab-bar {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
padding: 8px 0 24px;
|
||
background: var(--bgPrimary);
|
||
border-top: 0.5px solid var(--overlayMedium);
|
||
flex-shrink: 0;
|
||
}
|
||
.tab-item {
|
||
text-align: center;
|
||
color: var(--textHint);
|
||
font-size: 10px;
|
||
cursor: pointer;
|
||
transition: color 0.2s;
|
||
}
|
||
.tab-item.active { color: var(--primary); font-weight: 600; }
|
||
.tab-item .tab-icon { font-size: 22px; }
|
||
.session-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-2);
|
||
padding: 12px var(--space-3);
|
||
background: var(--bgCard);
|
||
margin: 0 var(--space-3) 2px;
|
||
border-radius: var(--radius-lg);
|
||
cursor: pointer;
|
||
transition: all 0.15s;
|
||
}
|
||
.session-row:hover { background: var(--bgSecondary); }
|
||
.session-row .session-avatar {
|
||
width: 44px;
|
||
height: 44px;
|
||
border-radius: var(--radius-full);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 22px;
|
||
flex-shrink: 0;
|
||
}
|
||
.session-row .session-info { flex: 1; }
|
||
.session-row .session-name { font-size: 15px; font-weight: 600; color: var(--textPrimary); }
|
||
.session-row .session-preview { font-size: 13px; color: var(--textHint); margin-top: 2px; }
|
||
.session-row .session-time { font-size: 11px; color: var(--textHint); }
|
||
.session-row .unread-badge {
|
||
min-width: 20px;
|
||
height: 20px;
|
||
border-radius: 10px;
|
||
background: var(--primary);
|
||
color: white;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 6px;
|
||
}
|
||
@media (max-width: 860px) {
|
||
body { padding: 10px; }
|
||
.phone-frame { width: 100%; max-width: 390px; height: 85vh; border-radius: 24px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- ==================== Phone 1: 发现页 — 主页面(3Tab) ==================== -->
|
||
<div class="phone-frame" id="phone-discover">
|
||
<div class="status-bar">
|
||
<span class="time">9:41</span>
|
||
<span class="icons">📶 📡 🔋</span>
|
||
</div>
|
||
|
||
<div style="flex:1; overflow-y:auto;">
|
||
<div style="padding: var(--space-3) var(--space-4) var(--space-2);">
|
||
<div style="display:flex; align-items:center; gap:var(--space-2);">
|
||
<span style="font-size:28px;">⚙️</span>
|
||
<span style="font-size:28px; font-weight:700; color:var(--textPrimary);">工作流</span>
|
||
<div style="flex:1;"></div>
|
||
<div style="width:36px; height:36px; border-radius:10px; background:var(--bgSecondary); display:flex; align-items:center; justify-content:center; font-size:16px; color:var(--textSecondary);">🔧</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 搜索栏 -->
|
||
<div style="padding: var(--space-1) var(--space-3) var(--space-2);">
|
||
<div style="display:flex; align-items:center; gap:var(--space-2); padding:8px 14px; background:var(--bgSecondary); border-radius:var(--radius-lg);">
|
||
<span style="color:var(--textHint); font-size:14px;">🔍</span>
|
||
<span style="color:var(--textHint); font-size:14px;">搜索</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 置顶会话 -->
|
||
<div style="padding: var(--space-2) var(--space-3) var(--space-1);">
|
||
<div style="display:flex; align-items:center; gap:4px;">
|
||
<span style="font-size:13px; font-weight:600; color:var(--textSecondary);">📌 置顶</span>
|
||
<span style="font-size:12px; color:var(--textHint);">1</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="session-row">
|
||
<div class="session-avatar" style="background:rgba(78,205,196,0.12);">📖</div>
|
||
<div class="session-info">
|
||
<div class="session-name">稍后读 <span style="font-size:10px; padding:1px 6px; border-radius:var(--radius-full); background:var(--secondary); color:white; font-weight:600; vertical-align:middle;">HOT</span></div>
|
||
<div class="session-preview">收藏内容,稍后阅读</div>
|
||
</div>
|
||
<span class="session-time">18:30</span>
|
||
</div>
|
||
|
||
<div style="padding: 0 var(--space-3);"><div style="height:0.5px; background:var(--overlayMedium); margin:var(--space-2) 0;"></div></div>
|
||
|
||
<!-- 对话会话 -->
|
||
<div style="padding: var(--space-2) var(--space-3) var(--space-1);">
|
||
<div style="display:flex; align-items:center; gap:4px;">
|
||
<span style="font-size:13px; font-weight:600; color:var(--textSecondary);">💬 对话</span>
|
||
<span style="font-size:12px; color:var(--textHint);">15</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="session-row" onclick="switchToTranslate()">
|
||
<div class="session-avatar" style="background:linear-gradient(135deg, rgba(108,99,255,0.15), rgba(78,205,196,0.15));">🌐</div>
|
||
<div class="session-info">
|
||
<div class="session-name">翻译助手 <span style="font-size:10px; padding:1px 6px; border-radius:var(--radius-full); background:var(--accent); color:white; font-weight:600; vertical-align:middle;">NEW</span></div>
|
||
<div class="session-preview">多语言智能翻译 · 自动识别语言</div>
|
||
</div>
|
||
<div class="unread-badge" id="translateBadge" style="background:var(--errorColor);">1</div>
|
||
</div>
|
||
|
||
<div class="session-row">
|
||
<div class="session-avatar" style="background:rgba(108,99,255,0.12);">🌤️</div>
|
||
<div class="session-info">
|
||
<div class="session-name">天气诗词</div>
|
||
<div class="session-preview">实时天气 · 天气关联诗词 · 心情推荐</div>
|
||
</div>
|
||
<span class="session-time">30分钟前</span>
|
||
</div>
|
||
|
||
<div class="session-row">
|
||
<div class="session-avatar" style="background:rgba(108,99,255,0.12);">📜</div>
|
||
<div class="session-info">
|
||
<div class="session-name">今日诗词</div>
|
||
<div class="session-preview">每日推荐 · 完整诗词 · 译文赏析</div>
|
||
</div>
|
||
<span class="session-time">1小时前</span>
|
||
</div>
|
||
|
||
<div class="session-row">
|
||
<div class="session-avatar" style="background:rgba(255,149,0,0.12);">📅</div>
|
||
<div class="session-info">
|
||
<div class="session-name">日签卡片</div>
|
||
<div class="session-preview">每日一句 · 样式切换 · 一键分享</div>
|
||
</div>
|
||
<span class="session-time">6小时前</span>
|
||
</div>
|
||
|
||
<div class="session-row">
|
||
<div class="session-avatar" style="background:rgba(255,107,107,0.12);">🎨</div>
|
||
<div class="session-info">
|
||
<div class="session-name">壁纸模板</div>
|
||
<div class="session-preview">预设模板 · 分类浏览 · 一键应用</div>
|
||
</div>
|
||
<span class="session-time">12小时前</span>
|
||
</div>
|
||
|
||
<div class="session-row">
|
||
<div class="session-avatar" style="background:rgba(78,205,196,0.12);">🔍</div>
|
||
<div class="session-info">
|
||
<div class="session-name">发现</div>
|
||
<div class="session-preview">热门句子 · 分类浏览 · 每日推荐</div>
|
||
</div>
|
||
<span class="session-time">18小时前</span>
|
||
</div>
|
||
|
||
<div class="session-row">
|
||
<div class="session-avatar" style="background:rgba(255,149,0,0.12);">👣</div>
|
||
<div class="session-info">
|
||
<div class="session-name">足迹</div>
|
||
<div class="session-preview">浏览 · 点赞 · 收藏 · 稍后读 · 笔记</div>
|
||
</div>
|
||
<span class="session-time">3天前</span>
|
||
</div>
|
||
|
||
<div class="session-row">
|
||
<div class="session-avatar" style="background:rgba(108,99,255,0.12);">📁</div>
|
||
<div class="session-info">
|
||
<div class="session-name">文件传输助手</div>
|
||
<div class="session-preview">局域网 · 蓝牙 · NFC · WebRTC · USB</div>
|
||
</div>
|
||
<span class="session-time">昨天</span>
|
||
</div>
|
||
|
||
<div style="padding:var(--space-4) 0; text-align:center;">
|
||
<span style="font-size:12px; color:var(--textHint);">⬆️ 下拉打开工具中心</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 3 Tab Bar -->
|
||
<div class="tab-bar">
|
||
<div class="tab-item">
|
||
<div class="tab-icon">🏠</div>闲言
|
||
</div>
|
||
<div class="tab-item active">
|
||
<div class="tab-icon">🧭</div>发现
|
||
</div>
|
||
<div class="tab-item">
|
||
<div class="tab-icon">👤</div>我的
|
||
</div>
|
||
</div>
|
||
<div class="page-label">📱 工作流页 — 会话流列表 · 翻译助手置顶</div>
|
||
</div>
|
||
|
||
<!-- ==================== Phone 2: 翻译助手主页面 ==================== -->
|
||
<div class="phone-frame" id="phone-translate">
|
||
<div class="status-bar">
|
||
<span class="time">9:41</span>
|
||
<span class="icons">📶 📡 🔋</span>
|
||
</div>
|
||
|
||
<div class="nav-bar">
|
||
<button class="back-btn">‹ 发现</button>
|
||
<span class="title">🌐 翻译助手</span>
|
||
<div class="actions">
|
||
<button class="nav-icon-btn" title="历史记录" onclick="showToast('📜 历史记录')">📋</button>
|
||
<button class="nav-icon-btn" title="设置" onclick="toggleSettings()">⚙️</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="lang-pair-bar">
|
||
<div class="lang-pair-item" id="sourceLang">
|
||
<span class="flag">🔍</span>
|
||
<span>自动检测</span>
|
||
<span class="detect-badge">AUTO</span>
|
||
</div>
|
||
<span class="lang-pair-arrow">→</span>
|
||
<div class="lang-pair-item" id="targetLang" onclick="showToast('🌍 选择目标语言')">
|
||
<span class="flag">🇨🇳</span>
|
||
<span>中文</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="lang-bar">
|
||
<button class="lang-chip selected" onclick="selectTargetLang(this, '🇨🇳', '中文')"><span class="flag">🇨🇳</span>中文</button>
|
||
<button class="lang-chip" onclick="selectTargetLang(this, '🇺🇸', '英语')"><span class="flag">🇺🇸</span>英语</button>
|
||
<button class="lang-chip" onclick="selectTargetLang(this, '🇯🇵', '日语')"><span class="flag">🇯🇵</span>日语</button>
|
||
<button class="lang-chip" onclick="selectTargetLang(this, '🇰🇷', '韩语')"><span class="flag">🇰🇷</span>韩语</button>
|
||
<button class="lang-chip" onclick="selectTargetLang(this, '🇫🇷', '法语')"><span class="flag">🇫🇷</span>法语</button>
|
||
<button class="lang-chip" onclick="selectTargetLang(this, '🇩🇪', '德语')"><span class="flag">🇩🇪</span>德语</button>
|
||
<button class="lang-chip" onclick="selectTargetLang(this, '🇪🇸', '西语')"><span class="flag">🇪🇸</span>西语</button>
|
||
<button class="lang-chip" onclick="selectTargetLang(this, '🇷🇺', '俄语')"><span class="flag">🇷🇺</span>俄语</button>
|
||
<button class="lang-chip" onclick="showToast('🌍 更多语言')"><span class="flag">🌍</span>更多</button>
|
||
</div>
|
||
|
||
<div class="message-area" id="messageArea">
|
||
<div class="empty-state" id="emptyState">
|
||
<div class="icon">🌐</div>
|
||
<div class="title">翻译助手</div>
|
||
<div class="subtitle">输入需要翻译的文本,选择目标语言,即可获得翻译结果。支持自动识别源语言。</div>
|
||
<div style="display:flex; flex-wrap:wrap; gap:8px; justify-content:center; margin-top:8px;">
|
||
<button class="lang-chip" onclick="quickTranslate('Hello, how are you today?')" style="font-size:12px; padding:6px 12px;">🇺🇸 Hello, how are you today?</button>
|
||
<button class="lang-chip" onclick="quickTranslate('こんにちは、元気ですか?')" style="font-size:12px; padding:6px 12px;">🇯🇵 こんにちは、元気ですか?</button>
|
||
<button class="lang-chip" onclick="quickTranslate('Bonjour le monde')" style="font-size:12px; padding:6px 12px;">🇫🇷 Bonjour le monde</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="input-bar">
|
||
<div class="input-wrapper">
|
||
<textarea id="inputField" rows="1" placeholder="输入需要翻译的文本..." oninput="autoResize(this)" onkeydown="handleKeyDown(event)"></textarea>
|
||
<button class="send-btn" id="sendBtn" onclick="sendMessage()" disabled>↑</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toast" id="toast"></div>
|
||
|
||
<!-- Settings Sheet -->
|
||
<div class="sheet-overlay" id="settingsOverlay" onclick="toggleSettings()"></div>
|
||
<div class="settings-sheet" id="settingsSheet">
|
||
<div class="sheet-handle"></div>
|
||
<div class="sheet-header">
|
||
<span class="title">⚙️ 翻译设置</span>
|
||
<button class="close-btn" onclick="toggleSettings()">✕</button>
|
||
</div>
|
||
<div class="sheet-content">
|
||
<div class="settings-group">
|
||
<div class="settings-group-title">翻译接口</div>
|
||
<div class="api-list">
|
||
<div class="api-item selected" onclick="selectApi(this)">
|
||
<div class="api-icon" style="background:rgba(66,133,244,0.12);">🔍</div>
|
||
<div class="api-info"><div class="api-name">Google Translate</div><div class="api-desc">免费 · 自动检测 · 100+语言</div></div>
|
||
<span class="api-status active">正常</span>
|
||
<div class="api-check">✓</div>
|
||
</div>
|
||
<div class="api-item" onclick="selectApi(this)">
|
||
<div class="api-icon" style="background:rgba(0,120,212,0.12);">🅱️</div>
|
||
<div class="api-info"><div class="api-name">Bing Translator</div><div class="api-desc">免费 · 自动检测 · 70+语言</div></div>
|
||
<span class="api-status active">正常</span>
|
||
<div class="api-check">✓</div>
|
||
</div>
|
||
<div class="api-item" onclick="selectApi(this)">
|
||
<div class="api-icon" style="background:rgba(78,205,196,0.12);">📖</div>
|
||
<div class="api-info"><div class="api-name">LibreTranslate</div><div class="api-desc">开源免费 · 自托管 · 30+语言</div></div>
|
||
<span class="api-status slow">较慢</span>
|
||
<div class="api-check">✓</div>
|
||
</div>
|
||
<div class="api-item" onclick="selectApi(this)">
|
||
<div class="api-icon" style="background:rgba(255,107,107,0.12);">💾</div>
|
||
<div class="api-info"><div class="api-name">MyMemory API</div><div class="api-desc">免费 · 无需Key · 逐句翻译</div></div>
|
||
<span class="api-status active">正常</span>
|
||
<div class="api-check">✓</div>
|
||
</div>
|
||
<div class="api-item" onclick="selectApi(this)">
|
||
<div class="api-icon" style="background:rgba(108,99,255,0.12);">🌐</div>
|
||
<div class="api-info"><div class="api-name">AppWorlds 翻译</div><div class="api-desc">免费 · 国内直连 · 100+语言</div></div>
|
||
<span class="api-status active">正常</span>
|
||
<div class="api-check">✓</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="settings-group">
|
||
<div class="settings-group-title">翻译设置</div>
|
||
<div class="settings-item">
|
||
<div class="left"><div class="icon-wrap" style="background:rgba(78,205,196,0.12);">🔍</div><div><div class="label">自动检测语言</div><div class="sublabel">自动识别输入文本的源语言</div></div></div>
|
||
<div class="ios-toggle on" onclick="this.classList.toggle('on')"><div class="knob"></div></div>
|
||
</div>
|
||
<div class="settings-item">
|
||
<div class="left"><div class="icon-wrap" style="background:rgba(108,99,255,0.12);">🔄</div><div><div class="label">自动翻译</div><div class="sublabel">输入后自动发送翻译请求</div></div></div>
|
||
<div class="ios-toggle" onclick="this.classList.toggle('on')"><div class="knob"></div></div>
|
||
</div>
|
||
<div class="settings-item">
|
||
<div class="left"><div class="icon-wrap" style="background:rgba(255,149,0,0.12);">📋</div><div><div class="label">翻译后自动复制</div><div class="sublabel">翻译结果自动复制到剪贴板</div></div></div>
|
||
<div class="ios-toggle" onclick="this.classList.toggle('on')"><div class="knob"></div></div>
|
||
</div>
|
||
<div class="settings-item">
|
||
<div class="left"><div class="icon-wrap" style="background:rgba(52,199,89,0.12);">🔊</div><div><div class="label">发音朗读</div><div class="sublabel">翻译结果自动朗读发音</div></div></div>
|
||
<div class="ios-toggle" onclick="this.classList.toggle('on')"><div class="knob"></div></div>
|
||
</div>
|
||
</div>
|
||
<div class="settings-group">
|
||
<div class="settings-group-title">会话管理</div>
|
||
<div class="conversation-list-item" style="border-radius:var(--radius-lg) var(--radius-lg) var(--radius-sm) var(--radius-sm);">
|
||
<div class="conv-avatar" style="background:rgba(108,99,255,0.12);">🌐</div>
|
||
<div class="conv-info"><div class="conv-name">默认翻译会话</div><div class="conv-preview">上次: Hello → 你好</div></div>
|
||
<span class="history-count">12</span>
|
||
</div>
|
||
<div class="conversation-list-item" style="border-radius:var(--radius-sm) var(--radius-sm) var(--radius-lg) var(--radius-lg);">
|
||
<div class="conv-avatar" style="background:rgba(78,205,196,0.12);">📚</div>
|
||
<div class="conv-info"><div class="conv-name">英语学习</div><div class="conv-preview">上次: 翻译了一段英文文章</div></div>
|
||
<span class="history-count">8</span>
|
||
</div>
|
||
<div style="padding:var(--space-3);">
|
||
<button style="width:100%; padding:12px; border-radius:var(--radius-lg); border:1.5px dashed var(--primary); background:none; color:var(--primary); font-size:14px; font-weight:600; cursor:pointer; font-family:inherit;">+ 新建翻译会话</button>
|
||
</div>
|
||
</div>
|
||
<div class="settings-group">
|
||
<div class="settings-group-title">数据管理</div>
|
||
<div class="settings-item" style="border-radius:var(--radius-lg);">
|
||
<div class="left"><div class="icon-wrap" style="background:rgba(108,99,255,0.12);">📤</div><div class="label">导出翻译记录</div></div>
|
||
<div class="right">›</div>
|
||
</div>
|
||
<div class="settings-item" style="border-radius:var(--radius-lg);">
|
||
<div class="left"><div class="icon-wrap" style="background:rgba(255,59,48,0.12);">🗑️</div><div class="label" style="color:var(--errorColor);">清空所有翻译记录</div></div>
|
||
<div class="right">›</div>
|
||
</div>
|
||
</div>
|
||
<div class="settings-group">
|
||
<div class="settings-group-title">调试</div>
|
||
<div class="settings-item" style="border-radius:var(--radius-lg);">
|
||
<div class="left"><div class="icon-wrap" style="background:rgba(255,149,0,0.12);">🐛</div><div><div class="label">接口测试</div><div class="sublabel">测试各翻译API的连通性和响应速度</div></div></div>
|
||
<div class="right">›</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ==================== Phone 3: 深色模式翻译效果 ==================== -->
|
||
<div class="phone-frame dark" id="phone-dark">
|
||
<div class="status-bar">
|
||
<span class="time">9:41</span>
|
||
<span class="icons">📶 📡 🔋</span>
|
||
</div>
|
||
<div class="nav-bar">
|
||
<button class="back-btn" style="color:var(--primary);">‹ 发现</button>
|
||
<span class="title" style="color:var(--textPrimary);">🌐 翻译助手</span>
|
||
<div class="actions">
|
||
<button class="nav-icon-btn" style="background:var(--bgSecondary); color:var(--textSecondary);">📋</button>
|
||
<button class="nav-icon-btn" style="background:var(--bgSecondary); color:var(--textSecondary);">⚙️</button>
|
||
</div>
|
||
</div>
|
||
<div class="lang-pair-bar">
|
||
<div class="lang-pair-item" style="background:var(--bgCard);">
|
||
<span class="flag">🇨🇳</span>
|
||
<span style="color:var(--textPrimary);">中文</span>
|
||
<span class="detect-badge" style="background:var(--accent);">已检测</span>
|
||
</div>
|
||
<span class="lang-pair-arrow" style="color:var(--textHint);">→</span>
|
||
<div class="lang-pair-item" style="background:var(--bgCard);">
|
||
<span class="flag">🇺🇸</span>
|
||
<span style="color:var(--textPrimary);">英语</span>
|
||
</div>
|
||
</div>
|
||
<div class="lang-bar" style="background:var(--bgSecondary);">
|
||
<button class="lang-chip" style="background:var(--bgCard); color:var(--textSecondary);"><span class="flag">🇨🇳</span>中文</button>
|
||
<button class="lang-chip selected"><span class="flag">🇺🇸</span>英语</button>
|
||
<button class="lang-chip" style="background:var(--bgCard); color:var(--textSecondary);"><span class="flag">🇯🇵</span>日语</button>
|
||
<button class="lang-chip" style="background:var(--bgCard); color:var(--textSecondary);"><span class="flag">🇰🇷</span>韩语</button>
|
||
<button class="lang-chip" style="background:var(--bgCard); color:var(--textSecondary);"><span class="flag">🇫🇷</span>法语</button>
|
||
</div>
|
||
<div class="message-area" style="background:var(--bgPrimary);">
|
||
<div class="msg-row user">
|
||
<div class="msg-avatar">👤</div>
|
||
<div>
|
||
<div class="msg-bubble">生活不是等待风暴过去,而是学会在雨中翩翩起舞。</div>
|
||
<div class="msg-meta"><span class="msg-lang-badge" style="background:rgba(108,99,255,0.2); color:var(--primary);">🇨🇳 中文</span><span>9:40</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="msg-row assistant">
|
||
<div class="msg-avatar" style="background:var(--accent);">🌐</div>
|
||
<div>
|
||
<div class="msg-bubble" style="background:var(--bgCard); color:var(--textPrimary);">Life isn't about waiting for the storm to pass, it's about learning to dance in the rain.</div>
|
||
<div class="msg-meta">
|
||
<span class="msg-lang-badge" style="background:rgba(78,205,196,0.15); color:var(--accent);">🇺🇸 英语</span>
|
||
<button class="msg-copy-btn" onclick="showToast('✅ 已复制')">📋</button>
|
||
<button class="msg-copy-btn" onclick="showToast('🔊 朗读中...')">🔊</button>
|
||
<span>9:40</span>
|
||
</div>
|
||
<div class="detect-result" style="background:rgba(78,205,196,0.1); color:var(--accent);">🔍 检测: 中文 → 英语 · Google Translate</div>
|
||
</div>
|
||
</div>
|
||
<div class="msg-row user">
|
||
<div class="msg-avatar">👤</div>
|
||
<div>
|
||
<div class="msg-bubble">你好世界</div>
|
||
<div class="msg-meta"><span class="msg-lang-badge" style="background:rgba(108,99,255,0.2); color:var(--primary);">🇨🇳 中文</span><span>9:41</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="msg-row assistant">
|
||
<div class="msg-avatar" style="background:var(--accent);">🌐</div>
|
||
<div>
|
||
<div class="msg-bubble" style="background:var(--bgCard); color:var(--textPrimary);">Hello World</div>
|
||
<div class="msg-meta">
|
||
<span class="msg-lang-badge" style="background:rgba(78,205,196,0.15); color:var(--accent);">🇺🇸 英语</span>
|
||
<button class="msg-copy-btn" onclick="showToast('✅ 已复制')">📋</button>
|
||
<button class="msg-copy-btn" onclick="showToast('🔊 朗读中...')">🔊</button>
|
||
<span>9:41</span>
|
||
</div>
|
||
<div class="detect-result" style="background:rgba(78,205,196,0.1); color:var(--accent);">🔍 检测: 中文 → 英语 · Google Translate</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="input-bar" style="background:var(--bgPrimary); border-color:var(--overlayMedium);">
|
||
<div class="input-wrapper" style="background:var(--bgSecondary);">
|
||
<textarea rows="1" placeholder="输入需要翻译的文本..." style="color:var(--textPrimary);" readonly></textarea>
|
||
<button class="send-btn" style="background:var(--primary);">↑</button>
|
||
</div>
|
||
</div>
|
||
<div class="page-label" style="background:var(--bgSecondary); color:var(--textHint);">🌙 深色模式 — 翻译对话效果</div>
|
||
</div>
|
||
|
||
<script>
|
||
const inputField = document.getElementById('inputField');
|
||
const sendBtn = document.getElementById('sendBtn');
|
||
const messageArea = document.getElementById('messageArea');
|
||
const emptyState = document.getElementById('emptyState');
|
||
let currentTarget = { flag: '🇨🇳', name: '中文', code: 'zh-CN' };
|
||
const translations = {
|
||
'Hello, how are you today?': { text: '你好,你今天怎么样?', lang: '中文', flag: '🇨🇳', detected: '英语', detectedFlag: '🇺🇸' },
|
||
'こんにちは、元気ですか?': { text: '你好,你还好吗?', lang: '中文', flag: '🇨🇳', detected: '日语', detectedFlag: '🇯🇵' },
|
||
'Bonjour le monde': { text: '你好世界', lang: '中文', flag: '🇨🇳', detected: '法语', detectedFlag: '🇫🇷' },
|
||
};
|
||
inputField.addEventListener('input', () => { sendBtn.disabled = inputField.value.trim() === ''; });
|
||
function autoResize(el) { el.style.height = 'auto'; el.style.height = Math.min(el.scrollHeight, 100) + 'px'; }
|
||
function handleKeyDown(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); } }
|
||
function sendMessage() {
|
||
const text = inputField.value.trim();
|
||
if (!text) return;
|
||
if (emptyState) emptyState.style.display = 'none';
|
||
addUserMessage(text);
|
||
inputField.value = '';
|
||
inputField.style.height = 'auto';
|
||
sendBtn.disabled = true;
|
||
setTimeout(() => {
|
||
addTypingIndicator();
|
||
setTimeout(() => {
|
||
removeTypingIndicator();
|
||
const translation = translations[text] || { text: '[翻译] ' + text, lang: currentTarget.name, flag: currentTarget.flag, detected: '自动', detectedFlag: '🔍' };
|
||
addAssistantMessage(translation);
|
||
}, 800 + Math.random() * 600);
|
||
}, 300);
|
||
}
|
||
function quickTranslate(text) { inputField.value = text; sendBtn.disabled = false; sendMessage(); }
|
||
function addUserMessage(text) {
|
||
const div = document.createElement('div');
|
||
div.className = 'msg-row user';
|
||
div.innerHTML = `<div class="msg-avatar">👤</div><div><div class="msg-bubble">${escapeHtml(text)}</div><div class="msg-meta"><span class="msg-lang-badge">🔍 ${currentTarget.name}</span><span>${new Date().toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'})}</span></div></div>`;
|
||
messageArea.appendChild(div);
|
||
scrollToBottom();
|
||
}
|
||
function addAssistantMessage(translation) {
|
||
const div = document.createElement('div');
|
||
div.className = 'msg-row assistant';
|
||
div.innerHTML = `<div class="msg-avatar">🌐</div><div><div class="msg-bubble">${escapeHtml(translation.text)}</div><div class="msg-meta"><span class="msg-lang-badge">${translation.flag} ${translation.lang}</span><button class="msg-copy-btn" onclick="copyText('${escapeHtml(translation.text)}')">📋</button><button class="msg-copy-btn" onclick="showToast('🔊 朗读中...')">🔊</button><span>${new Date().toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'})}</span></div><div class="detect-result">🔍 检测: ${translation.detectedFlag} ${translation.detected} → ${translation.flag} ${translation.lang} · Google Translate</div></div>`;
|
||
messageArea.appendChild(div);
|
||
scrollToBottom();
|
||
}
|
||
function addTypingIndicator() {
|
||
const div = document.createElement('div');
|
||
div.className = 'msg-row assistant';
|
||
div.id = 'typingIndicator';
|
||
div.innerHTML = `<div class="msg-avatar">🌐</div><div><div class="msg-bubble"><div class="typing-indicator"><span></span><span></span><span></span></div></div></div>`;
|
||
messageArea.appendChild(div);
|
||
scrollToBottom();
|
||
}
|
||
function removeTypingIndicator() { const el = document.getElementById('typingIndicator'); if (el) el.remove(); }
|
||
function scrollToBottom() { messageArea.scrollTop = messageArea.scrollHeight; }
|
||
function selectTargetLang(btn, flag, name) {
|
||
document.querySelectorAll('.lang-bar .lang-chip').forEach(c => c.classList.remove('selected'));
|
||
btn.classList.add('selected');
|
||
currentTarget = { flag, name, code: 'zh-CN' };
|
||
document.getElementById('targetLang').innerHTML = `<span class="flag">${flag}</span><span>${name}</span>`;
|
||
showToast(`🎯 目标语言: ${flag} ${name}`);
|
||
}
|
||
function toggleSettings() {
|
||
const overlay = document.getElementById('settingsOverlay');
|
||
const sheet = document.getElementById('settingsSheet');
|
||
const isOpen = sheet.classList.contains('show');
|
||
if (isOpen) { overlay.classList.remove('show'); sheet.classList.remove('show'); }
|
||
else { overlay.classList.add('show'); sheet.classList.add('show'); }
|
||
}
|
||
function selectApi(el) {
|
||
document.querySelectorAll('.api-item').forEach(i => i.classList.remove('selected'));
|
||
el.classList.add('selected');
|
||
showToast(`✅ 已选择: ${el.querySelector('.api-name').textContent}`);
|
||
}
|
||
function copyText(text) { navigator.clipboard?.writeText(text).then(() => showToast('✅ 已复制到剪贴板')).catch(() => showToast('✅ 已复制')); }
|
||
function showToast(msg) { const toast = document.getElementById('toast'); toast.textContent = msg; toast.classList.add('show'); setTimeout(() => toast.classList.remove('show'), 2000); }
|
||
function switchToTranslate() {
|
||
const badge = document.getElementById('translateBadge');
|
||
if (badge) badge.style.display = 'none';
|
||
document.getElementById('phone-translate').scrollIntoView({ behavior: 'smooth', inline: 'center' });
|
||
showToast('📱 切换到翻译助手');
|
||
}
|
||
function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; }
|
||
</script>
|
||
</body>
|
||
</html>
|