ConversationList State

最近更新时间:2026-07-01 16:34:30

我的收藏

概述

ConversationListStore 是会话列表的数据访问与数据结构层,为上层 UI 提供统一的会话列表能力。它主要管理会话列表数据、未读消息总数、会话置顶、删除、免打扰、标记未读、草稿、清空历史消息等会话级能力。
我们将 ConversationListStore 的创建、订阅、销毁以及当前会话切换等生命周期管理封装到了 useChatContext 中。
因此,在绝大多数业务场景下,推荐直接使用 useChatContext 获取 ConversationListStore 的属性和方法,而不是手动创建或管理 ConversationListStore 实例。只有在需要独立会话列表实例、特殊分组列表、浮窗隔离、多面板隔离等场景时,才需要直接接触 ConversationListStore 的能力。

基本使用

<script setup lang="ts">
import { onMounted } from 'vue';
import {
ConversationMarkType,
useChatContext,
} from '@tencentcloud/chat-uikit-vue3';

const {
activeConversation,
clearConversationUnreadCount,
conversationList,
loadConversations,
markConversation,
setActiveConversation,
totalUnreadCount,
} = useChatContext();

onMounted(() => {
loadConversations();
});

async function handleSelectConversation(conversationID: string) {
setActiveConversation(conversationID);
await clearConversationUnreadCount(conversationID);
await markConversation([conversationID], ConversationMarkType.Unread, false);
}

function isActiveConversation(conversationID: string) {
return activeConversation.value?.conversationID === conversationID;
}
</script>

<template>
<div class="conversation-list-basic-demo">
<div class="conversation-list-basic-demo__stat">
<span>未读消息总数</span>
<strong>{{ totalUnreadCount }}</strong>
</div>
<div class="conversation-list-basic-demo__list">
<button
v-for="conversation in conversationList"
:key="conversation.conversationID"
type="button"
:class="[
'conversation-list-basic-demo__item',
{ 'conversation-list-basic-demo__item--active': isActiveConversation(conversation.conversationID) },
]"
@click="handleSelectConversation(conversation.conversationID)"
>
<span>{{ conversation.title || conversation.conversationID }}</span>
<small>{{ conversation.conversationID }}</small>
<em v-if="conversation.unreadCount > 0">{{ conversation.unreadCount }}</em>
</button>
</div>
</div>
</template>

<style scoped>
.conversation-list-basic-demo {
display: flex;
width: 400px;
height: 100%;
flex-direction: column;
gap: 20px;
padding: 24px;
overflow: auto;
}

.conversation-list-basic-demo__stat {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px 20px;
border: 1px solid #edf0f5;
border-radius: 12px;
background: #f9fafb;
}

.conversation-list-basic-demo__stat span {
color: #6b7280;
}

.conversation-list-basic-demo__stat strong {
color: #111827;
font-size: 28px;
}

.conversation-list-basic-demo__list {
display: flex;
flex-direction: column;
gap: 10px;
}

.conversation-list-basic-demo__item {
position: relative;
display: flex;
flex-direction: column;
gap: 4px;
padding: 14px 48px 14px 16px;
border: 1px solid #edf0f5;
border-radius: 12px;
background: #fff;
color: #111827;
text-align: left;
cursor: pointer;
}

.conversation-list-basic-demo__item:hover,
.conversation-list-basic-demo__item--active {
border-color: #667eea;
background: #eef2ff;
}

.conversation-list-basic-demo__item small {
color: #6b7280;
}

.conversation-list-basic-demo__item em {
position: absolute;
top: 50%;
right: 16px;
min-width: 24px;
padding: 3px 7px;
border-radius: 999px;
background: #ff4d4f;
color: #fff;
font-style: normal;
text-align: center;
transform: translateY(-50%);
}
</style>


属性

属性名
类型
说明
conversationList
ConversationInfo[] | undefined
会话列表数据。
totalUnreadCount
number
总未读数。

方法

