[split-upload 4/6] f2fd4fa backup via proxy
This commit is contained in:
@@ -0,0 +1,550 @@
|
||||
<!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>
|
||||
@@ -0,0 +1,537 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>工具栏统一设计 v1.1 - InputBar 内上方居中</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;
|
||||
}
|
||||
.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: 240px;
|
||||
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;
|
||||
}
|
||||
|
||||
/* === 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 按钮(40-44px · 高级感) === */
|
||||
.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-active-voice { background: linear-gradient(135deg, rgba(139, 92, 246, 0.9) 0%, rgba(124, 58, 237, 0.9) 100%); border-color: rgba(255, 255, 255, 0.4); }
|
||||
.glass-btn.is-active-voice::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-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; }
|
||||
}
|
||||
|
||||
/* === 坐席按钮(图片头像) === */
|
||||
.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: hidden;
|
||||
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-btn.is-active { box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.5) inset; }
|
||||
.agent-btn.is-disabled { opacity: 0.4; filter: grayscale(0.7); }
|
||||
.agent-btn.is-urgent { border: 2.5px solid #ef4444; box-shadow: 0 0 0 0 rgba(239, 68, 68, 0), 0 4px 12px rgba(239, 68, 68, 0.3); animation: recordingPulse 1.5s ease-in-out infinite; }
|
||||
.agent-btn.is-waiting { border: 2.5px solid #f59e0b; box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3); }
|
||||
.agent-btn.is-end { border: 2.5px solid #10b981; box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); }
|
||||
.agent-btn.is-reopen { border: 2.5px solid #3b82f6; box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3); }
|
||||
|
||||
/* === 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); }
|
||||
</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.1 — InputBar 内上方居中 4 按钮</h1>
|
||||
<p class="meta">表情/文件/语音/坐席 · 消息发送框(InputBar)内上方居中 · v0.5 玻璃拟态 · 高级感 SVG + 真实图片头像 · 2026-08-04 凌晨</p>
|
||||
|
||||
<div class="note">
|
||||
📌 本版核心改动(对比 v1.0):<br>
|
||||
• <strong>位置校正:</strong> 工具栏在 <strong>InputBar(消息发送框)内</strong>,不是消息流里!<br>
|
||||
• InputBar 结构: <strong>[上方 4 按钮工具栏(居中)] [输入框(下方)]</strong><br>
|
||||
• 4 按钮(表情/文件/语音/坐席) · 高级感 SVG + 真实图片头像(沿用 v0.9 + v0.8)
|
||||
</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 is-active" title="客服在线 · 点击呼叫">
|
||||
<img src="./agent-avatar-v0.8.jpg" alt="客服" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 输入框(在工具栏下方) -->
|
||||
<div class="inputbar-mock-field">
|
||||
请输入消息...(输入框在工具栏下方,用户打字区)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>🎬 4 按钮不同状态演示</h2>
|
||||
<div class="demo-block">
|
||||
<div class="state-tabs">
|
||||
<button class="state-tab active" data-state="default">默认</button>
|
||||
<button class="state-tab" data-state="emoji">表情激活</button>
|
||||
<button class="state-tab" data-state="file">文件激活</button>
|
||||
<button class="state-tab" data-state="voice-active">语音激活</button>
|
||||
<button class="state-tab" data-state="voice-recording">语音录音中</button>
|
||||
<button class="state-tab" data-state="agent-active">坐席已呼叫</button>
|
||||
<button class="state-tab" data-state="agent-urgent">坐席紧急</button>
|
||||
</div>
|
||||
|
||||
<div class="inputbar-mock" style="border-radius: 12px;">
|
||||
<div class="glass-toolbar" id="state-stage"></div>
|
||||
<div class="inputbar-mock-field" style="min-height: 40px; padding: 8px 12px; font-size: 12px;">输入框</div>
|
||||
</div>
|
||||
<div class="state-desc" id="state-desc"></div>
|
||||
</div>
|
||||
|
||||
<h2>📊 v1.0 vs v1.1 关键差异</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.0(错)</th>
|
||||
<th style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px; text-align: left;"><strong>v1.1(对)</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;"><strong>消息流内</strong>(错)</td>
|
||||
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;"><strong>InputBar 内</strong>(对)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">InputBar 结构</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>[消息流]→[InputBar:工具栏→输入框]</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;">4(表情/文件/语音/坐席)</td>
|
||||
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">4(表情/文件/语音/坐席)✓</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;">v0.5 玻璃拟态</td>
|
||||
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">v0.5 玻璃拟态✓</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;">3 SVG + 图片头像</td>
|
||||
<td style="border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px;">3 SVG + 图片头像✓</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>❓ 待你拍板</h2>
|
||||
<ol style="margin-left: 20px; line-height: 1.8;">
|
||||
<li><strong>InputBar 内上方居中</strong>OK 吗?(不是消息流内)</li>
|
||||
<li><strong>4 按钮(表情/文件/语音/坐席)</strong>OK 吗?</li>
|
||||
<li><strong>坐席按钮 44px</strong>(比其他 40px 略大,突出)OK 吗?</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;">
|
||||
v1.1 InputBar 内上方居中 4 按钮 · 2026-08-04 · Duckula 主理人 · 等待用户拍板
|
||||
</p>
|
||||
|
||||
<script>
|
||||
const stateMap = {
|
||||
'default': { toolbar: '', desc: '<strong>默认状态</strong>: 4 按钮全部默认(浅玻璃) — 表情/文件/语音/坐席(图片头像紫粉渐变边框)都未激活' },
|
||||
'emoji': { toolbar: 'emojiActive', desc: '<strong>表情激活</strong>: 表情按钮变<strong>黄橙渐变</strong> — 表情面板已打开(emoji 网格弹出)' },
|
||||
'file': { toolbar: 'fileActive', desc: '<strong>文件激活</strong>: 文件按钮变<strong>蓝紫渐变</strong> — 文件选择器已打开(选择图片/文档)' },
|
||||
'voice-active': { toolbar: 'voiceActive', desc: '<strong>语音激活</strong>: 语音按钮变<strong>紫粉渐变</strong> — 准备录音(用户可点击开始)' },
|
||||
'voice-recording': { toolbar: 'voiceRecording', desc: '<strong>语音录音中</strong>: 语音按钮变<strong>红色 + 1.5s 发光呼吸</strong> — 正在录音(用户可点击停止)' },
|
||||
'agent-active': { toolbar: 'agentActive', desc: '<strong>坐席已呼叫</strong>: 坐席按钮<strong>紫粉渐变边框 + 阴影</strong> — 呼叫成功,等待坐席接入' },
|
||||
'agent-urgent': { toolbar: 'agentUrgent', desc: '<strong>坐席紧急</strong>: 坐席按钮<strong>红色边框 + 1.5s 发光呼吸</strong> — 紧急关键词命中,坐席直接接入' }
|
||||
};
|
||||
|
||||
const svgEmoji = `<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>`;
|
||||
const svgFile = `<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>`;
|
||||
const svgVoice = `<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>`;
|
||||
const imgAgent = `<img src="./agent-avatar-v0.8.jpg" alt="客服" />`;
|
||||
|
||||
function renderToolbar(stage, state) {
|
||||
const emojiClass = state === 'emojiActive' ? 'is-active-emoji' : '';
|
||||
const fileClass = state === 'fileActive' ? 'is-active-file' : '';
|
||||
const voiceClass = state === 'voiceActive' ? 'is-active-voice' : (state === 'voiceRecording' ? 'is-recording' : '');
|
||||
const agentClass = state === 'agentActive' ? 'is-active' : (state === 'agentUrgent' ? 'is-urgent' : 'is-active');
|
||||
stage.innerHTML = `
|
||||
<button class="glass-btn ${emojiClass}" title="表情">${svgEmoji}</button>
|
||||
<button class="glass-btn ${fileClass}" title="文件">${svgFile}</button>
|
||||
<button class="glass-btn ${voiceClass}" title="语音输入">${svgVoice}</button>
|
||||
<button class="agent-btn ${agentClass}" title="客服在线 · 点击呼叫">${imgAgent}</button>
|
||||
`;
|
||||
}
|
||||
|
||||
const toolbarStage = document.getElementById('toolbar-stage');
|
||||
const stateStage = document.getElementById('state-stage');
|
||||
const stateDesc = document.getElementById('state-desc');
|
||||
const stateTabs = document.querySelectorAll('.state-tab');
|
||||
|
||||
function renderAll(state) {
|
||||
const s = stateMap[state];
|
||||
if (toolbarStage) renderToolbar(toolbarStage, s.toolbar);
|
||||
if (stateStage) renderToolbar(stateStage, s.toolbar);
|
||||
if (stateDesc) stateDesc.innerHTML = s.desc;
|
||||
}
|
||||
|
||||
let currentState = 'default';
|
||||
stateTabs.forEach(tab => {
|
||||
tab.addEventListener('click', () => {
|
||||
stateTabs.forEach(t => t.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
currentState = tab.dataset.state;
|
||||
renderAll(currentState);
|
||||
});
|
||||
});
|
||||
|
||||
renderAll('default');
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,457 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>工具栏统一设计 v1.7 - 两端收口 · 中央隆起</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; }
|
||||
|
||||
/* === 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;
|
||||
}
|
||||
|
||||
/* === 普通工具栏(Before:v1.6 两端图标探出 + 坐席 54px) === */
|
||||
.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 2px 4px rgba(99,102,241,0.05), 0 8px 16px rgba(99,102,241,0.08);
|
||||
position: relative;
|
||||
}
|
||||
.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 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.75); transform: translateY(-1px) scale(1.06); }
|
||||
.glass-btn:active { transform: translateY(0) scale(0.95); }
|
||||
.glass-btn svg { width: 22px; height: 22px; display: block; }
|
||||
.agent-btn {
|
||||
width: 44px; height: 44px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid transparent;
|
||||
cursor: pointer;
|
||||
position: relative; z-index: 2;
|
||||
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-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; }
|
||||
|
||||
/* === 圆角长方形 · 中央隆起工具栏(After / v1.7) === */
|
||||
/* 容器:左右留 padding,使轨道能完整包住两端图标;高度留中央隆起空间 */
|
||||
.gem-toolbar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 16px;
|
||||
width: fit-content;
|
||||
height: 84px;
|
||||
margin: 0 auto 12px;
|
||||
}
|
||||
/* 圆角长方形轨道背景(SVG):两端收口包住图标、中央因大按钮隆起自然弧线 */
|
||||
.gem-toolbar-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
overflow: visible;
|
||||
}
|
||||
/* 按钮行(5 个,坐席居中且更大) */
|
||||
.gem-row { position: relative; z-index: 2; display: flex; align-items: center; justify-content: center; gap: 12px; }
|
||||
/* 人工坐席按钮 = 增大 50%(60px),居中,不探出,无光晕 */
|
||||
.gem-toolbar .agent-btn.gem {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin: 0 6px;
|
||||
z-index: 3;
|
||||
box-shadow: none;
|
||||
}
|
||||
.gem-toolbar .glass-btn { z-index: 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);
|
||||
}
|
||||
.compare-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
||||
.compare-panel { background: rgba(255, 255, 255, 0.5); border: 1px solid rgba(99, 102, 241, 0.15); border-radius: 12px; padding: 16px; }
|
||||
.compare-panel.before { border-left: 4px solid #f59e0b; }
|
||||
.compare-panel.after { border-left: 4px solid #10b981; }
|
||||
.compare-title { font-size: 13px; font-weight: 600; margin-bottom: 12px; }
|
||||
.compare-panel.before .compare-title { color: #b45309; }
|
||||
.compare-panel.after .compare-title { color: #047857; }
|
||||
|
||||
.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); }
|
||||
.note-success { background: rgba(209, 250, 229, 0.6); border-left: 3px solid #10b981; padding: 12px 16px; border-radius: 4px; font-size: 12.5px; color: #064e3b; margin: 16px 0; backdrop-filter: blur(10px); }
|
||||
.note-info { background: rgba(219, 234, 254, 0.6); border-left: 3px solid #3b82f6; padding: 12px 16px; border-radius: 4px; font-size: 12.5px; color: #1e3a8a; margin: 16px 0; backdrop-filter: blur(10px); }
|
||||
|
||||
table { width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12.5px; }
|
||||
thead tr { background: rgba(255, 255, 255, 0.6); }
|
||||
th { border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px; text-align: left; font-weight: 600; }
|
||||
td { border: 1px solid rgba(99, 102, 241, 0.15); padding: 8px; }
|
||||
</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-group" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#a5b4fc"/><stop offset="100%" stop-color="#c4b5fd"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="g-group-strong" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#6366f1"/><stop offset="50%" stop-color="#a855f7"/><stop offset="100%" stop-color="#ec4899"/>
|
||||
</linearGradient>
|
||||
<!-- 圆角长方形轨道渐变 -->
|
||||
<linearGradient id="g-rail" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stop-color="#818cf8" stop-opacity="0.5"/>
|
||||
<stop offset="50%" stop-color="#c4b5fd" stop-opacity="0.9"/>
|
||||
<stop offset="100%" stop-color="#818cf8" stop-opacity="0.5"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
<h1>工具栏统一设计 v1.7 — 两端收口 · 中央隆起</h1>
|
||||
<p class="meta">v1.6 修正版:两端图标完全收在工具栏范围内;人工坐席图标增大 50%(60px,较 40px 工具图标大 50%),将上下边框平滑撑起中央隆起 · 2026-08-05</p>
|
||||
|
||||
<div class="note-info">
|
||||
📐 <strong>v1.7 改动说明(修正 v1.6 的 2 点 + 过渡内收平滑)</strong>:<br>
|
||||
① <strong>两端图标收口</strong>:工具栏轨道向左右延伸、完整包住 emoji/文件/语音/群聊,图标在水平与垂直方向均有余量,<u>不再从左右圆角端探出</u><br>
|
||||
② <strong>坐席按钮增大 50%</strong>:人工坐席按钮由 54px → <strong>60px</strong>(较 40px 工具图标大 50%),其更大尺寸将上下边框从两端向中央平滑撑出弧线,按钮不探出、无光晕<br>
|
||||
③ <strong>两端直线、中央连续拱</strong>:除人工坐席外的两侧图标(emoji/文件/语音/群聊)上下方工具栏保持<strong>直线</strong>;仅中央坐席处为连续拱起的弧线,拱顶在坐席正中(156,6)/ 拱底(156,78),无中央直线段;坐席四周为<strong>渐升圆顶</strong>(从直线段平缓起步、均匀升起、圆润收顶),平滑无陡升折感<br>
|
||||
④ 仍保持:圆角长方形、无光晕、工具按钮不溢出
|
||||
</div>
|
||||
|
||||
<h2>🎯 v1.7 目标对比(Before / After)</h2>
|
||||
<div class="demo-block">
|
||||
<div class="compare-grid">
|
||||
<!-- BEFORE: v1.6 两端图标探出 + 坐席 54px -->
|
||||
<div class="compare-panel before">
|
||||
<div class="compare-title">v1.6(上一版:两端图标探出 + 坐席 54px)</div>
|
||||
<div style="text-align: center; padding: 12px; background: rgba(254, 243, 199, 0.4); border-radius: 10px;">
|
||||
<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="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"/>
|
||||
<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="客服在线" style="width:54px;height:54px;">
|
||||
<img src="./agent-avatar-v0.8.jpg" alt="客服"/>
|
||||
<span class="agent-badge is-online"></span>
|
||||
</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)"/>
|
||||
<path d="M3 12 Q3 18 12 18 Q21 18 21 12" fill="none" stroke="url(#g-mic-body)" stroke-width="2"/>
|
||||
<line x1="12" y1="18" x2="12" y2="22" stroke="url(#g-mic-body)" stroke-width="2"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="glass-btn" title="群聊">
|
||||
<svg viewBox="0 0 24 24" fill="none">
|
||||
<circle cx="8" cy="9" r="2.2" fill="url(#g-group)"/>
|
||||
<path d="M5 16 Q5 13 8 13 Q11 13 11 16 Z" fill="url(#g-group)"/>
|
||||
<circle cx="16" cy="9" r="2.2" fill="url(#g-group)"/>
|
||||
<path d="M13 16 Q13 13 16 13 Q19 13 19 16 Z" fill="url(#g-group)"/>
|
||||
<circle cx="12" cy="10.5" r="2.8" fill="url(#g-group-strong)"/>
|
||||
<path d="M8.5 18.5 Q8.5 14 12 14 Q15.5 14 15.5 18.5 Z" fill="url(#g-group-strong)"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="inputbar-mock-field" style="min-height: 36px; padding: 6px 12px; font-size: 12px;">请输入消息...</div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #92400e; margin-top: 8px;">
|
||||
⚠️ <strong>问题</strong>: 两端图标从圆角端探出;坐席 54px 隆起幅度偏小
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AFTER: v1.7 两端收口 + 坐席 60px -->
|
||||
<div class="compare-panel after">
|
||||
<div class="compare-title">v1.7(目标:两端收口 · 中央隆起)</div>
|
||||
<div style="text-align: center; padding: 12px; background: rgba(209, 250, 229, 0.4); border-radius: 10px;">
|
||||
<!-- 圆角长方形 · 中央隆起工具栏(两端收口) -->
|
||||
<div class="gem-toolbar">
|
||||
<svg class="gem-toolbar-bg" viewBox="0 0 312 84" preserveAspectRatio="xMidYMid meet">
|
||||
<!-- 圆角长方形轨道:两端(两侧图标处)保持直线,仅中央坐席处连续拱起(拱顶在坐席正中);坐席四周为渐升圆顶,平滑无陡升 -->
|
||||
<path d="M 18 18
|
||||
L 108 18
|
||||
C 120 14, 144 8, 156 6
|
||||
C 168 8, 192 14, 204 18
|
||||
L 294 18
|
||||
C 302 18, 312 26, 312 34
|
||||
L 312 50
|
||||
C 312 58, 302 66, 294 66
|
||||
L 204 66
|
||||
C 192 70, 168 76, 156 78
|
||||
C 144 76, 120 70, 108 66
|
||||
L 18 66
|
||||
C 0 66, 0 58, 0 50
|
||||
L 0 34
|
||||
C 0 26, 10 18, 18 18 Z"
|
||||
fill="url(#g-rail)" stroke="rgba(255,255,255,0.85)" stroke-width="1.2"/>
|
||||
</svg>
|
||||
<div class="gem-row">
|
||||
<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"/>
|
||||
</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"/>
|
||||
<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>
|
||||
<!-- 人工坐席按钮:增大 50%(60px),居中,不探出,无光晕 -->
|
||||
<button class="agent-btn gem" title="客服在线">
|
||||
<img src="./agent-avatar-v0.8.jpg" alt="客服"/>
|
||||
<span class="agent-badge is-online"></span>
|
||||
</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)"/>
|
||||
<path d="M3 12 Q3 18 12 18 Q21 18 21 12" fill="none" stroke="url(#g-mic-body)" stroke-width="2"/>
|
||||
<line x1="12" y1="18" x2="12" y2="22" stroke="url(#g-mic-body)" stroke-width="2"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="glass-btn" title="群聊">
|
||||
<svg viewBox="0 0 24 24" fill="none">
|
||||
<circle cx="8" cy="9" r="2.2" fill="url(#g-group)"/>
|
||||
<path d="M5 16 Q5 13 8 13 Q11 13 11 16 Z" fill="url(#g-group)"/>
|
||||
<circle cx="16" cy="9" r="2.2" fill="url(#g-group)"/>
|
||||
<path d="M13 16 Q13 13 16 13 Q19 13 19 16 Z" fill="url(#g-group)"/>
|
||||
<circle cx="12" cy="10.5" r="2.8" fill="url(#g-group-strong)"/>
|
||||
<path d="M8.5 18.5 Q8.5 14 12 14 Q15.5 14 15.5 18.5 Z" fill="url(#g-group-strong)"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inputbar-mock-field" style="min-height: 36px; padding: 6px 12px; font-size: 12px;">请输入消息...</div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #065f46; margin-top: 8px;">
|
||||
✅ <strong>效果</strong>: 两端图标完全在轨道内;坐席 60px 将上下边框平滑撑起中央隆起,不探出、无光晕
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>📊 v1.6 vs v1.7 改动对比</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>维度</th>
|
||||
<th>v1.6(上一版)</th>
|
||||
<th><strong>v1.7(目标)</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>两端图标是否超出轨道</strong></td>
|
||||
<td>是(从左右圆角端探出)</td>
|
||||
<td><strong>否</strong>(轨道向左右延伸完整包住,水平+垂直均有余量)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>人工坐席按钮尺寸</strong></td>
|
||||
<td>54px</td>
|
||||
<td><strong>60px(较 40px 工具图标大 50%)</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>中央隆起幅度</strong></td>
|
||||
<td>中央高 62 / 两端 48</td>
|
||||
<td><strong>中央高 72 / 两端 48</strong>(隆起更明显)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>坐席按钮探出 / 光晕</strong></td>
|
||||
<td>不探出 / 无光晕</td>
|
||||
<td><strong>不探出 / 无光晕(保持)</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>工具按钮溢出</strong></td>
|
||||
<td>不溢出</td>
|
||||
<td><strong>不溢出(保持)</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>🛠️ 需要修改的文件清单</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>文件</th>
|
||||
<th>改动</th>
|
||||
<th>影响</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>src/frontend-h5/src/components/chat/InputBar.vue</code></td>
|
||||
<td><strong>改</strong>:工具栏容器加左右 padding 使轨道包住两端图标;SVG path 左右延伸、中央因 60px 坐席按钮隆起;坐席按钮 60px、去除光晕、不探出;工具按钮保持 40px 在轨道内</td>
|
||||
<td>本文件工具栏局部重构</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>IntegrationZone.vue</code></td>
|
||||
<td><strong>不动</strong>(v1.3 已删除坐席按钮)</td>
|
||||
<td>无</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>inputBarCallAgentState.ts</code> / <code>integrationZoneLogic.ts</code></td>
|
||||
<td><strong>不动</strong>(helper 保留)</td>
|
||||
<td>无</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>InputBar.test.ts</code></td>
|
||||
<td>补充两端收口 + 坐席 60px 居中结构测试</td>
|
||||
<td>测试同步更新</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>⚠️ 注意事项与待确认点</h2>
|
||||
<ol style="margin-left: 20px; line-height: 1.8; font-size: 13px;">
|
||||
<li><strong>50% 口径</strong>:本次坐席按「较 40px 工具图标大 50%」= 60px。若你指 v1.6 的 54px 再 +50%(即 81px),告知我即改</li>
|
||||
<li><strong>两端收口</strong>:轨道现向左右各延伸 16px 包住图标;若想端帽更贴图标或更宽,调 .gem-toolbar 的 padding 与 path 的 x 端点</li>
|
||||
<li><strong>隆起幅度</strong>:中央 72 / 两端 48,由 path 的 y 值(6/78 与 18/66)控制</li>
|
||||
<li><strong>无光晕</strong>:保持干净,仅渐变描边</li>
|
||||
<li><strong>头像占位图</strong>:<code>./agent-avatar-v0.8.jpg</code> 为占位路径,实际集成时替换</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;">
|
||||
v1.7 两端收口 · 中央隆起 · 2026-08-05 · Duckula 主理人 · 等待用户拍板进入开发
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user