Files
wecom_it_smart_desk/docs/02-产品需求/坐席端截图拍照功能-PRD.md
T

189 lines
15 KiB
Markdown
Raw Normal View History

# 坐席端截图 + 拍照功能 PRD
## 项目信息
| 项 | 内容 |
|---|---|
| **语言** | 中文 |
| **技术栈** | Vue3 + Element Plus + Tailwind CSS |
| **项目名称** | agent_screenshot_camera |
| **前端目录** | `D:\资料\03-项目开发\wecom_it_smart_desk\frontend-agent` |
| **涉及组件** | `ReplyBox.vue` / `ScreenshotEditor.vue` / `ScreenCapture.vue`(改造)+ 新增 `CameraCapture.vue` |
### 原始需求复述
IT智能服务台坐席端(PC Web 应用)需要增加截图和相机拍照功能。客服在处理工单时经常需要截取屏幕内容或拍照来辅助沟通。截图需支持全屏/窗口/标签页选择(含跨屏),截图时屏幕变暗出现矩形选框 + 工具栏(马赛克、文字标注、箭头、撤销),样式参考微信/企微截图工具。拍照需用 `getUserMedia` + `<video>` 实现内嵌摄像头预览,支持重拍。截图和拍照结果均插入到聊天输入区作为图片消息等待发送(非立即发送)。
---
## 产品定义
### 产品目标
1. **提升沟通效率**:客服无需切换到外部截图工具或手机拍照,直接在工作台内完成截图/拍照→编辑→发送的全流程,减少上下文切换。
2. **保证信息准确性**:通过截图标注(马赛克打码、箭头指引、文字说明)和实时拍照,让客服能够精准传递屏幕画面和实物状况,减少口头描述的歧义。
3. **统一图片消息发送体验**:截图和拍照结果统一进入输入区待发送队列,客服可在发送前预览、补充文字说明或删除,与现有粘贴图片/文件上传的交互保持一致。
### 用户故事
1. **作为客服坐席**,我想直接在工作台点击截图按钮截取屏幕画面,这样我就能把用户报障的屏幕现象快速发给用户确认,而不需要切换到微信截图或系统截图工具。
2. **作为客服坐席**,我想在截图时用马赛克遮挡敏感信息(如密码、个人信息),这样在发送截图时不会泄露用户隐私。
3. **作为客服坐席**,我想在截图选区内用箭头和文字标注重点位置,这样用户能快速理解我指的具体是哪里。
4. **作为客服坐席**,我想通过摄像头拍照来记录实物设备状态(如硬件故障、线缆连接),这样比文字描述更直观。
5. **作为客服坐席**,我想截图/拍照后的图片先进入输入区等我自己确认后再发送,这样我能在发送前检查标注是否正确、是否打码到位。
---
## 技术规范
### 现有代码分析
通过对 `frontend-agent/src/components/chat/` 目录的代码审查,发现以下现状:
| 组件 | 现状 | 差距 |
|---|---|---|
| `ReplyBox.vue` | 工具栏有表情、文件、邀请、快速回复按钮;已有 `handleScreenshot()`(用 `html2canvas`)和 `handleScreenCapture()`(用 `getDisplayMedia`,但未接入任何按钮) | 缺少截图/拍照入口按钮;截图结果直接上传发送而非插入输入区 |
| `ScreenshotEditor.vue` | 裁剪 + 编辑两步模式,工具有画笔/高亮/矩形/箭头/文字,支持撤销/重做 | 缺少马赛克工具 |
| `ScreenCapture.vue` | 全屏遮罩框选模式,工具有画笔/矩形/箭头/文字 | 缺少马赛克工具;结果直接发送 |
| `upload.ts` | 文件上传 API,支持重试,返回 `{ url, filename, file_size, msg_type }` | 可复用 |
| 拍照功能 | **完全不存在** | 需新建 `CameraCapture.vue` 组件 |
**关键发现**`ReplyBox.vue` 中已有 `handleScreenCapture()` 方法调用了 `navigator.mediaDevices.getDisplayMedia()`,但该方法未绑定到任何 UI 按钮。当前截图按钮实际走的是 `handleScreenshot()``html2canvas`(仅能截取当前页面 DOM,无法截取其他窗口/屏幕)。
### 需求池
#### P0 — 必须实现(Must Have
| 编号 | 需求 | 验收标准 |
|---|---|---|
| P0-1 | **截图入口按钮**:在 `ReplyBox.vue` 工具栏新增截图按钮(图标裁剪刀或相机图标),与表情、文件等按钮并列 | 点击后触发 `getDisplayMedia()` 屏幕选择流程 |
| P0-2 | **`getDisplayMedia` 屏幕捕获**:调用 `navigator.mediaDevices.getDisplayMedia()` 获取屏幕流,捕获一帧画面传入截图编辑器 | 浏览器弹出屏幕/窗口/标签页选择器;支持选择跨屏显示器;用户取消时静默退出不报错 |
| P0-3 | **截图选区编辑**:全屏遮罩 + 矩形选框拖拽,选区内可编辑,选区外半透明遮罩(对标微信截图) | 屏幕变暗;拖拽出现选框;选框可拖动调整大小;8 个方向手柄 |
| P0-4 | **马赛克工具**:截图编辑工具栏新增马赛克工具,拖拽涂抹区域进行像素化打码 | 选择马赛克工具后在选区内拖拽,拖过区域被马赛克覆盖;支持撤销 |
| P0-5 | **文字标注工具**:点击选区内位置弹出文本输入,输入后渲染为画布上的文字标注 | 点击出现输入框(非 `prompt()`,用内联 input);回车确认渲染到 canvas |
| P0-6 | **箭头工具**:拖拽绘制带箭头的线段 | 起点到终点绘制箭头;箭头头部自动计算角度 |
| P0-7 | **撤销功能**:工具栏撤销按钮,逐步撤销编辑操作 | 每次操作入栈,撤销弹栈;撤销到空时禁用按钮 |
| P0-8 | **截图结果插入输入区**:截图确认后,图片以缩略图形式显示在输入框上方(textarea 之上),作为待发送图片,不自动发送 | 输入区上方出现图片缩略图 + 删除按钮;可继续输入文字;点击发送时图片和文字一起发送 |
| P0-9 | **拍照入口按钮**:在 `ReplyBox.vue` 工具栏新增拍照按钮(摄像头图标) | 点击后弹出摄像头预览弹窗 |
| P0-10 | **`getUserMedia` 摄像头预览**:用 `navigator.mediaDevices.getUserMedia({ video: true })` 获取摄像头流,渲染到 `<video>` 元素实时预览 | 弹窗内嵌视频预览;自动选择前置摄像头;摄像头不可用时显示错误提示 |
| P0-11 | **拍照捕获**:点击拍照按钮,从 `<video>` 当前帧 capture 到 canvas,转为图片 | 拍照后预览切换为静态图片;显示"重拍"和"确认"按钮 |
| P0-12 | **重拍功能**:拍照后点击"重拍"返回实时预览状态 | 重拍后清除上一张照片,恢复 `<video>` 实时预览 |
| P0-13 | **拍照结果插入输入区**:拍照确认后,图片以缩略图形式显示在输入框上方,作为待发送图片 | 与 P0-8 行为一致 |
| P0-14 | **待发送图片发送流程**:发送消息时,如果有待发送图片,先上传图片再发送图片消息(`msg_type: 'image'`),如有文字则额外发送文字消息 | 图片上传复用 `uploadFile()` API;发送成功后清空待发送图片和文字 |
| P0-15 | **待发送图片删除**:输入区待发送图片缩略图上有删除按钮,点击移除 | 点击 × 后缩略图消失,不影响文字内容 |
#### P1 — 应该实现(Should Have
| 编号 | 需求 | 验收标准 |
|---|---|---|
| P1-1 | **多张待发送图片**:输入区可同时插入多张待发送图片(如先截一张再拍一张) | 支持多张缩略图横向排列;发送时按顺序上传发送;可单独删除某一张 |
| P1-2 | **颜色选择**:截图编辑工具栏提供颜色选择(红/黄/蓝/绿/黑等常用色) | 点击颜色切换标注颜色;当前选中颜色高亮 |
| P1-3 | **矩形框工具**:拖拽绘制矩形边框(用于圈选区域) | 与微信截图矩形工具一致 |
| P1-4 | **截图保存到本地**:截图编辑器提供"保存"按钮,将截图下载到本地 | 下载为 PNG 文件,文件名 `screenshot-{timestamp}.png` |
| P1-5 | **摄像头切换**:如果有多个摄像头,支持切换前后摄像头 | 弹窗内显示切换按钮;切换后预览更新 |
| P1-6 | **ESC 退出**:截图模式和拍照弹窗均支持 ESC 键退出 | 按 ESC 等同于取消 |
| P1-7 | **截图选区尺寸显示**:拖拽选区时实时显示选区宽×高像素值 | 选区右下角或工具栏旁显示 `W×H` 像素值 |
#### P2 — 优先级较低(Nice to Have
| 编号 | 需求 | 验收标准 |
|---|---|---|
| P2-1 | **画笔自由绘制**:截图编辑器提供自由画笔工具 | 拖拽绘制自由曲线;线宽可调 |
| P2-2 | **高亮工具**:半透明黄色高亮笔 | 拖拽覆盖区域呈半透明高亮 |
| P2-3 | **快捷键截图**:支持 `Ctrl+Shift+A` 快捷键触发截图 | 全局快捷键,焦点不在输入框也能触发 |
| P2-4 | **拍照镜像翻转**:前置摄像头预览水平镜像(符合自拍习惯),但保存的图片不镜像 | 预览镜像、输出正向 |
| P2-5 | **截图延时捕获**:支持 3 秒延时截图(用于捕获鼠标悬停菜单等动态画面) | 选择延时后倒计时 3-2-1 再捕获 |
---
## UI 设计要点
### 1. 工具栏布局(ReplyBox.vue
现有工具栏顺序:`表情 | 文件 | 分隔线 | 邀请 | 快速回复`
**改造后**`截图 | 拍照 | 分隔线 | 表情 | 文件 | 分隔线 | 邀请 | 快速回复`
- 截图按钮放在最左侧(最高频使用),图标用裁剪刀 SVG 或 ✂️
- 拍照按钮紧跟截图按钮,图标用摄像头 SVG 或 📷
- 与现有按钮样式保持一致(`.tb-btn` 类,32×28pxhover 高亮 + tooltip
### 2. 截图模式(全屏覆盖层)
- **触发**:点击截图按钮 → 浏览器弹出 `getDisplayMedia` 选择器(选屏幕/窗口/标签页)
- **选区**:选中后屏幕变暗(`rgba(0,0,0,0.5)` 遮罩),鼠标变为十字光标
- **拖拽框选**:按住鼠标拖拽出现矩形选框(绿色边框 `#07C160`,对标微信),选区内画面清晰,选区外半透明
- **8 方向手柄**:选框四角 + 四边中点各一个手柄,可拖拽调整大小
- **工具栏**:选区下方居中浮动工具栏,从左到右:
- 工具组:`马赛克 | 文字 | 箭头 | 矩形`P1
- 颜色组:`🔴 🟡 🔵 🟢 ⚫`P1
- 操作组:`撤销 | 保存(P1) | 取消 | 确认✓`
- **尺寸提示**:选区右下角实时显示 `宽×高` 像素值(P1
- **ESC 退出**:按 ESC 取消截图
### 3. 拍照弹窗(CameraCapture.vue
- **弹出方式**Element Plus `el-dialog` 居中弹窗,宽度约 640px
- **预览区**`<video>` 元素填满弹窗主体,自适应摄像头分辨率
- **控制区**:弹窗底部居中放置拍照按钮(圆形大按钮,图标 📷)
- **拍照后状态**
- `<video>` 隐藏,显示 `<canvas>``<img>` 静态画面
- 底部按钮变为:`重拍` (左)| `确认` (右,绿色主按钮)
- **错误状态**:摄像头不可用时显示"无法访问摄像头,请检查权限设置"提示 + 关闭按钮
- **关闭**:右上角 ✕ 或 ESC 关闭弹窗,停止摄像头流
### 4. 待发送图片预览区(输入框上方)
- **位置**:在 `ReplyBox.vue``textarea` 上方、工具栏下方,新增一个待发送图片预览条
- **布局**:横向排列缩略图,每张缩略图约 80×80px,圆角,右上角有 × 删除按钮
- **样式**:浅色背景容器,与现有引用回复预览条(`.reply-preview`)风格一致
- **多张图片**:横向排列,超出宽度时可横向滚动
- **交互**
- 鼠标悬停缩略图可放大预览(可选 P2)
- 点击 × 删除该张待发送图片
- 发送后清空所有待发送图片
### 5. 视觉风格
- 主色调:与现有坐席端一致,使用 CSS 变量 `var(--accent)``var(--bg-secondary)`
- 截图选框颜色:`#07C160`(微信绿,与现有 `ScreenCapture.vue` 一致)
- 工具栏:白色背景 + 阴影,与现有 `ScreenshotEditor.vue` 工具栏风格一致
- 弹窗:Element Plus 默认主题,圆角 8px
---
## 待确认问题
| 编号 | 问题 | 影响范围 | 建议 |
|---|---|---|---|
| Q1 | **企微内嵌浏览器兼容性**`getDisplayMedia()``getUserMedia()` 在企微内置浏览器中是否可用?现有代码注释提到"Screen Capture API 在企微桌面端被限制,不稳定"。 | 截图功能核心可行性 | 建议在企微环境下做一次可用性测试;如不可用,保留 `html2canvas` 作为 fallback(仅能截当前页面) |
| Q2 | **HTTPS 要求**`getDisplayMedia()``getUserMedia()` 要求 HTTPS 环境(或 localhost)。坐席端部署是否为 HTTPS? | 截图 + 拍照功能可行性 | 确认生产环境域名是否为 HTTPS;如非 HTTPS 则两个功能都无法使用 |
| Q3 | **待发送图片与文字的组合发送**:用户在输入区有待发送图片 + 文字时,发送方式是:(a) 先发图片消息再发文字消息(两条消息)?还是 (b) 合并为一条富文本消息? | 消息发送逻辑 | 建议方案 (a):先发图片再发文字,与现有粘贴图片行为一致。后端如支持图文混排消息可改为 (b) |
| Q4 | **截图工具栏工具优先级**:需求明确提到"马赛克、文字标注、箭头、撤销"四个工具。是否也需要矩形框工具(P1)和高亮/画笔(P2)? | 编辑器功能范围 | 建议 P0 只做需求明确的 4 个工具,矩形框放入 P1 |
| Q5 | **摄像头权限提示**:首次使用拍照功能时浏览器会请求摄像头权限。是否需要自定义权限引导提示? | 用户体验 | 建议在调用 `getUserMedia` 前先显示一个简短提示"即将请求摄像头权限,请在弹窗中允许" |
| Q6 | **InputBox.vue 是否同步改造**:代码库中存在 `InputBox.vue`(旧版输入组件)和 `ReplyBox.vue`(当前使用)。是否需要同步改造 `InputBox.vue` | 改造范围 | 建议只改 `ReplyBox.vue``InputBox.vue` 如已废弃则不动 |
| Q7 | **截图后的编辑器复用**:现有 `ScreenshotEditor.vue`(裁剪+编辑两步)和 `ScreenCapture.vue`(全屏框选+编辑)两个组件功能重叠。新截图功能基于哪个改造? | 架构设计 | 建议基于 `ScreenCapture.vue` 改造(全屏遮罩框选更符合微信截图体验),废弃或保留 `ScreenshotEditor.vue``html2canvas` fallback 使用 |
---
## 附录:现有代码关键路径
```
frontend-agent/src/
├── components/chat/
│ ├── ReplyBox.vue ← 主输入组件(改造:加按钮 + 待发送图片区)
│ ├── InputBox.vue ← 旧版输入组件(待确认是否改造)
│ ├── ScreenshotEditor.vue ← 截图编辑器(改造:加马赛克工具)
│ ├── ScreenCapture.vue ← 全屏框选截图(改造:接入 getDisplayMedia + 加马赛克)
│ └── CameraCapture.vue ← 新建:摄像头拍照组件
├── api/
│ ├── upload.ts ← 文件上传 API(复用)
│ └── message.ts ← 消息发送 API(复用)
└── stores/
└── conversation.ts ← 会话状态管理(可能需扩展:待发送图片队列)
```