Files
wecom_it_smart_desk/docs/01-产品文档/04-坐席工作台/PRD-REQ-坐席-001-截图拍照-v1.0.md
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

192 lines
15 KiB
Markdown
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.
# 坐席端截图 + 拍照功能 PRD
> **子系统**: 04-坐席工作台
> **模块**: 截图拍照
## 项目信息
| 项 | 内容 |
|---|---|
| **语言** | 中文 |
| **技术栈** | 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 ← 会话状态管理(可能需扩展:待发送图片队列)
```