Files
wecom_it_smart_desk/docs/01-产品文档/02-会话管理/原型-REQ-会话-001-结束会话流程-v1.1.archive.html
T
Simon a8da4da0db docs(会话-001/用户-005): 版本合并与文档规范化整改 #9
REQ-会话-001 员工结束会话:
- PRD/原型 v1.0/v1.1/v1.2 归档为 .archive,现行收敛至单一 v1.3
- 技术方案 v1.2 归档,v1.3 为现行版本(位于 docs/02-技术文档/)
- PRD v1.3 §六 关联文档表指向 v1.3 原型与技术方案实际路径
- 三份任务说明书 + BUG-003 + TC-用户-008 引用同步至 .archive/v1.3

REQ-用户-005 头像菜单退出:
- PRD/原型/技术方案文件名 v1.0 -> v1.1,追平内容版本(铁律2)
- 三件套 + 任务说明书 + TC 互引版本对齐,相关 PRD 指向会话-001 v1.3

其他:
- 修复 4 处 UTF-8 乱码(U+FFFD)
- 新增 TR-会话-001-结束会话-v1.3.2 端到端测试报告(单测 75/75 + 生产构建通过)
- 整改记录 #9 写入 00-文档规范化整改记录.md

遗留: PRD v1.3「状态条永久显示」与代码 v1.3.5「状态条已删除」存在分歧,待产品拍板
2026-08-03 23:53:59 +08:00

