Files
wecom_it_smart_desk/docs/01-产品文档/02-会话管理/原型-REQ-会话-001-工具栏统一设计v2.0-员工端服务蓝扁平版.html
T

712 lines
32 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>工具栏统一设计 v2.0 — 员工端服务蓝扁平服务舱(PRD-通用-001 v1.2 对齐版)</title>
<style>
/* ============================================================
* Token 分层(PRD §4.1.1
* 基础色板层 → 角色主题层 → 语义用途层
* 组件只消费语义用途层,禁止直接写死角色品牌色
* ============================================================ */
:root {
/* 基础色板层 */
--palette-blue-600: #1769E0;
--palette-blue-700: #1258BC;
--palette-cyan-600: #0E9FBA;
--palette-cyan-700: #0E7490;
--palette-green-700: #15803D;
--palette-amber-700: #B45309;
--palette-red-700: #B42318;
--palette-gray-50: #F9FAFB;
--palette-gray-100: #F3F4F6;
--palette-gray-200: #E5E7EB;
--palette-gray-600: #4B5563;
--palette-gray-800: #1F2937;
/* 员工端角色主题层(PRD §4.1.3) */
--theme-accent: var(--palette-blue-600);
--theme-accent-hover: var(--palette-blue-700);
--theme-accent-soft: #E7F0FF;
--theme-secondary: var(--palette-cyan-600);
--surface-page: #F4F8FD;
--surface-panel: #FFFFFF;
--surface-ai: #F3F8FF;
--border-subtle: #D8E6F7;
--text-primary: #172B4D;
--text-secondary: #5B6B82;
/* 语义用途层(PRD §4.1.6 */
--color-action-primary: var(--theme-accent);
--color-focus-ring: var(--theme-accent);
--color-status-success: var(--palette-green-700);
--color-status-warning: var(--palette-amber-700);
--color-status-danger: var(--palette-red-700);
--color-status-info: var(--theme-accent);
--color-status-muted: #9CA3AF; /* 离线灰(语义层,仅状态徽标使用) */
--color-ai: var(--palette-cyan-700);
/* 排版/间距/圆角/阴影(PRD §4.1) */
--font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
--radius-md: 6px;
--radius-lg: 8px;
--radius-xl: 12px;
--radius-full: 999px;
--shadow-sm: 0 1px 2px rgba(23, 41, 77, 0.06);
--shadow-md: 0 2px 8px rgba(23, 41, 77, 0.08);
--duration-fast: 150ms;
--duration-normal: 200ms;
/* 蓝色水晶玻璃增强效果(可选,仅在支持 backdrop-filter 的设备启用)
PRD §4.1.3 员工端工具栏决策:扁平服务舱为生产默认,蓝色玻璃为增强效果 */
--glass-bg: rgba(231, 240, 255, 0.72);
--glass-stroke: rgba(23, 105, 224, 0.18);
}
/* 降级方案:未支持 backdrop-filter 的设备 → 实色扁平服务舱
PRD §6 技术方案:必须提供 @supports not (backdrop-filter: blur(1px)) 降级 */
@supports not (backdrop-filter: blur(1px)) {
:root {
--glass-bg: var(--theme-accent-soft); /* 实色浅蓝替代半透明 */
--glass-stroke: var(--theme-accent); /* 明确蓝色描边替代透明边 */
}
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: var(--font-family);
/* 页面基底 PRD §4.1.3--surface-page = #F4F8FD */
background-color: var(--surface-page);
color: var(--text-primary);
padding: 24px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
min-height: 100vh;
}
h1 { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; margin-bottom: 8px; color: var(--text-primary); }
h1 .ver { color: var(--theme-accent); }
h2 { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; margin: 32px 0 12px; color: var(--text-primary); }
.meta { color: var(--text-secondary); font-size: 12.5px; margin-bottom: 20px; }
/* === 员工端会话窗口 — 扁平卡片,蓝色描边(PRD §4.2.4:阴影 ≤2 层用于浮层,卡片仅用边框+表面) === */
.chatpanel-mock {
width: 100%;
max-width: 720px;
margin: 0 auto;
background-color: var(--surface-panel);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-sm); /* 仅 1 层阴影(PRD 约束装饰性外阴影 ≤2 层) */
overflow: hidden;
position: relative;
}
.chatpanel-mock-header {
padding: 12px 16px;
border-bottom: 1px solid var(--border-subtle); /* 仅窗口标题栏 chrome 分隔 */
background-color: var(--surface-panel);
font-size: 13px;
color: var(--text-primary);
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
}
.chatpanel-mock-header .dot {
width: 8px; height: 8px; border-radius: 50%;
background-color: var(--color-status-success); /* 语义色:在线绿 */
}
.chatpanel-mock-header .title { font-weight: 600; }
.chatpanel-mock-header .sub { color: var(--text-secondary); font-size: 11.5px; }
/* === 消息流区域 === */
.chatpanel-mock-messages {
min-height: 240px;
padding: 20px 16px;
background-color: var(--surface-panel);
display: flex;
flex-direction: column;
gap: 10px;
}
.mock-msg {
max-width: 74%;
padding: 9px 13px;
border-radius: var(--radius-xl);
font-size: 13px;
line-height: 1.55;
}
.mock-msg .who { font-size: 10.5px; opacity: 0.65; margin-bottom: 3px; }
.mock-msg.user {
align-self: flex-end;
background-color: var(--theme-accent); /* 实色服务蓝,无多色渐变 */
color: #FFFFFF;
border-bottom-right-radius: 4px;
}
.mock-msg.ai {
align-self: flex-start;
background-color: var(--surface-ai);
color: var(--text-primary);
border: 1px solid var(--border-subtle);
border-bottom-left-radius: 4px;
}
.mock-msg.ai .quick { margin-top: 8px; display: flex; gap: 6px; flex-wrap: wrap; }
.mock-msg.ai .quick span {
font-size: 11.5px; padding: 4px 10px; border-radius: var(--radius-md);
background-color: var(--theme-accent-soft);
color: var(--theme-accent);
border: 1px solid var(--border-subtle);
}
/* === v2.0 蓝色扁平服务舱 — 生产默认 === */
.toolbar-band {
padding: 6px 16px 10px;
display: flex;
justify-content: center;
}
.toolbar {
position: relative;
display: flex;
align-items: center;
justify-content: center;
padding: 0 14px;
width: fit-content;
height: 72px;
/* PRD §4.1.3:默认扁平蓝色服务舱(稳定对比度、低性能成本) */
background-color: var(--glass-bg);
border: 1px solid var(--glass-stroke);
border-radius: var(--radius-full);
box-shadow: var(--shadow-sm); /* 1 层阴影(PRD 约束) */
}
/* 蓝色水晶玻璃增强(@supports) — 玻璃模糊 + 顶部高光 */
@supports (backdrop-filter: blur(1px)) {
.toolbar {
backdrop-filter: blur(20px) saturate(160%);
-webkit-backdrop-filter: blur(20px) saturate(160%);
}
}
.toolbar-row { display: flex; align-items: center; justify-content: center; gap: 8px; }
.toolbar-row .agent-btn.is-main { width: 56px; height: 56px; margin: 0 6px; }
/* === InputBar — 扁平,无顶部边框(三区融合核心:v1.9.1 起 + v2.0 强化) === */
.inputbar-mock {
background-color: var(--surface-panel);
padding: 2px 16px 14px;
position: relative;
}
.inputbar-mock-field {
width: 100%;
min-height: 56px;
background-color: var(--surface-panel);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
padding: 10px 14px;
font-size: 13px;
color: var(--text-secondary);
line-height: 1.6;
display: flex;
align-items: center;
justify-content: space-between;
transition: border-color var(--duration-fast);
}
.inputbar-mock-field:focus-within {
border-color: var(--color-focus-ring);
outline: 2px solid var(--color-focus-ring);
outline-offset: 1px;
}
.inputbar-mock-field .send {
margin-left: 12px;
padding: 7px 18px;
border-radius: var(--radius-md);
background-color: var(--color-action-primary);
color: #FFFFFF;
font-size: 13px; font-weight: 600;
box-shadow: var(--shadow-sm);
}
/* === 通用按钮(v2.0 蓝色扁平):实色浅蓝,无多色发光 === */
.btn-circle {
width: 40px; height: 40px;
border: 1px solid var(--border-subtle);
background-color: var(--surface-panel);
border-radius: 50%;
cursor: pointer;
display: flex; align-items: center; justify-content: center;
transition: all var(--duration-fast) cubic-bezier(0.4, 0, 0.2, 1);
-webkit-tap-highlight-color: transparent;
position: relative;
box-shadow: var(--shadow-sm);
}
.btn-circle:hover {
background-color: var(--theme-accent-soft);
border-color: var(--theme-accent);
}
.btn-circle:active { transform: scale(0.95); }
.btn-circle svg { width: 22px; height: 22px; display: block; }
.btn-circle:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
/* === 56px 坐席按钮(v2.0:头像 = C-3(1).png + 蓝色主题描边 + 绿色在线点) === */
.agent-btn {
border-radius: 50%;
/* PRD §4.1.3:人工坐席头像使用蓝色主题描边 */
border: 2px solid var(--theme-accent);
cursor: pointer;
position: relative;
padding: 0;
overflow: hidden;
background-color: var(--surface-panel);
box-shadow: var(--shadow-sm);
}
.agent-btn img {
width: 100%; height: 100%; border-radius: 50%; object-fit: cover;
object-position: center 25%; /* 鸭子脸部特征居中略偏下 */
display: block;
}
.agent-badge {
position: absolute; bottom: -2px; right: -2px;
width: 14px; height: 14px;
border-radius: 50%;
border: 2px solid var(--surface-panel);
z-index: 3;
/* 默认 = 在线绿(PRD §4.1.3 在线语义) */
background-color: var(--color-status-success);
}
/* === 坐席状态徽标 5 色体系(v1.2 决策补齐,v2.0 服务蓝对齐)===
语义映射:在线=绿 / 紧急=红 / 等待=橙 / 结束|重连=蓝 / 离线=灰
头像本体不变色,仅徽标承载状态色(v1.2 §坐席状态决策) */
.agent-badge.is-online { background-color: var(--color-status-success); } /* 绿 #15803D 在线 */
.agent-badge.is-urgent { background-color: var(--color-status-danger); } /* 红 #B42318 紧急 */
.agent-badge.is-waiting { background-color: var(--color-status-warning); } /* 橙 #B45309 等待 */
.agent-badge.is-end { background-color: var(--color-status-info); } /* 蓝 #1769E0 结束|重连 */
.agent-badge.is-offline { background-color: var(--color-status-muted); } /* 灰 #9CA3AF 离线 */
/* 紧急状态 - 徽标呼吸(红色脉动,v1.2 badgePulse 对齐) */
.agent-btn.is-urgent .agent-badge { animation: badgePulse 1.5s ease-in-out infinite; }
@keyframes badgePulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(180, 35, 24, 0), 0 1px 2px rgba(0,0,0,0.2); }
50% { box-shadow: 0 0 0 4px rgba(180, 35, 24, 0.30), 0 1px 2px rgba(0,0,0,0.2); }
}
/* 离线状态 - 整体弱化(保留头像品牌,仅降低不透明度) */
.agent-btn.is-offline { opacity: 0.5; }
/* === 头像加载失败时的降级占位(避免破图)===
图片 onerror 标记 .img-broken 后隐藏,并以服务蓝胶囊 + 🦆 占位 */
.agent-btn img.img-broken { display: none; }
.agent-btn:has(img.img-broken)::before {
content: "\01F986"; /* 🦆 */
position: absolute; inset: 0;
display: flex; align-items: center; justify-content: center;
font-size: 26px;
background-color: var(--theme-accent-soft);
border-radius: 50%;
z-index: 1;
}
/* === 5 色状态徽标演示(v2.0 服务蓝对齐) === */
.badge-demo-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 12px;
margin: 16px 0;
}
.badge-demo-card {
background-color: var(--surface-panel);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
padding: 18px 10px 14px;
text-align: center;
box-shadow: var(--shadow-sm);
}
.badge-demo-stage {
display: flex;
justify-content: center;
align-items: center;
padding: 4px 0;
}
.badge-demo-card .label {
font-size: 11.5px;
color: var(--text-secondary);
margin-top: 12px;
font-weight: 500;
}
.badge-demo-card .swatch {
display: inline-block;
width: 10px; height: 10px;
border-radius: 50%;
margin-right: 5px;
vertical-align: middle;
border: 1px solid var(--border-subtle);
}
@media (max-width: 560px) {
.badge-demo-grid { grid-template-columns: repeat(2, 1fr); }
}
/* === 提示块 === */
.note-info {
background-color: var(--theme-accent-soft);
border-left: 3px solid var(--theme-accent);
padding: 12px 16px; border-radius: 4px;
font-size: 12.5px; color: var(--text-primary);
margin: 16px 0;
}
.note-success {
background-color: rgba(21, 128, 61, 0.08);
border-left: 3px solid var(--color-status-success);
padding: 12px 16px; border-radius: 4px;
font-size: 12.5px; color: #064E3B;
margin: 16px 0;
}
.note-warn {
background-color: rgba(180, 83, 9, 0.08);
border-left: 3px solid var(--color-status-warning);
padding: 12px 16px; border-radius: 4px;
font-size: 12.5px; color: #78350F;
margin: 16px 0;
}
table { width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 12.5px; }
thead tr { background-color: var(--theme-accent-soft); }
th { border: 1px solid var(--border-subtle); padding: 8px; text-align: left; font-weight: 600; color: var(--text-primary); }
td { border: 1px solid var(--border-subtle); padding: 8px; }
.checklist li { list-style: none; padding-left: 22px; position: relative; line-height: 1.9; font-size: 13px; }
.checklist li::before { content: "□"; position: absolute; left: 4px; color: var(--theme-accent); font-weight: 700; }
.checklist li.done::before { content: "☑"; color: var(--color-status-success); }
/* 头像悬停提示 */
.agent-btn:hover::after {
content: attr(data-tip);
position: absolute;
bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
background-color: rgba(23, 41, 77, 0.92); color: #fff;
font-size: 11px; padding: 4px 8px; border-radius: 6px;
white-space: nowrap; z-index: 10;
}
/* === 降级对照演示 === */
.fallback-band {
margin: 16px 0;
padding: 16px;
background-color: var(--surface-panel);
border: 1px dashed var(--border-subtle);
border-radius: var(--radius-lg);
font-size: 12.5px;
color: var(--text-secondary);
}
.fallback-band code {
background-color: var(--surface-page);
padding: 2px 6px;
border-radius: 4px;
color: var(--theme-accent);
font-family: ui-monospace, "SF Mono", monospace;
}
</style>
</head>
<body>
<h1>工具栏统一设计 v2.0 — <span class="ver">员工端服务蓝扁平服务舱</span></h1>
<p class="meta">
按 PRD-REQ-通用-001-前端设计系统 v1.2 重定义 · 2026-08-06 · Duckula 主理人
&nbsp;|&nbsp; 基线:v1.9.2 主绿水晶玻璃版
</p>
<div class="note-info">
<strong>v2.0 关键决策(PRD v1.2 §4.1.3</strong>
<br><strong>主色迁移</strong>:企微绿 → <strong>服务蓝 #1769E0</strong>(员工端新角色主题);绿色回归成功/在线/已解决语义
<br><strong>工具栏定位</strong>:默认采用<strong>扁平蓝色服务舱</strong>(稳定对比度、低性能成本),蓝色水晶玻璃作为 <code>@supports (backdrop-filter)</code> 增强
<br><strong>降级保证</strong><code>@supports not (backdrop-filter)</code> 时自动切换为实色浅蓝 + 蓝色描边,布局/对比度/可操作性不变
<br><strong>阴影约束</strong>:装饰性外阴影 ≤2 层(原 v1.9.2 是 3 层 feDropShadow,现收敛为 1 层)
<br><strong>Token 分层</strong>:基础色板层 → 角色主题层 → 语义用途层,组件只消费语义用途层
<br><strong>三端区分</strong>:员工端蓝 / 坐席端深海蓝 / 管理端海军蓝,三端共享字体/间距/圆角/图标/交互,主题色按角色变化
</div>
<h2>🎯 员工端落地效果(v2.0 最终视觉)</h2>
<div class="chatpanel-mock">
<div class="chatpanel-mock-header">
<span class="dot" aria-label="在线"></span>
<span class="title">IT 智能服务台</span>
<span class="sub">· 在线 · 工单 #SR-20260805-0392</span>
</div>
<div class="chatpanel-mock-messages">
<div class="mock-msg user">
<div class="who"></div>
你好,我的 VPN 连不上,提示 691 错误,影响今天远程办公。
</div>
<div class="mock-msg ai">
<div class="who">智能助手</div>
您好,VPN 691 通常是账号密码错误或账号被锁定。已为您查询:账号状态正常、未过期。<br>
建议先自助排查:① 确认密码未过期;② 在 portal 重置密码后重试。
<div class="quick">
<span>重置 VPN 密码</span><span>查看排障指引</span><span>转人工坐席</span>
</div>
</div>
<div class="mock-msg user">
<div class="who"></div>
重置了还是不行,麻烦转人工。
</div>
<div class="mock-msg ai">
<div class="who">智能助手</div>
已为您转接人工坐席,请稍候。也可点击下方工具栏「人工坐席」按钮随时发起通话。
</div>
</div>
<div class="toolbar-band">
<div class="toolbar" role="toolbar" aria-label="会话操作工具栏">
<div class="toolbar-row">
<button class="btn-circle" title="表情" aria-label="表情">
<svg viewBox="0 0 24 24" fill="none">
<circle cx="12" cy="12" r="9" fill="#fde68a" stroke="#d97706" stroke-width="1.2"/>
<ellipse cx="8.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
<ellipse cx="15.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b"/>
<circle cx="8.9" cy="10.4" r="0.5" fill="white"/>
<circle cx="15.9" cy="10.4" r="0.5" fill="white"/>
<path d="M8 15 Q12 18 16 15" fill="none" stroke="#1e1b4b" stroke-width="1.6" stroke-linecap="round"/>
</svg>
</button>
<button class="btn-circle" title="文件" aria-label="文件">
<svg viewBox="0 0 24 24" fill="none">
<path d="M4 2 L14 2 L20 8 L20 20 L4 20 Z" fill="#FFFFFF" stroke="var(--theme-accent)" stroke-width="1.2"/>
<path d="M14 2 L14 8 L20 8" fill="var(--theme-accent-soft)" stroke="var(--theme-accent)" stroke-width="1.2"/>
<rect x="7" y="11.5" width="10" height="0.8" rx="0.4" fill="var(--theme-accent)"/>
<rect x="7" y="14" width="7" height="0.8" rx="0.4" fill="var(--theme-secondary)"/>
</svg>
</button>
<button class="agent-btn is-main" title="人工坐席" aria-label="转接人工坐席" data-tip="不吸血的守卫者 · 在线">
<img src="./agent-avatar-v2.0.png" alt="人工坐席" class="agent-avatar-img" onerror="this.classList.add('img-broken')"/>
<span class="agent-badge is-online" aria-label="在线"></span>
</button>
<button class="btn-circle" title="语音输入" aria-label="语音输入">
<svg viewBox="0 0 24 24" fill="none">
<rect x="8" y="2" width="8" height="13" rx="4" fill="var(--theme-accent)"/>
<path d="M3 12 Q3 18 12 18 Q21 18 21 12" fill="none" stroke="var(--theme-accent)" stroke-width="2"/>
<line x1="12" y1="18" x2="12" y2="22" stroke="var(--theme-accent)" stroke-width="2"/>
</svg>
</button>
<button class="btn-circle" title="群聊" aria-label="发起群聊">
<svg viewBox="0 0 24 24" fill="none">
<circle cx="8" cy="9" r="2.2" fill="var(--theme-secondary)" stroke="var(--color-ai)" stroke-width="0.5"/>
<path d="M5 16 Q5 13 8 13 Q11 13 11 16 Z" fill="var(--theme-secondary)"/>
<circle cx="16" cy="9" r="2.2" fill="var(--theme-secondary)"/>
<path d="M13 16 Q13 13 16 13 Q19 13 19 16 Z" fill="var(--theme-secondary)"/>
<circle cx="12" cy="10.5" r="2.8" fill="var(--color-ai)"/>
<path d="M8.5 18.5 Q8.5 14 12 14 Q15.5 14 15.5 18.5 Z" fill="var(--color-ai)"/>
</svg>
</button>
</div>
</div>
</div>
<div class="inputbar-mock">
<div class="inputbar-mock-field" tabindex="0">
<span>描述您的问题,或点击上方工具栏发起操作…</span>
<span class="send">发送</span>
</div>
</div>
</div>
<div class="fallback-band">
<strong>🔁 降级对照</strong>PRD §6 技术方案)
<br>支持 <code>backdrop-filter: blur(1px)</code> 时,<code>.toolbar</code> 启用蓝色水晶玻璃(<code>backdrop-filter: blur(20px) saturate(160%)</code>),背后消息内容被柔化透出。
<br>不支持时(如低端 Android 浏览器、关闭玻璃效果的系统设置),<code>@supports not</code> 规则生效:<code>--glass-bg</code> 改为实色浅蓝 <code>#E7F0FF</code><code>--glass-stroke</code> 改为实色蓝 <code>#1769E0</code>,布局、对比度、操作性完全一致。
</div>
<h2>🎭 坐席按钮 - 头像 + 状态徽标(5 色,v2.0 服务蓝对齐)</h2>
<div class="note-info">
<strong>补齐 v1.2 状态徽标 5 色体系</strong>(原 v2.0 仅保留单一在线绿,已缺失完整状态色)。
<br>· 头像本体不变色,<strong>仅右下角徽标承载状态色</strong>(v1.2 §坐席状态决策:简洁、不喧宾夺主)
<br>· 颜色全部取自 v2.0 语义层 Token:在线=成功绿 <code>#15803D</code> / 紧急=危险红 <code>#B42318</code> / 等待=告警橙 <code>#B45309</code> / 结束·重连=信息蓝 <code>#1769E0</code> / 离线=中性灰 <code>#9CA3AF</code>
<br>· 紧急状态徽标 1.5s 红色呼吸脉动;离线状态整体不透明度降至 0.5 弱化
</div>
<div class="badge-demo-grid">
<div class="badge-demo-card">
<div class="badge-demo-stage">
<button class="agent-btn is-main" style="cursor:default;">
<img src="./agent-avatar-v2.0.png" alt="人工坐席" class="agent-avatar-img" onerror="this.classList.add('img-broken')"/>
<span class="agent-badge is-online"></span>
</button>
</div>
<div class="label"><span class="swatch" style="background:#15803D"></span>在线 🟢</div>
</div>
<div class="badge-demo-card">
<div class="badge-demo-stage">
<button class="agent-btn is-main is-urgent" style="cursor:default;">
<img src="./agent-avatar-v2.0.png" alt="人工坐席" class="agent-avatar-img" onerror="this.classList.add('img-broken')"/>
<span class="agent-badge is-urgent"></span>
</button>
</div>
<div class="label"><span class="swatch" style="background:#B42318"></span>紧急 🔴(呼吸)</div>
</div>
<div class="badge-demo-card">
<div class="badge-demo-stage">
<button class="agent-btn is-main" style="cursor:default;">
<img src="./agent-avatar-v2.0.png" alt="人工坐席" class="agent-avatar-img" onerror="this.classList.add('img-broken')"/>
<span class="agent-badge is-waiting"></span>
</button>
</div>
<div class="label"><span class="swatch" style="background:#B45309"></span>等待 🟠</div>
</div>
<div class="badge-demo-card">
<div class="badge-demo-stage">
<button class="agent-btn is-main" style="cursor:default;">
<img src="./agent-avatar-v2.0.png" alt="人工坐席" class="agent-avatar-img" onerror="this.classList.add('img-broken')"/>
<span class="agent-badge is-end"></span>
</button>
</div>
<div class="label"><span class="swatch" style="background:#1769E0"></span>结束·重连 🔵</div>
</div>
<div class="badge-demo-card">
<div class="badge-demo-stage">
<button class="agent-btn is-main is-offline" style="cursor:default;">
<img src="./agent-avatar-v2.0.png" alt="人工坐席" class="agent-avatar-img" onerror="this.classList.add('img-broken')"/>
<span class="agent-badge is-offline"></span>
</button>
</div>
<div class="label"><span class="swatch" style="background:#9CA3AF"></span>离线 ⚫(弱化)</div>
</div>
</div>
<h2>📋 v2.0 落地检查清单(PRD v1.2 强约束)</h2>
<ul class="checklist">
<li class="done">圆角长方形 + 中央圆润拱形轨道(SVG path 沿用 v1.9 交付清单 §三 锁定)</li>
<li class="done">🆕 <strong>主色由企微绿迁至服务蓝</strong>:#1769E0 角色主题色,员工端产品语义清晰(可信、亲和、低压力)</li>
<li class="done">🆕 <strong>工具栏默认 = 扁平蓝色服务舱</strong>:实色 #E7F0FF 浅蓝 + 实色 #1769E0 描边(PRD §4.1.3 决策)</li>
<li class="done">🆕 <strong>蓝色水晶玻璃 = 可选增强</strong>:仅 <code>@supports (backdrop-filter)</code> 时启用 <code>blur(20px) saturate(160%)</code></li>
<li class="done">🆕 <strong>降级方案完整</strong><code>@supports not (backdrop-filter: blur(1px))</code> 实色回退,对比度 WCAG ≥4.5:1 维持</li>
<li class="done">🆕 <strong>装饰性外阴影 ≤2 层</strong>:本版 = 1 层(卡片 + 工具栏 + 按钮各 1 层 inset/外阴影)</li>
<li class="done">🆕 <strong>Token 分层落地</strong>:组件消费 <code>--color-action-primary</code> / <code>--color-focus-ring</code> / <code>--color-status-success</code> 等语义层,禁止直接写 <code>#1769E0</code></li>
<li class="done">🆕 <strong>坐席状态徽标 5 色体系补齐</strong>v1.2 决策回归):在线绿 <code>#15803D</code> / 紧急红 <code>#B42318</code> / 等待橙 <code>#B45309</code> / 结束·重连蓝 <code>#1769E0</code> / 离线灰 <code>#9CA3AF</code>,颜色均取自语义层,头像本体不变色</li>
<li class="done">🆕 <strong>头像加载失败降级</strong><code>onerror</code> 标记 <code>.img-broken</code> 隐藏破图,<code>:has()</code> 占位服务蓝胶囊 + 🦆,避免原型再次出现破图</li>
<li class="done">🆕 <strong>人工坐席描边 = 蓝色主题</strong><code>border: 2px solid var(--theme-accent)</code>,不再是绿色描边</li>
<li class="done">人工坐席头像沿用 C-3(1).pngv1.9.2 已接入)</li>
<li class="done">三区无边框融合:仅保留窗口标题栏 chrome 分隔(v1.9.1 起)</li>
<li class="done">键盘可达:所有按钮 title + aria-label,可见 <code>:focus-visible</code> 服务蓝环</li>
<li>开发实现:<code>InputBar.vue</code> 升级到 v2.0PRD v1.2 主题层 + 降级 CSS</li>
<li>回归测试:服务蓝主题在浅色/深色/低性能设备三态回归</li>
<li>响应式:≤480px fallback 沿用 v1.9 方案 A 扁平胶囊</li>
</ul>
<h2>🆚 v1.9.2 → v2.0 差异对比(PRD v1.2 主题重定义)</h2>
<table>
<thead>
<tr><th>维度</th><th>v1.9.2 主绿水晶玻璃版</th><th>v2.0 服务蓝扁平版</th></tr>
</thead>
<tbody>
<tr>
<td>PRD 基础</td>
<td>v1.0 / v1.1(企微绿主色)</td>
<td><strong>v1.2</strong>(服务蓝主色)</td>
</tr>
<tr>
<td>主色(角色主题)</td>
<td>企微绿 <code>#07C160</code></td>
<td><strong>服务蓝 <code>#1769E0</code></strong></td>
</tr>
<tr>
<td>辅助色(角色主题)</td>
<td>成功绿 <code>#10B981</code></td>
<td><strong>青蓝 <code>#0E9FBA</code></strong></td>
</tr>
<tr>
<td>页面基底</td>
<td>主绿径向渐变(装饰性)</td>
<td><strong><code>#F4F8FD</code></strong><code>--surface-page</code> 实色)</td>
</tr>
<tr>
<td>工具栏默认</td>
<td>水晶玻璃主导(强制 backdrop-filter</td>
<td><strong>扁平蓝色服务舱</strong>(实色 + 蓝色描边)</td>
</tr>
<tr>
<td>水晶玻璃</td>
<td>默认即开,<code>blur(28px) saturate(180%)</code></td>
<td><strong>可选增强</strong>,仅 <code>@supports</code> 启用 <code>blur(20px) saturate(160%)</code></td>
</tr>
<tr>
<td>降级方案</td>
<td>无(不支持 backdrop-filter 时画面残缺)</td>
<td><strong><code>@supports not</code> 实色回退</strong>,对比度/布局不变</td>
</tr>
<tr>
<td>装饰性外阴影</td>
<td>3 层 feDropShadow + 多层 box-shadow</td>
<td><strong>1 层 <code>--shadow-sm</code></strong>PRD 约束 ≤2 层)</td>
</tr>
<tr>
<td>坐席描边</td>
<td>主绿渐变 <code>#10B981 → #07C160 → #34D399</code></td>
<td><strong>实色服务蓝 <code>#1769E0</code></strong></td>
</tr>
<tr>
<td>坐席在线徽标</td>
<td><code>#10B981</code> 成功绿</td>
<td><strong><code>#15803D</code></strong> 语义成功绿(更深的对比度)</td>
</tr>
<tr>
<td>用户消息气泡</td>
<td>主绿渐变(多色发光)</td>
<td><strong>实色服务蓝</strong>(无渐变,符合 PRD §4.1.2</td>
</tr>
<tr>
<td>AI 消息气泡</td>
<td>浅绿 + 绿边</td>
<td><strong>浅蓝 <code>#F3F8FF</code> + 蓝边 <code>#D8E6F7</code></strong></td>
</tr>
<tr>
<td>语音 / 群聊图标</td>
<td>主绿渐变(紫粉已弃)</td>
<td><strong>实色服务蓝 / 青蓝</strong>(符合角色主题)</td>
</tr>
<tr>
<td>Token 架构</td>
<td>扁平 <code>--color-primary</code> 单层</td>
<td><strong>三层架构</strong>:基础色板 → 角色主题 → 语义用途</td>
</tr>
<tr>
<td>多色发光</td>
<td>存在(紫粉 → 绿)</td>
<td><strong>禁止</strong>PRD §4.1.3</td>
</tr>
<tr>
<td>头像素材</td>
<td>C-3(1).png</td>
<td><strong>C-3(1).png</strong>(沿用,不变)</td>
</tr>
<tr>
<td>几何(SVG path</td>
<td>严格按清单 §三</td>
<td>不变(架构稳定)</td>
</tr>
</tbody>
</table>
<h2>🧭 决策记录</h2>
<div class="note-info">
本版按 PRD-REQ-通用-001-前端设计系统 <strong>v1.2</strong> 重定义员工端主题。关键决策:
<br>· 员工端由「企微绿主色」迁移为「服务蓝主色」(<code>--theme-accent: #1769E0</code>
<br>· 工具栏由「水晶玻璃主导」转为「扁平蓝色服务舱主导 + 玻璃增强可降级」
<br>· 装饰性外阴影 ≤2 层(原 v1.9.2 是 3 层 feDropShadow,现收敛为 1 层 <code>--shadow-sm</code>
<br>· Token 三层架构(基础色板 / 角色主题 / 语义用途),组件只消费语义层
<br>· 绿色仅保留为成功/在线/已解决语义,不再作为品牌主色
<br>· 紫色 <code>#6366f1</code> 完全清退(PRD §4.1.2 仅用于 AI 能力或管理端辅助)
</div>
<div class="note-warn">
⚠️ <strong>已归档</strong>:v1.9.2 主绿水晶玻璃版同步归档为 <code>原型-REQ-会话-001-工具栏统一设计v1.9.2-员工端主绿水晶玻璃版.archive.html</code>,保留历史轨迹但不作为最终交付。
</div>
<h2>⚠️ 待开发对齐的开放项</h2>
<ol style="margin-left: 20px; line-height: 1.8; font-size: 13px;">
<li><strong>Token 文件统一注入</strong>:在 <code>src/frontend-h5/src/styles/tokens.css</code> 落地三层架构,并通过根容器 <code>[data-product="employee"]</code> 注入</li>
<li><strong>降级验证</strong>:在 Safari iOS 旧机型、Android Chrome 90 以下、关闭系统玻璃效果三种环境实测 <code>@supports</code> 切换</li>
<li><strong>WCAG 对比度复测</strong>#FFFFFF on #1769E0 = 5.6:1 ✓ / #172B4D on #FFFFFF = 11.7:1 ✓ / #15803D on #FFFFFF = 4.6:1 ✓</li>
<li><strong>坐席 60→56px</strong>:本版扁平化后将坐席从 60px 收敛到 56px(与扁平工具栏更协调),但需用户确认</li>
<li><strong>三端主题一致性</strong>:坐席端深海蓝 <code>#155E75</code> / 管理端海军蓝 <code>#4F72D8</code> 同步切换,参考 PRD §4.1.4 / §4.1.5</li>
<li><strong>头像素材保留</strong><code>agent-avatar-v2.0.png</code>(已生成于本目录,1024×974)沿用,与品牌一致;v2.0 主工具栏已修正引用路径(原误引 v1.9.2 不存在文件)</li>
</ol>
<p style="margin-top: 32px; padding-top: 16px; border-top: 1px solid var(--border-subtle); color: var(--text-secondary); font-size: 11.5px;">
v2.0 员工端服务蓝扁平服务舱 · 2026-08-06 · Duckula 主理人 · 按 PRD-通用-001 v1.2 重定义 · 已开发实现并视觉验收
</p>
</body>
</html>