Files
wecom_it_smart_desk/docs/01-产品文档/02-会话管理/原型-REQ-会话-001-人工坐席按钮-灵动岛v0.1.html
T
Simon facc04aa65 chore: docs 结构整改 + compose 双目录对齐(合并重建提交)
本提交为 .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-*/
2026-08-07 22:31:32 +08:00

555 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>人工坐席按钮 - 灵动岛风格 v0.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>