# ConversationList 组件自定义文档

## 概述

ConversationList 是一个功能完整的会话列表组件，用于展示和管理用户的所有会话。它集成了会话搜索、会话创建、会话预览、会话操作等功能，支持高度自定义的界面和交互。组件内置了排序、过滤、占位符等功能，适用于各种即时通讯场景，包括在线会议、在线直播、在线教育等音视频应用。

## Props 配置表格

| 字段 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| enableSearch | `boolean` | `true` | 是否启用会话搜索功能 |
| enableCreate | `boolean` | `true` | 是否启用会话创建功能 |
| enableActions | `boolean` | `true` | 是否启用会话操作功能 |
| actionsConfig | `ConversationActionsConfig` | - | 会话操作配置 |
| Header | `React.ComponentType<ConversationListHeaderProps>` | `DefaultConversationListHeader` | 自定义头部组件 |
| List | `React.ComponentType<ConversationListContentProps>` | `DefaultConversationListContent` | 自定义列表容器组件 |
| Preview | `React.ComponentType<ConversationPreviewUIProps>` | `DefaultConversationPreviewUI` | 自定义会话预览组件 |
| ConversationCreate | `React.ComponentType<ConversationCreateProps>` | `DefaultConversationCreate` | 自定义会话创建组件 |
| ConversationSearch | `React.ComponentType` | `DefaultConversationSearch` | 自定义会话搜索组件 |
| ConversationActions | `React.ComponentType<ConversationActionsProps>` | `DefaultConversationActions` | 自定义会话操作组件 |
| PlaceholderEmptyList | `React.ReactNode` | `<PlaceHolder type={PlaceHolderTypes.NO_CONVERSATIONS} />` | 空列表占位符 |
| PlaceholderLoading | `React.ReactNode` | `<PlaceHolder type={PlaceHolderTypes.LOADING} />` | 加载中占位符 |
| PlaceholderLoadError | `React.ReactNode` | `<PlaceHolder type={PlaceHolderTypes.WRONG} />` | 加载错误占位符 |
| Avatar | `React.ComponentType<IAvatarProps>` | `DefaultAvatar` | 自定义头像组件 |
| filter | `(conversationList: ConversationModel[]) => ConversationModel[]` | - | 会话过滤函数 |
| sort | `(conversationList: ConversationModel[]) => ConversationModel[]` | - | 会话排序函数 |
| onSelectConversation | `(conversation: ConversationModel) => void` | - | 会话选择回调 |
| onBeforeCreateConversation | `(params: string \| CreateGroupParams) => string \| CreateGroupParams` | - | 创建会话前回调 |
| onConversationCreated | `(conversation: ConversationModel) => void` | - | 会话创建成功回调 |
| className | `string` | - | 自定义样式类名 |
| style | `React.CSSProperties` | - | 自定义样式 |

## Props 详解

### enableSearch

type: `boolean`

enableSearch 用于控制是否显示会话搜索功能，默认值为 `true`。

### enableCreate

type: `boolean`

enableCreate 用于控制是否显示会话创建功能，默认值为 `true`。

### enableActions

type: `boolean`

enableActions 用于控制是否显示会话操作功能（如置顶、静音、删除等），默认值为 `true`。

### actionsConfig

type: `ConversationActionsConfig`

actionsConfig 用于配置会话操作的具体行为和自定义操作，默认值为 `-`。

#### Example1: 基础操作配置

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';

