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
This commit is contained in:
+103
-298
@@ -1,321 +1,126 @@
|
||||
%% 坐席端截图+拍照功能 — 类图
|
||||
%% 文件: docs/03-技术架构/class-diagram.mermaid
|
||||
|
||||
classDiagram
|
||||
direction TB
|
||||
|
||||
%% ── 枚举 ──────────────────────────────────────────
|
||||
class AudienceEnum {
|
||||
<<enumeration>>
|
||||
employee_quick_reply
|
||||
engineer_workguide
|
||||
%% ===== 类型定义 =====
|
||||
class PendingImage {
|
||||
+id: string
|
||||
+blob: Blob
|
||||
+previewUrl: string
|
||||
+source: "screenshot" | "camera"
|
||||
+createdAt: number
|
||||
}
|
||||
|
||||
class SuggestionStatusEnum {
|
||||
<<enumeration>>
|
||||
pending
|
||||
queued
|
||||
approved
|
||||
rejected
|
||||
applied
|
||||
graph_synced
|
||||
expired
|
||||
class SelectionBox {
|
||||
+x: number
|
||||
+y: number
|
||||
+w: number
|
||||
+h: number
|
||||
}
|
||||
|
||||
class GraphSyncStatusEnum {
|
||||
<<enumeration>>
|
||||
pending
|
||||
synced
|
||||
failed
|
||||
class EditHistoryEntry {
|
||||
+imageData: ImageData
|
||||
+timestamp: number
|
||||
}
|
||||
|
||||
class SourceTypeEnum {
|
||||
<<enumeration>>
|
||||
annotation
|
||||
conversation
|
||||
ai_uncertain
|
||||
manual
|
||||
document_ragflow
|
||||
class ScreenshotToolConfig {
|
||||
+name: ScreenshotTool
|
||||
+icon: string
|
||||
+label: string
|
||||
}
|
||||
|
||||
class RelationTypeEnum {
|
||||
<<enumeration>>
|
||||
LEADS_TO
|
||||
RELATES_TO
|
||||
CAN_JUMP_TO
|
||||
%% ===== Composables =====
|
||||
class useScreenCapture {
|
||||
-isCapturing: Ref~boolean~
|
||||
+isScreenCaptureSupported() boolean
|
||||
+captureScreen() Promise~Blob | null~
|
||||
+captureScreenAsCanvas() Promise~HTMLCanvasElement | null~
|
||||
}
|
||||
|
||||
%% ── PostgreSQL 模型 ───────────────────────────────
|
||||
class KnowledgeSuggestion {
|
||||
+str id
|
||||
+str suggestion_type
|
||||
+SuggestionStatusEnum status
|
||||
+str title
|
||||
+str content
|
||||
+str category
|
||||
+List~str~ tags
|
||||
+SourceTypeEnum source_type
|
||||
+List~str~ source_data
|
||||
+str reason
|
||||
+str reject_reason
|
||||
+str reviewer_id
|
||||
+datetime reviewed_at
|
||||
+datetime created_at
|
||||
+datetime updated_at
|
||||
+float confidence
|
||||
+AudienceEnum audience
|
||||
+str issue
|
||||
+str action
|
||||
+RelationTypeEnum relation_type
|
||||
+str parent_issue
|
||||
+dict graph_meta
|
||||
+GraphSyncStatusEnum graph_sync_status
|
||||
+bool source_failed
|
||||
+datetime queued_at
|
||||
+datetime applied_at
|
||||
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 KnowledgeBase {
|
||||
+str id
|
||||
+str category
|
||||
+str title
|
||||
+str content
|
||||
+List~str~ tags
|
||||
+int view_count
|
||||
+int use_count
|
||||
+GraphSyncStatusEnum graph_sync_status
|
||||
+str graph_node_uuid
|
||||
+datetime created_at
|
||||
+datetime updated_at
|
||||
class usePendingImages {
|
||||
-images: Ref~PendingImage[]~
|
||||
+addImage(blob: Blob, source: string) void
|
||||
+removeImage(id: string) void
|
||||
+clearAll() void
|
||||
+hasImages: ComputedRef~boolean~
|
||||
+count: ComputedRef~number~
|
||||
}
|
||||
|
||||
class Conversation {
|
||||
+str id
|
||||
+str employee_id
|
||||
+str status
|
||||
+str session_type
|
||||
+datetime created_at
|
||||
%% ===== 组件 =====
|
||||
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
|
||||
}
|
||||
|
||||
%% ── Neo4j 图节点模型 ──────────────────────────────
|
||||
class IssueNode {
|
||||
+str uuid
|
||||
+str name
|
||||
+str category
|
||||
+datetime created_at
|
||||
+datetime updated_at
|
||||
+str source_suggestion_id
|
||||
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 ActionNode {
|
||||
+str uuid
|
||||
+str name
|
||||
+str description
|
||||
+datetime created_at
|
||||
+str source_suggestion_id
|
||||
class PendingImagePreview {
|
||||
+props: images: PendingImage[]
|
||||
+emit: remove(id: string)
|
||||
}
|
||||
|
||||
class InfoNode {
|
||||
+str uuid
|
||||
+str name
|
||||
+str value
|
||||
+List~str~ modifiers
|
||||
+datetime created_at
|
||||
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~
|
||||
}
|
||||
|
||||
class RelationEdge {
|
||||
+str from_uuid
|
||||
+str to_uuid
|
||||
+RelationTypeEnum type
|
||||
+int order
|
||||
+float weight
|
||||
}
|
||||
|
||||
%% ── Pydantic Schema ───────────────────────────────
|
||||
class KnowledgeSuggestionCreate {
|
||||
+str suggestion_type
|
||||
+str title
|
||||
+str content
|
||||
+str category
|
||||
+List~str~ tags
|
||||
+SourceTypeEnum source_type
|
||||
+List~str~ source_data
|
||||
+str reason
|
||||
+float confidence
|
||||
+AudienceEnum audience
|
||||
+str issue
|
||||
+str action
|
||||
+RelationTypeEnum relation_type
|
||||
+str parent_issue
|
||||
+dict graph_meta
|
||||
}
|
||||
|
||||
class KnowledgeSuggestionResponse {
|
||||
+str id
|
||||
+str suggestion_type
|
||||
+SuggestionStatusEnum status
|
||||
+str title
|
||||
+str content
|
||||
+str category
|
||||
+List~str~ tags
|
||||
+SourceTypeEnum source_type
|
||||
+float confidence
|
||||
+AudienceEnum audience
|
||||
+str issue
|
||||
+str action
|
||||
+RelationTypeEnum relation_type
|
||||
+str parent_issue
|
||||
+dict graph_meta
|
||||
+GraphSyncStatusEnum graph_sync_status
|
||||
+bool source_failed
|
||||
+datetime queued_at
|
||||
+datetime applied_at
|
||||
+datetime created_at
|
||||
}
|
||||
|
||||
class KnowledgeSuggestionApprove {
|
||||
<<request>>
|
||||
}
|
||||
|
||||
class KnowledgeSuggestionReject {
|
||||
<<request>>
|
||||
+str reject_reason
|
||||
}
|
||||
|
||||
class KnowledgeSuggestionRewrite {
|
||||
<<request>>
|
||||
+str title
|
||||
+str content
|
||||
+str category
|
||||
+List~str~ tags
|
||||
+float confidence
|
||||
+AudienceEnum audience
|
||||
+str issue
|
||||
+str action
|
||||
+RelationTypeEnum relation_type
|
||||
+str parent_issue
|
||||
}
|
||||
|
||||
class VisionRequest {
|
||||
<<request>>
|
||||
+str conversation_id
|
||||
+bytes image_file
|
||||
}
|
||||
|
||||
class VisionResponse {
|
||||
+str description
|
||||
+float confidence
|
||||
+dict metadata
|
||||
}
|
||||
|
||||
class RagflowIngestionRequest {
|
||||
<<request>>
|
||||
+str file_name
|
||||
+bytes file_data
|
||||
+str category_hint
|
||||
}
|
||||
|
||||
class RagflowIngestionResponse {
|
||||
+str task_id
|
||||
+str status
|
||||
+List~KnowledgeSuggestionResponse~ suggestions
|
||||
}
|
||||
|
||||
%% ── 服务类 ────────────────────────────────────────
|
||||
class KnowledgeIterationService {
|
||||
-str ai_api_url
|
||||
-str ai_api_key
|
||||
+analyze_and_generate_suggestions(db, days) dict
|
||||
-_analyze_annotation_data(db, days) dict
|
||||
-_analyze_conversation_data(db, days) dict
|
||||
-_generate_update_suggestion(db, source_type, source_data, reason) KnowledgeSuggestion
|
||||
-_generate_new_faq_suggestion(db, source_type, source_data, reason) KnowledgeSuggestion
|
||||
-_check_existing_suggestion(db, source_id) bool
|
||||
-_auto_tag_audience(db, source_type, source_data) AudienceEnum
|
||||
+approve_suggestion(db, suggestion_id, reviewer_id) KnowledgeSuggestion
|
||||
+reject_suggestion(db, suggestion_id, reviewer_id, reason) KnowledgeSuggestion
|
||||
+rewrite_suggestion(db, suggestion_id, reviewer_id, data) KnowledgeSuggestion
|
||||
+queue_suggestion(db, suggestion_id) KnowledgeSuggestion
|
||||
+dequeue_approve(db, suggestion_id, reviewer_id) KnowledgeSuggestion
|
||||
+sync_to_neo4j(neo4j_client, suggestion) bool
|
||||
+get_suggestion_stats(db) dict
|
||||
+get_queue_stats(db) dict
|
||||
}
|
||||
|
||||
class WingmanService {
|
||||
-str api_url
|
||||
-str api_key
|
||||
-int timeout
|
||||
-httpx.AsyncClient _client
|
||||
+generate_draft(conversation_id, messages, db) dict
|
||||
+generate_summary(conversation_id, messages) dict
|
||||
+suggest_tags(conversation_id, messages, existing_tags) dict
|
||||
+generate_knowledge_suggestion(context_messages) dict
|
||||
-_build_context_messages(messages, system_prompt) list
|
||||
-_call_wingman_api(context_messages) str
|
||||
-_parse_json_response(content, default) dict
|
||||
-_estimate_confidence(content) float
|
||||
+close()
|
||||
}
|
||||
|
||||
class Neo4jClient {
|
||||
-str uri
|
||||
-str user
|
||||
-str password
|
||||
-str database
|
||||
-AsyncDriver _driver
|
||||
+initialize()
|
||||
+close()
|
||||
+create_issue_node(issue) IssueNode
|
||||
+create_action_node(action) ActionNode
|
||||
+create_relation(from_uuid, to_uuid, rel) RelationEdge
|
||||
+merge_issue(name, category, props) IssueNode
|
||||
+merge_action(name, props) ActionNode
|
||||
+find_issue_by_name(name) IssueNode
|
||||
+find_related_issues(uuid, rel_type) List~IssueNode~
|
||||
+execute_write_query(cypher, params) result
|
||||
+execute_read_query(cypher, params) result
|
||||
+health_check() bool
|
||||
}
|
||||
|
||||
class VisionService {
|
||||
-str dify_vision_api_url
|
||||
-str dify_vision_api_key
|
||||
-str local_vision_model
|
||||
+analyze_screenshot(image_bytes, conversation_id) VisionResponse
|
||||
-_preprocess_image(image_bytes) bytes
|
||||
-_call_vision_workflow(processed_image) dict
|
||||
+inject_to_conversation_context(description, conversation_id)
|
||||
}
|
||||
|
||||
class RagflowIngestionService {
|
||||
-RagflowClient client
|
||||
+upload_and_process(file_data, file_name, category_hint) RagflowIngestionResponse
|
||||
+poll_processing_status(task_id) str
|
||||
+create_suggestions_from_result(result) List~KnowledgeSuggestion~
|
||||
}
|
||||
|
||||
%% ── 关系 ──────────────────────────────────────────
|
||||
KnowledgeSuggestion ..> AudienceEnum : uses
|
||||
KnowledgeSuggestion ..> SuggestionStatusEnum : uses
|
||||
KnowledgeSuggestion ..> SourceTypeEnum : uses
|
||||
KnowledgeSuggestion ..> RelationTypeEnum : uses
|
||||
KnowledgeSuggestion ..> GraphSyncStatusEnum : uses
|
||||
KnowledgeBase ..> GraphSyncStatusEnum : uses
|
||||
|
||||
KnowledgeIterationService --> WingmanService : 调用 AI 生成
|
||||
KnowledgeIterationService --> Neo4jClient : 写图同步
|
||||
KnowledgeIterationService --> KnowledgeSuggestion : 管理
|
||||
KnowledgeIterationService --> KnowledgeBase : 落库
|
||||
|
||||
KnowledgeSuggestionCreate --> KnowledgeSuggestion : 创建
|
||||
KnowledgeSuggestionResponse --> KnowledgeSuggestion : 返回
|
||||
KnowledgeSuggestionApprove --> KnowledgeSuggestion : 状态变更
|
||||
KnowledgeSuggestionReject --> KnowledgeSuggestion : 状态变更
|
||||
KnowledgeSuggestionRewrite --> KnowledgeSuggestion : 内容更新
|
||||
|
||||
IssueNode <--> RelationEdge : 关联
|
||||
ActionNode <--> RelationEdge : 关联
|
||||
Neo4jClient --> IssueNode : CRUD
|
||||
Neo4jClient --> ActionNode : CRUD
|
||||
Neo4jClient --> RelationEdge : 管理
|
||||
|
||||
VisionService --> WingmanService : 复用 _call_wingman_api 范式
|
||||
RagflowIngestionService --> KnowledgeSuggestion : 产出
|
||||
%% ===== 关系 =====
|
||||
ReplyBox --> useScreenCapture : 调用截图
|
||||
ReplyBox --> useCamera : 调用拍照
|
||||
ReplyBox --> usePendingImages : 管理待发送图片
|
||||
ReplyBox --> ScreenCapture : 挂载截图编辑器
|
||||
ReplyBox --> CameraCapture : 挂载拍照弹窗
|
||||
ReplyBox --> PendingImagePreview : 挂载预览条
|
||||
ScreenCapture --> SelectionBox : 选区状态
|
||||
ScreenCapture --> EditHistoryEntry : 撤销历史
|
||||
CameraCapture --> useCamera : 摄像头逻辑
|
||||
PendingImagePreview --> PendingImage : 渲染缩略图
|
||||
usePendingImages --> PendingImage : 管理队列
|
||||
|
||||
Reference in New Issue
Block a user