facc04aa65
本提交为 .git 对象库损坏后的重建提交,内容等价于原先三个本地提交 (5e2fd4c2 / 57a53c98 / 5d7e1873)的累积结果,未做任何额外改动。 一、docs 结构整改(整改 #14) 根因:重构时新结构为 untracked 文件,执行 git stash(未带 -u)未纳入, 随后 git reset 拉回 HEAD 旧 tracked 树,导致旧树复活、新旧两棵目录 树并存于 docs/,共 791 文件、双分类体系冲突。 修复动作: - b2 同名异主题文件改名迁移保全 9 个 - C 类 39 个孤立文件按主题正确归类 - A/B1 类 222 个重复文件删除(新结构已有内容副本) - 9 个旧独有空目录删除 - 270 处内部引用按 verified 映射改写 - 整改记录 #14 登记于 04-运维文档/部署运维 结果:docs 791 → 569 文件,顶层仅规范 8 类 + 治理文件,单树恢复。 残留:约 20 处指向从未存在文件的陈旧死链,归入独立文档卫生任务。 二、compose 双目录对齐(消除踩坑 A) - docker-compose.yml:nginx 前端挂载全部由根目录 frontend-*/dist 改为 src/frontend-*/dist(h5 / agent / admin / terminal) - docker-compose.dev.yml:dev 服务 build context 与卷同步改 src/ - 效果:本地 docker compose up 不再把根目录 stale dist 挂回, 与线上一致,分叉隐患消除(已 docker compose config 校验通过) 防复发铁律: - 重构须提交;仓库修复须 git stash -u 或先 commit - 新结构须 git add 并提交,避免再次 untracked 复活 - H5 改动只动 src/frontend-h5/,禁改根目录遗留 frontend-*/
638 lines
32 KiB
HTML
638 lines
32 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>工具栏统一设计 v0.6 - 图标与坐席头像突破</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;
|
|
}
|
|
|
|
.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);
|
|
overflow: hidden;
|
|
}
|
|
.glass-btn:hover {
|
|
background: rgba(255, 255, 255, 0.7);
|
|
transform: translateY(-1px) scale(1.04);
|
|
}
|
|
.glass-btn:active { transform: translateY(0) scale(0.95); }
|
|
.glass-btn svg { width: 22px; height: 22px; }
|
|
|
|
.agent-btn { width: 42px; height: 42px; }
|
|
|
|
.agent-btn.is-active {
|
|
background: linear-gradient(135deg, rgba(99, 102, 241, 0.95) 0%, rgba(168, 85, 247, 0.95) 50%, rgba(236, 72, 153, 0.95) 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.35) 0%, transparent 50%);
|
|
pointer-events: none;
|
|
}
|
|
.agent-btn.is-urgent {
|
|
background: linear-gradient(135deg, rgba(239, 68, 68, 0.95) 0%, rgba(220, 38, 38, 0.95) 50%, rgba(185, 28, 28, 0.95) 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; }
|
|
50% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0.18), 0 1px 0 rgba(255, 255, 255, 0.9) inset; }
|
|
}
|
|
.agent-btn.is-waiting { background: linear-gradient(135deg, rgba(245, 158, 11, 0.95) 0%, rgba(217, 119, 6, 0.95) 50%, rgba(180, 83, 9, 0.95) 100%); border-color: rgba(255, 255, 255, 0.4); }
|
|
.agent-btn.is-end { background: linear-gradient(135deg, rgba(16, 185, 129, 0.95) 0%, rgba(5, 150, 105, 0.95) 50%, rgba(4, 120, 87, 0.95) 100%); border-color: rgba(255, 255, 255, 0.4); }
|
|
.agent-btn.is-reopen { background: linear-gradient(135deg, rgba(59, 130, 246, 0.95) 0%, rgba(37, 99, 235, 0.95) 50%, rgba(29, 78, 216, 0.95) 100%); border-color: rgba(255, 255, 255, 0.4); }
|
|
.agent-btn.is-disabled { opacity: 0.4; cursor: not-allowed; }
|
|
.agent-btn.is-disabled:hover { transform: none; background: rgba(255, 255, 255, 0.5); }
|
|
.agent-btn.is-disabled svg { filter: grayscale(1); }
|
|
|
|
.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;
|
|
}
|
|
|
|
.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; }
|
|
|
|
/* 坐席头像风格对比 */
|
|
.avatar-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 16px;
|
|
margin: 16px 0;
|
|
}
|
|
.avatar-card {
|
|
background: rgba(255, 255, 255, 0.7);
|
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
border-radius: 16px;
|
|
padding: 24px 16px 16px;
|
|
text-align: center;
|
|
backdrop-filter: blur(20px);
|
|
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset, 0 8px 16px rgba(99, 102, 241, 0.08);
|
|
transition: all 0.2s;
|
|
cursor: pointer;
|
|
}
|
|
.avatar-card:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 1px 0 rgba(255, 255, 255, 1) inset, 0 12px 24px rgba(99, 102, 241, 0.15);
|
|
}
|
|
.avatar-card.recommend { border: 2px solid #6366f1; }
|
|
.avatar-card .stage {
|
|
width: 100px;
|
|
height: 100px;
|
|
margin: 0 auto 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.avatar-card .stage svg { width: 100%; height: 100%; }
|
|
.avatar-card h4 { font-size: 13px; font-weight: 600; margin-bottom: 4px; color: #1a1a1a; }
|
|
.avatar-card p { font-size: 11.5px; color: #6b7280; line-height: 1.5; }
|
|
.avatar-card .badge {
|
|
display: inline-block;
|
|
margin-top: 8px;
|
|
padding: 2px 8px;
|
|
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
|
color: #fff;
|
|
font-size: 10.5px;
|
|
border-radius: 10px;
|
|
font-weight: 500;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<svg width="0" height="0" style="position: absolute;">
|
|
<defs>
|
|
<linearGradient id="g-active" 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-urgent" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#fca5a5"/><stop offset="100%" stop-color="#dc2626"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-waiting" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#fcd34d"/><stop offset="100%" stop-color="#f59e0b"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-success" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#6ee7b7"/><stop offset="100%" stop-color="#10b981"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-reopen" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#93c5fd"/><stop offset="100%" stop-color="#3b82f6"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-head-warm" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#fde68a"/><stop offset="100%" stop-color="#fbbf24"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-head-cool" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#a5b4fc"/><stop offset="100%" stop-color="#6366f1"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-body-cool" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#c7d2fe"/><stop offset="100%" stop-color="#818cf8"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-earphone" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#475569"/><stop offset="100%" stop-color="#1e293b"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-earphone-soft" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#cbd5e1"/><stop offset="100%" stop-color="#64748b"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-doc-body" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#ffffff"/><stop offset="100%" stop-color="#dbeafe"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-doc-fold" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#c7d2fe"/><stop offset="100%" stop-color="#818cf8"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-mic-body" 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="#6d28d9"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-emoji-face" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#fef3c7"/><stop offset="100%" stop-color="#fbbf24"/>
|
|
</linearGradient>
|
|
<linearGradient id="g-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="g-deep" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="white" stop-opacity="0"/>
|
|
<stop offset="100%" stop-color="black" stop-opacity="0.15"/>
|
|
</linearGradient>
|
|
</defs>
|
|
</svg>
|
|
|
|
<h1>工具栏统一设计 v0.6 — 图标与坐席头像突破</h1>
|
|
<p class="meta">整体玻璃工具栏保留 + 4 工具图标升级(高质感几何)+ 坐席头像 3 套风格对比 · 2026-08-04 凌晨</p>
|
|
|
|
<div class="note">
|
|
📌 本版核心改动(对比 v0.5):<br>
|
|
• 整体水晶玻璃工具栏✅ 沿用 v0.5<br>
|
|
• 4 工具图标<strong>高质感升级</strong>:<br>
|
|
- 😊 表情:渐变圆脸 + 立体眼睛(双高光点) + 弧形嘴 + 阴影<br>
|
|
- 📎 文件:立体文档(白色→浅蓝渐变 + 折角 + 文字行)<br>
|
|
- 🎤 语音:专业录音棚麦克风(深紫渐变 + 高光条 + 弧形底座)<br>
|
|
• <strong>坐席头像 3 套风格</strong>对比(点击下方 tab 切换查看):<br>
|
|
- A. 几何抽象 IP(Linear/Notion 风)— 极简专业<br>
|
|
- B. Q 版拟人客服(Apple 风)— 圆脸 + 戴耳机,亲和力强<br>
|
|
- C. 3D 立体拟人(Spotify 风)— 多层渐变 + 立体光影<br>
|
|
</div>
|
|
|
|
<h2>🎨 整体工具栏(玻璃拟态 + 升级图标)</h2>
|
|
<div class="demo-block">
|
|
<div class="demo-label">4 按钮工具栏完整效果(点击下方 tab 切换坐席头像风格 A/B/C)</div>
|
|
<div class="demo-stage-bg">
|
|
<div class="glass-toolbar">
|
|
<!-- 表情(升级版) -->
|
|
<button class="glass-btn" title="表情">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<circle cx="12" cy="12" r="9" fill="url(#g-emoji-face)"/>
|
|
<ellipse cx="12" cy="6" rx="6" ry="2" 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.4" stroke-linecap="round"/>
|
|
<path d="M3 12 Q3 21 12 21 Q21 21 21 12 Q21 3 12 3 Q3 3 3 12" fill="url(#g-deep)" opacity="0.3"/>
|
|
</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="12" cy="4" rx="5" ry="0.8" fill="url(#g-highlight)"/>
|
|
<line x1="7" y1="12" x2="17" y2="12" stroke="#6366f1" stroke-width="0.8" opacity="0.5"/>
|
|
<line x1="7" y1="15" x2="15" y2="15" stroke="#6366f1" stroke-width="0.8" opacity="0.5"/>
|
|
<line x1="7" y1="18" x2="13" y2="18" stroke="#6366f1" stroke-width="0.8" opacity="0.5"/>
|
|
</svg>
|
|
</button>
|
|
<div class="glass-divider"></div>
|
|
<!-- 语音(升级版) -->
|
|
<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)"/>
|
|
<ellipse cx="10" cy="3.5" rx="1.2" ry="3" fill="white" opacity="0.55"/>
|
|
<line x1="10" y1="6" x2="10" y2="11" stroke="white" stroke-width="0.3" opacity="0.4"/>
|
|
<line x1="14" y1="6" x2="14" 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>
|
|
<!-- 坐席(动态切换) -->
|
|
<div id="agent-stage"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>👤 坐席头像 3 套风格对比(突破方向)</h2>
|
|
<div class="demo-block">
|
|
<div class="state-tabs">
|
|
<button class="state-tab active" data-style="A">A. 几何抽象 IP(Linear 风)</button>
|
|
<button class="state-tab" data-style="B">B. Q 版拟人(Apple 风)</button>
|
|
<button class="state-tab" data-style="C">C. 3D 立体拟人(Spotify 风)</button>
|
|
</div>
|
|
|
|
<div class="avatar-grid">
|
|
<div class="avatar-card recommend" data-style="A">
|
|
<div class="stage">
|
|
<svg viewBox="0 0 100 100" fill="none">
|
|
<defs>
|
|
<linearGradient id="aA-bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" stop-color="#6366f1"/><stop offset="100%" stop-color="#8b5cf6"/>
|
|
</linearGradient>
|
|
</defs>
|
|
<!-- 圆形渐变背景 -->
|
|
<circle cx="50" cy="50" r="48" fill="url(#aA-bg)"/>
|
|
<ellipse cx="50" cy="30" rx="30" ry="8" fill="white" opacity="0.25"/>
|
|
<!-- 抽象几何"听筒"符号 -->
|
|
<circle cx="50" cy="55" r="22" fill="none" stroke="white" stroke-width="3" opacity="0.9"/>
|
|
<path d="M28 55 Q28 35 50 35 Q72 35 72 55" fill="none" stroke="white" stroke-width="3" opacity="0.9"/>
|
|
<circle cx="28" cy="55" r="5" fill="white"/>
|
|
<circle cx="72" cy="55" r="5" fill="white"/>
|
|
<circle cx="50" cy="55" r="3" fill="white" opacity="0.6"/>
|
|
</svg>
|
|
</div>
|
|
<h4>A. 几何抽象 IP</h4>
|
|
<p>Linear / Notion 风<br>极简专业 · 抽象听筒<br>不拟人 · 品牌色强</p>
|
|
<div class="badge">推荐专业 SaaS</div>
|
|
</div>
|
|
|
|
<div class="avatar-card" data-style="B">
|
|
<div class="stage">
|
|
<svg viewBox="0 0 100 100" fill="none">
|
|
<defs>
|
|
<linearGradient id="aB-bg" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#fde68a"/><stop offset="100%" stop-color="#fb923c"/>
|
|
</linearGradient>
|
|
<linearGradient id="aB-head" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#fef3c7"/><stop offset="100%" stop-color="#fde68a"/>
|
|
</linearGradient>
|
|
</defs>
|
|
<!-- 圆形背景 -->
|
|
<circle cx="50" cy="50" r="48" fill="url(#aB-bg)"/>
|
|
<ellipse cx="50" cy="20" rx="35" ry="8" fill="white" opacity="0.3"/>
|
|
<!-- 拟人客服 -->
|
|
<ellipse cx="50" cy="68" rx="22" ry="14" fill="white" opacity="0.4"/>
|
|
<circle cx="50" cy="48" r="18" fill="url(#aB-head)"/>
|
|
<ellipse cx="50" cy="40" rx="12" ry="3" fill="white" opacity="0.6"/>
|
|
<!-- 耳罩(渐变) -->
|
|
<ellipse cx="32" cy="48" rx="5" ry="8" fill="url(#g-earphone-soft)"/>
|
|
<ellipse cx="68" cy="48" rx="5" ry="8" fill="url(#g-earphone-soft)"/>
|
|
<ellipse cx="32" cy="48" rx="2.5" ry="4" fill="#475569"/>
|
|
<ellipse cx="68" cy="48" rx="2.5" ry="4" fill="#475569"/>
|
|
<!-- 眼睛 -->
|
|
<ellipse cx="42" cy="48" rx="2" ry="2.5" fill="#1e1b4b"/>
|
|
<ellipse cx="58" cy="48" rx="2" ry="2.5" fill="#1e1b4b"/>
|
|
<circle cx="42.6" cy="47.2" r="0.7" fill="white"/>
|
|
<circle cx="58.6" cy="47.2" r="0.7" fill="white"/>
|
|
<!-- 嘴(微笑) -->
|
|
<path d="M44 56 Q50 60 56 56" fill="none" stroke="#1e1b4b" stroke-width="2" stroke-linecap="round"/>
|
|
<!-- 颈 -->
|
|
<rect x="44" y="64" width="12" height="6" fill="#fde68a"/>
|
|
</svg>
|
|
</div>
|
|
<h4>B. Q 版拟人客服</h4>
|
|
<p>Apple 风格<br>圆脸 + 戴耳罩 + 颈<br>亲和力强 · 易识别</p>
|
|
<div class="badge">推荐</div>
|
|
</div>
|
|
|
|
<div class="avatar-card" data-style="C">
|
|
<div class="stage">
|
|
<svg viewBox="0 0 100 100" fill="none">
|
|
<defs>
|
|
<radialGradient id="aC-bg" cx="30%" cy="30%" r="80%">
|
|
<stop offset="0%" stop-color="#a78bfa"/><stop offset="50%" stop-color="#6366f1"/><stop offset="100%" stop-color="#312e81"/>
|
|
</radialGradient>
|
|
<linearGradient id="aC-skin" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#fef3c7"/><stop offset="100%" stop-color="#fcd34d"/>
|
|
</linearGradient>
|
|
<linearGradient id="aC-jacket" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#7c3aed"/><stop offset="100%" stop-color="#4c1d95"/>
|
|
</linearGradient>
|
|
</defs>
|
|
<!-- 3D 渐变背景(径向光) -->
|
|
<circle cx="50" cy="50" r="48" fill="url(#aC-bg)"/>
|
|
<ellipse cx="35" cy="20" rx="25" ry="12" fill="white" opacity="0.3"/>
|
|
<!-- 肩(西装) -->
|
|
<path d="M22 80 Q22 70 32 65 L68 65 Q78 70 78 80 L78 92 L22 92 Z" fill="url(#aC-jacket)"/>
|
|
<!-- 衬衣领 -->
|
|
<path d="M40 65 L50 75 L60 65 L60 60 L50 65 L40 60 Z" fill="white" opacity="0.9"/>
|
|
<!-- 颈 -->
|
|
<rect x="44" y="55" width="12" height="14" fill="url(#aC-skin)"/>
|
|
<!-- 头部(3D 立体) -->
|
|
<circle cx="50" cy="40" r="20" fill="url(#aC-skin)"/>
|
|
<ellipse cx="50" cy="28" rx="14" ry="6" fill="white" opacity="0.4"/>
|
|
<!-- 头发(深色渐变) -->
|
|
<path d="M30 38 Q30 22 50 20 Q70 22 70 38 L70 32 Q70 28 65 26 L60 28 Q55 24 50 24 Q45 24 40 28 L35 26 Q30 28 30 32 Z" fill="#1e1b4b" opacity="0.9"/>
|
|
<!-- 耳罩(3D 立体金属感) -->
|
|
<ellipse cx="28" cy="42" rx="6" ry="9" fill="url(#g-earphone)"/>
|
|
<ellipse cx="72" cy="42" rx="6" ry="9" fill="url(#g-earphone)"/>
|
|
<ellipse cx="28" cy="42" rx="3" ry="5" fill="#0f172a"/>
|
|
<ellipse cx="72" cy="42" rx="3" ry="5" fill="#0f172a"/>
|
|
<ellipse cx="28" cy="40" rx="1" ry="2" fill="white" opacity="0.4"/>
|
|
<ellipse cx="72" cy="40" rx="1" ry="2" fill="white" opacity="0.4"/>
|
|
<!-- 麦克风臂 -->
|
|
<path d="M28 50 Q28 56 35 58" fill="none" stroke="url(#g-earphone)" stroke-width="2" stroke-linecap="round"/>
|
|
<circle cx="35" cy="58" r="2" fill="#dc2626"/>
|
|
<!-- 眼睛(锐利) -->
|
|
<ellipse cx="42" cy="40" rx="2" ry="2.5" fill="#1e1b4b"/>
|
|
<ellipse cx="58" cy="40" rx="2" ry="2.5" fill="#1e1b4b"/>
|
|
<circle cx="42.7" cy="39.2" r="0.7" fill="white"/>
|
|
<circle cx="58.7" cy="39.2" r="0.7" fill="white"/>
|
|
<!-- 眉(浓) -->
|
|
<path d="M38 35 Q42 33 46 35" fill="none" stroke="#1e1b4b" stroke-width="1.5" stroke-linecap="round"/>
|
|
<path d="M54 35 Q58 33 62 35" fill="none" stroke="#1e1b4b" stroke-width="1.5" stroke-linecap="round"/>
|
|
<!-- 鼻 -->
|
|
<path d="M50 42 L48 48 L52 48" fill="none" stroke="#d97706" stroke-width="1" stroke-linecap="round" opacity="0.6"/>
|
|
<!-- 嘴(专业微笑) -->
|
|
<path d="M44 52 Q50 56 56 52" fill="none" stroke="#1e1b4b" stroke-width="1.5" stroke-linecap="round"/>
|
|
</svg>
|
|
</div>
|
|
<h4>C. 3D 立体拟人</h4>
|
|
<p>Spotify / Cuberto 风<br>西装 + 头发 + 锐利五官<br>高级感最强 · 品牌化</p>
|
|
<div class="badge">推荐</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>🎬 客服按钮 6 态(风格 A 演示)</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="state-stage"></div>
|
|
</div>
|
|
</div>
|
|
<div class="state-desc" id="state-desc"></div>
|
|
</div>
|
|
|
|
<h2>📊 3 套坐席头像风格对比</h2>
|
|
<table class="cmp-table" style="width:100%; border-collapse: collapse; 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;">A. 几何抽象 IP</th>
|
|
<th style="border:1px solid rgba(99,102,241,0.15); padding:8px; text-align:left;">B. Q 版拟人</th>
|
|
<th style="border:1px solid rgba(99,102,241,0.15); padding:8px; text-align:left;">C. 3D 立体拟人</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;">Linear / Notion</td><td style="border:1px solid rgba(99,102,241,0.15); padding:8px;">Apple 拟人助手</td><td style="border:1px solid rgba(99,102,241,0.15); padding:8px;">Spotify / Cuberto</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;">高(拟人亲和)</td><td style="border:1px solid rgba(99,102,241,0.15); padding:8px;">高(品牌感)</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;">★★★★</td><td style="border:1px solid rgba(99,102,241,0.15); padding:8px;">★★★★★(顶级)</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;">★★★★★(暖)</td><td style="border:1px solid rgba(99,102,241,0.15); padding:8px;">★★★★(平衡)</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;">中</td><td style="border:1px solid rgba(99,102,241,0.15); padding:8px;">高(SVG 复杂)</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;">中(角色化)</td><td style="border:1px solid rgba(99,102,241,0.15); padding:8px;">高(可做更多表情/姿态)</td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h2>❓ 待你拍板</h2>
|
|
<ol style="margin-left: 20px; line-height: 1.8;">
|
|
<li><strong>坐席头像选 A / B / C 哪套</strong>?或需要混合(如默认 A,排队/紧急用 C 增加情感)?</li>
|
|
<li><strong>4 工具图标升级版</strong>(高质感几何)OK 吗?如仍需调整(比如简化或更抽象),告诉我</li>
|
|
<li>坐席头像 <strong>大小</strong>:42px(当前,比工具按钮大)还是 38px(与其他一致)?</li>
|
|
<li>如果选 C(3D 立体),需<strong>请专业设计师</strong>重画吗?我做的 SVG 复杂度有限,实际效果可能不如设计稿精美</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.6 图标与坐席头像突破 · 2026-08-04 · Duckula 主理人 · 等待用户拍板
|
|
</p>
|
|
|
|
<script>
|
|
const agentSvgs = {
|
|
A: `<svg viewBox="0 0 100 100" fill="none">
|
|
<circle cx="50" cy="50" r="48" fill="url(#g-active)"/>
|
|
<ellipse cx="50" cy="30" rx="30" ry="8" fill="white" opacity="0.25"/>
|
|
<circle cx="50" cy="55" r="22" fill="none" stroke="white" stroke-width="3" opacity="0.9"/>
|
|
<path d="M28 55 Q28 35 50 35 Q72 35 72 55" fill="none" stroke="white" stroke-width="3" opacity="0.9"/>
|
|
<circle cx="28" cy="55" r="5" fill="white"/>
|
|
<circle cx="72" cy="55" r="5" fill="white"/>
|
|
<circle cx="50" cy="55" r="3" fill="white" opacity="0.6"/>
|
|
</svg>`,
|
|
B: `<svg viewBox="0 0 100 100" fill="none">
|
|
<circle cx="50" cy="50" r="48" fill="url(#g-head-warm)"/>
|
|
<ellipse cx="50" cy="20" rx="35" ry="8" fill="white" opacity="0.3"/>
|
|
<ellipse cx="50" cy="68" rx="22" ry="14" fill="white" opacity="0.4"/>
|
|
<circle cx="50" cy="48" r="18" fill="url(#aB-head)"/>
|
|
<ellipse cx="50" cy="40" rx="12" ry="3" fill="white" opacity="0.6"/>
|
|
<ellipse cx="32" cy="48" rx="5" ry="8" fill="url(#g-earphone-soft)"/>
|
|
<ellipse cx="68" cy="48" rx="5" ry="8" fill="url(#g-earphone-soft)"/>
|
|
<ellipse cx="32" cy="48" rx="2.5" ry="4" fill="#475569"/>
|
|
<ellipse cx="68" cy="48" rx="2.5" ry="4" fill="#475569"/>
|
|
<ellipse cx="42" cy="48" rx="2" ry="2.5" fill="#1e1b4b"/>
|
|
<ellipse cx="58" cy="48" rx="2" ry="2.5" fill="#1e1b4b"/>
|
|
<circle cx="42.6" cy="47.2" r="0.7" fill="white"/>
|
|
<circle cx="58.6" cy="47.2" r="0.7" fill="white"/>
|
|
<path d="M44 56 Q50 60 56 56" fill="none" stroke="#1e1b4b" stroke-width="2" stroke-linecap="round"/>
|
|
</svg>`,
|
|
C: `<svg viewBox="0 0 100 100" fill="none">
|
|
<circle cx="50" cy="50" r="48" fill="url(#aC-bg)"/>
|
|
<ellipse cx="35" cy="20" rx="25" ry="12" fill="white" opacity="0.3"/>
|
|
<path d="M22 80 Q22 70 32 65 L68 65 Q78 70 78 80 L78 92 L22 92 Z" fill="url(#aC-jacket)"/>
|
|
<path d="M40 65 L50 75 L60 65 L60 60 L50 65 L40 60 Z" fill="white" opacity="0.9"/>
|
|
<rect x="44" y="55" width="12" height="14" fill="url(#aC-skin)"/>
|
|
<circle cx="50" cy="40" r="20" fill="url(#aC-skin)"/>
|
|
<ellipse cx="50" cy="28" rx="14" ry="6" fill="white" opacity="0.4"/>
|
|
<path d="M30 38 Q30 22 50 20 Q70 22 70 38 L70 32 Q70 28 65 26 L60 28 Q55 24 50 24 Q45 24 40 28 L35 26 Q30 28 30 32 Z" fill="#1e1b4b" opacity="0.9"/>
|
|
<ellipse cx="28" cy="42" rx="6" ry="9" fill="url(#g-earphone)"/>
|
|
<ellipse cx="72" cy="42" rx="6" ry="9" fill="url(#g-earphone)"/>
|
|
<ellipse cx="28" cy="42" rx="3" ry="5" fill="#0f172a"/>
|
|
<ellipse cx="72" cy="42" rx="3" ry="5" fill="#0f172a"/>
|
|
<path d="M28 50 Q28 56 35 58" fill="none" stroke="url(#g-earphone)" stroke-width="2" stroke-linecap="round"/>
|
|
<circle cx="35" cy="58" r="2" fill="#dc2626"/>
|
|
<ellipse cx="42" cy="40" rx="2" ry="2.5" fill="#1e1b4b"/>
|
|
<ellipse cx="58" cy="40" rx="2" ry="2.5" fill="#1e1b4b"/>
|
|
<circle cx="42.7" cy="39.2" r="0.7" fill="white"/>
|
|
<circle cx="58.7" cy="39.2" r="0.7" fill="white"/>
|
|
<path d="M38 35 Q42 33 46 35" fill="none" stroke="#1e1b4b" stroke-width="1.5" stroke-linecap="round"/>
|
|
<path d="M54 35 Q58 33 62 35" fill="none" stroke="#1e1b4b" stroke-width="1.5" stroke-linecap="round"/>
|
|
<path d="M50 42 L48 48 L52 48" fill="none" stroke="#d97706" stroke-width="1" stroke-linecap="round" opacity="0.6"/>
|
|
<path d="M44 52 Q50 56 56 52" fill="none" stroke="#1e1b4b" stroke-width="1.5" stroke-linecap="round"/>
|
|
</svg>`
|
|
};
|
|
|
|
const stateMap = {
|
|
active: { cls: 'is-active', desc: '<strong>active</strong>: 紫粉渐变 + 立体感头像 — 默认"客服在线"。点击切换风格对比 3 套设计' },
|
|
disabled: { cls: 'is-disabled', desc: '<strong>disabled</strong>: 半透明白 + 灰度滤镜 + opacity 0.4 — 表达"不可用"' },
|
|
urgent: { cls: 'is-urgent', desc: '<strong>urgent</strong>: 红色渐变 + 1.6s 发光呼吸(光晕扩散) — 表达"紧急"' },
|
|
waiting: { cls: 'is-waiting', desc: '<strong>waiting</strong>: 橙黄渐变 — 表达"排队中"' },
|
|
end: { cls: 'is-end', desc: '<strong>end</strong>: 绿色渐变 — 表达"已接入坐席,通话中"' },
|
|
reopen: { cls: 'is-reopen', desc: '<strong>reopen</strong>: 蓝色渐变 — 表达"会话已关闭,可重新打开"' }
|
|
};
|
|
|
|
let currentStyle = 'A';
|
|
let currentState = 'active';
|
|
|
|
function renderAgent() {
|
|
const stage = document.getElementById('agent-stage');
|
|
const stateCls = stateMap[currentState].cls;
|
|
const svg = agentSvgs[currentStyle];
|
|
stage.innerHTML = `<button class="glass-btn agent-btn ${stateCls}">${svg}</button>`;
|
|
}
|
|
|
|
function renderState() {
|
|
const stage = document.getElementById('state-stage');
|
|
const desc = document.getElementById('state-desc');
|
|
const s = stateMap[currentState];
|
|
const svg = agentSvgs.A;
|
|
stage.innerHTML = `<button class="glass-btn agent-btn ${s.cls}">${svg}</button>`;
|
|
desc.innerHTML = s.desc;
|
|
}
|
|
|
|
// 风格切换
|
|
document.querySelectorAll('.avatar-card').forEach(card => {
|
|
card.addEventListener('click', () => {
|
|
document.querySelectorAll('.avatar-card').forEach(c => c.classList.remove('recommend'));
|
|
card.classList.add('recommend');
|
|
currentStyle = card.dataset.style;
|
|
document.querySelectorAll('.state-tab[data-style]').forEach(t => {
|
|
t.classList.toggle('active', t.dataset.style === currentStyle);
|
|
});
|
|
renderAgent();
|
|
});
|
|
});
|
|
|
|
// 风格 tab
|
|
document.querySelectorAll('.state-tab[data-style]').forEach(tab => {
|
|
tab.addEventListener('click', () => {
|
|
currentStyle = tab.dataset.style;
|
|
document.querySelectorAll('.state-tab[data-style]').forEach(t => t.classList.remove('active'));
|
|
tab.classList.add('active');
|
|
document.querySelectorAll('.avatar-card').forEach(c => {
|
|
c.classList.toggle('recommend', c.dataset.style === currentStyle);
|
|
});
|
|
renderAgent();
|
|
});
|
|
});
|
|
|
|
// 状态切换
|
|
document.querySelectorAll('.state-tab[data-state]').forEach(tab => {
|
|
tab.addEventListener('click', () => {
|
|
currentState = tab.dataset.state;
|
|
document.querySelectorAll('.state-tab[data-state]').forEach(t => t.classList.remove('active'));
|
|
tab.classList.add('active');
|
|
renderState();
|
|
});
|
|
});
|
|
|
|
renderAgent();
|
|
renderState();
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|