function ConversationListWithBasicActions() {
  const actionsConfig = {
    enablePin: true,
    enableMute: true,
    enableDelete: true,
    enableMarkUnread: true,
    onConversationPin: (conversation: ConversationModel) => {
      console.log('置顶会话:', conversation.conversationID);
    },
    onConversationMute: (conversation: ConversationModel) => {
      console.log('静音会话:', conversation.conversationID);
    },
    onConversationDelete: (conversation: ConversationModel) => {
      if (confirm('确定要删除这个会话吗？')) {
        console.log('删除会话:', conversation.conversationID);
      }
    }
  };

  return (
    <ConversationList
      actionsConfig={actionsConfig}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
```

#### Example2: 自定义操作配置

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';

function ConversationListWithCustomActions() {
  const actionsConfig = {
    // 基础操作
    enablePin: true,
    enableMute: false, // 禁用静音功能
    enableDelete: true,
    enableMarkUnread: true,
    
    // 自定义操作
    customConversationActions: {
      archive: {
        enable: true,
        label: '归档',
        onClick: (conversation: ConversationModel) => {
          // 归档会话逻辑
          archiveConversation(conversation.conversationID);
        }
      },
      export: {
        enable: true,
        label: '导出聊天记录',
        onClick: (conversation: ConversationModel) => {
          // 导出聊天记录逻辑
          exportChatHistory(conversation.conversationID);
        }
      },
      addToFavorites: {
        enable: true,
        label: '添加到收藏',
        onClick: (conversation: ConversationModel) => {
          // 添加到收藏逻辑
          addConversationToFavorites(conversation.conversationID);
        }
      }
    },
    
    // 操作点击统一处理
    onClick: (e, key, conversation) => {
      console.log('操作点击:', key, conversation?.conversationID);
      
      // 统计操作使用情况
      analytics.track('conversation_action', {
        action: key,
        conversationId: conversation?.conversationID,
        timestamp: Date.now()
      });
    }
  };

  return (
    <ConversationList
      actionsConfig={actionsConfig}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
```

#### Example3: 权限控制的操作配置

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';
import { useState, useEffect } from 'react';

function ConversationListWithPermissionControl() {
  const [userPermissions, setUserPermissions] = useState({
    canDelete: false,
    canPin: false,
    canMute: true,
    canExport: false
  });

  useEffect(() => {
    // 获取用户权限
    fetchUserPermissions().then(setUserPermissions);
  }, []);

  const actionsConfig = {
    enablePin: userPermissions.canPin,
    enableMute: userPermissions.canMute,
    enableDelete: userPermissions.canDelete,
    enableMarkUnread: true, // 标记未读通常都允许
    
    customConversationActions: {
      export: {
        enable: userPermissions.canExport,
        label: '导出记录',
        onClick: async (conversation: ConversationModel) => {
          try {
            // 检查具体会话的导出权限
            const hasPermission = await checkExportPermission(conversation.conversationID);
            if (!hasPermission) {
              alert('您没有权限导出此会话的聊天记录');
              return;
            }
            
            // 执行导出
            await exportConversationHistory(conversation.conversationID);
            alert('导出成功');
          } catch (error) {
            console.error('导出失败:', error);
            alert('导出失败，请重试');
          }
        }
      },
      report: {
        enable: true, // 举报功能通常都开放
        label: '举报',
        onClick: (conversation: ConversationModel) => {
          // 打开举报弹窗
          showReportDialog(conversation);
        }
      }
    },
    
    // 操作前权限检查
    onConversationDelete: async (conversation: ConversationModel) => {
      const canDelete = await checkDeletePermission(conversation.conversationID);
      if (!canDelete) {
        alert('您没有权限删除此会话');
        return;
      }
      
      if (confirm('确定要删除这个会话吗？删除后无法恢复。')) {
        await deleteConversation(conversation.conversationID);
      }
    }
  };

  return (
    <ConversationList
      actionsConfig={actionsConfig}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
```

### Header

type: `React.ComponentType<ConversationListHeaderProps>`

Header 用于自定义会话列表头部组件，默认值为 `DefaultConversationListHeader`。

#### Example1: 自定义头部标题

```tsx
import { ConversationList, ConversationListHeaderProps } from 'tuikit-atomicx-react';

const CustomHeader = ({ children }: ConversationListHeaderProps) => (
  <div className="custom-conversation-header">
    <div className="header-title">
      <h2>我的会话</h2>
      <span className="online-status">在线</span>
    </div>
    <div className="header-content">
      {children}
    </div>
  </div>
);

function ConversationListWithCustomHeader() {
  return (
    <ConversationList
      Header={CustomHeader}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
```

#### Example2: 带操作按钮的头部

```tsx
import { ConversationList, ConversationListHeaderProps } from 'tuikit-atomicx-react';
import { Icon, IconSettings, IconNotification } from '@tencentcloud/uikit-base-component-react';

const HeaderWithActions = ({ children }: ConversationListHeaderProps) => {
  const handleSettings = () => {
    console.log('打开设置');
  };

  const handleNotifications = () => {
    console.log('打开通知设置');
  };

  return (
    <div className="conversation-header-with-actions">
      <div className="header-left">
        <h2>消息</h2>
      </div>
      
      <div className="header-main">
        {children}
      </div>
      
      <div className="header-right">
        <button className="header-action-btn" onClick={handleNotifications}>
          <Icon><IconNotification /></Icon>
        </button>
        <button className="header-action-btn" onClick={handleSettings}>
          <Icon><IconSettings /></Icon>
        </button>
      </div>
    </div>
  );
};

function ConversationListWithHeaderActions() {
  return (
    <ConversationList
      Header={HeaderWithActions}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
```

### Preview

type: `React.ComponentType<ConversationPreviewUIProps>`

Preview 用于自定义会话预览组件的展示，默认值为 `DefaultConversationPreviewUI`。

#### Example1: 自定义会话预览样式

```tsx
import { ConversationList, ConversationPreviewUIProps } from 'tuikit-atomicx-react';

const CustomConversationPreview = ({
  conversation,
  isSelected,
  onSelectConversation,
  Avatar,
  enableActions,
  ConversationActions,
  actionsConfig
}: ConversationPreviewUIProps) => (
  <div 
    className={`custom-conversation-preview ${isSelected ? 'selected' : ''}`}
    onClick={() => onSelectConversation?.(conversation)}
  >
    <div className="preview-avatar">
      <Avatar src={conversation.getAvatar()} />
      {conversation.unreadCount > 0 && (
        <span className="unread-badge">{conversation.unreadCount}</span>
      )}
    </div>
    
    <div className="preview-content">
      <div className="preview-header">
        <h3 className="conversation-name">{conversation.getShowName()}</h3>
        <span className="last-time">
          {formatTime(conversation.lastMessage?.lastTime)}
        </span>
      </div>
      
      <div className="preview-body">
        <p className="last-message">
          {conversation.lastMessage?.messageForShow || '暂无消息'}
        </p>
        
        <div className="preview-indicators">
          {conversation.isPinned && <span className="pin-indicator">📌</span>}
          {conversation.isMuted && <span className="mute-indicator">🔇</span>}
        </div>
      </div>
    </div>
    
    {enableActions && (
      <div className="preview-actions">
        <ConversationActions
          conversation={conversation}
          {...actionsConfig}
        />
      </div>
    )}
  </div>
);

function ConversationListWithCustomPreview() {
  return (
    <ConversationList
      Preview={CustomConversationPreview}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
```

#### Example2: 卡片式会话预览

```tsx
import { ConversationList, ConversationPreviewUIProps } from 'tuikit-atomicx-react';

const CardConversationPreview = ({
  conversation,
  isSelected,
  onSelectConversation,
  Avatar
}: ConversationPreviewUIProps) => (
  <div 
    className={`conversation-card ${isSelected ? 'selected' : ''}`}
    onClick={() => onSelectConversation?.(conversation)}
  >
    <div className="card-header">
      <Avatar src={conversation.getAvatar()} size="48px" />
      <div className="card-title">
        <h4>{conversation.getShowName()}</h4>
        <span className="member-count">
          {conversation.type === 'GROUP' ? `${conversation.memberCount} 人` : '私聊'}
        </span>
      </div>
    </div>
    
    <div className="card-body">
      <p className="last-message">
        {conversation.lastMessage?.messageForShow || '开始聊天吧'}
      </p>
    </div>
    
    <div className="card-footer">
      <span className="last-time">
        {formatTime(conversation.lastMessage?.lastTime)}
      </span>
      {conversation.unreadCount > 0 && (
        <span className="unread-count">{conversation.unreadCount}</span>
      )}
    </div>
  </div>
);

function ConversationListWithCardPreview() {
  return (
    <div className="card-conversation-list">
      <ConversationList
        Preview={CardConversationPreview}
        className="card-layout"
        onSelectConversation={(conversation) => {
          console.log('选择会话:', conversation.conversationID);
        }}
      />
    </div>
  );
}
```

### filter

type: `(conversationList: ConversationModel[]) => ConversationModel[]`

filter 用于过滤会话列表，可以根据业务需求筛选显示的会话，默认值为 `-`。

#### Example1: 基础会话过滤

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';

function ConversationListWithFilter() {
  // 只显示有未读消息的会话
  const filterUnreadConversations = (conversationList: ConversationModel[]) => {
    return conversationList.filter(conversation => conversation.unreadCount > 0);
  };

  // 只显示群聊会话
  const filterGroupConversations = (conversationList: ConversationModel[]) => {
    return conversationList.filter(conversation => conversation.type === 'GROUP');
  };

  // 只显示私聊会话
  const filterPrivateConversations = (conversationList: ConversationModel[]) => {
    return conversationList.filter(conversation => conversation.type === 'C2C');
  };

  return (
    <div>
      <h3>未读消息</h3>
      <ConversationList
        filter={filterUnreadConversations}
        onSelectConversation={(conversation) => {
          console.log('选择未读会话:', conversation.conversationID);
        }}
      />
      
      <h3>群聊</h3>
      <ConversationList
        filter={filterGroupConversations}
        onSelectConversation={(conversation) => {
          console.log('选择群聊:', conversation.conversationID);
        }}
      />
    </div>
  );
}
```

#### Example2: 高级过滤功能

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';
import { useState } from 'react';

function ConversationListWithAdvancedFilter() {
  const [filterType, setFilterType] = useState<'all' | 'unread' | 'pinned' | 'muted'>('all');
  const [searchKeyword, setSearchKeyword] = useState('');

  const filterConversations = (conversationList: ConversationModel[]) => {
    let filtered = conversationList;

    // 按关键词搜索
    if (searchKeyword) {
      filtered = filtered.filter(conversation => 
        conversation.getShowName().toLowerCase().includes(searchKeyword.toLowerCase()) ||
        (conversation.lastMessage?.messageForShow || '').toLowerCase().includes(searchKeyword.toLowerCase())
      );
    }

    // 按类型过滤
    switch (filterType) {
      case 'unread':
        filtered = filtered.filter(conversation => conversation.unreadCount > 0);
        break;
      case 'pinned':
        filtered = filtered.filter(conversation => conversation.isPinned);
        break;
      case 'muted':
        filtered = filtered.filter(conversation => conversation.isMuted);
        break;
      case 'all':
      default:
        // 不过滤
        break;
    }

    return filtered;
  };

  return (
    <div>
      {/* 过滤控制器 */}
      <div className="filter-controls">
        <input
          type="text"
          placeholder="搜索会话..."
          value={searchKeyword}
          onChange={(e) => setSearchKeyword(e.target.value)}
          className="search-input"
        />
        
        <div className="filter-tabs">
          {[
            { key: 'all', label: '全部' },
            { key: 'unread', label: '未读' },
            { key: 'pinned', label: '置顶' },
            { key: 'muted', label: '静音' }
          ].map(tab => (
            <button
              key={tab.key}
              className={`filter-tab ${filterType === tab.key ? 'active' : ''}`}
              onClick={() => setFilterType(tab.key as any)}
            >
              {tab.label}
            </button>
          ))}
        </div>
      </div>

      {/* 会话列表 */}
      <ConversationList
        filter={filterConversations}
        onSelectConversation={(conversation) => {
          console.log('选择会话:', conversation.conversationID);
        }}
      />
    </div>
  );
}
```

### sort

type: `(conversationList: ConversationModel[]) => ConversationModel[]`

sort 用于对会话列表进行排序，可以根据业务需求调整会话的显示顺序，默认值为 `-`。

#### Example1: 基础排序功能

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';

function ConversationListWithSort() {
  // 按最后消息时间排序（最新的在前）
  const sortByLastMessageTime = (conversationList: ConversationModel[]) => {
    return [...conversationList].sort((a, b) => {
      const timeA = a.lastMessage?.lastTime || 0;
      const timeB = b.lastMessage?.lastTime || 0;
      return timeB - timeA;
    });
  };

  // 按未读消息数量排序（未读多的在前）
  const sortByUnreadCount = (conversationList: ConversationModel[]) => {
    return [...conversationList].sort((a, b) => {
      if (a.unreadCount === b.unreadCount) {
        // 未读数相同时，按最后消息时间排序
        return (b.lastMessage?.lastTime || 0) - (a.lastMessage?.lastTime || 0);
      }
      return b.unreadCount - a.unreadCount;
    });
  };

  // 按会话名称排序（字母顺序）
  const sortByName = (conversationList: ConversationModel[]) => {
    return [...conversationList].sort((a, b) => {
      return a.getShowName().localeCompare(b.getShowName());
    });
  };

  return (
    <div>
      <h3>按时间排序</h3>
      <ConversationList
        sort={sortByLastMessageTime}
        onSelectConversation={(conversation) => {
          console.log('选择会话:', conversation.conversationID);
        }}
      />
      
      <h3>按未读数排序</h3>
      <ConversationList
        sort={sortByUnreadCount}
        onSelectConversation={(conversation) => {
          console.log('选择会话:', conversation.conversationID);
        }}
      />
    </div>
  );
}
```

#### Example2: 智能排序功能

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';

function ConversationListWithSmartSort() {
  const smartSort = (conversationList: ConversationModel[]) => {
    return [...conversationList].sort((a, b) => {
      // 1. 置顶会话优先
      if (a.isPinned && !b.isPinned) return -1;
      if (!a.isPinned && b.isPinned) return 1;

      // 2. 有未读消息的会话优先
      if (a.unreadCount > 0 && b.unreadCount === 0) return -1;
      if (a.unreadCount === 0 && b.unreadCount > 0) return 1;

      // 3. 在同等条件下，按最后消息时间排序
      const timeA = a.lastMessage?.lastTime || 0;
      const timeB = b.lastMessage?.lastTime || 0;
      if (timeA !== timeB) return timeB - timeA;

      // 4. 最后按会话类型排序（群聊优先）
      if (a.type === 'GROUP' && b.type === 'C2C') return -1;
      if (a.type === 'C2C' && b.type === 'GROUP') return 1;

      // 5. 最终按名称排序
      return a.getShowName().localeCompare(b.getShowName());
    });
  };

  // 带权重的排序
  const weightedSort = (conversationList: ConversationModel[]) => {
    return [...conversationList].sort((a, b) => {
      const getWeight = (conversation: ConversationModel) => {
        let weight = 0;
        
        // 置顶会话权重最高
        if (conversation.isPinned) weight += 1000;
        
        // 未读消息权重
        weight += conversation.unreadCount * 10;
        
        // 最近活跃权重
        const lastTime = conversation.lastMessage?.lastTime || 0;
        const hoursSinceLastMessage = (Date.now() - lastTime * 1000) / (1000 * 60 * 60);
        if (hoursSinceLastMessage < 1) weight += 100;
        else if (hoursSinceLastMessage < 24) weight += 50;
        else if (hoursSinceLastMessage < 168) weight += 20; // 一周内
        
        // 群聊稍微优先
        if (conversation.type === 'GROUP') weight += 5;
        
        return weight;
      };

      return getWeight(b) - getWeight(a);
    });
  };

  return (
    <ConversationList
      sort={smartSort}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
```

### onSelectConversation

type: `(conversation: ConversationModel) => void`

onSelectConversation 用于处理用户选择会话时的回调，默认值为 `-`。

#### Example1: 基础会话选择处理

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';
import { useNavigate } from 'react-router-dom';

function ConversationListWithSelection() {
  const navigate = useNavigate();

  const handleSelectConversation = (conversation: ConversationModel) => {
    console.log('选择会话:', conversation.conversationID);
    
    // 跳转到聊天页面
    navigate(`/chat/${conversation.conversationID}`);
    
    // 清除未读消息标记
    if (conversation.unreadCount > 0) {
      conversation.markConversationRead();
    }
  };

  return (
    <ConversationList
      onSelectConversation={handleSelectConversation}
    />
  );
}
```

#### Example2: 会话选择统计和权限控制

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';
import { useState } from 'react';

function ConversationListWithAnalytics() {
  const [selectedHistory, setSelectedHistory] = useState<string[]>([]);

  const handleSelectConversation = async (conversation: ConversationModel) => {
    try {
      // 权限检查
      const hasPermission = await checkConversationPermission(conversation.conversationID);
      if (!hasPermission) {
        alert('您没有权限访问此会话');
        return;
      }

      // 记录选择历史
      setSelectedHistory(prev => [
        conversation.conversationID,
        ...prev.filter(id => id !== conversation.conversationID).slice(0, 9)
      ]);

      // 发送统计数据
      analytics.track('conversation_selected', {
        conversationId: conversation.conversationID,
        conversationType: conversation.type,
        hasUnread: conversation.unreadCount > 0,
        isPinned: conversation.isPinned,
        timestamp: Date.now()
      });

      // 更新最近访问时间
      await updateConversationLastAccess(conversation.conversationID);

      // 执行选择逻辑
      console.log('选择会话:', conversation.conversationID);
      
      // 标记已读
      if (conversation.unreadCount > 0) {
        await conversation.markConversationRead();
      }

    } catch (error) {
      console.error('选择会话失败:', error);
      alert('访问会话失败，请重试');
    }
  };

  return (
    <div>
      <ConversationList
        onSelectConversation={handleSelectConversation}
      />
      
      {/* 最近访问记录 */}
      {selectedHistory.length > 0 && (
        <div className="recent-conversations">
          <h4>最近访问</h4>
          <div className="recent-list">
            {selectedHistory.slice(0, 5).map(conversationId => (
              <div key={conversationId} className="recent-item">
                {conversationId}
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
```

### onConversationCreated

type: `(conversation: ConversationModel) => void`

onConversationCreated 用于处理会话创建成功后的回调，默认值为 `-`。

#### Example1: 会话创建成功处理

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';
import { useNavigate } from 'react-router-dom';

function ConversationListWithCreation() {
  const navigate = useNavigate();

  const handleConversationCreated = (conversation: ConversationModel) => {
    console.log('会话创建成功:', conversation.conversationID);
    
    // 显示成功提示
    alert(`成功创建${conversation.type === 'GROUP' ? '群聊' : '私聊'}`);
    
    // 自动跳转到新创建的会话
    navigate(`/chat/${conversation.conversationID}`);
    
    // 发送创建成功统计
    analytics.track('conversation_created', {
      conversationId: conversation.conversationID,
      conversationType: conversation.type,
      timestamp: Date.now()
    });
  };

  return (
    <ConversationList
      onConversationCreated={handleConversationCreated}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
```

#### Example2: 会话创建后的复杂处理

```tsx
import { ConversationList, ConversationModel } from 'tuikit-atomicx-react';
import { useState } from 'react';

function ConversationListWithAdvancedCreation() {
  const [recentlyCreated, setRecentlyCreated] = useState<ConversationModel[]>([]);

  const handleConversationCreated = async (conversation: ConversationModel) => {
    try {
      console.log('会话创建成功:', conversation.conversationID);
      
      // 添加到最近创建列表
      setRecentlyCreated(prev => [conversation, ...prev.slice(0, 4)]);
      
      // 设置初始配置
      if (conversation.type === 'GROUP') {
        // 群聊的初始设置
        await setupGroupConversation(conversation);
      } else {
        // 私聊的初始设置
        await setupPrivateConversation(conversation);
      }
      
      // 发送欢迎消息
      await sendWelcomeMessage(conversation.conversationID);
      
      // 通知其他相关组件
      window.dispatchEvent(new CustomEvent('conversationCreated', {
        detail: conversation
      }));
      
      // 显示成功提示
      showSuccessToast(`${conversation.getShowName()} 创建成功`);
      
    } catch (error) {
      console.error('会话创建后处理失败:', error);
      showErrorToast('会话创建成功，但初始化失败');
    }
  };

  const setupGroupConversation = async (conversation: ConversationModel) => {
    // 设置群公告
    await conversation.updateGroupProfile({
      notification: '欢迎加入群聊！'
    });
    
    // 设置群管理员
    // await setGroupAdmins(conversation.conversationID);
  };

  const setupPrivateConversation = async (conversation: ConversationModel) => {
    // 私聊的特殊设置
    console.log('设置私聊:', conversation.conversationID);
  };

  return (
    <div>
      <ConversationList
        onConversationCreated={handleConversationCreated}
        onSelectConversation={(conversation) => {
          console.log('选择会话:', conversation.conversationID);
        }}
      />
      
      {/* 最近创建的会话 */}
      {recentlyCreated.length > 0 && (
        <div className="recently-created">
          <h4>最近创建</h4>
          <div className="created-list">
            {recentlyCreated.map(conversation => (
              <div key={conversation.conversationID} className="created-item">
                <span>{conversation.getShowName()}</span>
                <span className="created-time">
                  {new Date(conversation.createTime * 1000).toLocaleString()}
                </span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
```

### PlaceholderEmptyList

type: `React.ReactNode`

PlaceholderEmptyList 用于自定义空会话列表时的占位符，默认值为 `<PlaceHolder type={PlaceHolderTypes.NO_CONVERSATIONS} />`。

#### Example1: 自定义空列表占位符

```tsx
import { ConversationList } from 'tuikit-atomicx-react';

const CustomEmptyPlaceholder = () => (
  <div className="custom-empty-placeholder">
    <div className="empty-icon">💬</div>
    <h3>还没有会话</h3>
    <p>开始您的第一次对话吧</p>
    <button className="start-chat-btn">
      开始聊天
    </button>
  </div>
);

function ConversationListWithCustomEmpty() {
  return (
    <ConversationList
      PlaceholderEmptyList={<CustomEmptyPlaceholder />}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
```

### PlaceholderLoading

type: `React.ReactNode`

PlaceholderLoading 用于自定义加载中的占位符，默认值为 `<PlaceHolder type={PlaceHolderTypes.LOADING} />`。

#### Example1: 自定义加载占位符

```tsx
import { ConversationList } from 'tuikit-atomicx-react';

const CustomLoadingPlaceholder = () => (
  <div className="custom-loading-placeholder">
    <div className="loading-spinner">
      <div className="spinner"></div>
    </div>
    <p>正在加载会话列表...</p>
  </div>
);

function ConversationListWithCustomLoading() {
  return (
    <ConversationList
      PlaceholderLoading={<CustomLoadingPlaceholder />}
      onSelectConversation={(conversation) => {
        console.log('选择会话:', conversation.conversationID);
      }}
    />
  );
}
``` 