Files
wecom_it_smart_desk/docs/01-产品文档/02-会话管理/原型-REQ-会话-001-工具栏统一设计v0.5-玻璃拟态.archive.html
T
2026-08-11 14:17:15 +08:00

551 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>工具栏统一设计 v0.5 - 玻璃拟态 + 立体图标</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: 32px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
min-height: 100vh;
}
h1 { font-size: 24px; font-weight: 600; letter-spacing: -0.02em; margin-bottom: 8px; color: #1a1a1a; }
h2 { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; margin: 40px 0 12px; color: #1a1a1a; }
h3 { font-size: 14px; font-weight: 600; margin: 16px 0 8px; color: #333; }
.meta { color: #6b7280; font-size: 12.5px; margin-bottom: 24px; }
/* === 整体玻璃拟态背景工具栏 === */
.glass-toolbar {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 6px 8px;
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: 18px;
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: 18px;
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: 18px;
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;
}
.glass-divider {
width: 1px;
height: 24px;
background: linear-gradient(180deg, transparent 0%, rgba(99, 102, 241, 0.2) 50%, transparent 100%);
margin: 0 4px;
position: relative;
z-index: 1;
}
/* === 玻璃拟态按钮(38px 圆形) === */
.glass-btn {
width: 38px;
height: 38px;
border: 1px solid rgba(255, 255, 255, 0.6);
background: rgba(255, 255, 255, 0.5);
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);
}
.glass-btn:hover {
background: rgba(255, 255, 255, 0.7);
transform: translateY(-1px) scale(1.04);
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 6px 12px rgba(99, 102, 241, 0.12);
}
.glass-btn:active { transform: translateY(0) scale(0.95); }
.glass-btn svg { width: 20px; height: 20px; }
/* === 立体感图标通用(渐变填充 + 高光) === */
.ico-3d path.face { fill: url(#grad-cool); }
.ico-3d path.highlight { fill: url(#grad-highlight); opacity: 0.6; }
.ico-3d path.shadow { fill: url(#grad-shadow); opacity: 0.4; }
/* === 客服按钮 6 态(玻璃拟态) === */
.agent-btn.is-active {
background: linear-gradient(135deg, rgba(99, 102, 241, 0.85) 0%, rgba(168, 85, 247, 0.85) 50%, rgba(236, 72, 153, 0.85) 100%);
border-color: rgba(255, 255, 255, 0.4);
}
.agent-btn.is-active::before {
content: "";
position: absolute;
inset: 1px;
border-radius: 50%;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.3) 0%, transparent 50%);
pointer-events: none;
}
.agent-btn.is-active svg { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.2)); }
.agent-btn.is-disabled { opacity: 0.4; cursor: not-allowed; }
.agent-btn.is-disabled:hover { transform: none; box-shadow: none; background: rgba(255, 255, 255, 0.5); }
.agent-btn.is-disabled svg { filter: grayscale(1); }
.agent-btn.is-urgent {
background: linear-gradient(135deg, rgba(239, 68, 68, 0.9) 0%, rgba(220, 38, 38, 0.9) 50%, rgba(185, 28, 28, 0.9) 100%);
border-color: rgba(255, 255, 255, 0.4);
animation: agentGlow 1.6s ease-in-out infinite;
}
@keyframes agentGlow {
0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0), 0 1px 0 rgba(255, 255, 255, 0.9) inset, 0 1px 2px rgba(0, 0, 0, 0.04), 0 2px 4px rgba(0, 0, 0, 0.04); }
50% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0.18), 0 1px 0 rgba(255, 255, 255, 0.9) inset, 0 1px 2px rgba(0, 0, 0, 0.04), 0 2px 4px rgba(0, 0, 0, 0.04); }
}
.agent-btn.is-waiting {
background: linear-gradient(135deg, rgba(245, 158, 11, 0.9) 0%, rgba(217, 119, 6, 0.9) 50%, rgba(180, 83, 9, 0.9) 100%);
border-color: rgba(255, 255, 255, 0.4);
}
.agent-btn.is-end {
background: linear-gradient(135deg, rgba(16, 185, 129, 0.9) 0%, rgba(5, 150, 105, 0.9) 50%, rgba(4, 120, 87, 0.9) 100%);
border-color: rgba(255, 255, 255, 0.4);
}
.agent-btn.is-reopen {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.9) 0%, rgba(37, 99, 235, 0.9) 50%, rgba(29, 78, 216, 0.9) 100%);
border-color: rgba(255, 255, 255, 0.4);
}
/* === 演示容器 === */
.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: 32px;
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; }
.demo-stage-bg {
background: linear-gradient(135deg, #e0e7ff 0%, #f3e8ff 50%, #fce7f3 100%);
border-radius: 14px;
padding: 48px 32px;
min-height: 140px;
display: flex;
align-items: center;
justify-content: center;
}
/* === 状态切换 tab === */
.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; }
/* === 4 按钮并排 === */
.four-btns {
display: flex;
align-items: center;
justify-content: center;
}
/* === 对比表 === */
.cmp-table { width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12.5px; }
.cmp-table th, .cmp-table td { border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px 10px; text-align: left; }
.cmp-table th { background: rgba(255, 255, 255, 0.6); font-weight: 600; }
.yes { color: #059669; }
.no { color: #dc2626; }
.partial { color: #d97706; }
.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); }
</style>
</head>
<body>
<!-- 全局 SVG 渐变定义 -->
<svg width="0" height="0" style="position: absolute;">
<defs>
<!-- 通用渐变 -->
<linearGradient id="grad-cool" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#a5b4fc"/>
<stop offset="50%" stop-color="#c4b5fd"/>
<stop offset="100%" stop-color="#f0abfc"/>
</linearGradient>
<linearGradient id="grad-warm" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#fbbf24"/>
<stop offset="50%" stop-color="#fb923c"/>
<stop offset="100%" stop-color="#f87171"/>
</linearGradient>
<linearGradient id="grad-cool-3d" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#c7d2fe"/>
<stop offset="50%" stop-color="#a5b4fc"/>
<stop offset="100%" stop-color="#818cf8"/>
</linearGradient>
<linearGradient id="grad-document" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#e0e7ff"/>
<stop offset="100%" stop-color="#c7d2fe"/>
</linearGradient>
<linearGradient id="grad-microphone" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#a78bfa"/>
<stop offset="50%" stop-color="#8b5cf6"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
<linearGradient id="grad-agent-head" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#fbbf24"/>
<stop offset="100%" stop-color="#f59e0b"/>
</linearGradient>
<linearGradient id="grad-agent-head-active" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="100%" stop-color="#fbbf24"/>
</linearGradient>
<linearGradient id="grad-earphone" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#cbd5e1"/>
<stop offset="100%" stop-color="#64748b"/>
</linearGradient>
<linearGradient id="grad-highlight" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="white" stop-opacity="0.95"/>
<stop offset="100%" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="grad-urgent" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#fca5a5"/>
<stop offset="100%" stop-color="#ef4444"/>
</linearGradient>
<linearGradient id="grad-waiting" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#fcd34d"/>
<stop offset="100%" stop-color="#f59e0b"/>
</linearGradient>
<linearGradient id="grad-success" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#6ee7b7"/>
<stop offset="100%" stop-color="#10b981"/>
</linearGradient>
<linearGradient id="grad-reopen" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#93c5fd"/>
<stop offset="100%" stop-color="#3b82f6"/>
</linearGradient>
</defs>
</svg>
<h1>工具栏统一设计 v0.5 — 玻璃拟态 + 立体图标</h1>
<p class="meta">整体水晶玻璃背景 + 立体感 SVG 图标(渐变填充 + 高光 + 阴影)· 2026-08-04 凌晨</p>
<div class="note">
📌 本版核心改动(对比 v0.4):<br>
<strong>整体玻璃拟态背景</strong>:工具栏 = 半透明 + backdrop-filter blur(28px) + 顶部高光 + 多层阴影 + 紫粉径向渐变 — 整个工具栏是一个"水晶玻璃容器"<br>
<strong>立体感图标</strong>:不再用简单几何,采用 SVG <strong>渐变填充 + 高光 + 阴影</strong> 表现立体感(类似 iOS 立体图标)<br>
<strong>多层 box-shadow</strong>:深 + 浅 + 内嵌高光,模拟真实光照<br>
<strong>backdrop-filter</strong>:背景模糊,所有按钮"浮"在玻璃上
</div>
<h2>🎨 整体水晶玻璃工具栏</h2>
<div class="demo-block">
<div class="demo-label">InputBar 工具栏完整效果(4 按钮浮在水晶玻璃上)</div>
<div class="demo-stage-bg">
<div class="glass-toolbar">
<!-- 表情(立体感) -->
<button class="glass-btn" title="表情">
<svg class="ico-3d" viewBox="0 0 22 22" fill="none">
<!-- 脸(渐变填充) -->
<circle cx="11" cy="11" r="8" fill="url(#grad-cool-3d)"/>
<!-- 顶部高光 -->
<ellipse cx="11" cy="6" rx="5" ry="2" fill="url(#grad-highlight)"/>
<!-- 眼睛 -->
<ellipse cx="8" cy="10" rx="1.2" ry="1.4" fill="#1e1b4b"/>
<ellipse cx="14" cy="10" rx="1.2" ry="1.4" fill="#1e1b4b"/>
<ellipse cx="8.4" cy="9.5" rx="0.4" ry="0.4" fill="white"/>
<ellipse cx="14.4" cy="9.5" rx="0.4" ry="0.4" fill="white"/>
<!-- 嘴(弧形) -->
<path d="M7.5 13.5 Q11 16 14.5 13.5" fill="none" stroke="#1e1b4b" stroke-width="1.4" stroke-linecap="round"/>
</svg>
</button>
<!-- 文件(立体感) -->
<button class="glass-btn" title="文件">
<svg class="ico-3d" viewBox="0 0 22 22" fill="none">
<!-- 文档主体(渐变填充) -->
<path d="M4 2 L13 2 L19 8 L19 19 L4 19 Z" fill="url(#grad-document)" stroke="#818cf8" stroke-width="0.8" stroke-linejoin="round"/>
<!-- 折角(渐变) -->
<path d="M13 2 L13 8 L19 8" fill="url(#grad-cool-3d)" stroke="#818cf8" stroke-width="0.8" stroke-linejoin="round"/>
<!-- 顶部高光 -->
<path d="M5 3 L12 3" stroke="white" stroke-width="0.8" stroke-linecap="round" opacity="0.8"/>
<!-- 文字行 -->
<line x1="6" y1="11" x2="16" y2="11" stroke="#6366f1" stroke-width="0.8" opacity="0.6"/>
<line x1="6" y1="14" x2="14" y2="14" stroke="#6366f1" stroke-width="0.8" opacity="0.6"/>
<line x1="6" y1="17" x2="12" y2="17" stroke="#6366f1" stroke-width="0.8" opacity="0.6"/>
</svg>
</button>
<div class="glass-divider"></div>
<!-- 语音(立体感) -->
<button class="glass-btn" title="语音">
<svg class="ico-3d" viewBox="0 0 22 22" fill="none">
<!-- 麦克风主体(渐变 + 圆柱) -->
<rect x="7" y="2" width="8" height="12" rx="4" fill="url(#grad-microphone)"/>
<!-- 顶部高光 -->
<rect x="8" y="3" width="2" height="9" rx="1" fill="white" opacity="0.5"/>
<!-- 麦克风底座弧线 -->
<path d="M3 11 Q3 17 11 17 Q19 17 19 11" fill="none" stroke="url(#grad-microphone)" stroke-width="2" stroke-linecap="round"/>
<!-- 支柱 -->
<line x1="11" y1="17" x2="11" y2="20" stroke="#7c3aed" stroke-width="2" stroke-linecap="round"/>
<line x1="8" y1="20" x2="14" y2="20" stroke="#7c3aed" stroke-width="2" stroke-linecap="round"/>
</svg>
</button>
<!-- 客服(立体感) -->
<button class="glass-btn agent-btn is-active" title="客服在线 · 点击呼叫">
<svg class="ico-3d" viewBox="0 0 22 22" fill="none">
<!-- 头部(渐变 + 高光) -->
<circle cx="11" cy="9" r="5" fill="url(#grad-agent-head)"/>
<ellipse cx="11" cy="6.5" rx="3.5" ry="1.5" fill="white" opacity="0.5"/>
<!-- 耳罩(渐变 + 立体) -->
<ellipse cx="4" cy="9" rx="1.8" ry="2.5" fill="url(#grad-earphone)"/>
<ellipse cx="18" cy="9" rx="1.8" ry="2.5" fill="url(#grad-earphone)"/>
<!-- 耳罩内侧(深色) -->
<ellipse cx="4" cy="9" rx="1" ry="1.5" fill="#475569"/>
<ellipse cx="18" cy="9" rx="1" ry="1.5" fill="#475569"/>
<!-- 眼睛 -->
<circle cx="9" cy="9" r="0.9" fill="#1e1b4b"/>
<circle cx="13" cy="9" r="0.9" fill="#1e1b4b"/>
<circle cx="9.3" cy="8.7" r="0.3" fill="white"/>
<circle cx="13.3" cy="8.7" r="0.3" fill="white"/>
<!-- 微笑嘴 -->
<path d="M9 11.5 Q11 13 13 11.5" fill="none" stroke="#1e1b4b" stroke-width="1.2" stroke-linecap="round"/>
<!-- 麦克风臂(连接耳罩的小线) -->
<path d="M4 9 Q4 14 11 14" fill="none" stroke="url(#grad-earphone)" stroke-width="1.2" opacity="0.6"/>
</svg>
</button>
</div>
</div>
<p style="font-size: 12px; color: #6b7280; margin-top: 12px;">
视觉特点: 半透明紫粉渐变 + 顶部高光 + 多层阴影 + 4 按钮浮在上面 + 立体感 SVG 图标(渐变 + 高光)
</p>
</div>
<h2>🎬 客服按钮 6 态切换</h2>
<div class="demo-block">
<div class="state-tabs">
<button class="state-tab active" data-state="active">active</button>
<button class="state-tab" data-state="disabled">disabled</button>
<button class="state-tab" data-state="urgent">urgent</button>
<button class="state-tab" data-state="waiting">waiting</button>
<button class="state-tab" data-state="end">end</button>
<button class="state-tab" data-state="reopen">reopen</button>
</div>
<div class="demo-stage-bg">
<div class="glass-toolbar">
<div id="stage" style="display: flex; align-items: center; justify-content: center;"></div>
</div>
</div>
<div class="state-desc" id="desc"></div>
</div>
<h2>📊 与之前版本对比(v0.5 关键升级)</h2>
<table class="cmp-table">
<thead>
<tr>
<th>维度</th>
<th>v0.1 方块</th>
<th>v0.2 灵动岛</th>
<th>v0.3 克制</th>
<th>v0.4 圆形渐变</th>
<th>v0.5 玻璃拟态 ⭐</th>
</tr>
</thead>
<tbody>
<tr>
<td>整体背景</td>
<td class="no">无(纯白)</td>
<td class="no"></td>
<td class="no"></td>
<td class="partial">白底 + 阴影</td>
<td class="yes"><strong>水晶玻璃 + 紫粉径向渐变</strong></td>
</tr>
<tr>
<td>图标质感</td>
<td class="no">emoji</td>
<td class="no">夸张卡通</td>
<td class="partial">简单几何</td>
<td class="partial">抽象 + 客服图</td>
<td class="yes"><strong>渐变填充 + 高光 + 阴影(立体感)</strong></td>
</tr>
<tr>
<td>backdrop-filter</td>
<td class="no">×</td>
<td class="no">×</td>
<td class="no">×</td>
<td class="no">×</td>
<td class="yes"><strong>✓ blur(28px) saturate(180%)</strong></td>
</tr>
<tr>
<td>多层阴影</td>
<td class="no">1 层</td>
<td class="no">1 层</td>
<td class="no">1 层</td>
<td class="partial">2 层</td>
<td class="yes"><strong>3 层(深 + 浅 + 内嵌高光)</strong></td>
</tr>
<tr>
<td>按钮形态</td>
<td>方块</td>
<td>方块</td>
<td>方块</td>
<td>圆形</td>
<td class="yes"><strong>圆形 + 玻璃质感</strong></td>
</tr>
<tr>
<td>高级感</td>
<td>★★★</td>
<td></td>
<td>★★★★</td>
<td>★★★★★</td>
<td class="yes"><strong>★★★★★+(顶级 SaaS 工具级)</strong></td>
</tr>
</tbody>
</table>
<h2>❓ 待你拍板</h2>
<ol style="margin-left: 20px; line-height: 1.8;">
<li><strong>整体玻璃背景</strong>符合你期望吗?(水晶质感 + 紫粉渐变 + 顶部高光)</li>
<li><strong>立体感图标</strong>的"质变效果"如何?如仍需更大优化(比如复杂 3D 渲染、动态光影),需要请设计师重画</li>
<li><strong>工具栏大小</strong>:当前 38px 按钮,需要更大(40px)或更小(36px)吗?</li>
<li><strong>渐变色调</strong>:紫粉(当前)还是其他?(蓝绿、纯蓝、暖橙、对比色?)</li>
</ol>
<p style="margin-top: 32px; padding-top: 16px; border-top: 1px solid rgba(99, 102, 241, 0.15); color: #6b7280; font-size: 11.5px;">
v0.5 玻璃拟态 · 2026-08-04 · Duckula 主理人 · 等待用户拍板
</p>
<script>
const states = {
active: {
cls: 'is-active',
desc: '<strong>active</strong>: 紫粉渐变(蓝→紫→粉)+ 顶部高光 + 立体感图标 — 默认"客服在线"。玻璃质感最强,像 iOS 控制中心按钮'
},
disabled: {
cls: 'is-disabled',
desc: '<strong>disabled</strong>: 半透明白 + 灰度滤镜(grayscale)+ opacity 0.4 — 表达"不可用",保留玻璃质感但无彩色'
},
urgent: {
cls: 'is-urgent',
desc: '<strong>urgent</strong>: 红色渐变 + 1.6s 发光呼吸(box-shadow 扩散 6px 红色光晕) — 表达"紧急,需关注"'
},
waiting: {
cls: 'is-waiting',
desc: '<strong>waiting</strong>: 橙黄渐变(浅黄→深橙)+ 立体感图标 — 表达"排队中"'
},
end: {
cls: 'is-end',
desc: '<strong>end</strong>: 绿色渐变(浅绿→深绿)+ 立体感图标 — 表达"已接入坐席,通话中"'
},
reopen: {
cls: 'is-reopen',
desc: '<strong>reopen</strong>: 蓝色渐变(浅蓝→深蓝)+ 立体感图标 — 表达"会话已关闭,可重新打开"'
}
};
const svgAgent = `<svg class="ico-3d" viewBox="0 0 22 22" fill="none">
<circle cx="11" cy="9" r="5" fill="url(#grad-agent-head)"/>
<ellipse cx="11" cy="6.5" rx="3.5" ry="1.5" fill="white" opacity="0.5"/>
<ellipse cx="4" cy="9" rx="1.8" ry="2.5" fill="url(#grad-earphone)"/>
<ellipse cx="18" cy="9" rx="1.8" ry="2.5" fill="url(#grad-earphone)"/>
<ellipse cx="4" cy="9" rx="1" ry="1.5" fill="#475569"/>
<ellipse cx="18" cy="9" rx="1" ry="1.5" fill="#475569"/>
<circle cx="9" cy="9" r="0.9" fill="#1e1b4b"/>
<circle cx="13" cy="9" r="0.9" fill="#1e1b4b"/>
<circle cx="9.3" cy="8.7" r="0.3" fill="white"/>
<circle cx="13.3" cy="8.7" r="0.3" fill="white"/>
<path d="M9 11.5 Q11 13 13 11.5" fill="none" stroke="#1e1b4b" stroke-width="1.2" stroke-linecap="round"/>
<path d="M4 9 Q4 14 11 14" fill="none" stroke="url(#grad-earphone)" stroke-width="1.2" opacity="0.6"/>
</svg>`;
const stage = document.getElementById('stage');
const descEl = document.getElementById('desc');
const tabs = document.querySelectorAll('.state-tab');
function render(state) {
const s = states[state];
const gradMap = {
active: 'url(#grad-agent-head)',
urgent: 'url(#grad-urgent)',
waiting: 'url(#grad-waiting)',
end: 'url(#grad-success)',
reopen: 'url(#grad-reopen)',
};
const headGrad = state === 'active' ? 'url(#grad-agent-head-active)' : (gradMap[state] || 'url(#grad-agent-head)');
const svg = `<svg class="ico-3d" viewBox="0 0 22 22" fill="none">
<circle cx="11" cy="9" r="5" fill="${headGrad}"/>
<ellipse cx="11" cy="6.5" rx="3.5" ry="1.5" fill="white" opacity="0.5"/>
<ellipse cx="4" cy="9" rx="1.8" ry="2.5" fill="url(#grad-earphone)"/>
<ellipse cx="18" cy="9" rx="1.8" ry="2.5" fill="url(#grad-earphone)"/>
<ellipse cx="4" cy="9" rx="1" ry="1.5" fill="#475569"/>
<ellipse cx="18" cy="9" rx="1" ry="1.5" fill="#475569"/>
<circle cx="9" cy="9" r="0.9" fill="#1e1b4b"/>
<circle cx="13" cy="9" r="0.9" fill="#1e1b4b"/>
<circle cx="9.3" cy="8.7" r="0.3" fill="white"/>
<circle cx="13.3" cy="8.7" r="0.3" fill="white"/>
<path d="M9 11.5 Q11 13 13 11.5" fill="none" stroke="#1e1b4b" stroke-width="1.2" stroke-linecap="round"/>
</svg>`;
stage.innerHTML = `<button class="glass-btn agent-btn ${s.cls}" style="width: 60px; height: 60px;">${svg}</button>`;
descEl.innerHTML = s.desc;
}
tabs.forEach(tab => {
tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
render(tab.dataset.state);
});
});
render('active');
</script>
</body>
</html>