%% 坐席端截图+拍照功能 — 类图 %% 文件: docs/03-技术架构/class-diagram.mermaid classDiagram %% ===== 类型定义 ===== class PendingImage { +id: string +blob: Blob +previewUrl: string +source: "screenshot" | "camera" +createdAt: number } class SelectionBox { +x: number +y: number +w: number +h: number } class EditHistoryEntry { +imageData: ImageData +timestamp: number } class ScreenshotToolConfig { +name: ScreenshotTool +icon: string +label: string } %% ===== Composables ===== class useScreenCapture { -isCapturing: Ref~boolean~ +isScreenCaptureSupported() boolean +captureScreen() Promise~Blob | null~ +captureScreenAsCanvas() Promise~HTMLCanvasElement | null~ } class useCamera { -isActive: Ref~boolean~ -error: Ref~CameraError | null~ -stream: MediaStream | null +startCamera(facingMode?) Promise~boolean~ +stopCamera() void +captureFrame() Promise~Blob | null~ +switchCamera() Promise~boolean~ } class usePendingImages { -images: Ref~PendingImage[]~ +addImage(blob: Blob, source: string) void +removeImage(id: string) void +clearAll() void +hasImages: ComputedRef~boolean~ +count: ComputedRef~number~ } %% ===== 组件 ===== class ScreenCapture { +props: screenshotCanvas: HTMLCanvasElement +emit: confirm(blob: Blob) +emit: cancel() -box: Ref~SelectionBox~ -currentTool: Ref~ScreenshotTool~ -currentColor: Ref~string~ -history: EditHistoryEntry[] -historyIndex: number +startSelect(e: MouseEvent) void +onMove(e: MouseEvent) void +startResize(dir: string, e: MouseEvent) void +drawMosaic(x1, y1, x2, y2) void +drawArrow(x1, y1, x2, y2) void +drawText(x, y, text) void +undo() void +confirm() void +cancel() void } class CameraCapture { +props: modelValue: boolean +emit: confirm(blob: Blob) +emit: cancel() +emit: update:modelValue(boolean) -videoRef: Ref~HTMLVideoElement~ -capturedImage: Ref~string | null~ -cameraError: Ref~CameraError | null~ +startCamera() void +capture() void +retake() void +confirm() void +close() void } class PendingImagePreview { +props: images: PendingImage[] +emit: remove(id: string) } class ReplyBox { -pendingImages: usePendingImages -showScreenCapture: Ref~boolean~ -showCameraDialog: Ref~boolean~ -screenshotCanvas: Ref~HTMLCanvasElement | null~ +handleScreenshot() Promise~void~ +handleCamera() void +onScreenCaptureConfirm(blob: Blob) void +onCameraConfirm(blob: Blob) void +onCameraCancel() void +removePendingImage(id: string) void +handleSend() Promise~void~ +sendPendingImages(convId: string) Promise~void~ } %% ===== 关系 ===== ReplyBox --> useScreenCapture : 调用截图 ReplyBox --> useCamera : 调用拍照 ReplyBox --> usePendingImages : 管理待发送图片 ReplyBox --> ScreenCapture : 挂载截图编辑器 ReplyBox --> CameraCapture : 挂载拍照弹窗 ReplyBox --> PendingImagePreview : 挂载预览条 ScreenCapture --> SelectionBox : 选区状态 ScreenCapture --> EditHistoryEntry : 撤销历史 CameraCapture --> useCamera : 摄像头逻辑 PendingImagePreview --> PendingImage : 渲染缩略图 usePendingImages --> PendingImage : 管理队列