sequenceDiagram
    participant WX as 企微消息
    participant API as FastAPI
    participant Router as MessageRouter
    participant Score as ScoringService
    participant Vip as VipService
    participant DB as PostgreSQL
    participant Redis as Redis

    WX->>API: 员工消息回调
    API->>Router: route_message(msg)

    rect rgb(255, 240, 240)
        Note over Router,Score: Step 1: VIP检测
        Router->>Vip: is_vip(employee_id)
        Vip->>Redis: GET vip_cache:{employee_id}
        alt 缓存命中
            Redis-->>Vip: is_vip=True/False
        else 缓存未命中
            Vip->>Vip: get_user_info(employee_id)
            Vip->>Vip: _check_vip_rules(user_info)
            Note over Vip: 规则: 总监及以上 或 关键部门
            Vip->>Redis: SET vip_cache:{employee_id} EX 3600
        end
        Vip-->>Router: is_vip=True/False
    end

    rect rgb(255, 255, 220)
        Note over Router,Score: Step 2: 情绪关键词检测
        Router->>Score: detect_emotion(msg)
        Score->>DB: SELECT FROM system_configs WHERE key LIKE 'emotion_keywords_%'
        DB-->>Score: 关键词列表
        Score->>Score: 遍历关键词匹配消息内容
        Score-->>Router: emotion="urgent"
    end

    rect rgb(220, 255, 220)
        Note over Router,Score: Step 3: 举手检测
        Router->>Score: detect_hand_raise(msg)
        Score->>DB: SELECT FROM system_configs WHERE key='hand_raise_keywords'
        DB-->>Score: ["转人工","人工",...]
        Score->>Score: 遍历关键词匹配
        Score-->>Router: hand_raise=True
    end

    rect rgb(220, 220, 255)
        Note over Router,Score: Step 4: 需介入检测
        Router->>Score: detect_need_intervene(conv)
        Score->>DB: SELECT COUNT FROM messages WHERE conversation_id=... AND sender_type='employee'
        DB-->>Score: 员工消息数
        Score->>DB: SELECT FROM system_configs WHERE key='intervene_round_threshold'
        DB-->>Score: 3
        Score->>Score: 员工连续追问 > 3轮?
        Score-->>Router: need_intervene=True
    end

    rect rgb(255, 220, 255)
        Note over Router,Score: Step 5: 紧急度计算
        Router->>Score: calculate_urgency(conv, msg)
        Score->>Score: base = keyword_score(1)
        Score->>Score: + emotion_bonus(1)
        Score->>Score: + vip_bonus(1)
        Score->>Score: + repeat_bonus(1)
        Score->>Score: total = min(5, base+emotion+vip+repeat)
        Score-->>Router: urgency_score=4
    end

    Router->>DB: UPDATE conversations SET tags=..., urgency_score=4, is_vip=...
    Router-->>API: 更新后的会话