798 lines
30 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">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>员工结束会话 - 原型图 v1.1</title>
<style>
:root {
--primary: #07C160;
--primary-light: #e8f9ed;
--text: #333;
--text-light: #666;
--text-tertiary: #999;
--border: #e5e5e5;
--bg: #f7f7f7;
--white: #fff;
--warning: #ff976a;
--danger: #ee0a24;
--danger-soft: rgba(239, 68, 68, 0.1);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', sans-serif;
background: var(--bg);
padding: 20px;
min-height: 100vh;
color: var(--text);
line-height: 1.6;
}
.container { max-width: 900px; margin: 0 auto; }
h1 { text-align: center; margin-bottom: 8px; font-size: 24px; }
.subtitle { text-align: center; color: var(--text-light); margin-bottom: 30px; font-size: 13px; }
.section {
background: var(--white);
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
.section-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 16px;
color: var(--text);
display: flex;
align-items: center;
gap: 8px;
}
.section-title::before {
content: '';
width: 4px;
height: 16px;
background: var(--primary);
border-radius: 2px;
}
.section-desc {
font-size: 13px;
color: var(--text-light);
margin-bottom: 16px;
}
/* === 标题栏 mockup === */
.header-mock {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: var(--white);
border: 1px solid var(--border);
border-radius: 12px;
}
.header-mock__left {
display: flex;
align-items: center;
gap: 12px;
}
.header-mock__brand {
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
}
.header-mock__logo {
background: var(--primary);
color: var(--white);
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 700;
}
.header-mock__status {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 3px 10px;
border-radius: 12px;
font-size: 12px;
font-weight: 500;
}
.header-mock__status--online {
background: var(--primary-light);
color: var(--primary);
}
.header-mock__status--offline {
background: #f5f5f5;
color: var(--text-tertiary);
}
.header-mock__status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: currentColor;
}
.header-mock__actions {
display: flex;
align-items: center;
gap: 12px;
}
.header-mock__avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
color: var(--text-light);
}
.header-mock__exit {
width: 36px;
height: 36px;
border-radius: 8px;
border: 1px solid var(--danger);
color: var(--danger);
background: var(--danger-soft);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 16px;
}
/* === 对话区 mockup === */
.chat-mock {
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
background: var(--bg);
max-width: 480px;
margin: 0 auto;
}
.chat-mock__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 14px;
background: var(--white);
border-bottom: 1px solid var(--border);
font-size: 13px;
}
.chat-mock__messages {
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
min-height: 220px;
}
.msg {
max-width: 75%;
padding: 8px 12px;
border-radius: 12px;
font-size: 13px;
line-height: 1.5;
}
.msg--employee {
align-self: flex-end;
background: var(--primary);
color: var(--white);
border-bottom-right-radius: 4px;
}
.msg--ai {
align-self: flex-start;
background: var(--white);
color: var(--text);
border-bottom-left-radius: 4px;
}
.msg--system {
align-self: center;
background: rgba(0,0,0,0.05);
color: var(--text-light);
font-size: 12px;
text-align: center;
max-width: 90%;
}
/* 排队进度胶囊 — v1.1 核心新增 */
.queue-capsule {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
margin: 12px 16px;
padding: 10px 14px;
border-radius: 20px;
font-size: 13px;
font-weight: 500;
background: rgba(245, 158, 11, 0.1);
color: var(--warning);
border: 1px solid var(--warning);
text-align: center;
}
.queue-capsule--connected {
background: var(--primary-light);
color: var(--primary);
border-color: var(--primary);
}
.queue-capsule--closed {
background: rgba(0,0,0,0.05);
color: var(--text-light);
border-color: var(--border);
}
.queue-capsule__icon { font-size: 14px; }
/* 输入栏 — 5 态按钮展示 */
.input-bar-mock {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
background: var(--white);
border-top: 1px solid var(--border);
}
.input-bar-mock__field {
flex: 1;
padding: 6px 10px;
border: 1px solid var(--border);
border-radius: 8px;
font-size: 13px;
color: var(--text-light);
}
.input-bar-mock__send {
padding: 6px 14px;
background: var(--primary);
color: var(--white);
border: none;
border-radius: 6px;
font-size: 13px;
cursor: pointer;
}
.call-btn {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 12px;
border-radius: 14px;
font-size: 12px;
font-weight: 600;
border: 1.5px solid;
cursor: pointer;
white-space: nowrap;
}
.call-btn--disabled {
border-color: var(--border);
background: var(--bg);
color: var(--text-tertiary);
opacity: 0.6;
cursor: not-allowed;
}
.call-btn--active {
border-color: var(--primary);
background: var(--primary-light);
color: var(--primary);
}
.call-btn--urgent {
border-color: var(--danger);
background: var(--danger-soft);
color: var(--danger);
animation: pulse 1.5s ease-in-out infinite;
}
.call-btn--waiting {
border-color: var(--warning);
background: rgba(245, 158, 11, 0.1);
color: var(--warning);
}
@keyframes pulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
50% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); }
}
/* 5 态网格 */
.states-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 12px;
margin-top: 16px;
}
.state-card {
border: 1.5px dashed var(--border);
border-radius: 10px;
padding: 14px;
text-align: center;
}
.state-card__label {
font-size: 11px;
color: var(--text-tertiary);
margin-bottom: 10px;
font-family: monospace;
}
/* 对比布局 */
.compare-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
margin-top: 16px;
}
.compare-pane {
border: 1px solid var(--border);
border-radius: 10px;
padding: 14px;
background: var(--bg);
}
.compare-pane__title {
font-size: 13px;
font-weight: 600;
margin-bottom: 10px;
color: var(--text);
}
.compare-pane--v1 {
border-top: 3px solid var(--text-tertiary);
}
.compare-pane--v11 {
border-top: 3px solid var(--primary);
}
.mini-panel {
background: var(--white);
border-radius: 8px;
padding: 10px;
margin-bottom: 6px;
font-size: 12px;
color: var(--text-light);
}
.mini-panel--removed {
background: #fff0f0;
color: var(--danger);
text-decoration: line-through;
}
.mini-panel__title {
font-weight: 600;
color: var(--text);
margin-bottom: 4px;
}
/* 流程图 */
.flow {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 6px;
flex-wrap: wrap;
padding: 16px 0;
}
.flow-step {
background: var(--primary);
color: var(--white);
padding: 8px 14px;
border-radius: 16px;
font-size: 13px;
font-weight: 500;
}
.flow-step--system {
background: var(--text-tertiary);
}
.flow-step--warn {
background: var(--warning);
}
.flow-arrow {
font-size: 18px;
color: var(--text-light);
}
/* 注释 */
.note {
background: #fff7e6;
border: 1px solid #ffd591;
border-radius: 8px;
padding: 12px;
font-size: 13px;
color: #d46b08;
margin-top: 12px;
}
.note--info {
background: var(--primary-light);
border-color: var(--primary);
color: var(--text);
}
.note--danger {
background: #fff0f0;
border-color: #ffccc7;
color: var(--danger);
}
/* 表格式对比 */
.cmp-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
margin-top: 12px;
}
.cmp-table th, .cmp-table td {
text-align: left;
padding: 8px 10px;
border: 1px solid var(--border);
}
.cmp-table th {
background: var(--bg);
font-weight: 600;
}
.cmp-table td {
color: var(--text-light);
}
.cmp-table tr td:first-child {
font-weight: 600;
color: var(--text);
}
</style>
</head>
<body>
<div class="container">
<h1>🎯 员工结束会话功能 · 原型图 v1.1</h1>
<div class="subtitle">
v1.1 调整(2026-07-30)— 维度分离 + 排队进度消息胶囊 + 右栏简化
</div>
<!-- ========== 章节 1:设计哲学 ========== -->
<div class="section">
<div class="section-title">设计哲学:维度分离</div>
<div class="section-desc">
把 v1.0 的 5 个按钮状态按"性质"拆成 3 个独立维度,每个维度用最合适的 UI 形式呈现。
</div>
<table class="cmp-table">
<thead>
<tr>
<th>维度</th>
<th>性质</th>
<th>UI 形式</th>
<th>位置</th>
</tr>
</thead>
<tbody>
<tr>
<td>A. 服务可用性</td>
<td>系统状态(坐席/排班)</td>
<td>标题栏徽章 🟢/⚫</td>
<td>顶部,永远可见</td>
</tr>
<tr>
<td>B. 会话进程</td>
<td>用户动作(点击)</td>
<td>操作按钮 5 态切换</td>
<td>输入栏控件区</td>
</tr>
<tr>
<td>C. 排队进度 🆕</td>
<td>实时反馈(WS 推送)</td>
<td>底部消息胶囊</td>
<td>输入框上方,锚定底部</td>
</tr>
</tbody>
</table>
</div>
<!-- ========== 章节 2:标题栏 + 服务可用性 ========== -->
<div class="section">
<div class="section-title">① 标题栏 · 服务可用性指示(v1.1 G4)</div>
<div class="section-desc">
永远显示,不随页面滚动消失。后续 v1.2 可扩展为"在线/繁忙/离线"三态。
</div>
<div class="header-mock">
<div class="header-mock__left">
<div class="header-mock__brand">
<span class="header-mock__logo">IT</span>
<span>智能IT服务</span>
</div>
<span class="header-mock__status header-mock__status--online">
<span class="header-mock__status-dot"></span>
坐席在线
</span>
</div>
<div class="header-mock__actions">
<span style="color:var(--text-light);font-size:13px;">☀️ 🌙</span>
<div class="header-mock__avatar">S</div>
<div class="header-mock__exit" title="结束会话"></div>
</div>
</div>
<div style="margin-top:12px;"></div>
<div class="header-mock">
<div class="header-mock__left">
<div class="header-mock__brand">
<span class="header-mock__logo">IT</span>
<span>智能IT服务</span>
</div>
<span class="header-mock__status header-mock__status--offline">
<span class="header-mock__status-dot"></span>
坐席离线
</span>
</div>
<div class="header-mock__actions">
<span style="color:var(--text-light);font-size:13px;">☀️ 🌙</span>
<div class="header-mock__avatar">S</div>
<div class="header-mock__exit" title="结束会话"></div>
</div>
</div>
<div class="note note--info">
💡 结束会话入口:标题栏右侧红色退出按钮(不再用"结束咨询"按钮态)
</div>
</div>
<!-- ========== 章节 3:操作按钮 5 态 ========== -->
<div class="section">
<div class="section-title">② 操作按钮 · 5 态合并(与 InputBar.vue 实现对齐)</div>
<div class="section-desc">
5 种状态合并到同一按钮位置,通过文案 + 图标 + 颜色区分。<b>2026-07-27 变更</b>:移除"结束咨询"按钮态,由标题栏红色按钮统一触发。
</div>
<div class="states-grid">
<div class="state-card">
<div class="state-card__label">hidden</div>
<button class="call-btn call-btn--disabled" style="visibility:hidden;">占位</button>
<div style="margin-top:8px;font-size:12px;color:var(--text-light);">不显示按钮</div>
</div>
<div class="state-card">
<div class="state-card__label">disabled</div>
<button class="call-btn call-btn--disabled">🔒 人工坐席</button>
<div style="margin-top:8px;font-size:12px;color:var(--text-light);">坐席离线</div>
</div>
<div class="state-card">
<div class="state-card__label">active</div>
<button class="call-btn call-btn--active">🎧 人工坐席</button>
<div style="margin-top:8px;font-size:12px;color:var(--text-light);">AI ≥ 3 次</div>
</div>
<div class="state-card">
<div class="state-card__label">urgent</div>
<button class="call-btn call-btn--urgent">🚨 人工坐席</button>
<div style="margin-top:8px;font-size:12px;color:var(--text-light);">紧急关键词</div>
</div>
<div class="state-card">
<div class="state-card__label">waiting</div>
<button class="call-btn call-btn--waiting">⏳ 排队等待</button>
<div style="margin-top:8px;font-size:12px;color:var(--text-light);">已呼叫队列</div>
</div>
</div>
<div class="note">
⚠️ 优先级:hidden &gt; waiting &gt; active/urgent &gt; disabled
</div>
</div>
<!-- ========== 章节 4:底部排队进度胶囊 ⭐核心新增⭐ ========== -->
<div class="section" style="border:2px solid var(--primary);">
<div class="section-title">⭐ ③ 底部排队进度消息胶囊(v1.1 G5 · 核心新增)</div>
<div class="section-desc">
<b>位置</b>:主对话流底部(输入框上方),视觉样式参照"会话已关闭"系统消息,但<b>锚定底部不随滚动消失</b><br>
<b>更新机制</b>:仅在关键节点更新内容(进入排队、每跳 3 位、接听),不每次位置变化都重渲染。<br>
<b>设计哲学</b>:不作为消息插入对话流,避免污染 AI 上下文与推荐系统。
</div>
<!-- 状态 1:未排队 -->
<div style="font-size:12px;color:var(--text-tertiary);margin-bottom:6px;">▸ 未排队(不显示胶囊)</div>
<div class="chat-mock">
<div class="chat-mock__header">
<span>💬 对话</span>
<span style="color:var(--text-tertiary);">🩺 信息</span>
</div>
<div class="chat-mock__messages">
<div class="msg msg--employee">VPN 连不上怎么解决?</div>
<div class="msg msg--ai">请尝试以下步骤...</div>
</div>
<div class="input-bar-mock">
<span>😊</span><span>📎</span>
<div class="input-bar-mock__field">请输入消息...</div>
<button class="call-btn call-btn--active">🎧 人工坐席</button>
<button class="input-bar-mock__send">发送</button>
</div>
</div>
<!-- 状态 2:排队中 -->
<div style="font-size:12px;color:var(--text-tertiary);margin:24px 0 6px;">▸ 排队中(橙色胶囊 · 关键节点更新内容)</div>
<div class="chat-mock">
<div class="chat-mock__header">
<span>💬 对话</span>
<span style="color:var(--text-tertiary);">🩺 信息</span>
</div>
<div class="chat-mock__messages">
<div class="msg msg--employee">VPN 连不上</div>
<div class="msg msg--ai">请尝试...</div>
<div class="msg msg--system">系统已为您接入人工队列,请稍候</div>
</div>
<div class="queue-capsule">
<span class="queue-capsule__icon"></span>
<span>排队中 · 前面 <b>3</b> 人 · 预计 <b>1:32</b></span>
</div>
<div class="input-bar-mock">
<span>😊</span><span>📎</span>
<div class="input-bar-mock__field">请输入消息...</div>
<button class="call-btn call-btn--waiting">⏳ 排队等待</button>
<button class="input-bar-mock__send">发送</button>
</div>
</div>
<!-- 状态 3:已接入 -->
<div style="font-size:12px;color:var(--text-tertiary);margin:24px 0 6px;">▸ 已接入(绿色胶囊 · 3 秒后淡出)</div>
<div class="chat-mock">
<div class="chat-mock__header">
<span>💬 对话</span>
<span style="color:var(--text-tertiary);">🩺 信息</span>
</div>
<div class="chat-mock__messages">
<div class="msg msg--employee">VPN 连不上</div>
<div class="msg msg--ai">请尝试...</div>
<div class="msg msg--system">客服小王已接入服务</div>
</div>
<div class="queue-capsule queue-capsule--connected">
<span class="queue-capsule__icon">🟢</span>
<span>已接入 · 客服小王</span>
</div>
<div class="input-bar-mock">
<span>😊</span><span>📎</span>
<div class="input-bar-mock__field">请输入问题...</div>
<button class="call-btn call-btn--active">🎧 人工坐席</button>
<button class="input-bar-mock__send">发送</button>
</div>
</div>
<!-- 状态 4:会话已关闭 -->
<div style="font-size:12px;color:var(--text-tertiary);margin:24px 0 6px;">▸ 会话已关闭(灰色提示 · 参照"会话已关闭"消息样式)</div>
<div class="chat-mock">
<div class="chat-mock__header">
<span>💬 对话</span>
<span style="color:var(--text-tertiary);">🩺 信息</span>
</div>
<div class="chat-mock__messages">
<div class="msg msg--employee">问题解决了,谢谢</div>
<div class="msg msg--ai">不客气,需要再帮您吗?</div>
<div class="msg msg--system">✅ 问题已解决,会话已关闭。24 小时内可重新打开。</div>
</div>
<div class="queue-capsule queue-capsule--closed" style="margin-top:0;">
<span class="queue-capsule__icon"></span>
<span>会话已结束</span>
</div>
<div class="input-bar-mock">
<span>😊</span><span>📎</span>
<div class="input-bar-mock__field" style="opacity:0.5;">会话已关闭</div>
<button class="input-bar-mock__send" disabled style="opacity:0.5;">发送</button>
</div>
</div>
</div>
<!-- ========== 章节 5:右栏对比 ========== -->
<div class="section">
<div class="section-title">④ 右栏简化(v1.1 G6</div>
<div class="section-desc">
删除右栏底部"排队等待" + "答题挑战",聚焦核心:设备诊断 + 智能推荐。移动端(&lt;500px)不渲染右栏,无变化。
</div>
<div class="compare-grid">
<div class="compare-pane compare-pane--v1">
<div class="compare-pane__title">v1.0 右栏(4 大区块)</div>
<div class="mini-panel">
<div class="mini-panel__title">▼ 设备信息</div>
CPU / 内存 / 硬盘
</div>
<div class="mini-panel">
<div class="mini-panel__title">▼ 自助诊断</div>
一键诊断 + 异常徽章
</div>
<div class="mini-panel">
<div class="mini-panel__title">⚡ 智能推荐</div>
操作步骤 / 联系人 / 下载
</div>
<div class="mini-panel mini-panel--removed">
<div class="mini-panel__title">⏳ 排队等待</div>
位置 / 预计时长 / 答题挑战
</div>
</div>
<div class="compare-pane compare-pane--v11">
<div class="compare-pane__title">v1.1 右栏(2 大区块)✅</div>
<div class="mini-panel">
<div class="mini-panel__title">▼ 设备信息</div>
CPU / 内存 / 硬盘
</div>
<div class="mini-panel">
<div class="mini-panel__title">▼ 自助诊断</div>
一键诊断 + 异常徽章
</div>
<div class="mini-panel">
<div class="mini-panel__title">⚡ 智能推荐</div>
操作步骤 / 联系人 / 下载
</div>
<div class="mini-panel" style="background:#f5f5f5;color:var(--text-tertiary);text-align:center;">
(剩余滚动空间)
</div>
</div>
</div>
<div class="note note--danger">
⚠️ 同步清理:api/queue、api/quiz、store.queuePositionData、WS queue_position_update 回调
</div>
</div>
<!-- ========== 章节 6:完整流程 ========== -->
<div class="section">
<div class="section-title">⑤ 完整流程(员工视角)</div>
<div class="flow">
<div class="flow-step">🎧 人工坐席</div>
<span class="flow-arrow"></span>
<div class="flow-step flow-step--system">系统接入队列</div>
<span class="flow-arrow"></span>
<div class="flow-step flow-step--warn">⏳ 排队胶囊出现</div>
<span class="flow-arrow"></span>
<div class="flow-step flow-step--system">客服接听</div>
<span class="flow-arrow"></span>
<div class="flow-step flow-step--warn">🟢 已接入胶囊</div>
<span class="flow-arrow"></span>
<div class="flow-step">⏏ 标题栏退出按钮</div>
<span class="flow-arrow"></span>
<div class="flow-step">😊 满意度评价</div>
<span class="flow-arrow"></span>
<div class="flow-step flow-step--system">🚪 关闭窗口</div>
</div>
</div>
<!-- ========== 章节 7:变更摘要 ========== -->
<div class="section">
<div class="section-title">⑥ v1.0 → v1.1 关键变更</div>
<table class="cmp-table">
<thead>
<tr>
<th>变更项</th>
<th>v1.0</th>
<th>v1.1</th>
</tr>
</thead>
<tbody>
<tr>
<td>按钮状态数</td>
<td>3 态</td>
<td>5 态(与代码对齐)</td>
</tr>
<tr>
<td>服务可用性 UI</td>
<td>未单独呈现</td>
<td>标题栏徽章 🆕</td>
</tr>
<tr>
<td>排队进度位置</td>
<td>右栏底部卡片</td>
<td>底部消息胶囊 🆕</td>
</tr>
<tr>
<td>答题挑战</td>
<td>右栏内嵌(含插队机制)</td>
<td>完全移除</td>
</tr>
<tr>
<td>结束会话入口</td>
<td>操作按钮"结束咨询"</td>
<td>标题栏红色按钮(2026-07-27 变更)</td>
</tr>
<tr>
<td>右栏结构</td>
<td>4 大区块</td>
<td>2 大区块</td>
</tr>
<tr>
<td>API 清理</td>
<td>保留 queue + quiz</td>
<td>移除</td>
</tr>
</tbody>
</table>
<div class="note">
📌 对应 PRD:<code>PRD-REQ-会话-001-员工结束会话-v1.1.md</code>
</div>
</div>
</div>
</body>
</html>