Files
wecom_it_smart_desk/docs/01-产品文档/04-坐席工作台/PRD-REQ-坐席-001-截图拍照-v1.0.md
T
Simon 44e77dcb0e chore(docs): docs/ 目录全面重新编号 + 重组
**重构前**(旧编号 02-11):
- docs/02-产品需求/      → 00 产品规划/PRD
- docs/03-技术架构/      → 01-05 子目录散落
- docs/04-原型设计/      → 01-02 产品设计(HTML 原型)
- docs/05-原型设计/      → screens/
- docs/06-测试素材/      → 02-E2E / 03-功能 / 04-版本测试
- docs/07-项目管理/      → 任务说明书/日报/计划
- docs/08-安全审计/      → 审计报告
- docs/09-堡垒运维/      → toolbox / deploy
- docs/10-项目管理/      → 任务说明书(重复)
- docs/11-历史归档/      → deploy-nas-archived

**重构后**(新编号 00-07,语义化):
- docs/00-产品开发流程与文档管理规范.md
- docs/00-版本迭代总览.md
- docs/01-产品文档/      (PRD/原型/认证/会话/AI 服务/坐席/集成)
- docs/02-技术文档/      (技术方案/架构图/重构记录/前端改造/实现配置)
- docs/03-测试文档/      (E2E/功能用例/版本报告/缺陷单)
- docs/04-运维文档/      (部署运维/运维指南)
- docs/05-运营文档/      (品牌推广/用户手册)
- docs/06-安全审计/      (审计报告)
- docs/07-项目管理/      (任务说明书/日报/计划/看板)

**净收益**:
- 目录编号与产品文档管理规范对齐(按文档阶段 01-07 编号)
- 消除 02-产品需求 与 10-项目管理 的编号重叠
- 子目录按文档类型分组(如 01-产品文档/00-产品规划、01-产品文档/01-认证与登录)
- 把运维/安全/项目管理从 0X 散落改为 04/06/07

合计 494 文件 + 78495 行 / - 14076 行
2026-08-03 18:46:55 +08:00

15 KiB
Raw Blame History

坐席端截图 + 拍照功能 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.vuetextarea 上方、工具栏下方,新增一个待发送图片预览条
  • 布局:横向排列缩略图,每张缩略图约 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.vueInputBox.vue 如已废弃则不动
Q7 截图后的编辑器复用:现有 ScreenshotEditor.vue(裁剪+编辑两步)和 ScreenCapture.vue(全屏框选+编辑)两个组件功能重叠。新截图功能基于哪个改造? 架构设计 建议基于 ScreenCapture.vue 改造(全屏遮罩框选更符合微信截图体验),废弃或保留 ScreenshotEditor.vuehtml2canvas 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        ← 会话状态管理(可能需扩展:待发送图片队列)