# 业务路由推荐 — 时序图 > 核心流程:员工发送非IT消息 → Dify识别 → 后端发送名片 → 前端渲染 → 点击跳转企微 ```mermaid sequenceDiagram autonumber participant E as 员工(H5) participant H5 as H5前端 participant BE as 后端API
(h5.py) participant TASK as 后台AI任务
(h5_ai_task.py) participant RS as 路由服务
(routing_service.py) participant DIFY as Dify API
(统一意图识别) participant DB as PostgreSQL participant WS as WebSocket
(ws_manager) participant AG as 坐席端 participant WECOM as 企微 %% ===== 第1阶段:员工发送消息 ===== rect rgb(240, 248, 255) E->>H5: 发送非IT消息 "打印机坏了" H5->>BE: POST /h5/conversations/current/messages BE->>DB: 存储员工消息(msg_type=text) BE->>WS: broadcast(new_message → 坐席) BE-->>H5: 即时返回(user_message, ai_reply=null) BE->>TASK: asyncio.create_task(process_h5_ai_reply) end %% ===== 第2阶段:后台任务 - 路由检测 ===== rect rgb(255, 248, 240) Note over TASK: ① BYOD关键词检查(未命中,跳过) TASK->>RS: 路由关键词预过滤("打印机") RS-->>TASK: 命中 → 需调Dify TASK->>RS: detect_routing_intent(text, employee_id) RS->>DIFY: POST /v1/chat-messages
{query: "打印机坏了"} DIFY-->>RS: {intent_type: "non_it_routing",
business_category: "行政",
routing_confidence: 0.85} RS-->>TASK: 路由结果(非IT, 行政, 0.85) Note over TASK: routing_confidence ≥ 0.7 → 触发名片推荐 end %% ===== 第3阶段:查询联系人 + 发送名片 ===== rect rgb(240, 255, 240) TASK->>RS: get_contact_by_category("行政") RS->>DB: SELECT * FROM business_contacts
WHERE category='行政' AND is_active=true LIMIT 1 DB-->>RS: 返回联系人(王芳, wecom_userid=WangFang) RS-->>TASK: BusinessContact对象 TASK->>RS: send_contact_card(db, conversation, employee_id, contact, reason) %% 消息1: 路由说明文本 RS->>DB: 存Message(ai, text, "打印机问题属于行政...") RS->>WS: broadcast_to_employees([employee_id], ai_reply) WS-->>H5: ai_reply(路由文本) RS->>WS: broadcast(new_message → 坐席) WS-->>AG: new_message(路由文本) %% 消息2: 名片卡片 RS->>DB: 存Message(ai, contact_card, extra_data={contact, reason}) RS->>WS: broadcast_to_employees([employee_id], ai_reply) WS-->>H5: ai_reply(msg_type=contact_card, extra_data) RS->>WS: broadcast(new_message → 坐席) WS-->>AG: new_message(msg_type=contact_card, extra_data) %% 消息3: 系统提示 RS->>DB: 存Message(system, "以上为AI自动推荐...") RS->>WS: broadcast_to_employees([employee_id], ai_reply) WS-->>H5: ai_reply(系统提示) RS->>WS: broadcast(new_message → 坐席) WS-->>AG: new_message(系统提示) %% P1: 记录路由事件 RS->>DB: INSERT routing_event(P1统计) end %% ===== 第4阶段:前端渲染 ===== rect rgb(255, 245, 238) H5->>H5: MessageBubble渲染
路由文本(AI气泡) H5->>H5: MessageBubble渲染
ContactCard名片卡片 H5->>E: 显示名片(头像/姓名/部门/负责业务/联系TA) H5->>H5: MessageBubble渲染
系统消息(居中灰字) AG->>AG: MessageBubble渲染
名片卡片(坐席端, 无联系TA按钮) end %% ===== 第5阶段:点击跳转 ===== rect rgb(248, 240, 255) E->>H5: 点击「联系TA」 H5->>H5: 读取 extra_data.contact.wecom_userid alt userid 非空 && SDK就绪 H5->>WECOM: wx.invoke('openEnterpriseChat',
{userids: 'WangFang', chatTitle: '王芳'}) WECOM-->>E: 打开企微单聊窗口 else userid为空 || SDK未就绪 H5->>E: Toast("暂时无法发起聊天,请联系管理员") end Note over E,BE: 当前IT服务台会话不自动结束
员工可返回继续咨询 end ``` ## 降级兜底流程 ```mermaid sequenceDiagram autonumber participant TASK as 后台AI任务 participant RS as 路由服务 participant DIFY as Dify API participant DB as PostgreSQL TASK->>RS: 路由关键词预过滤("工牌丢了") RS-->>TASK: 命中("工牌" → 人力资源) TASK->>RS: detect_routing_intent(text) RS->>DIFY: 调用统一意图识别 alt Dify 调用成功 DIFY-->>RS: {intent_type: "non_it_routing", business_category: "人力资源", routing_confidence: 0.88} RS-->>TASK: 使用Dify结果 else Dify 调用失败/超时 DIFY--xRS: 异常/超时 RS->>RS: 降级兜底:ROUTING_KEYWORD_TO_CATEGORY["工牌"] = "人力资源" RS-->>TASK: 降级结果(business_category="人力资源", routing_confidence=0.6, source="fallback") Note over RS: confidence < 0.7 → 不触发名片推荐 TASK->>TASK: 继续走正常AI回复流程 end ``` ## 坐席手动发名片流程(P1) ```mermaid sequenceDiagram autonumber participant AG as 坐席端 participant BE as 后端API
(routing.py) participant RS as 路由服务 participant DB as PostgreSQL participant WS as WebSocket participant H5 as H5前端 AG->>AG: 点击「发名片」按钮 AG->>BE: GET /routing/contacts?business_category=财务 BE->>RS: get_contacts(category="财务") RS->>DB: SELECT * FROM business_contacts WHERE category='财务' DB-->>RS: 联系人列表 RS-->>BE: 联系人列表 BE-->>AG: 返回联系人列表 AG->>AG: 坐席选择联系人(李明) AG->>BE: POST /conversations/{id}/send-contact-card
{contact_id: 5, reason: "员工咨询报销问题"} BE->>RS: send_contact_card(db, conversation, agent_id, contact, reason) RS->>DB: 查询 BusinessContact by id=5 DB-->>RS: 返回联系人(李明) RS->>DB: 创建 contact_card 消息
(sender_type=ai, msg_type=contact_card,
extra_data={contact, reason}) RS->>WS: broadcast_to_employees([employee_id], ai_reply) WS-->>H5: ai_reply(contact_card) RS->>WS: broadcast(new_message → 坐席) WS-->>AG: new_message(contact_card) BE-->>AG: 返回成功 H5->>H5: 渲染名片卡片 ```