Files
wecom_it_smart_desk/docs/03-技术架构/sequence-diagram.mermaid
T
Simon bea288e414 feat: 2026-07-11 全量更新 - 代办集成+会议室预定+知识迭代修复+UI统一+Bug修复
== 已部署上线 (9项) ==
- 代办事项真实数据源集成 (企微审批API 8bug修复链)
- H5/坐席端 Logo样式统一+绿色背景
- 视频引导页修复 (localStorage key v2)
- 坐席端 v9 Vue版本修复 (ElMessage._context)
- 截图按钮 v10 修复 (getDisplayMedia user gesture)
- 扫码样式恢复+H5扫码登录跳转修复
- H5截图快捷键提示

== 代码完成待部署 (3项) ==
- 知识迭代3Bug修复 (#8 POST端点/#7 MERGE幂等/#6 过期检查)
- 会议室预定-小鱼易联终端 (40文件, 40/40测试通过)
- IT资产升级审批推送 (asset_service.py)

== 需求文档 (2项) ==
- 坐席端AI辅助消息框-PRD (4项新功能确认)
- 坐席端布局优化建议 v2.0 (7天计划)

== 新增文档 ==
- 日报-2026-07-11.md
- 知识迭代Bug修复报告-20260711.md
- 会议室预定-部署指南.md
- CHANGELOG.md 更新

== 测试 ==
- test_todo_integration.py: 40/40
- test_meetingroom.py: 40/40
- test_bugfix_ki_suggestions.py: 21/21
2026-07-11 23:13:10 +08:00

204 lines
6.7 KiB
Plaintext
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.
%% 坐席端截图+拍照功能 — 时序图
%% 文件: docs/03-技术架构/sequence-diagram.mermaid
%% 包含 4 个关键流程:截图、拍照、图文发送、初始化与资源清理
%% ============================================
%% 流程 1:截图完整流程
%% ============================================
sequenceDiagram
participant User as 用户
participant RB as ReplyBox.vue
participant USC as useScreenCapture
participant SC as ScreenCapture.vue
participant UPI as usePendingImages
participant PIP as PendingImagePreview.vue
User->>RB: 点击截图按钮
RB->>RB: handleScreenshot()
RB->>USC: captureScreenAsCanvas()
Note over USC: 浏览器弹出 getDisplayMedia 选择器
User->>USC: 选择屏幕/窗口/标签页
USC->>USC: getDisplayMedia() 获取视频流
USC->>USC: video.play() → canvas.drawImage() 捕获一帧
USC->>USC: stream.getTracks().stop() 停止共享
USC-->>RB: 返回 HTMLCanvasElement
RB->>RB: screenshotCanvas = canvas
RB->>RB: showScreenCapture = true
Note over SC: 组件挂载,显示全屏遮罩
SC->>SC: 初始化:底图 Canvas + 遮罩 Canvas
SC->>SC: drawMask() 绘制半透明遮罩
User->>SC: 鼠标拖拽框选区域
SC->>SC: 更新 box {x, y, w, h}
SC->>SC: drawMask() 清除选区内遮罩
User->>SC: 选择马赛克工具
User->>SC: 在选区内拖拽涂抹
SC->>SC: saveHistory() 保存当前状态
SC->>SC: drawMosaic() 像素化处理
User->>SC: 选择箭头工具
User->>SC: 拖拽绘制箭头
SC->>SC: saveHistory() 保存当前状态
SC->>SC: drawArrow() 绘制箭头线段
User->>SC: 点击撤销
SC->>SC: historyIndex--
SC->>SC: ctx.putImageData() 恢复上一状态
User->>SC: 点击确认 ✓
SC->>SC: 从编辑 Canvas 裁剪选区
SC->>SC: canvas.toBlob() 转 Blob
SC-->>RB: emit('confirm', blob)
RB->>RB: showScreenCapture = false
RB->>UPI: addImage(blob, 'screenshot')
UPI->>UPI: URL.createObjectURL(blob) 生成预览URL
UPI->>UPI: images.push({ id, blob, previewUrl, source })
UPI-->>RB: 队列已更新
RB->>PIP: 响应式传递 images
PIP->>PIP: 渲染缩略图 + × 删除按钮
PIP-->>User: 显示待发送图片预览
%% ============================================
%% 流程 2:拍照完整流程
%% ============================================
sequenceDiagram
participant User as 用户
participant RB as ReplyBox.vue
participant CC as CameraCapture.vue
participant UC as useCamera
participant UPI as usePendingImages
User->>RB: 点击拍照按钮
RB->>RB: handleCamera()
RB->>RB: showCameraDialog = true
RB->>CC: 挂载组件(v-model=true
CC->>CC: ElMessage.info('即将请求摄像头权限...')
CC->>UC: startCamera()
UC->>UC: getUserMedia({ video: { facingMode: 'user' } })
Note over UC: 浏览器弹出权限请求
User->>UC: 允许摄像头访问
UC->>UC: stream 赋值到 video.srcObject
UC->>UC: video.play()
UC-->>CC: 摄像头预览已启动
CC-->>User: 显示实时摄像头预览
User->>CC: 点击拍照按钮
CC->>UC: captureFrame()
UC->>UC: canvas.drawImage(video, 0, 0)
UC->>UC: canvas.toDataURL('image/png')
UC-->>CC: 返回图片 dataURL
CC->>CC: capturedImage = dataURL
CC->>CC: 隐藏 video,显示 img 静态画面
CC-->>User: 显示拍照结果 + 重拍/确认按钮
alt 用户点击重拍
User->>CC: 点击重拍
CC->>CC: capturedImage = null
CC->>CC: 恢复 video 实时预览
CC-->>User: 回到实时预览状态
else 用户点击确认
User->>CC: 点击确认 ✓
CC->>UC: captureFrame()
CC->>CC: dataURL → Blob 转换
CC->>UC: stopCamera() 停止摄像头
CC-->>RB: emit('confirm', blob)
CC-->>RB: emit('update:modelValue', false)
end
RB->>RB: showCameraDialog = false
RB->>UPI: addImage(blob, 'camera')
UPI->>UPI: 生成 previewUrl,加入队列
UPI-->>RB: 队列已更新
RB-->>User: 输入区显示拍照缩略图
%% ============================================
%% 流程 3:图文组合发送流程
%% ============================================
sequenceDiagram
participant User as 用户
participant RB as ReplyBox.vue
participant UPI as usePendingImages
participant API_U as uploadFile()
participant API_M as sendMessage()
participant Store as conversationStore
User->>RB: 输入文字 + 有待发送图片
User->>RB: 点击发送 / 按 Enter
RB->>RB: handleSend()
RB->>RB: content = inputText.trim()
RB->>RB: hasImages = pendingImages.count > 0
RB->>RB: hasText = content.length > 0
alt 无图片且无文字
RB->>RB: return(不发送)
else 有图片
RB->>RB: ElMessage.info('发送中...')
RB->>UPI: 获取 images 数组
loop 遍历每张图片
RB->>API_U: uploadFile(image.blob)
API_U-->>RB: { url, filename, file_size }
RB->>API_M: sendMessage(convId, '[图片]', 'image', { media_url, file_name, file_size })
API_M-->>RB: 返回新消息 Message
RB->>Store: messages.push(newMsg)
end
RB->>UPI: clearAll() 清空图片队列
RB->>RB: URL.revokeObjectURL() 释放预览URL
end
opt 有文字
RB->>RB: emit('send', content)
RB->>RB: inputText = ''
end
RB->>RB: textareaHeight = 60
RB-->>User: 发送完成,输入区清空
%% ============================================
%% 流程 4:组件初始化与资源清理
%% ============================================
sequenceDiagram
participant RB as ReplyBox
participant SC as ScreenCapture
participant CC as CameraCapture
participant UPI as usePendingImages
Note over RB: 组件挂载 onMounted
RB->>RB: 注册全局快捷键
Note over RB: 用户触发截图
RB->>SC: v-if="showScreenCapture" 挂载
SC->>SC: onMounted → 初始化 Canvas、事件监听
SC->>SC: drawMask() 绘制初始遮罩
Note over RB: 截图取消/确认
RB->>SC: v-if=false 卸载
SC->>SC: onUnmounted → 移除事件监听、清空 history
Note over RB: 用户触发拍照
RB->>CC: v-model=true 挂载
CC->>CC: onMounted → startCamera()
Note over RB: 拍照取消/确认
RB->>CC: v-model=false 卸载
CC->>CC: onUnmounted → stopCamera() 停止流
Note over RB: ReplyBox 卸载
RB->>RB: onUnmounted
RB->>UPI: clearAll() → revokeObjectURL 释放内存
RB->>RB: 移除快捷键监听