# 技术方案 — 员工端结束会话固定按钮 > **版本**: v1.1 > **日期**: 2026-07-26 > **REQ编号**: REQ-用户-005 > **状态**: [已实现] > **作者**: Simon > **关联文档**: > - PRD: `01-产品文档/05-用户端H5/PRD-REQ-用户-005-头像菜单退出-v1.1.md` > - 原型: `01-产品文档/05-用户端H5/原型-REQ-用户-005-头像菜单退出-v1.1.html` --- ## 一、方案概要 **纯前端改动,后端零调整。** 改动范围仅限一个组件:`ChatPanel.vue`。 核心逻辑:头像右侧固定「结束会话」按钮 → 点击弹出确认框 → 串行调用 `employeeClose()` + `logout()` → 关闭窗口/跳转登录页。 | 维度 | 决策 | |------|------| | 后端改动 | **无**(复用已有 close + logout API) | | 前端改动文件 | `ChatPanel.vue`(1 个文件) | | 引用 API | `closing.ts` → `employeeClose()`,`auth.ts` → `logout()` | | 引用 Store | `employeeStore.logout()`,`conversationStore`(判断是否有活跃会话) | | 交互模式 | 头像右侧固定红色边框按钮 → 直接弹出确认对话框(去掉了中间的下拉菜单步骤) | --- ## 二、ChatPanel.vue 改动细节 ### 2.1 模板改动 **标题栏右侧区域(header-actions)**: 头像+姓名改为纯展示(去掉 `@click`/箭头/下拉菜单),新增固定按钮: ```html
{{ employeeStore.employeeName }}
``` ### 2.2 确认对话框 ```html ``` ### 2.3 <script setup> 逻辑 与 v1.0 相比,移除以下**不再需要的**代码: - `showUserMenu` ref - `toggleUserMenu()` 函数 - `closeUserMenu()` 函数 - `handleExitClick()` 函数 保留以下核心逻辑: - `showExitConfirm` / `isExiting` refs - `executeExit()` — 完整退出流程 - `closeWindowOrRedirect()` — 三层窗口关闭降级 按钮点击直接设置 `showExitConfirm = true`,无需中间函数。 ### 2.4 CSS 新增样式 移除所有下拉菜单相关样式(dropdown/item/overlay/arrow 等 80+ 行),新增按钮样式: ```css /* "结束会话"固定按钮 */ .chat-panel__exit-btn { flex-shrink: 0; padding: 4px 12px; font-size: 12px; color: var(--danger, #ee0a24); background: transparent; border: 1px solid var(--danger, #ee0a24); border-radius: 14px; cursor: pointer; transition: all 0.15s ease; white-space: nowrap; line-height: 1.4; } .chat-panel__exit-btn:hover { background: var(--danger, #ee0a24); color: #fff; } .chat-panel__exit-btn:active { opacity: 0.8; } ``` --- ## 三、数据流 ``` 用户看到「结束会话」固定按钮 │ ▼ 用户点击按钮 │ ▼ showExitConfirm = true ──→ 弹出 │ ├── [取消] → showExitConfirm = false → 回到聊天页 │ └── [确定退出] │ ▼ isExiting = true(防重复点击) │ ▼ ┌─ employeeClose('用户主动退出') ← 条件:有活跃会话 │ (失败不阻塞,toast 提示后继续) │ ▼ ┌─ logoutApi() ← 调用 POST /api/auth/logout │ (失败则停止流程,留在当前页) │ ▼ ┌─ employeeStore.logout() ← 清 token、employeeInfo、localStorage │ ▼ ┌─ closeWindowOrRedirect() ← 三层降级关闭窗口 ``` --- ## 四、错误处理矩阵 | 步骤 | 失败场景 | 用户感知 | 是否继续流程 | |------|---------|---------|-------------| | employeeClose | 网络错误/会话已关闭 | Toast "会话关闭失败,继续退出…" | ✅ 继续(不阻塞) | | logoutApi | 网络错误/Token 已失效 | Toast "退出失败,请稍后重试" | ❌ 停止(留在当前页) | | WeixinJSBridge | 非企微环境/JS-SDK未加载 | 静默降级到下一步 | ✅ 继续 | | window.close() | 浏览器安全限制 | 静默降级到跳转 | ✅ 继续 | | 跳转 /h5/login | URL 错误 | 白屏(极端情况,概率极低) | — | --- ## 五、WebSocket 处理 退出后无需显式断开 WebSocket——`employeeStore.logout()` 清除 token 后,路由守卫会将用户重定向到 `/h5/login`,此时页面销毁,WebSocket 连接自然中断。login 页不建立 WS 连接。 若使用 `window.close()` 关闭窗口,浏览器会自动断开所有 WebSocket。 --- ## 六、影响范围 | 影响 | 说明 | |------|------| | ChatPanel.vue | 唯一改动文件,改动量约 -80 行(删下拉菜单)+20 行(加按钮) | | 其他组件 | 无影响 | | 后端 | 无改动 | | 已有功能 | InputBar「结束咨询」按钮不受影响,两入口并存 | | 暗黑模式 | 按钮使用 CSS 变量 `var(--danger)` 自动适配 | --- ## 七、暗黑模式适配 按钮使用 CSS 变量,自动适配: ```css .chat-panel__exit-btn { color: var(--danger, #ee0a24); border: 1px solid var(--danger, #ee0a24); } ``` van-dialog 本身已适配暗黑模式(Vant ConfigProvider),无需额外处理。 --- ## 八、验证清单 | # | 验证项 | 方法 | |---|--------|------| | 1 | 「结束会话」固定按钮可见 | 浏览器手动测试 | | 2 | 点击按钮弹出确认框 | 点击按钮 | | 3 | 确认框文案正确 | 核对"退出后会话记录会清空" | | 4 | 点击取消返回聊天页 | 点击取消 | | 5 | 确认退出全流程走通 | 有活跃会话 → 点击确定 → 跳转 /h5/login | | 6 | 无活跃会话退出 | 新登录直接退出 → 不报错 | | 7 | close API 失败不阻塞 | 断网模拟 → Toast 后继续 | | 8 | logout API 失败留在当前页 | 断网模拟 → Toast 提示 | | 9 | 企微 WebView 真实环境 | 企微打开 H5 → 确认能关闭/跳转 | | 10 | 暗黑模式按钮样式正常 | 切换深色模式后重测 | --- ## 九、变更记录 | 日期 | 版本 | 变更内容 | 变更人 | 变更原因 | |------|------|----------|--------|----------| | 2026-07-26 | v1.0 | 初始版本(下拉菜单方案) | Simon | 新增需求 | | 2026-07-26 | v1.1 | 交互调整为固定按钮方案:移除下拉菜单全部代码,新增 chat-panel__exit-btn 固定按钮 | Simon | 用户反馈:固定按钮更直观 | --- *文档结束*