sequenceDiagram
    participant Browser as 坐席浏览器
    participant App as Vue3 App
    participant Store as Pinia Store
    participant API as Backend API
    participant DB as PostgreSQL

    Note over Browser,App: 页面加载

    Browser->>App: 挂载 Workspace.vue
    App->>Store: 初始化 conversationStore
    Store->>API: GET /api/conversations
    API->>DB: SELECT * FROM conversations WHERE status IN ('queued','serving') ORDER BY ...
    DB-->>API: 会话列表
    API-->>Store: 会话数据
    Store-->>App: 渲染会话列表

    loop 每3秒 setInterval
        App->>Store: pollConversations()
        Store->>API: GET /api/conversations?page=1&page_size=50
        API->>DB: SELECT ... (同上)
        DB-->>API: 最新会话列表
        API-->>Store: 最新数据

        alt 数据有变化
            Store->>Store: diff 比较，更新变化的会话
            Store-->>App: 触发响应式更新
            App->>App: 更新列表项标签/排序/未读数
        else 数据无变化
            Store-->>App: 无需更新
        end
    end

    Note over App: 用户点击某个会话

    App->>Store: selectConversation(id)
    Store->>API: GET /api/conversations/{id}/messages?limit=50
    API->>DB: SELECT * FROM messages WHERE conversation_id=... ORDER BY created_at
    DB-->>API: 消息列表
    API-->>Store: messages
    Store-->>App: 渲染对话区

    loop 选中会话的消息轮询
        App->>Store: pollMessages(conv_id)
        Store->>API: GET /api/conversations/{id}/messages?limit=20&before=latest_id
        API->>DB: SELECT ... WHERE created_at > latest
        DB-->>API: 新消息
        API-->>Store: 新消息列表
        alt 有新消息
            Store->>Store: 追加消息到列表
            Store-->>App: 滚动到底部，显示新消息
        end
    end

    Note over App: 坐席发送回复

    App->>Store: sendMessage(conv_id, content)
    Store->>API: POST /api/conversations/{id}/messages {content}
    API->>DB: INSERT INTO messages ...
    API-->>Store: 发送的消息对象
    Store->>Store: 追加到消息列表
    Store-->>App: 显示在对话区