方法名
类型
说明
loadConversations
(option?: ConversationLoadOption) => Promise<any>
加载会话列表,支持传入加载参数。
getConversationInfo
(conversationID: string) => Promise<ConversationInfo>
根据会话 ID 获取会话详情。
deleteConversation
(conversationID: string) => Promise<any>
删除指定会话。
pinConversation
(conversationID: string, pin: boolean) => Promise<any>
设置或取消指定会话置顶。
markConversation
(conversationIDList: string[], markType: ConversationMarkType, enable: boolean) => Promise<any>
对一组会话设置或取消指定标记。
setReceiveMessageOpt
(conversationID: string, opt: ReceiveMessageOption) => Promise<any>
设置指定会话的消息接收选项。
setConversationDraft
(conversationID: string, draft: string) => Promise<any>
设置指定会话的草稿内容。
clearConversationMessages
(conversationID: string) => Promise<any>
清空指定会话的消息记录。
clearConversationUnreadCount
(conversationID: string) => Promise<any>
清空指定会话的未读数。

使用示例

这个示例使用 ConversationListStore 的基础会话列表能力:加载会话、展示未读总数、选中会话并清空未读、置顶/取消置顶、发起 C2C 会话。
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import {
ConversationMarkType,
ConversationListStore
} from '@tencentcloud/chat-uikit-vue3';

const {
clearConversationUnreadCount,
conversationList,
loadConversations,
markConversation,
totalUnreadCount,
} = ConversationListStore.create();

const activeConversationID = ref('');

onMounted(() => {
loadConversations();
});

async function handleSelectConversation(conversationID: string) {
activeConversationID.value = conversationID;
await clearConversationUnreadCount(conversationID);
await markConversation([conversationID], ConversationMarkType.Unread, false);
}

function isActiveConversation(conversationID: string) {
return activeConversationID.value === conversationID;
}
</script>

<template>
<div class="conversation-list-basic-demo">
<div class="conversation-list-basic-demo__stat">
<span>未读消息总数</span>
<strong>{{ totalUnreadCount }}</strong>
</div>
<div class="conversation-list-basic-demo__list">
<button
v-for="conversation in conversationList"
:key="conversation.conversationID"
type="button"
:class="[
'conversation-list-basic-demo__item',
{ 'conversation-list-basic-demo__item--active': isActiveConversation(conversation.conversationID) },
]"
@click="handleSelectConversation(conversation.conversationID)"
>
<span>{{ conversation.title || conversation.conversationID }}</span>
<small>{{ conversation.conversationID }}</small>
<em v-if="conversation.unreadCount > 0">{{ conversation.unreadCount }}</em>
</button>
</div>
</div>
</template>

<style scoped>
.conversation-list-basic-demo {
display: flex;
width: 400px;
height: 100%;
flex-direction: column;
gap: 20px;
padding: 24px;
overflow: auto;
}

.conversation-list-basic-demo__stat {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px 20px;
border: 1px solid #edf0f5;
border-radius: 12px;
background: #f9fafb;
}

.conversation-list-basic-demo__stat span {
color: #6b7280;
}

.conversation-list-basic-demo__stat strong {
color: #111827;
font-size: 28px;
}

.conversation-list-basic-demo__list {
display: flex;
flex-direction: column;
gap: 10px;
}

.conversation-list-basic-demo__item {
position: relative;
display: flex;
flex-direction: column;
gap: 4px;
padding: 14px 48px 14px 16px;
border: 1px solid #edf0f5;
border-radius: 12px;
background: #fff;
color: #111827;
text-align: left;
cursor: pointer;
}

.conversation-list-basic-demo__item:hover,
.conversation-list-basic-demo__item--active {
border-color: #667eea;
background: #eef2ff;
}

.conversation-list-basic-demo__item small {
color: #6b7280;
}

.conversation-list-basic-demo__item em {
position: absolute;
top: 50%;
right: 16px;
min-width: 24px;
padding: 3px 7px;
border-radius: 999px;
background: #ff4d4f;
color: #fff;
font-style: normal;
text-align: center;
transform: translateY(-50%);
}
</style>