862 lines
38 KiB
HTML
862 lines
38 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>工具栏统一设计 v1.2 - 状态徽标 + 展开面板</title>
|
|
<style>
|
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
body {
|
|
font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
background: linear-gradient(135deg, #e0e7ff 0%, #f3e8ff 50%, #fce7f3 100%);
|
|
color: #1a1a1a;
|
|
padding: 24px;
|
|
line-height: 1.5;
|
|
-webkit-font-smoothing: antialiased;
|
|
min-height: 100vh;
|
|
}
|
|
h1 { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; margin-bottom: 8px; color: #1a1a1a; }
|
|
h2 { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; margin: 32px 0 12px; color: #1a1a1a; }
|
|
h3 { font-size: 14px; font-weight: 600; margin: 12px 0 8px; color: #333; }
|
|
.meta { color: #6b7280; font-size: 12.5px; margin-bottom: 20px; }
|
|
|
|
/* === ChatPanel 整体 === */
|
|
.chatpanel-mock {
|
|
width: 100%;
|
|
max-width: 720px;
|
|
margin: 0 auto;
|
|
background: rgba(255, 255, 255, 0.85);
|
|
backdrop-filter: blur(20px) saturate(180%);
|
|
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
border: 1px solid rgba(255, 255, 255, 0.9);
|
|
border-radius: 16px;
|
|
box-shadow: 0 8px 32px rgba(99, 102, 241, 0.1);
|
|
overflow: hidden;
|
|
position: relative;
|
|
}
|
|
.chatpanel-mock-header {
|
|
padding: 12px 16px;
|
|
border-bottom: 1px solid rgba(99, 102, 241, 0.1);
|
|
background: rgba(255, 255, 255, 0.5);
|
|
font-size: 13px;
|
|
color: #6b7280;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.chatpanel-mock-header .dot { width: 8px; height: 8px; border-radius: 50%; background: #10b981; }
|
|
|
|
/* === 消息流区域 === */
|
|
.chatpanel-mock-messages {
|
|
min-height: 200px;
|
|
padding: 20px 16px;
|
|
background: linear-gradient(180deg, #fafbfc 0%, #f5f7fa 100%);
|
|
}
|
|
.mock-msg {
|
|
max-width: 70%;
|
|
padding: 8px 12px;
|
|
border-radius: 12px;
|
|
margin-bottom: 8px;
|
|
font-size: 13px;
|
|
line-height: 1.5;
|
|
}
|
|
.mock-msg.user {
|
|
margin-left: auto;
|
|
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
|
color: #fff;
|
|
}
|
|
.mock-msg.ai {
|
|
background: rgba(255, 255, 255, 0.8);
|
|
color: #1a1a1a;
|
|
border: 1px solid rgba(99, 102, 241, 0.1);
|
|
}
|
|
.mock-msg .meta { font-size: 10.5px; opacity: 0.7; margin-bottom: 2px; color: #6b7280; }
|
|
.mock-msg.user .meta { color: rgba(255, 255, 255, 0.7); }
|
|
|
|
/* === InputBar(消息发送框) === */
|
|
.inputbar-mock {
|
|
background: rgba(255, 255, 255, 0.7);
|
|
backdrop-filter: blur(20px) saturate(180%);
|
|
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
border-top: 1px solid rgba(99, 102, 241, 0.15);
|
|
padding: 12px 16px 16px;
|
|
position: relative;
|
|
}
|
|
|
|
/* === 4 按钮工具栏(InputBar 内上方居中) === */
|
|
.glass-toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
padding: 8px 16px;
|
|
margin: 0 auto 12px;
|
|
width: fit-content;
|
|
background: rgba(255, 255, 255, 0.55);
|
|
backdrop-filter: blur(28px) saturate(180%);
|
|
-webkit-backdrop-filter: blur(28px) saturate(180%);
|
|
border: 1px solid rgba(255, 255, 255, 0.7);
|
|
border-radius: 20px;
|
|
box-shadow:
|
|
0 1px 0 rgba(255, 255, 255, 0.9) inset,
|
|
0 -1px 0 rgba(99, 102, 241, 0.08) inset,
|
|
0 2px 4px rgba(99, 102, 241, 0.05),
|
|
0 8px 16px rgba(99, 102, 241, 0.08),
|
|
0 24px 48px rgba(99, 102, 241, 0.05);
|
|
position: relative;
|
|
}
|
|
.glass-toolbar::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
border-radius: 20px;
|
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.6) 0%, rgba(255, 255, 255, 0.1) 40%, transparent 60%);
|
|
pointer-events: none;
|
|
}
|
|
.glass-toolbar::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
border-radius: 20px;
|
|
background: radial-gradient(circle at 20% 20%, rgba(99, 102, 241, 0.15) 0%, transparent 50%),
|
|
radial-gradient(circle at 80% 80%, rgba(236, 72, 153, 0.12) 0%, transparent 50%);
|
|
pointer-events: none;
|
|
z-index: 0;
|
|
}
|
|
|
|
/* === 4 按钮(40px 圆形玻璃) === */
|
|
.glass-btn {
|
|
width: 40px;
|
|
height: 40px;
|
|
border: 1px solid rgba(255, 255, 255, 0.6);
|
|
background: rgba(255, 255, 255, 0.55);
|
|
backdrop-filter: blur(20px);
|
|
-webkit-backdrop-filter: blur(20px);
|
|
border-radius: 50%;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
-webkit-tap-highlight-color: transparent;
|
|
position: relative;
|
|
z-index: 2;
|
|
box-shadow:
|
|
0 1px 0 rgba(255, 255, 255, 0.9) inset,
|
|
0 -1px 0 rgba(0, 0, 0, 0.04) inset,
|
|
0 1px 2px rgba(0, 0, 0, 0.04),
|
|
0 2px 4px rgba(0, 0, 0, 0.04);
|
|
overflow: visible;
|
|
}
|
|
.glass-btn:hover {
|
|
background: rgba(255, 255, 255, 0.75);
|
|
transform: translateY(-1px) scale(1.06);
|
|
box-shadow:
|
|
0 1px 0 rgba(255, 255, 255, 1) inset,
|
|
0 -1px 0 rgba(0, 0, 0, 0.04) inset,
|
|
0 2px 4px rgba(0, 0, 0, 0.06),
|
|
0 8px 16px rgba(99, 102, 241, 0.15);
|
|
}
|
|
.glass-btn:active { transform: translateY(0) scale(0.95); }
|
|
.glass-btn svg { width: 22px; height: 22px; display: block; }
|
|
|
|
/* === 表情激活(黄橙渐变) === */
|
|
.glass-btn.is-active-emoji {
|
|
background: linear-gradient(135deg, rgba(251, 191, 36, 0.9) 0%, rgba(245, 158, 11, 0.9) 100%);
|
|
border-color: rgba(255, 255, 255, 0.4);
|
|
}
|
|
.glass-btn.is-active-emoji::before {
|
|
content: ""; position: absolute; inset: 1px; border-radius: 50%;
|
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.35) 0%, transparent 50%);
|
|
pointer-events: none;
|
|
}
|
|
/* === 文件激活(蓝紫渐变) === */
|
|
.glass-btn.is-active-file {
|
|
background: linear-gradient(135deg, rgba(59, 130, 246, 0.9) 0%, rgba(37, 99, 235, 0.9) 100%);
|
|
border-color: rgba(255, 255, 255, 0.4);
|
|
}
|
|
.glass-btn.is-active-file::before {
|
|
content: ""; position: absolute; inset: 1px; border-radius: 50%;
|
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.35) 0%, transparent 50%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* === 语音:颜色+形态双变 === */
|
|
.glass-btn.is-voice-recording {
|
|
background: linear-gradient(135deg, rgba(239, 68, 68, 0.95) 0%, rgba(220, 38, 38, 0.95) 100%);
|
|
border-color: rgba(255, 255, 255, 0.4);
|
|
animation: recordingPulse 1.5s ease-in-out infinite;
|
|
}
|
|
@keyframes recordingPulse {
|
|
0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0), 0 1px 0 rgba(255, 255, 255, 0.9) inset; }
|
|
50% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0.15), 0 1px 0 rgba(255, 255, 255, 0.9) inset; }
|
|
}
|
|
.glass-btn.is-voice-recognized {
|
|
background: linear-gradient(135deg, rgba(16, 185, 129, 0.95) 0%, rgba(5, 150, 105, 0.95) 100%);
|
|
border-color: rgba(255, 255, 255, 0.4);
|
|
}
|
|
|
|
/* === 坐席按钮(图片头像 44px + 状态徽标) === */
|
|
.agent-btn {
|
|
width: 44px;
|
|
height: 44px;
|
|
border-radius: 50%;
|
|
border: 2px solid transparent;
|
|
cursor: pointer;
|
|
position: relative;
|
|
z-index: 2;
|
|
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
-webkit-tap-highlight-color: transparent;
|
|
overflow: visible;
|
|
padding: 0;
|
|
background: linear-gradient(135deg, #6366f1 0%, #a855f7 50%, #ec4899 100%) padding-box;
|
|
}
|
|
.agent-btn::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: -2px;
|
|
border-radius: 50%;
|
|
background: linear-gradient(135deg, #6366f1 0%, #a855f7 50%, #ec4899 100%);
|
|
z-index: -1;
|
|
}
|
|
.agent-btn img {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
object-position: center 15%;
|
|
display: block;
|
|
}
|
|
.agent-btn:hover { transform: translateY(-1px) scale(1.05); }
|
|
|
|
/* === 状态徽标(头像右下角小圆点) === */
|
|
.agent-badge {
|
|
position: absolute;
|
|
bottom: 0;
|
|
right: 0;
|
|
width: 12px;
|
|
height: 12px;
|
|
border-radius: 50%;
|
|
border: 2px solid white;
|
|
z-index: 3;
|
|
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
|
}
|
|
.agent-badge.is-online { background: #10b981; } /* 绿 = 在线 */
|
|
.agent-badge.is-urgent { background: #ef4444; } /* 红 = 紧急 */
|
|
.agent-badge.is-waiting { background: #f59e0b; } /* 橙 = 等待 */
|
|
.agent-badge.is-offline { background: #9ca3af; } /* 灰 = 离线 */
|
|
.agent-badge.is-end { background: #3b82f6; } /* 蓝 = 结束/重连 */
|
|
|
|
/* 紧急状态 - 徽标呼吸 */
|
|
.agent-btn.is-urgent .agent-badge { animation: badgePulse 1.5s ease-in-out infinite; }
|
|
@keyframes badgePulse {
|
|
0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.6), 0 1px 2px rgba(0,0,0,0.2); }
|
|
50% { box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.3), 0 1px 2px rgba(0,0,0,0.2); }
|
|
}
|
|
|
|
/* === InputBar 输入框 === */
|
|
.inputbar-mock-field {
|
|
width: 100%;
|
|
min-height: 60px;
|
|
background: rgba(255, 255, 255, 0.5);
|
|
border: 1px solid rgba(99, 102, 241, 0.12);
|
|
border-radius: 12px;
|
|
padding: 10px 14px;
|
|
font-size: 13px;
|
|
color: #9ca3af;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
/* === 演示容器 === */
|
|
.demo-block {
|
|
background: rgba(255, 255, 255, 0.6);
|
|
backdrop-filter: blur(20px);
|
|
-webkit-backdrop-filter: blur(20px);
|
|
border: 1px solid rgba(255, 255, 255, 0.7);
|
|
border-radius: 18px;
|
|
padding: 24px;
|
|
margin-bottom: 20px;
|
|
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset, 0 8px 16px rgba(99, 102, 241, 0.06);
|
|
}
|
|
.demo-label { font-size: 11.5px; color: #6b7280; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 14px; font-weight: 500; }
|
|
|
|
.state-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 20px; padding-bottom: 16px; border-bottom: 1px solid rgba(99, 102, 241, 0.12); }
|
|
.state-tab {
|
|
padding: 6px 12px;
|
|
border: 1px solid rgba(99, 102, 241, 0.2);
|
|
background: rgba(255, 255, 255, 0.6);
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
font-size: 12.5px;
|
|
color: #4b5563;
|
|
transition: all 0.15s;
|
|
font-family: inherit;
|
|
}
|
|
.state-tab:hover { background: rgba(255, 255, 255, 0.8); }
|
|
.state-tab.active { background: linear-gradient(135deg, #6366f1, #8b5cf6); color: #fff; border-color: transparent; }
|
|
|
|
.state-desc { color: #4b5563; font-size: 12.5px; line-height: 1.7; background: rgba(255, 255, 255, 0.5); padding: 12px 14px; border-radius: 10px; border-left: 2px solid #6366f1; margin-top: 12px; backdrop-filter: blur(10px); }
|
|
.state-desc strong { color: #1a1a1a; }
|
|
|
|
.note { background: rgba(254, 243, 199, 0.6); border-left: 3px solid #d97706; padding: 12px 16px; border-radius: 4px; font-size: 12.5px; color: #78350f; margin: 16px 0; backdrop-filter: blur(10px); }
|
|
|
|
/* === 表情面板(从 InputBar 顶部上滑展开) === */
|
|
.emoji-panel {
|
|
background: rgba(255, 255, 255, 0.85);
|
|
backdrop-filter: blur(20px) saturate(180%);
|
|
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
border: 1px solid rgba(99, 102, 241, 0.15);
|
|
border-radius: 14px;
|
|
padding: 12px;
|
|
margin-bottom: 12px;
|
|
box-shadow: 0 -4px 16px rgba(99, 102, 241, 0.1);
|
|
animation: slideUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
@keyframes slideUp {
|
|
from { opacity: 0; transform: translateY(20px); max-height: 0; }
|
|
to { opacity: 1; transform: translateY(0); max-height: 400px; }
|
|
}
|
|
.emoji-panel-tabs {
|
|
display: flex;
|
|
gap: 4px;
|
|
margin-bottom: 10px;
|
|
padding-bottom: 8px;
|
|
border-bottom: 1px solid rgba(99, 102, 241, 0.1);
|
|
}
|
|
.emoji-panel-tab {
|
|
padding: 4px 10px;
|
|
border-radius: 6px;
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
color: #6b7280;
|
|
transition: all 0.15s;
|
|
}
|
|
.emoji-panel-tab.active { background: linear-gradient(135deg, #6366f1, #8b5cf6); color: white; }
|
|
.emoji-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(8, 1fr);
|
|
gap: 4px;
|
|
max-height: 180px;
|
|
overflow-y: auto;
|
|
}
|
|
.emoji-cell {
|
|
aspect-ratio: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 22px;
|
|
cursor: pointer;
|
|
border-radius: 6px;
|
|
transition: background 0.15s;
|
|
}
|
|
.emoji-cell:hover { background: rgba(99, 102, 241, 0.1); }
|
|
|
|
/* === 文件面板 === */
|
|
.file-panel {
|
|
background: rgba(255, 255, 255, 0.85);
|
|
backdrop-filter: blur(20px) saturate(180%);
|
|
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
border: 1px solid rgba(99, 102, 241, 0.15);
|
|
border-radius: 14px;
|
|
padding: 12px;
|
|
margin-bottom: 12px;
|
|
box-shadow: 0 -4px 16px rgba(99, 102, 241, 0.1);
|
|
animation: slideUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
.file-panel-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 8px;
|
|
}
|
|
.file-panel-item {
|
|
aspect-ratio: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 4px;
|
|
background: rgba(99, 102, 241, 0.05);
|
|
border-radius: 10px;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
font-size: 11.5px;
|
|
color: #4b5563;
|
|
}
|
|
.file-panel-item:hover { background: rgba(99, 102, 241, 0.12); transform: translateY(-1px); }
|
|
.file-panel-item .icon { font-size: 26px; }
|
|
|
|
/* === InputBar 扩展演示容器 === */
|
|
.inputbar-stage {
|
|
background: rgba(255, 255, 255, 0.7);
|
|
backdrop-filter: blur(20px) saturate(180%);
|
|
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
border: 1px solid rgba(99, 102, 241, 0.15);
|
|
border-radius: 12px;
|
|
padding: 12px;
|
|
overflow: hidden;
|
|
min-height: 80px;
|
|
}
|
|
|
|
/* === 4 状态网格(坐席徽标+语音形态) === */
|
|
.status-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 16px;
|
|
}
|
|
.status-card {
|
|
background: rgba(255, 255, 255, 0.5);
|
|
border: 1px solid rgba(99, 102, 241, 0.15);
|
|
border-radius: 12px;
|
|
padding: 20px 12px;
|
|
text-align: center;
|
|
}
|
|
.status-card .label { font-size: 11px; color: #6b7280; margin-top: 10px; font-weight: 500; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<svg width="0" height="0" style="position: absolute;">
|
|
<defs>
|
|
<linearGradient id="g-emoji" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#fde68a"/><stop offset="60%" stop-color="#fbbf24"/><stop offset="100%" stop-color="#d97706"/>
|
|
</linearGradient>
|
|
<radialGradient id="g-emoji-blush" cx="50%" cy="50%" r="50%">
|
|
<stop offset="0%" stop-color="rgba(244, 63, 94, 0.4)"/>
|
|
<stop offset="100%" stop-color="rgba(244, 63, 94, 0)"/>
|
|
</radialGradient>
|
|
<linearGradient id="g-highlight" x1="50%" y1="0%" x2="50%" y2="100%">
|
|
<stop offset="0%" stop-color="white" stop-opacity="0.7"/>
|
|
<stop offset="100%" stop-color="white" stop-opacity="0"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-doc-body" x1="50%" y1="0%" x2="50%" y2="100%">
|
|
<stop offset="0%" stop-color="#ffffff"/><stop offset="100%" stop-color="#dbeafe"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-doc-fold" x1="50%" y1="0%" x2="50%" y2="100%">
|
|
<stop offset="0%" stop-color="#c7d2fe"/><stop offset="100%" stop-color="#6366f1"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-doc-text" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
<stop offset="0%" stop-color="#6366f1"/><stop offset="100%" stop-color="#a855f7"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-mic-body" x1="50%" y1="0%" x2="50%" y2="100%">
|
|
<stop offset="0%" stop-color="#c4b5fd"/><stop offset="50%" stop-color="#8b5cf6"/><stop offset="100%" stop-color="#6d28d9"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-mic-shine" x1="50%" y1="0%" x2="50%" y2="100%">
|
|
<stop offset="0%" stop-color="white" stop-opacity="0.65"/><stop offset="100%" stop-color="white" stop-opacity="0"/>
|
|
</linearGradient>
|
|
</defs>
|
|
</svg>
|
|
|
|
<h1>工具栏统一设计 v1.2 — 状态徽标 + 颜色&形态双变 + 展开面板</h1>
|
|
<p class="meta">v1.1 基础 + 3 项关键决策 · 坐席徽标(头像右下角) · 语音形态双变 · 表情/文件面板从 InputBar 顶部上滑展开 · 2026-08-04</p>
|
|
|
|
<div class="note">
|
|
📌 <strong>v1.2 三大升级</strong>(基于你的 3 项决策):<br>
|
|
• 🎭 <strong>坐席状态:只用头像+徽标</strong>(绿/红/橙/灰/蓝 5 色徽标,圆角头像不变色)<br>
|
|
• 🎙️ <strong>语音状态:颜色+形态双变</strong>(话筒→红色脉动声波→绿色对勾)<br>
|
|
• 📤 <strong>展开面板:从 InputBar 顶部上滑</strong>(表情网格 / 文件选择面板)
|
|
</div>
|
|
|
|
<h2>🎨 ChatPanel 完整布局(工具栏在 InputBar 内)</h2>
|
|
<div class="chatpanel-mock">
|
|
<div class="chatpanel-mock-header">
|
|
<span class="dot"></span>
|
|
<span>IT 智能服务台 · 在线 · 客服小王</span>
|
|
</div>
|
|
<div class="chatpanel-mock-messages">
|
|
<div class="mock-msg user">
|
|
<div class="meta">我 10:23</div>
|
|
你好,我电脑经常蓝屏
|
|
</div>
|
|
<div class="mock-msg ai">
|
|
<div class="meta">AI 10:23</div>
|
|
您好!电脑蓝屏可能由驱动/内存/温度等问题引起。建议先尝试安全模式启动...
|
|
</div>
|
|
<div class="mock-msg user">
|
|
<div class="meta">我 10:25</div>
|
|
还有其他办法吗?紧急,需要尽快恢复
|
|
</div>
|
|
</div>
|
|
|
|
<!-- InputBar(消息发送框) -->
|
|
<div class="inputbar-mock">
|
|
<!-- 4 按钮工具栏(InputBar 内上方居中) -->
|
|
<div class="glass-toolbar" id="toolbar-stage">
|
|
<!-- 1. 表情 -->
|
|
<button class="glass-btn" title="表情">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<circle cx="12" cy="12" r="9" fill="url(#g-emoji)"/>
|
|
<ellipse cx="12" cy="6" rx="6" ry="2.5" fill="url(#g-highlight)"/>
|
|
<ellipse cx="6.5" cy="14" rx="1.5" ry="1" fill="url(#g-emoji-blush)"/>
|
|
<ellipse cx="17.5" cy="14" rx="1.5" ry="1" fill="url(#g-emoji-blush)"/>
|
|
<ellipse cx="8.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
|
|
<ellipse cx="15.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
|
|
<circle cx="8.9" cy="10.4" r="0.5" fill="white"/>
|
|
<circle cx="15.9" cy="10.4" r="0.5" fill="white"/>
|
|
<path d="M8 15 Q12 18 16 15" fill="none" stroke="#1e1b4b" stroke-width="1.6" stroke-linecap="round"/>
|
|
<path d="M8 15 Q12 17 16 15" fill="rgba(244, 63, 94, 0.2)"/>
|
|
</svg>
|
|
</button>
|
|
<!-- 2. 文件 -->
|
|
<button class="glass-btn" title="文件">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<path d="M4 2 L14 2 L20 8 L20 20 L4 20 Z" fill="url(#g-doc-body)" stroke="#818cf8" stroke-width="0.8" stroke-linejoin="round"/>
|
|
<path d="M14 2 L14 8 L20 8" fill="url(#g-doc-fold)" stroke="#818cf8" stroke-width="0.8" stroke-linejoin="round"/>
|
|
<ellipse cx="10" cy="4" rx="5" ry="0.8" fill="url(#g-highlight)"/>
|
|
<rect x="7" y="11.5" width="10" height="0.8" rx="0.4" fill="url(#g-doc-text)"/>
|
|
<rect x="7" y="14" width="8" height="0.8" rx="0.4" fill="url(#g-doc-text)" opacity="0.7"/>
|
|
<rect x="7" y="16.5" width="6" height="0.8" rx="0.4" fill="url(#g-doc-text)" opacity="0.5"/>
|
|
</svg>
|
|
</button>
|
|
<!-- 3. 语音 -->
|
|
<button class="glass-btn" title="语音输入">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<rect x="8" y="2" width="8" height="13" rx="4" fill="url(#g-mic-body)"/>
|
|
<rect x="9" y="3" width="2" height="11" rx="1" fill="url(#g-mic-shine)"/>
|
|
<line x1="10.5" y1="6" x2="10.5" y2="11" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<line x1="12" y1="5" x2="12" y2="12" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<line x1="13.5" y1="6" x2="13.5" y2="11" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<path d="M3 12 Q3 18 12 18 Q21 18 21 12" fill="none" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="12" y1="18" x2="12" y2="22" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="8" y1="22" x2="16" y2="22" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
</svg>
|
|
</button>
|
|
<!-- 4. 坐席(图片头像 + 状态徽标) -->
|
|
<button class="agent-btn" title="客服在线">
|
|
<img src="./agent-avatar-v0.8.jpg" alt="客服" />
|
|
<span class="agent-badge is-online"></span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 输入框 -->
|
|
<div class="inputbar-mock-field">
|
|
请输入消息...(输入框在工具栏下方,用户打字区)
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>🎙️ 语音按钮 - 颜色+形态双变(3 状态)</h2>
|
|
<div class="demo-block">
|
|
<div class="demo-label">点击下方 Tab 切换语音按钮形态</div>
|
|
<div class="state-tabs" id="voice-tabs">
|
|
<button class="state-tab active" data-voice="default">① 默认(话筒)</button>
|
|
<button class="state-tab" data-voice="recording">② 录音中(红色脉动声波)</button>
|
|
<button class="state-tab" data-voice="recognized">③ 已识别(绿色对勾)</button>
|
|
</div>
|
|
<div class="inputbar-stage">
|
|
<div class="glass-toolbar" id="voice-stage" style="margin: 0 auto;"></div>
|
|
</div>
|
|
<div class="state-desc" id="voice-desc"></div>
|
|
</div>
|
|
|
|
<h2>🎭 坐席按钮 - 头像 + 状态徽标(5 色)</h2>
|
|
<div class="demo-block">
|
|
<div class="demo-label">徽标颜色映射坐席状态,头像本体不变色</div>
|
|
<div class="status-grid">
|
|
<div class="status-card">
|
|
<div class="glass-toolbar" style="margin: 0 auto; padding: 16px 24px;">
|
|
<button class="agent-btn" style="cursor: default;">
|
|
<img src="./agent-avatar-v0.8.jpg" alt="客服" />
|
|
<span class="agent-badge is-online"></span>
|
|
</button>
|
|
</div>
|
|
<div class="label">在线 🟢</div>
|
|
</div>
|
|
<div class="status-card">
|
|
<div class="glass-toolbar" style="margin: 0 auto; padding: 16px 24px;">
|
|
<button class="agent-btn is-urgent" style="cursor: default;">
|
|
<img src="./agent-avatar-v0.8.jpg" alt="客服" />
|
|
<span class="agent-badge is-urgent"></span>
|
|
</button>
|
|
</div>
|
|
<div class="label">紧急 🔴 (徽标呼吸)</div>
|
|
</div>
|
|
<div class="status-card">
|
|
<div class="glass-toolbar" style="margin: 0 auto; padding: 16px 24px;">
|
|
<button class="agent-btn" style="cursor: default;">
|
|
<img src="./agent-avatar-v0.8.jpg" alt="客服" />
|
|
<span class="agent-badge is-waiting"></span>
|
|
</button>
|
|
</div>
|
|
<div class="label">等待 🟠</div>
|
|
</div>
|
|
<div class="status-card">
|
|
<div class="glass-toolbar" style="margin: 0 auto; padding: 16px 24px;">
|
|
<button class="agent-btn" style="cursor: default;">
|
|
<img src="./agent-avatar-v0.8.jpg" alt="客服" />
|
|
<span class="agent-badge is-end"></span>
|
|
</button>
|
|
</div>
|
|
<div class="label">结束/重连 🔵</div>
|
|
</div>
|
|
</div>
|
|
<div class="status-grid" style="grid-template-columns: 1fr; margin-top: 16px;">
|
|
<div class="status-card" style="padding: 16px 12px;">
|
|
<div class="glass-toolbar" style="margin: 0 auto; padding: 12px 16px;">
|
|
<button class="agent-btn" style="cursor: default; opacity: 0.4; filter: grayscale(0.7);">
|
|
<img src="./agent-avatar-v0.8.jpg" alt="客服" />
|
|
<span class="agent-badge is-offline"></span>
|
|
</button>
|
|
</div>
|
|
<div class="label">离线 ⚫ (灰度+灰色徽标)</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>📤 表情面板 - 从 InputBar 顶部上滑展开</h2>
|
|
<div class="demo-block">
|
|
<div class="demo-label">点击表情按钮 → 表情网格从工具栏下方(InputBar 内)向上滑出</div>
|
|
<div class="inputbar-stage" style="padding: 0;">
|
|
<div class="inputbar-mock" style="border-radius: 12px;">
|
|
<!-- 表情面板 -->
|
|
<div class="emoji-panel">
|
|
<div class="emoji-panel-tabs">
|
|
<span class="emoji-panel-tab active">😀 表情</span>
|
|
<span class="emoji-panel-tab">🐶 动物</span>
|
|
<span class="emoji-panel-tab">🍔 食物</span>
|
|
<span class="emoji-panel-tab">⚽ 活动</span>
|
|
<span class="emoji-panel-tab">🚗 旅行</span>
|
|
<span class="emoji-panel-tab">💡 物品</span>
|
|
<span class="emoji-panel-tab">❤️ 符号</span>
|
|
</div>
|
|
<div class="emoji-grid">
|
|
<div class="emoji-cell">😀</div><div class="emoji-cell">😃</div><div class="emoji-cell">😄</div><div class="emoji-cell">😁</div>
|
|
<div class="emoji-cell">😆</div><div class="emoji-cell">😅</div><div class="emoji-cell">🤣</div><div class="emoji-cell">😂</div>
|
|
<div class="emoji-cell">🙂</div><div class="emoji-cell">🙃</div><div class="emoji-cell">😉</div><div class="emoji-cell">😊</div>
|
|
<div class="emoji-cell">😇</div><div class="emoji-cell">🥰</div><div class="emoji-cell">😍</div><div class="emoji-cell">🤩</div>
|
|
<div class="emoji-cell">😘</div><div class="emoji-cell">😗</div><div class="emoji-cell">☺️</div><div class="emoji-cell">😚</div>
|
|
<div class="emoji-cell">😙</div><div class="emoji-cell">🥲</div><div class="emoji-cell">😋</div><div class="emoji-cell">😛</div>
|
|
</div>
|
|
</div>
|
|
<!-- 4 按钮工具栏 -->
|
|
<div class="glass-toolbar" style="margin-bottom: 8px;">
|
|
<button class="glass-btn is-active-emoji" title="表情">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<circle cx="12" cy="12" r="9" fill="url(#g-emoji)"/>
|
|
<ellipse cx="12" cy="6" rx="6" ry="2.5" fill="url(#g-highlight)"/>
|
|
<ellipse cx="6.5" cy="14" rx="1.5" ry="1" fill="url(#g-emoji-blush)"/>
|
|
<ellipse cx="17.5" cy="14" rx="1.5" ry="1" fill="url(#g-emoji-blush)"/>
|
|
<ellipse cx="8.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
|
|
<ellipse cx="15.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
|
|
<circle cx="8.9" cy="10.4" r="0.5" fill="white"/>
|
|
<circle cx="15.9" cy="10.4" r="0.5" fill="white"/>
|
|
<path d="M8 15 Q12 18 16 15" fill="none" stroke="#1e1b4b" stroke-width="1.6" stroke-linecap="round"/>
|
|
</svg>
|
|
</button>
|
|
<button class="glass-btn" title="文件">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<path d="M4 2 L14 2 L20 8 L20 20 L4 20 Z" fill="url(#g-doc-body)" stroke="#818cf8" stroke-width="0.8" stroke-linejoin="round"/>
|
|
<path d="M14 2 L14 8 L20 8" fill="url(#g-doc-fold)" stroke="#818cf8" stroke-width="0.8" stroke-linejoin="round"/>
|
|
<ellipse cx="10" cy="4" rx="5" ry="0.8" fill="url(#g-highlight)"/>
|
|
<rect x="7" y="11.5" width="10" height="0.8" rx="0.4" fill="url(#g-doc-text)"/>
|
|
<rect x="7" y="14" width="8" height="0.8" rx="0.4" fill="url(#g-doc-text)" opacity="0.7"/>
|
|
<rect x="7" y="16.5" width="6" height="0.8" rx="0.4" fill="url(#g-doc-text)" opacity="0.5"/>
|
|
</svg>
|
|
</button>
|
|
<button class="glass-btn" title="语音输入">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<rect x="8" y="2" width="8" height="13" rx="4" fill="url(#g-mic-body)"/>
|
|
<rect x="9" y="3" width="2" height="11" rx="1" fill="url(#g-mic-shine)"/>
|
|
<line x1="10.5" y1="6" x2="10.5" y2="11" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<line x1="12" y1="5" x2="12" y2="12" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<line x1="13.5" y1="6" x2="13.5" y2="11" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<path d="M3 12 Q3 18 12 18 Q21 18 21 12" fill="none" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="12" y1="18" x2="12" y2="22" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="8" y1="22" x2="16" y2="22" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
</svg>
|
|
</button>
|
|
<button class="agent-btn" title="客服在线">
|
|
<img src="./agent-avatar-v0.8.jpg" alt="客服" />
|
|
<span class="agent-badge is-online"></span>
|
|
</button>
|
|
</div>
|
|
<div class="inputbar-mock-field" style="min-height: 40px; padding: 6px 12px; font-size: 12px;">输入框</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>📁 文件面板 - 从 InputBar 顶部上滑展开</h2>
|
|
<div class="demo-block">
|
|
<div class="demo-label">点击文件按钮 → 文件选择面板从工具栏下方(InputBar 内)向上滑出</div>
|
|
<div class="inputbar-stage" style="padding: 0;">
|
|
<div class="inputbar-mock" style="border-radius: 12px;">
|
|
<!-- 文件面板 -->
|
|
<div class="file-panel">
|
|
<div class="file-panel-grid">
|
|
<div class="file-panel-item"><div class="icon">🖼️</div>图片</div>
|
|
<div class="file-panel-item"><div class="icon">📄</div>文档</div>
|
|
<div class="file-panel-item"><div class="icon">🎬</div>视频</div>
|
|
<div class="file-panel-item"><div class="icon">🎵</div>音频</div>
|
|
<div class="file-panel-item"><div class="icon">📷</div>拍照</div>
|
|
<div class="file-panel-item"><div class="icon">📁</div>文件夹</div>
|
|
<div class="file-panel-item"><div class="icon">📎</div>其他</div>
|
|
<div class="file-panel-item"><div class="icon">📊</div>表格</div>
|
|
</div>
|
|
</div>
|
|
<!-- 4 按钮工具栏 -->
|
|
<div class="glass-toolbar" style="margin-bottom: 8px;">
|
|
<button class="glass-btn" title="表情">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<circle cx="12" cy="12" r="9" fill="url(#g-emoji)"/>
|
|
<ellipse cx="12" cy="6" rx="6" ry="2.5" fill="url(#g-highlight)"/>
|
|
<ellipse cx="8.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
|
|
<ellipse cx="15.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
|
|
<circle cx="8.9" cy="10.4" r="0.5" fill="white"/>
|
|
<circle cx="15.9" cy="10.4" r="0.5" fill="white"/>
|
|
<path d="M8 15 Q12 18 16 15" fill="none" stroke="#1e1b4b" stroke-width="1.6" stroke-linecap="round"/>
|
|
</svg>
|
|
</button>
|
|
<button class="glass-btn is-active-file" title="文件">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<path d="M4 2 L14 2 L20 8 L20 20 L4 20 Z" fill="url(#g-doc-body)" stroke="#818cf8" stroke-width="0.8" stroke-linejoin="round"/>
|
|
<path d="M14 2 L14 8 L20 8" fill="url(#g-doc-fold)" stroke="#818cf8" stroke-width="0.8" stroke-linejoin="round"/>
|
|
<ellipse cx="10" cy="4" rx="5" ry="0.8" fill="url(#g-highlight)"/>
|
|
<rect x="7" y="11.5" width="10" height="0.8" rx="0.4" fill="url(#g-doc-text)"/>
|
|
<rect x="7" y="14" width="8" height="0.8" rx="0.4" fill="url(#g-doc-text)" opacity="0.7"/>
|
|
<rect x="7" y="16.5" width="6" height="0.8" rx="0.4" fill="url(#g-doc-text)" opacity="0.5"/>
|
|
</svg>
|
|
</button>
|
|
<button class="glass-btn" title="语音输入">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<rect x="8" y="2" width="8" height="13" rx="4" fill="url(#g-mic-body)"/>
|
|
<rect x="9" y="3" width="2" height="11" rx="1" fill="url(#g-mic-shine)"/>
|
|
<line x1="10.5" y1="6" x2="10.5" y2="11" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<line x1="12" y1="5" x2="12" y2="12" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<line x1="13.5" y1="6" x2="13.5" y2="11" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<path d="M3 12 Q3 18 12 18 Q21 18 21 12" fill="none" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="12" y1="18" x2="12" y2="22" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="8" y1="22" x2="16" y2="22" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
</svg>
|
|
</button>
|
|
<button class="agent-btn" title="客服在线">
|
|
<img src="./agent-avatar-v0.8.jpg" alt="客服" />
|
|
<span class="agent-badge is-online"></span>
|
|
</button>
|
|
</div>
|
|
<div class="inputbar-mock-field" style="min-height: 40px; padding: 6px 12px; font-size: 12px;">输入框</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>📊 v1.1 vs v1.2 关键差异</h2>
|
|
<table style="width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12.5px;">
|
|
<thead>
|
|
<tr style="background: rgba(255, 255, 255, 0.6);">
|
|
<th style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px; text-align: left;">维度</th>
|
|
<th style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px; text-align: left;">v1.1</th>
|
|
<th style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px; text-align: left;"><strong>v1.2</strong></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">坐席状态</td>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">按钮边框变色(紫粉/红/橙/绿/蓝)</td>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;"><strong>头像右下角徽标(5 色)</strong> 简洁不喧宾夺主</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">语音形态</td>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">只换颜色(灰/紫/红)</td>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;"><strong>颜色+形态双变</strong>(话筒→红色脉动声波→绿色对勾)</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">展开面板</td>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">未实现(占位)</td>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;"><strong>表情网格 / 文件选择器</strong>,从 InputBar 顶部上滑(slideUp 0.3s)</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">离线坐席</td>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">灰色边框</td>
|
|
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;"><strong>整体灰度 + 灰色徽标</strong>(完全弱化)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<p style="margin-top: 32px; padding-top: 16px; border-top: 1px solid rgba(99, 102, 241, 0.15); color: #6b7280; font-size: 11.5px;">
|
|
v1.2 状态徽标 + 颜色&形态双变 + 展开面板 · 2026-08-04 · Duckula 主理人 · 等待用户最终拍板进入开发
|
|
</p>
|
|
|
|
<script>
|
|
// === 语音状态切换 ===
|
|
const voiceMap = {
|
|
'default': {
|
|
cls: '',
|
|
svg: `<svg viewBox="0 0 24 24" fill="none">
|
|
<rect x="8" y="2" width="8" height="13" rx="4" fill="url(#g-mic-body)"/>
|
|
<rect x="9" y="3" width="2" height="11" rx="1" fill="url(#g-mic-shine)"/>
|
|
<line x1="10.5" y1="6" x2="10.5" y2="11" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<line x1="12" y1="5" x2="12" y2="12" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<line x1="13.5" y1="6" x2="13.5" y2="11" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<path d="M3 12 Q3 18 12 18 Q21 18 21 12" fill="none" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="12" y1="18" x2="12" y2="22" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="8" y1="22" x2="16" y2="22" stroke="url(#g-mic-body)" stroke-width="2" stroke-linecap="round"/>
|
|
</svg>`,
|
|
desc: '<strong>① 默认状态</strong>:话筒图标 + 紫粉渐变。等待用户长按或点击开始录音'
|
|
},
|
|
'recording': {
|
|
cls: 'is-voice-recording',
|
|
svg: `<svg viewBox="0 0 24 24" fill="none">
|
|
<rect x="8" y="2" width="8" height="13" rx="4" fill="white"/>
|
|
<path d="M3 12 Q3 18 12 18 Q21 18 21 12" fill="none" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="12" y1="18" x2="12" y2="22" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="8" y1="22" x2="16" y2="22" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
|
<circle cx="5" cy="12" r="1.5" fill="white" opacity="0.8">
|
|
<animate attributeName="r" values="1.5;2.5;1.5" dur="1s" repeatCount="indefinite"/>
|
|
</circle>
|
|
<circle cx="19" cy="12" r="1.5" fill="white" opacity="0.8">
|
|
<animate attributeName="r" values="1.5;2.5;1.5" dur="1s" repeatCount="indefinite"/>
|
|
</circle>
|
|
</svg>`,
|
|
desc: '<strong>② 录音中</strong>:白色话筒 + 红色背景 + 1.5s 呼吸光环。两侧脉动声波提示正在收音,点击停止'
|
|
},
|
|
'recognized': {
|
|
cls: 'is-voice-recognized',
|
|
svg: `<svg viewBox="0 0 24 24" fill="none">
|
|
<circle cx="12" cy="12" r="9" fill="none" stroke="white" stroke-width="2"/>
|
|
<path d="M7 12 L11 16 L17 9" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</svg>`,
|
|
desc: '<strong>③ 已识别</strong>:绿色背景 + 白色对勾。语音识别成功,文本已填入输入框,可继续编辑发送'
|
|
}
|
|
};
|
|
|
|
const voiceTabs = document.querySelectorAll('#voice-tabs .state-tab');
|
|
const voiceStage = document.getElementById('voice-stage');
|
|
const voiceDesc = document.getElementById('voice-desc');
|
|
|
|
function renderVoice(state) {
|
|
const s = voiceMap[state];
|
|
voiceStage.innerHTML = `
|
|
<button class="glass-btn ${s.cls}" title="语音">${s.svg}</button>
|
|
<button class="glass-btn" title="表情" style="opacity: 0.5;">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<circle cx="12" cy="12" r="9" fill="url(#g-emoji)"/>
|
|
<ellipse cx="8.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
|
|
<ellipse cx="15.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
|
|
<path d="M8 15 Q12 18 16 15" fill="none" stroke="#1e1b4b" stroke-width="1.6" stroke-linecap="round"/>
|
|
</svg>
|
|
</button>
|
|
<button class="glass-btn" title="文件" style="opacity: 0.5;">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<path d="M4 2 L14 2 L20 8 L20 20 L4 20 Z" fill="url(#g-doc-body)" stroke="#818cf8" stroke-width="0.8"/>
|
|
<path d="M14 2 L14 8 L20 8" fill="url(#g-doc-fold)" stroke="#818cf8" stroke-width="0.8"/>
|
|
<rect x="7" y="11.5" width="10" height="0.8" rx="0.4" fill="url(#g-doc-text)"/>
|
|
</svg>
|
|
</button>
|
|
<button class="agent-btn" title="客服">
|
|
<img src="./agent-avatar-v0.8.jpg" alt="客服"/>
|
|
<span class="agent-badge is-online"></span>
|
|
</button>
|
|
`;
|
|
voiceDesc.innerHTML = s.desc;
|
|
}
|
|
|
|
voiceTabs.forEach(tab => {
|
|
tab.addEventListener('click', () => {
|
|
voiceTabs.forEach(t => t.classList.remove('active'));
|
|
tab.classList.add('active');
|
|
renderVoice(tab.dataset.voice);
|
|
});
|
|
});
|
|
|
|
renderVoice('default');
|
|
</script>
|
|
|
|
</body>
|
|
</html> |