wip: 2026-08-11 工作树快照(docs/memory/h5.py/scripts 等 447 项未评审改动,安全提交到 feat 分支)
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
> **REQ 编号**: REQ-会话-001
|
||||
> **负责人**: Duckula 主理人
|
||||
> **状态**: ✅ 已拍板,正式交付开发
|
||||
> **基线原型**: `原型-REQ-会话-001-工具栏统一设计v1.9-员工端落地版.html`
|
||||
> **基线原型**: `原型-REQ-会话-001-工具栏统一设计v1.9-员工端落地版.archive.html`
|
||||
> **历史版本**(已归档,仅供回溯): v1.3 / v1.4 / v1.5 / v1.6 / v1.7 / v1.8
|
||||
|
||||
---
|
||||
|
||||
@@ -1,554 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>人工坐席按钮 - 灵动岛风格 v0.1</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
background: #f5f5f5;
|
||||
color: #1f2937;
|
||||
padding: 24px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
h1 { font-size: 22px; font-weight: 600; margin-bottom: 8px; }
|
||||
h2 { font-size: 18px; font-weight: 600; margin: 32px 0 12px; padding-bottom: 6px; border-bottom: 1px solid #e5e7eb; }
|
||||
.meta { color: #6b7280; font-size: 13px; margin-bottom: 24px; }
|
||||
|
||||
/* === 现有工具按钮(基准) === */
|
||||
.baseline { background: #fff; border: 1px solid #e5e7eb; border-radius: 10px; padding: 20px; margin-bottom: 20px; }
|
||||
.baseline-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; }
|
||||
.baseline-row .name { width: 100px; font-size: 12px; color: #6b7280; }
|
||||
.input-bar__tool-btn {
|
||||
width: 36px; height: 36px; border-radius: 8px;
|
||||
border: 1px solid #e5e7eb; background: #ffffff;
|
||||
cursor: pointer; display: flex; align-items: center; justify-content: center;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
/* === 灵动岛按钮(核心) === */
|
||||
.island-stage {
|
||||
background: linear-gradient(135deg, #f0f4ff 0%, #fef7ff 100%);
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 12px;
|
||||
padding: 32px 24px;
|
||||
margin: 16px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.island-title { font-size: 12px; color: #6b7280; margin-bottom: 16px; }
|
||||
|
||||
/* 灵动岛主按钮 - 黑色胶囊 */
|
||||
.island-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
height: 36px;
|
||||
min-width: 36px;
|
||||
padding: 0 12px;
|
||||
background: #000;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 18px;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.island-btn:hover { transform: scale(1.05); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); }
|
||||
.island-btn:active { transform: scale(0.96); }
|
||||
|
||||
/* 灵动岛状态标签 */
|
||||
.island-label {
|
||||
display: inline-block;
|
||||
max-width: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
transition: max-width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease;
|
||||
}
|
||||
.island-btn:hover .island-label,
|
||||
.island-btn.show-label .island-label {
|
||||
max-width: 100px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* SVG 拟人客服容器 */
|
||||
.island-char {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.island-char svg { width: 100%; height: 100%; }
|
||||
|
||||
/* === 6 态特定样式 + 动画 === */
|
||||
|
||||
/* disabled 态:灰色 + 闭眼 */
|
||||
.island-btn.is-disabled {
|
||||
background: #6b7280;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.island-btn.is-disabled:hover { transform: none; }
|
||||
.island-btn.is-disabled .island-char { animation: sleepBreath 3s ease-in-out infinite; }
|
||||
@keyframes sleepBreath {
|
||||
0%, 100% { transform: translateY(0) scale(1); }
|
||||
50% { transform: translateY(-2px) scale(0.95); }
|
||||
}
|
||||
|
||||
/* active 态:默认 + 站立 */
|
||||
.island-btn.is-active {
|
||||
background: #1f2937;
|
||||
}
|
||||
.island-btn.is-active .island-char { animation: idleBounce 2s ease-in-out infinite; }
|
||||
@keyframes idleBounce {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-1.5px); }
|
||||
}
|
||||
|
||||
/* urgent 态:红色 + 抖动 + 脉冲 */
|
||||
.island-btn.is-urgent {
|
||||
background: #dc2626;
|
||||
animation: urgentShake 0.4s ease-in-out infinite, urgentPulse 1.2s ease-in-out infinite;
|
||||
}
|
||||
@keyframes urgentShake {
|
||||
0%, 100% { transform: translateX(0) rotate(0deg); }
|
||||
25% { transform: translateX(-1.5px) rotate(-3deg); }
|
||||
75% { transform: translateX(1.5px) rotate(3deg); }
|
||||
}
|
||||
@keyframes urgentPulse {
|
||||
0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.6), 0 2px 8px rgba(0, 0, 0, 0.15); }
|
||||
50% { box-shadow: 0 0 0 8px rgba(220, 38, 38, 0), 0 2px 8px rgba(0, 0, 0, 0.15); }
|
||||
}
|
||||
|
||||
/* waiting 态:橙色 + 摇头 */
|
||||
.island-btn.is-waiting {
|
||||
background: #ea580c;
|
||||
}
|
||||
.island-btn.is-waiting .island-char { animation: waitingThink 2.5s ease-in-out infinite; }
|
||||
@keyframes waitingThink {
|
||||
0%, 100% { transform: rotate(0deg); }
|
||||
20% { transform: rotate(-8deg); }
|
||||
40% { transform: rotate(8deg); }
|
||||
60% { transform: rotate(-6deg); }
|
||||
80% { transform: rotate(6deg); }
|
||||
}
|
||||
|
||||
/* end 态:绿色 + 电话中 */
|
||||
.island-btn.is-end {
|
||||
background: #16a34a;
|
||||
}
|
||||
.island-btn.is-end .island-char { animation: phoneTalk 1s ease-in-out infinite; }
|
||||
@keyframes phoneTalk {
|
||||
0%, 100% { transform: scale(1); }
|
||||
50% { transform: scale(1.15); }
|
||||
}
|
||||
|
||||
/* reopen 态:蓝色 + 招手 */
|
||||
.island-btn.is-reopen {
|
||||
background: #2563eb;
|
||||
}
|
||||
.island-btn.is-reopen .island-char { animation: reopenWave 1.5s ease-in-out infinite; }
|
||||
@keyframes reopenWave {
|
||||
0%, 100% { transform: rotate(0deg) translateX(0); }
|
||||
25% { transform: rotate(-15deg) translateX(-1px); }
|
||||
75% { transform: rotate(15deg) translateX(1px); }
|
||||
}
|
||||
|
||||
/* === 演示区:状态切换 === */
|
||||
.state-demo {
|
||||
background: #fff;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 10px;
|
||||
padding: 24px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
.state-tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
.state-tab {
|
||||
padding: 6px 14px;
|
||||
border: 1px solid #e5e7eb;
|
||||
background: #fff;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.state-tab.active {
|
||||
background: #1f2937;
|
||||
color: #fff;
|
||||
border-color: #1f2937;
|
||||
}
|
||||
.state-tab:hover:not(.active) { background: #f3f4f6; }
|
||||
|
||||
.state-stage {
|
||||
min-height: 140px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #f0f4ff 0%, #fef7ff 100%);
|
||||
border-radius: 12px;
|
||||
padding: 32px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.state-desc {
|
||||
color: #4b5563;
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
background: #f9fafb;
|
||||
padding: 12px 16px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.state-desc strong { color: #1f2937; }
|
||||
|
||||
/* === 对比表 === */
|
||||
.cmp-table { width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; }
|
||||
.cmp-table th, .cmp-table td { border: 1px solid #e5e7eb; padding: 8px 10px; text-align: left; }
|
||||
.cmp-table th { background: #f9fafb; font-weight: 500; }
|
||||
.cmp-table .yes { color: #16a34a; }
|
||||
.cmp-table .no { color: #dc2626; }
|
||||
.cmp-table .partial { color: #f59e0b; }
|
||||
|
||||
.divider { border: 0; border-top: 1px dashed #d1d5db; margin: 24px 0; }
|
||||
.note { background: #fef3c7; border-left: 3px solid #f59e0b; padding: 12px 16px; border-radius: 4px; font-size: 13px; color: #78350f; margin: 12px 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>🎧 人工坐席按钮 - 灵动岛风格 v0.1</h1>
|
||||
<p class="meta">参考 iPhone 灵动岛(Dynamic Island)动画 + 拟人卡通客服 · 设计时间: 2026-08-04 凌晨</p>
|
||||
|
||||
<div class="note">
|
||||
⚠️ 这是新方向(灵动岛)的概念原型,只做 1 套主方案。如认可,再扩成 2-3 套横向对比(不同卡通风格/不同灵动岛形状)。
|
||||
</div>
|
||||
|
||||
<h2>📐 与现有工具按钮对比(尺寸/位置)</h2>
|
||||
<div class="baseline">
|
||||
<div class="baseline-row">
|
||||
<span class="name">现有工具按钮</span>
|
||||
<button class="input-bar__tool-btn">😊</button>
|
||||
<button class="input-bar__tool-btn">📎</button>
|
||||
<button class="input-bar__tool-btn">🎤</button>
|
||||
<span style="color: #9ca3af; font-size: 12px;">36×36 / 8px 圆角 / 1px 浅灰边框 / 18px 图标</span>
|
||||
</div>
|
||||
<div class="baseline-row">
|
||||
<span class="name">灵动岛按钮</span>
|
||||
<button class="island-btn is-active">
|
||||
<span class="island-char">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="9" r="3" fill="#fbbf24"/>
|
||||
<path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/>
|
||||
<circle cx="9" cy="9" r="0.5" fill="#1f2937"/>
|
||||
<circle cx="15" cy="9" r="0.5" fill="#1f2937"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="island-label">客服在线</span>
|
||||
</button>
|
||||
<span style="color: #6b7280; font-size: 12px;">36×36 / 18px 圆角胶囊 / 纯黑背景 / 24px SVG 卡通</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>🎮 6 态实时切换(点击下方 tab 切换)</h2>
|
||||
<div class="state-demo">
|
||||
<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="state-stage">
|
||||
<div id="stage"></div>
|
||||
</div>
|
||||
|
||||
<div class="state-desc" id="desc"></div>
|
||||
</div>
|
||||
|
||||
<h2>🎨 6 态设计详解</h2>
|
||||
|
||||
<div class="state-demo">
|
||||
<h3 style="margin-bottom: 16px;">disabled(无会话/坐席离线)</h3>
|
||||
<div class="state-stage" style="background: #f3f4f6;">
|
||||
<button class="island-btn is-disabled">
|
||||
<span class="island-char">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="9" r="3" fill="#d1d5db"/>
|
||||
<path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#d1d5db"/>
|
||||
<path d="M9 9.5l2 1 2-1" stroke="#1f2937" stroke-width="0.5" stroke-linecap="round"/>
|
||||
<path d="M7 7l4 2 4-2" stroke="#6b7280" stroke-width="0.8" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="island-label">无会话</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="state-desc">
|
||||
<strong>视觉</strong>: 灰色 (#6b7280) 背景 + 灰色卡通闭眼/打盹姿态<br>
|
||||
<strong>动画</strong>: sleepBreath 3s 呼吸(微缩放 0.95-1.0),表达"睡着了/不在"<br>
|
||||
<strong>交互</strong>: cursor: not-allowed + opacity 0.7,点击无响应
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="state-demo">
|
||||
<h3 style="margin-bottom: 16px;">active(可呼叫人工坐席)</h3>
|
||||
<div class="state-stage">
|
||||
<button class="island-btn is-active">
|
||||
<span class="island-char">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="9" r="3" fill="#fbbf24"/>
|
||||
<path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/>
|
||||
<circle cx="9" cy="9" r="0.6" fill="#1f2937"/>
|
||||
<circle cx="15" cy="9" r="0.6" fill="#1f2937"/>
|
||||
<path d="M10 11c0.5 0.5 3 0.5 4 0" stroke="#1f2937" stroke-width="0.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="island-label">客服在线</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="state-desc">
|
||||
<strong>视觉</strong>: 深灰 (#1f2937) 背景 + 卡通标准姿态(眼睛+微笑)<br>
|
||||
<strong>动画</strong>: idleBounce 2s 微弹跳(上下 1.5px),表达"待机/有活力"<br>
|
||||
<strong>交互</strong>: hover 弹出文字标签"客服在线",点击触发 shakeAgent
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="state-demo">
|
||||
<h3 style="margin-bottom: 16px;">urgent(检测到紧急关键词)</h3>
|
||||
<div class="state-stage" style="background: #fef2f2;">
|
||||
<button class="island-btn is-urgent">
|
||||
<span class="island-char">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="9" r="3" fill="#fbbf24"/>
|
||||
<path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/>
|
||||
<circle cx="9" cy="8" r="0.8" fill="#1f2937"/>
|
||||
<circle cx="15" cy="8" r="0.8" fill="#1f2937"/>
|
||||
<ellipse cx="12" cy="12" rx="1.5" ry="0.8" fill="#1f2937"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="island-label">紧急!</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="state-desc">
|
||||
<strong>视觉</strong>: 红色 (#dc2626) 背景 + 卡通惊恐表情(大眼睛+张嘴)<br>
|
||||
<strong>动画</strong>: urgentShake 0.4s 抖动(左右摇) + urgentPulse 1.2s 脉冲(box-shadow 扩散)<br>
|
||||
<strong>交互</strong>: hover 弹出"紧急!"提示,点击直接 shakeAgent(跳过 AI 拦截)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="state-demo">
|
||||
<h3 style="margin-bottom: 16px;">waiting(排队等待中)</h3>
|
||||
<div class="state-stage" style="background: #fff7ed;">
|
||||
<button class="island-btn is-waiting">
|
||||
<span class="island-char">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="9" r="3" fill="#fbbf24"/>
|
||||
<path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/>
|
||||
<circle cx="9" cy="9" r="0.5" fill="#1f2937"/>
|
||||
<circle cx="15" cy="9" r="0.5" fill="#1f2937"/>
|
||||
<path d="M8 4l-1 2 2-1" stroke="#1f2937" stroke-width="0.8" stroke-linecap="round" fill="none"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="island-label">排队中</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="state-desc">
|
||||
<strong>视觉</strong>: 橙色 (#ea580c) 背景 + 卡通思考姿态(问号/挠头)<br>
|
||||
<strong>动画</strong>: waitingThink 2.5s 摇头(左右 8°-6°-8°),表达"思考/等待"<br>
|
||||
<strong>交互</strong>: hover 弹出"排队中 · 前面 N 人",点击取消排队
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="state-demo">
|
||||
<h3 style="margin-bottom: 16px;">end(已接入坐席)</h3>
|
||||
<div class="state-stage" style="background: #f0fdf4;">
|
||||
<button class="island-btn is-end">
|
||||
<span class="island-char">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="9" r="3" fill="#fbbf24"/>
|
||||
<path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/>
|
||||
<path d="M6 11 Q4 11 4 13 Q4 15 6 15 L7 14" stroke="#16a34a" stroke-width="1.5" fill="none" stroke-linecap="round"/>
|
||||
<circle cx="9" cy="9" r="0.5" fill="#1f2937"/>
|
||||
<circle cx="15" cy="9" r="0.5" fill="#1f2937"/>
|
||||
<path d="M10 11.5c0.5 0.4 3 0.4 4 0" stroke="#1f2937" stroke-width="0.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="island-label">通话中</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="state-desc">
|
||||
<strong>视觉</strong>: 绿色 (#16a34a) 背景 + 卡通+耳机图标(电话通话中)<br>
|
||||
<strong>动画</strong>: phoneTalk 1s 缩放脉冲(1.0-1.15),表达"对话/活跃"<br>
|
||||
<strong>交互</strong>: hover 弹出"通话中 · 客服小王",点击结束会话
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="state-demo">
|
||||
<h3 style="margin-bottom: 16px;">reopen(会话已关闭,可重新打开)</h3>
|
||||
<div class="state-stage" style="background: #eff6ff;">
|
||||
<button class="island-btn is-reopen">
|
||||
<span class="island-char">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="9" r="3" fill="#fbbf24"/>
|
||||
<path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/>
|
||||
<circle cx="9" cy="9" r="0.5" fill="#1f2937"/>
|
||||
<circle cx="15" cy="9" r="0.5" fill="#1f2937"/>
|
||||
<path d="M9 11 Q9 13 12 13 Q15 13 15 11" stroke="#1f2937" stroke-width="0.5" fill="none"/>
|
||||
<path d="M5 4 Q4 3 5 2" stroke="#2563eb" stroke-width="1" fill="none" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="island-label">重新打开</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="state-desc">
|
||||
<strong>视觉</strong>: 蓝色 (#2563eb) 背景 + 卡通招手姿态(嘴笑+招手)<br>
|
||||
<strong>动画</strong>: reopenWave 1.5s 招手(左右 15° 旋转)<br>
|
||||
<strong>交互</strong>: hover 弹出"重新打开 · 24h 内有效",点击 reopenCurrentConversation
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="divider">
|
||||
|
||||
<h2>📊 与之前方案对比(为什么改方向)</h2>
|
||||
<table class="cmp-table">
|
||||
<thead>
|
||||
<tr><th>维度</th><th>v0.1(4 套方块按钮)</th><th>v0.2(灵动岛 + 卡通)</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>视觉</td>
|
||||
<td class="partial">方块按钮 + emoji</td>
|
||||
<td class="yes">黑色胶囊 + 拟人卡通</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>动画</td>
|
||||
<td class="no">静态 6 态切换,无过渡</td>
|
||||
<td class="yes">每态有专属动画(呼吸/抖动/摇头/招手)+ 状态间过渡</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>iPhone 灵动岛感</td>
|
||||
<td class="no">无</td>
|
||||
<td class="yes">黑色胶囊 + 弹性动画 + label 弹出</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>视觉吸引力</td>
|
||||
<td class="partial">功能可见,情感弱</td>
|
||||
<td class="yes">卡通表情 + 动作,情感化(用户会"喜欢"这按钮)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>与现有工具按钮统一性</td>
|
||||
<td class="yes">★★★★★(同尺寸/同边框)</td>
|
||||
<td class="partial">★★★(尺寸 36×36 一致,但黑色胶囊 + 圆角 18px 与方块 8px 不同)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>hover 反馈</td>
|
||||
<td class="partial">背景变灰</td>
|
||||
<td class="yes">scale 1.05 + label 弹出文字"客服在线"等</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6 态区分度</td>
|
||||
<td class="partial">靠颜色(普通)</td>
|
||||
<td class="yes">颜色 + 卡通表情 + 动画(强区分)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>技术实现</td>
|
||||
<td class="yes">纯 CSS 简单</td>
|
||||
<td class="partial">CSS + SVG 卡通(中等)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>❓ 待你拍板</h2>
|
||||
<ol style="margin-left: 20px; line-height: 1.8;">
|
||||
<li>这个 <strong>灵动岛 + 拟人小客服</strong> 方向 OK 吗?(如 OK,我会做 2-3 套不同卡通风格对比)</li>
|
||||
<li>卡通角色是 <strong>拟人客服(戴耳机小黄人风格)</strong> 还是其他?(动物?机器人?抽象图形?)</li>
|
||||
<li>hover 时是否要 <strong>弹出文字标签</strong>?("客服在线" / "排队中" 等)——这与"图标 only"工具有冲突</li>
|
||||
<li>如整体 OK,要 <strong>画 2-3 个不同卡通风格</strong> 让你挑,还是先微调当前这套?</li>
|
||||
</ol>
|
||||
|
||||
<p style="margin-top: 32px; padding-top: 16px; border-top: 1px solid #e5e7eb; color: #6b7280; font-size: 12px;">
|
||||
v0.1 高保真原型 · 2026-08-04 · Duckula 主理人 · 等待用户拍板方向
|
||||
</p>
|
||||
|
||||
<script>
|
||||
// 6 态实时切换逻辑
|
||||
const states = {
|
||||
active: {
|
||||
cls: 'is-active',
|
||||
label: '客服在线',
|
||||
char: '<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="9" r="3" fill="#fbbf24"/><path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/><circle cx="9" cy="9" r="0.6" fill="#1f2937"/><circle cx="15" cy="9" r="0.6" fill="#1f2937"/><path d="M10 11c0.5 0.5 3 0.5 4 0" stroke="#1f2937" stroke-width="0.5" stroke-linecap="round"/></svg>',
|
||||
desc: '<strong>视觉</strong>: 深灰背景 + 卡通标准姿态(眼睛+微笑) | <strong>动画</strong>: idleBounce 2s 微弹跳 | <strong>交互</strong>: hover 弹出文字"客服在线",点击呼叫人工坐席'
|
||||
},
|
||||
disabled: {
|
||||
cls: 'is-disabled',
|
||||
label: '无会话',
|
||||
char: '<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="9" r="3" fill="#d1d5db"/><path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#d1d5db"/><path d="M9 9.5l2 1 2-1" stroke="#1f2937" stroke-width="0.5" stroke-linecap="round"/><path d="M7 7l4 2 4-2" stroke="#6b7280" stroke-width="0.8" stroke-linecap="round"/></svg>',
|
||||
desc: '<strong>视觉</strong>: 灰色背景 + 卡通闭眼/打盹 | <strong>动画</strong>: sleepBreath 3s 呼吸(微缩放 0.95-1.0) | <strong>交互</strong>: cursor not-allowed,点击无响应'
|
||||
},
|
||||
urgent: {
|
||||
cls: 'is-urgent',
|
||||
label: '紧急!',
|
||||
char: '<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="9" r="3" fill="#fbbf24"/><path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/><circle cx="9" cy="8" r="0.8" fill="#1f2937"/><circle cx="15" cy="8" r="0.8" fill="#1f2937"/><ellipse cx="12" cy="12" rx="1.5" ry="0.8" fill="#1f2937"/></svg>',
|
||||
desc: '<strong>视觉</strong>: 红色背景 + 卡通惊恐表情(大眼睛+张嘴) | <strong>动画</strong>: urgentShake 0.4s 抖动 + urgentPulse 1.2s 脉冲 | <strong>交互</strong>: hover 弹出"紧急!"提示,点击直接呼叫坐席'
|
||||
},
|
||||
waiting: {
|
||||
cls: 'is-waiting',
|
||||
label: '排队中',
|
||||
char: '<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="9" r="3" fill="#fbbf24"/><path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/><circle cx="9" cy="9" r="0.5" fill="#1f2937"/><circle cx="15" cy="9" r="0.5" fill="#1f2937"/><path d="M8 4l-1 2 2-1" stroke="#1f2937" stroke-width="0.8" stroke-linecap="round" fill="none"/></svg>',
|
||||
desc: '<strong>视觉</strong>: 橙色背景 + 卡通思考姿态(问号/挠头) | <strong>动画</strong>: waitingThink 2.5s 摇头(左右 8°-6°-8°) | <strong>交互</strong>: hover 弹出"排队中 · 前面 N 人",点击取消排队'
|
||||
},
|
||||
end: {
|
||||
cls: 'is-end',
|
||||
label: '通话中',
|
||||
char: '<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="9" r="3" fill="#fbbf24"/><path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/><path d="M6 11 Q4 11 4 13 Q4 15 6 15 L7 14" stroke="#16a34a" stroke-width="1.5" fill="none" stroke-linecap="round"/><circle cx="9" cy="9" r="0.5" fill="#1f2937"/><circle cx="15" cy="9" r="0.5" fill="#1f2937"/><path d="M10 11.5c0.5 0.4 3 0.4 4 0" stroke="#1f2937" stroke-width="0.5" stroke-linecap="round"/></svg>',
|
||||
desc: '<strong>视觉</strong>: 绿色背景 + 卡通+耳机图标(电话通话中) | <strong>动画</strong>: phoneTalk 1s 缩放脉冲(1.0-1.15) | <strong>交互</strong>: hover 弹出"通话中 · 客服小王",点击结束会话'
|
||||
},
|
||||
reopen: {
|
||||
cls: 'is-reopen',
|
||||
label: '重新打开',
|
||||
char: '<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="9" r="3" fill="#fbbf24"/><path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7" fill="#fbbf24"/><circle cx="9" cy="9" r="0.5" fill="#1f2937"/><circle cx="15" cy="9" r="0.5" fill="#1f2937"/><path d="M9 11 Q9 13 12 13 Q15 13 15 11" stroke="#1f2937" stroke-width="0.5" fill="none"/><path d="M5 4 Q4 3 5 2" stroke="#2563eb" stroke-width="1" fill="none" stroke-linecap="round"/></svg>',
|
||||
desc: '<strong>视觉</strong>: 蓝色背景 + 卡通招手姿态(嘴笑+招手) | <strong>动画</strong>: reopenWave 1.5s 招手(左右 15° 旋转) | <strong>交互</strong>: hover 弹出"重新打开 · 24h 内有效",点击 reopenCurrentConversation'
|
||||
}
|
||||
};
|
||||
|
||||
const stage = document.getElementById('stage');
|
||||
const descEl = document.getElementById('desc');
|
||||
const tabs = document.querySelectorAll('.state-tab');
|
||||
|
||||
function render(state) {
|
||||
const s = states[state];
|
||||
stage.innerHTML = `<button class="island-btn ${s.cls} show-label">
|
||||
<span class="island-char">${s.char}</span>
|
||||
<span class="island-label">${s.label}</span>
|
||||
</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>
|
||||
@@ -1,561 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>人工坐席按钮设计方案 v0.1 — 4 套候选</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
background: #f5f5f5;
|
||||
color: #1f2937;
|
||||
padding: 24px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
h1 { font-size: 22px; font-weight: 600; margin-bottom: 8px; }
|
||||
h2 { font-size: 18px; font-weight: 600; margin: 32px 0 12px; padding-bottom: 6px; border-bottom: 1px solid #e5e7eb; }
|
||||
h3 { font-size: 15px; font-weight: 600; margin: 20px 0 10px; }
|
||||
.meta { color: #6b7280; font-size: 13px; margin-bottom: 24px; }
|
||||
|
||||
/* 方案卡片 */
|
||||
.scheme { background: #fff; border: 1px solid #e5e7eb; border-radius: 10px; padding: 20px; margin-bottom: 20px; }
|
||||
.scheme.recommend { border: 2px solid #1989fa; box-shadow: 0 0 0 4px rgba(25, 137, 250, 0.08); }
|
||||
.scheme-title { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
|
||||
.scheme-title h3 { margin: 0; }
|
||||
.badge { display: inline-block; padding: 2px 8px; font-size: 11px; border-radius: 4px; font-weight: 500; }
|
||||
.badge-rec { background: #1989fa; color: #fff; }
|
||||
.badge-info { background: #ecf5ff; color: #1989fa; }
|
||||
.scheme-desc { color: #4b5563; font-size: 13px; margin-bottom: 14px; }
|
||||
.pros-cons { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }
|
||||
.pros, .cons { padding: 10px 12px; border-radius: 6px; font-size: 12.5px; }
|
||||
.pros { background: #f0fdf4; border-left: 3px solid #16a34a; }
|
||||
.cons { background: #fef2f2; border-left: 3px solid #dc2626; }
|
||||
.pros h4, .cons h4 { font-size: 12px; margin-bottom: 6px; color: #166534; }
|
||||
.cons h4 { color: #991b1b; }
|
||||
.pros ul, .cons ul { list-style: none; padding: 0; }
|
||||
.pros li::before { content: "✓ "; color: #16a34a; }
|
||||
.cons li::before { content: "✗ "; color: #dc2626; }
|
||||
.pros li, .cons li { padding: 2px 0; }
|
||||
|
||||
/* 按钮展示区 */
|
||||
.demo-area {
|
||||
background: #fafafa;
|
||||
border: 1px dashed #d1d5db;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
margin: 12px 0;
|
||||
}
|
||||
.demo-label { font-size: 12px; color: #6b7280; margin-bottom: 10px; }
|
||||
.demo-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; padding: 8px 0; }
|
||||
.demo-name { width: 80px; font-size: 12px; color: #6b7280; }
|
||||
.demo-buttons { display: flex; align-items: center; gap: 8px; }
|
||||
|
||||
/* 现有工具按钮(基准) */
|
||||
.input-bar__tool-btn {
|
||||
width: 36px; height: 36px; border-radius: 8px;
|
||||
border: 1px solid #e5e7eb; background: #ffffff;
|
||||
cursor: pointer; display: flex; align-items: center; justify-content: center;
|
||||
font-size: 18px; transition: all 0.2s;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.input-bar__tool-btn:hover { background: #f3f4f6; border-color: #1989fa; }
|
||||
|
||||
/* 方案 A:轻量图标态 */
|
||||
.scheme-a .btn { width: 36px; height: 36px; border-radius: 8px; border: 1px solid transparent; background: transparent; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 18px; transition: all 0.2s; -webkit-tap-highlight-color: transparent; }
|
||||
.scheme-a .btn:hover { background: #f3f4f6; }
|
||||
.scheme-a .btn--disabled { color: #9ca3af; cursor: not-allowed; }
|
||||
.scheme-a .btn--active { color: #1989fa; }
|
||||
.scheme-a .btn--urgent { color: #ee0a24; animation: pulseA 1.5s ease-in-out infinite; }
|
||||
.scheme-a .btn--waiting { color: #f59e0b; }
|
||||
.scheme-a .btn--end { color: #ee0a24; }
|
||||
.scheme-a .btn--reopen { color: #1989fa; }
|
||||
@keyframes pulseA { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); } }
|
||||
|
||||
/* 方案 B:边框+底色态(8px 圆角) */
|
||||
.scheme-b .btn { width: 36px; height: 36px; border-radius: 8px; border: 1px solid #e5e7eb; background: #ffffff; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 18px; transition: all 0.2s; -webkit-tap-highlight-color: transparent; }
|
||||
.scheme-b .btn--disabled { color: #9ca3af; border-color: #e5e7eb; background: #f9fafb; cursor: not-allowed; opacity: 0.7; }
|
||||
.scheme-b .btn--active { color: #1989fa; border-color: #1989fa; background: rgba(25, 137, 250, 0.08); }
|
||||
.scheme-b .btn--active:hover { background: rgba(25, 137, 250, 0.15); }
|
||||
.scheme-b .btn--urgent { color: #ee0a24; border-color: #ee0a24; background: rgba(238, 10, 36, 0.08); animation: pulseB 1.5s ease-in-out infinite; }
|
||||
.scheme-b .btn--waiting { color: #f59e0b; border-color: #f59e0b; background: rgba(245, 158, 11, 0.08); }
|
||||
.scheme-b .btn--end { color: #ee0a24; border-color: #ee0a24; background: #ee0a24; }
|
||||
.scheme-b .btn--end:hover { background: #dc2626; }
|
||||
.scheme-b .btn--end .ico { color: #fff; }
|
||||
.scheme-b .btn--reopen { color: #1989fa; border-color: #1989fa; background: #ecf5ff; }
|
||||
@keyframes pulseB { 0%, 100% { box-shadow: 0 0 0 0 rgba(238, 10, 36, 0.4); } 50% { box-shadow: 0 0 0 6px rgba(238, 10, 36, 0); } }
|
||||
|
||||
/* 方案 C:仅 disabled/active 两态 */
|
||||
.scheme-c .btn { width: 36px; height: 36px; border-radius: 8px; border: 1px solid #e5e7eb; background: #ffffff; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 18px; transition: all 0.2s; -webkit-tap-highlight-color: transparent; }
|
||||
.scheme-c .btn--disabled { color: #9ca3af; cursor: not-allowed; opacity: 0.6; }
|
||||
.scheme-c .btn--active { color: #1989fa; border-color: #1989fa; background: rgba(25, 137, 250, 0.08); }
|
||||
.scheme-c .btn--active:hover { background: rgba(25, 137, 250, 0.15); }
|
||||
.scheme-c .btn--urgent, .scheme-c .btn--waiting, .scheme-c .btn--end, .scheme-c .btn--reopen {
|
||||
color: #1989fa; border-color: #1989fa; background: rgba(25, 137, 250, 0.08);
|
||||
}
|
||||
.scheme-c .btn--urgent::after { content: "•"; color: #ee0a24; position: absolute; margin-left: 16px; margin-top: -12px; font-size: 24px; }
|
||||
|
||||
/* 方案 D:边框+底色+右上角小圆点 */
|
||||
.scheme-d .btn { width: 36px; height: 36px; border-radius: 8px; border: 1px solid #e5e7eb; background: #ffffff; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 18px; transition: all 0.2s; position: relative; -webkit-tap-highlight-color: transparent; }
|
||||
.scheme-d .btn::after { content: ""; position: absolute; top: 4px; right: 4px; width: 8px; height: 8px; border-radius: 50%; background: #e5e7eb; }
|
||||
.scheme-d .btn--disabled { color: #9ca3af; cursor: not-allowed; opacity: 0.6; }
|
||||
.scheme-d .btn--disabled::after { background: #d1d5db; }
|
||||
.scheme-d .btn--active::after { background: #1989fa; }
|
||||
.scheme-d .btn--urgent { color: #ee0a24; border-color: #ee0a24; }
|
||||
.scheme-d .btn--urgent::after { background: #ee0a24; animation: pulseD 1.5s ease-in-out infinite; }
|
||||
.scheme-d .btn--waiting { color: #f59e0b; border-color: #f59e0b; }
|
||||
.scheme-d .btn--waiting::after { background: #f59e0b; }
|
||||
.scheme-d .btn--end { color: #ee0a24; border-color: #ee0a24; background: rgba(238, 10, 36, 0.05); }
|
||||
.scheme-d .btn--end::after { background: #ee0a24; }
|
||||
.scheme-d .btn--reopen { color: #1989fa; border-color: #1989fa; background: #ecf5ff; }
|
||||
.scheme-d .btn--reopen::after { background: #1989fa; }
|
||||
@keyframes pulseD { 0%, 100% { box-shadow: 0 0 0 0 rgba(238, 10, 36, 0.6); } 50% { box-shadow: 0 0 0 4px rgba(238, 10, 36, 0); } }
|
||||
|
||||
/* 对比表 */
|
||||
.cmp-table { width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13px; }
|
||||
.cmp-table th, .cmp-table td { border: 1px solid #e5e7eb; padding: 8px 10px; text-align: left; }
|
||||
.cmp-table th { background: #f9fafb; font-weight: 500; }
|
||||
.cmp-table .yes { color: #16a34a; }
|
||||
.cmp-table .no { color: #dc2626; }
|
||||
.cmp-table .partial { color: #f59e0b; }
|
||||
|
||||
/* 标题区分 */
|
||||
.emoji-set { display: inline-block; min-width: 28px; text-align: center; font-size: 18px; }
|
||||
.section-divider { border: 0; border-top: 1px dashed #d1d5db; margin: 24px 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>🎧 人工坐席按钮设计方案 v0.1</h1>
|
||||
<p class="meta">4 套候选方案 · 6 态对比 · 与现有 😊📎🎤 工具按钮视觉统一 | 设计时间: 2026-08-04</p>
|
||||
|
||||
<h2>📐 现有工具按钮基准(😊📎🎤)</h2>
|
||||
<div class="demo-area">
|
||||
<div class="demo-label">规格: 36×36 / 8px 圆角 / 1px 边框 / 18px 图标</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">正常</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="input-bar__tool-btn" title="表情">😊</button>
|
||||
<button class="input-bar__tool-btn" title="文件">📎</button>
|
||||
<button class="input-bar__tool-btn" title="语音">🎤</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">hover</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="input-bar__tool-btn" style="background: #f3f4f6; border-color: #1989fa;">😊</button>
|
||||
<button class="input-bar__tool-btn" style="background: #f3f4f6; border-color: #1989fa;">📎</button>
|
||||
<button class="input-bar__tool-btn" style="background: #f3f4f6; border-color: #1989fa;">🎤</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
|
||||
<!-- ============== 方案 A ============== -->
|
||||
<div class="scheme scheme-a recommend">
|
||||
<div class="scheme-title">
|
||||
<h3>方案 A: 轻量图标态(⭐推荐)</h3>
|
||||
<span class="badge badge-rec">推荐</span>
|
||||
<span class="badge badge-info">最轻量</span>
|
||||
</div>
|
||||
<p class="scheme-desc">36×36 与现有工具按钮完全一致的尺寸,默认无背景无边框(透明),仅 emoji 图标 + 颜色变化区分 6 态。最符合"工具栏统一"的设计意图。</p>
|
||||
|
||||
<div class="demo-area">
|
||||
<div class="demo-label">6 态对比(实际 HTML/CSS 渲染效果)</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">disabled</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--disabled" title="无会话">🔒</button>
|
||||
<span class="emoji-set">🔒</span>
|
||||
<span style="color: #9ca3af; font-size: 12px;">无会话 / 不可点击</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">active</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--active" title="可呼叫">🎧</button>
|
||||
<span class="emoji-set">🎧</span>
|
||||
<span style="color: #1989fa; font-size: 12px;">可呼叫人工坐席(默认蓝)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">urgent</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--urgent" title="紧急">🚨</button>
|
||||
<span class="emoji-set">🚨</span>
|
||||
<span style="color: #ee0a24; font-size: 12px;">紧急关键词命中(脉冲动画)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">waiting</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--waiting" title="排队中">⏳</button>
|
||||
<span class="emoji-set">⏳</span>
|
||||
<span style="color: #f59e0b; font-size: 12px;">排队等待中(橙色)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">end</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--end" title="已接入">📴</button>
|
||||
<span class="emoji-set">📴</button>
|
||||
<span style="color: #ee0a24; font-size: 12px;">已接入坐席(红色)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">reopen</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--reopen" title="重新打开">🔄</button>
|
||||
<span class="emoji-set">🔄</span>
|
||||
<span style="color: #1989fa; font-size: 12px;">会话已关闭,可重新打开</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pros-cons">
|
||||
<div class="pros">
|
||||
<h4>✓ 优点</h4>
|
||||
<ul>
|
||||
<li>视觉与现有工具按钮完全统一</li>
|
||||
<li>工具栏最干净,无视觉噪音</li>
|
||||
<li>hover 状态与现有 😊📎 完全一致</li>
|
||||
<li>代码量最少(CSS 简单)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="cons">
|
||||
<h4>✗ 缺点</h4>
|
||||
<ul>
|
||||
<li>6 态仅靠图标 + 颜色区分,变化幅度小</li>
|
||||
<li>重要状态(urgent 红 + 脉冲)可能不够醒目</li>
|
||||
<li>disabled 状态可能与其他工具按钮混淆(都是灰色图标)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============== 方案 B ============== -->
|
||||
<div class="scheme scheme-b">
|
||||
<div class="scheme-title">
|
||||
<h3>方案 B: 边框+底色态(沿用 v1.3 风格,8px 圆角)</h3>
|
||||
<span class="badge badge-info">视觉强</span>
|
||||
</div>
|
||||
<p class="scheme-desc">36×36 与现有按钮尺寸一致,8px 圆角与现有工具按钮对齐,1px 边框 + 底色变化区分 6 态。继承 v1.3 整合区 .call-agent-btn 视觉风格,只是缩小到与现有按钮一致。</p>
|
||||
|
||||
<div class="demo-area">
|
||||
<div class="demo-label">6 态对比</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">disabled</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--disabled" title="无会话">🔒</button>
|
||||
<span style="color: #9ca3af; font-size: 12px;">灰色边框 + 浅灰背景</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">active</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--active" title="可呼叫">🎧</button>
|
||||
<span style="color: #1989fa; font-size: 12px;">蓝色边框 + 浅蓝背景</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">urgent</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--urgent" title="紧急">🚨</button>
|
||||
<span style="color: #ee0a24; font-size: 12px;">红色边框 + 浅红背景 + 脉冲</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">waiting</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--waiting" title="排队中">⏳</button>
|
||||
<span style="color: #f59e0b; font-size: 12px;">橙色边框 + 浅橙背景</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">end</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--end" title="已接入"><span class="ico">📴</span></button>
|
||||
<span style="color: #ee0a24; font-size: 12px;">红色填充 + 白字</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">reopen</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--reopen" title="重新打开">🔄</button>
|
||||
<span style="color: #1989fa; font-size: 12px;">蓝色边框 + 浅蓝背景</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pros-cons">
|
||||
<div class="pros">
|
||||
<h4>✓ 优点</h4>
|
||||
<ul>
|
||||
<li>6 态视觉变化最明显(边框 + 底色 + 文字色)</li>
|
||||
<li>继承 v1.3 整合区 .call-agent-btn 风格,代码复用高</li>
|
||||
<li>disabled 状态明显区别于正常态</li>
|
||||
<li>end 态红色填充强警示</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="cons">
|
||||
<h4>✗ 缺点</h4>
|
||||
<ul>
|
||||
<li>比其他工具按钮视觉更"重"(有底色)</li>
|
||||
<li>工具栏看起来像"3 个轻 + 1 个重",略不协调</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============== 方案 C ============== -->
|
||||
<div class="scheme scheme-c">
|
||||
<div class="scheme-title">
|
||||
<h3>方案 C: 仅 disabled/active 两态(其他用 title 提示)</h3>
|
||||
<span class="badge badge-info">最简洁</span>
|
||||
</div>
|
||||
<p class="scheme-desc">36×36 与现有工具按钮完全一致,只有 disabled 和 active 在工具栏有视觉变化。其他 4 态(urgent/waiting/end/reopen)保持 active 蓝边框,靠 title 属性 + 整合区 toast 提示。</p>
|
||||
|
||||
<div class="demo-area">
|
||||
<div class="demo-label">6 态对比(除 disabled 外,其他都用 active 蓝边框)</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">disabled</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--disabled" title="无会话,暂不可用">🔒</button>
|
||||
<span style="color: #9ca3af; font-size: 12px;">灰色 + 不可点击</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">active</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--active" title="点击呼叫人工坐席">🎧</button>
|
||||
<span style="color: #1989fa; font-size: 12px;">蓝边框(可点击)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">urgent</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--urgent" title="检测到紧急问题,点击直接呼叫">🚨</button>
|
||||
<span style="color: #1989fa; font-size: 12px;">同 active 视觉,靠 title 提示</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">waiting</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--waiting" title="排队中,点击取消">⏳</button>
|
||||
<span style="color: #1989fa; font-size: 12px;">同 active 视觉,靠 title 提示</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">end</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--end" title="已接入,点击结束咨询">📴</button>
|
||||
<span style="color: #1989fa; font-size: 12px;">同 active 视觉,靠 title 提示</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">reopen</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--reopen" title="会话已关闭,点击重新打开">🔄</button>
|
||||
<span style="color: #1989fa; font-size: 12px;">同 active 视觉,靠 title 提示</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pros-cons">
|
||||
<div class="pros">
|
||||
<h4>✓ 优点</h4>
|
||||
<ul>
|
||||
<li>工具栏最简洁(只有蓝/灰两态视觉)</li>
|
||||
<li>完全不会"视觉抢戏"其他工具按钮</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="cons">
|
||||
<h4>✗ 缺点</h4>
|
||||
<ul>
|
||||
<li>用户错过重要状态(urgent 红 + 脉冲 失效)</li>
|
||||
<li>必须依赖整合区 toast 提示,体验割裂</li>
|
||||
<li>disabled 状态和其他工具按钮可点击状态难以区分</li>
|
||||
<li>功能降级感明显,用户可能不知道当前是哪种状态</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============== 方案 D ============== -->
|
||||
<div class="scheme scheme-d">
|
||||
<div class="scheme-title">
|
||||
<h3>方案 D: 边框+底色+右上角小圆点(角标方案)</h3>
|
||||
<span class="badge badge-info">状态最强</span>
|
||||
</div>
|
||||
<p class="scheme-desc">36×36 与现有工具按钮完全一致,8px 圆角,默认无边框(与其他工具风格统一),靠右上角小圆点(8×8 圆)区分 6 态。状态最显眼的方案,但视觉复杂。</p>
|
||||
|
||||
<div class="demo-area">
|
||||
<div class="demo-label">6 态对比(右上角小圆点不同色)</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">disabled</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--disabled" title="无会话,暂不可用">🔒</button>
|
||||
<span style="color: #6b7280; font-size: 12px;">灰色 + 灰色角标</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">active</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--active" title="点击呼叫人工坐席">🎧</button>
|
||||
<span style="color: #1989fa; font-size: 12px;">蓝色角标</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">urgent</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--urgent" title="紧急,点击直接呼叫">🚨</button>
|
||||
<span style="color: #ee0a24; font-size: 12px;">红色边框 + 红色角标(脉冲)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">waiting</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--waiting" title="排队中,点击取消">⏳</button>
|
||||
<span style="color: #f59e0b; font-size: 12px;">橙色边框 + 橙色角标</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">end</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--end" title="已接入,点击结束">📴</button>
|
||||
<span style="color: #ee0a24; font-size: 12px;">红色边框 + 红色角标</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-row">
|
||||
<span class="demo-name">reopen</span>
|
||||
<div class="demo-buttons">
|
||||
<button class="btn btn--reopen" title="重新打开">🔄</button>
|
||||
<span style="color: #1989fa; font-size: 12px;">蓝色边框 + 蓝色角标</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pros-cons">
|
||||
<div class="pros">
|
||||
<h4>✓ 优点</h4>
|
||||
<ul>
|
||||
<li>状态最强视觉(角标 + 边框 + 颜色三重提示)</li>
|
||||
<li>图标不变(只用角标),不切换图标含义</li>
|
||||
<li>扩展性好(可加更多状态)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="cons">
|
||||
<h4>✗ 缺点</h4>
|
||||
<ul>
|
||||
<li>CSS 最复杂(角标需要 ::after 伪元素)</li>
|
||||
<li>小圆点在 36×36 空间内视觉占比偏大</li>
|
||||
<li>多个状态同时存在时可能视觉混乱</li>
|
||||
<li>其他工具按钮没有角标,只这一个有"特殊"</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
|
||||
<h2>📊 4 套方案对比表</h2>
|
||||
<table class="cmp-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>维度</th>
|
||||
<th>方案 A(轻量)</th>
|
||||
<th>方案 B(边框底色)</th>
|
||||
<th>方案 C(仅两态)</th>
|
||||
<th>方案 D(角标)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>尺寸 / 圆角</td>
|
||||
<td>36×36 / 8px ✓</td>
|
||||
<td>36×36 / 8px ✓</td>
|
||||
<td>36×36 / 8px ✓</td>
|
||||
<td>36×36 / 8px ✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>与现有工具按钮视觉一致</td>
|
||||
<td class="yes">★★★★★</td>
|
||||
<td class="partial">★★★</td>
|
||||
<td class="yes">★★★★★</td>
|
||||
<td class="partial">★★★</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6 态视觉变化强度</td>
|
||||
<td class="partial">★★</td>
|
||||
<td class="yes">★★★★★</td>
|
||||
<td class="no">★</td>
|
||||
<td class="yes">★★★★★</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>disabled 区分度</td>
|
||||
<td class="partial">★★</td>
|
||||
<td class="yes">★★★★</td>
|
||||
<td class="yes">★★★★</td>
|
||||
<td class="yes">★★★★</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>紧急态(urgent)醒目度</td>
|
||||
<td class="partial">★★★(脉冲动画)</td>
|
||||
<td class="yes">★★★★★(红+脉冲)</td>
|
||||
<td class="no">★(无变化)</td>
|
||||
<td class="yes">★★★★★(角标脉冲)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSS 复杂度</td>
|
||||
<td class="yes">低</td>
|
||||
<td class="partial">中</td>
|
||||
<td class="yes">低</td>
|
||||
<td class="no">高(::after)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>代码改动量</td>
|
||||
<td class="yes">最小</td>
|
||||
<td class="partial">中</td>
|
||||
<td class="yes">最小</td>
|
||||
<td class="partial">中</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>工具栏整体协调性</td>
|
||||
<td class="yes">★★★★★</td>
|
||||
<td class="partial">★★★</td>
|
||||
<td class="yes">★★★★★</td>
|
||||
<td class="partial">★★</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>💡 我的推荐</h2>
|
||||
<p><strong>方案 A(轻量图标态)⭐推荐</strong></p>
|
||||
<ul style="margin-left: 20px; line-height: 1.8;">
|
||||
<li>完全符合你的需求("与现有表情、文件大小基本一致")</li>
|
||||
<li>工具栏最干净,4 个按钮视觉完全统一</li>
|
||||
<li>6 态用 emoji + 颜色 + 脉冲动画组合,够用且不抢戏</li>
|
||||
<li>CSS 最简单,后续维护成本低</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>备选:方案 B(边框底色态)</strong></p>
|
||||
<ul style="margin-left: 20px; line-height: 1.8;">
|
||||
<li>如果你觉得 A 的 6 态视觉变化不够强,选 B</li>
|
||||
<li>继承 v1.3 整合区 .call-agent-btn 风格,代码复用高</li>
|
||||
<li>但工具栏看起来像"3 个轻 + 1 个重"</li>
|
||||
</ul>
|
||||
|
||||
<h2>❓ 待你拍板</h2>
|
||||
<ol style="margin-left: 20px; line-height: 1.8;">
|
||||
<li>选 A / B / C / D 哪套?(或需要微调?)</li>
|
||||
<li>6 态 emoji 选用是否同意?(🔒/🎧/🚨/⏳/📴/🔄)</li>
|
||||
<li>动画(urgent 脉冲 + waiting 黄色 + end 红色填充)是否都保留?</li>
|
||||
<li>如选 B 或 D:边框颜色是否与现有工具按钮 hover 色(--accent)一致?</li>
|
||||
</ol>
|
||||
|
||||
<p style="margin-top: 32px; padding-top: 16px; border-top: 1px solid #e5e7eb; color: #6b7280; font-size: 12px;">
|
||||
原型 v0.1 · 2026-08-04 · Duckula 主理人 · 等待用户拍板后实施
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user