# SearchResultsItem 组件自定义文档

## 概述

SearchResultsItem 是搜索结果项组件，负责根据不同的搜索类型渲染相应的搜索结果展示。组件支持用户搜索、群组搜索、消息搜索和聊天消息搜索四种类型，能够自动选择合适的子组件进行渲染，并支持关键词高亮显示。组件提供统一的点击事件处理和样式自定义功能，为用户提供一致的搜索结果浏览体验。

## Props 配置表格

| 字段 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| keyword | `string` | - | 搜索关键词，用于高亮显示 |
| data | `ResultItemMap[SearchType]` | - | 搜索结果数据，根据类型不同包含不同的数据结构 |
| type | `SearchType` | - | 搜索结果类型，决定使用哪个子组件渲染 |
| className | `string` | - | 自定义样式类名 |
| style | `React.CSSProperties` | - | 自定义内联样式 |
| onClick | `(data: SearchResultItem, type: SearchType) => void` | - | 点击结果项回调函数 |

## Props 详解

### keyword

type: `string`

keyword 用于指定搜索关键词，组件会在渲染结果时高亮显示匹配的文本内容，默认值为 `-`。

### data

type: `ResultItemMap[SearchType]`

data 用于提供搜索结果的具体数据，根据搜索类型不同包含不同的数据结构，默认值为 `-`。

### type

type: `SearchType`

type 用于指定搜索结果的类型，组件根据此类型选择对应的子组件进行渲染，默认值为 `-`。

#### Example1: 用户搜索结果渲染

```tsx
import { SearchResultsItem, SearchType } from 'tuikit-atomicx-react';

function UserSearchResult() {
  const userSearchData = {
    profile: {
      userID: 'user123',
      nick: '张三',
      avatar: 'https://example.com/avatar.jpg',
      selfSignature: '这是一个用户签名',
      gender: 'male',
      birthday: 19900101
    }
  };

  const handleUserClick = (data: any, type: SearchType) => {
    console.log('点击用户结果:', data);
    // 导航到用户详情页或发起私聊
    if (type === SearchType.USER) {
      // 处理用户点击逻辑
      navigateToUserProfile(data.profile.userID);
    }
  };

  return (
    <div style={{ padding: '20px' }}>
      <h3>用户搜索结果</h3>
      <SearchResultsItem
        keyword="张三"
        data={userSearchData}
        type={SearchType.USER}
        onClick={handleUserClick}
      />
    </div>
  );
}

function navigateToUserProfile(userID: string) {
  // 用户详情页导航逻辑
  console.log('导航到用户详情页:', userID);
}
```

#### Example2: 群组搜索结果渲染

```tsx
import { SearchResultsItem, SearchType } from 'tuikit-atomicx-react';

function GroupSearchResult() {
  const groupSearchData = {
    groupInfo: {
      groupID: 'group456',
      name: '技术交流群',
      avatar: 'https://example.com/group-avatar.jpg',
      introduction: '这是一个专业的技术交流群组，欢迎大家分享技术心得',
      memberCount: 128,
      maxMemberCount: 200
    }
  };

  const handleGroupClick = (data: any, type: SearchType) => {
    console.log('点击群组结果:', data);
    if (type === SearchType.GROUP) {
      // 处理群组点击逻辑
      const { groupInfo } = data;
      if (groupInfo.memberCount < groupInfo.maxMemberCount) {
        joinGroup(groupInfo.groupID);
      } else {
        showMessage('群组已满，无法加入');
      }
    }
  };

  return (
    <div style={{ padding: '20px' }}>
      <h3>群组搜索结果</h3>
      <SearchResultsItem
        keyword="技术"
        data={groupSearchData}
        type={SearchType.GROUP}
        onClick={handleGroupClick}
      />
      
      {/* 搜索结果统计 */}
      <div style={{ marginTop: '12px', fontSize: '12px', color: '#666' }}>
        群组成员: {groupSearchData.groupInfo.memberCount}/{groupSearchData.groupInfo.maxMemberCount}
      </div>
    </div>
  );
}

function joinGroup(groupID: string) {
  console.log('申请加入群组:', groupID);
}

function showMessage(message: string) {
  alert(message);
}
```

### className

type: `string`

className 用于自定义组件的样式类名，默认值为 `-`。

### style

type: `React.CSSProperties`

style 用于自定义组件的内联样式，默认值为 `-`。

### onClick

type: `(data: SearchResultItem, type: SearchType) => void`

onClick 用于处理搜索结果项点击事件，接收结果数据和类型参数，默认值为 `-`。

#### Example1: 基础点击处理

```tsx
import { SearchResultsItem, SearchType } from 'tuikit-atomicx-react';
import { useState } from 'react';

function BasicClickHandler() {
  const [clickHistory, setClickHistory] = useState<Array<{
    type: string;
    data: any;
    timestamp: number;
  }>>([]);

  const handleResultClick = (data: any, type: ISearchType) => {
    // 记录点击历史
    const clickRecord = {
      type: type,
      data: data,
      timestamp: Date.now()
    };
    
    setClickHistory(prev => [clickRecord, ...prev.slice(0, 9)]);
    
    // 根据类型执行不同操作
    switch (type) {
      case SearchType.USER:
        console.log('用户点击:', data.profile?.nick || data.profile?.userID);
        break;
      case SearchType.GROUP:
        console.log('群组点击:', data.groupInfo?.name || data.groupInfo?.groupID);
        break;
      case SearchType.MESSAGE:
        console.log('消息点击:', data.conversation?.conversationID);
        break;
      case SearchType.CHAT_MESSAGE:
        console.log('聊天消息点击:', data.ID);
        break;
      default:
        console.log('未知类型点击:', type);
    }
  };

  const mockUserData = {
    profile: {
      userID: 'user123',
      nick: '测试用户',
      avatar: 'https://example.com/avatar.jpg'
    }
  };

  return (
    <div style={{ padding: '20px' }}>
      <SearchResultsItem
        keyword="测试"
        data={mockUserData}
        type={SearchType.USER}
        onClick={handleResultClick}
      />
      
      {/* 点击历史记录 */}
      {clickHistory.length > 0 && (
        <div style={{ marginTop: '16px' }}>
          <h4 style={{ fontSize: '14px', margin: '0 0 8px 0' }}>点击历史:</h4>
          {clickHistory.map((record, index) => (
            <div key={index} style={{ 
              fontSize: '12px', 
              padding: '4px 8px', 
              backgroundColor: '#f5f5f5',
              marginBottom: '4px',
              borderRadius: '4px'
            }}>
              {new Date(record.timestamp).toLocaleTimeString()} - {record.type}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
```

#### Example2: 高级点击处理与权限控制

```tsx
import { SearchResultsItem, SearchType } from 'tuikit-atomicx-react';
import { useState, useCallback } from 'react';

interface UserPermissions {
  canViewProfile: boolean;
  canStartChat: boolean;
  canJoinGroup: boolean;
  canViewMessages: boolean;
}

function AdvancedClickHandler() {
  const [userPermissions] = useState<UserPermissions>({
    canViewProfile: true,
    canStartChat: true,
    canJoinGroup: false, // 假设用户没有加群权限
    canViewMessages: true
  });

  const [operationLog, setOperationLog] = useState<string[]>([]);

  const logOperation = useCallback((message: string) => {
    setOperationLog(prev => [`${new Date().toLocaleTimeString()}: ${message}`, ...prev.slice(0, 4)]);
  }, []);

  const handleAdvancedClick = async (data: any, type: ISearchType) => {
    try {
      // 权限检查
      const hasPermission = checkPermission(type, userPermissions);
      if (!hasPermission) {
        logOperation(`权限不足，无法执行 ${getTypeLabel(type)} 操作`);
        return;
      }

      // 执行相应操作
      switch (type) {
        case SearchType.USER:
          await handleUserAction(data);
          break;
        case SearchType.GROUP:
          await handleGroupAction(data);
          break;
        case SearchType.MESSAGE:
          await handleMessageAction(data);
          break;
        case SearchType.CHAT_MESSAGE:
          await handleChatMessageAction(data);
          break;
      }
    } catch (error) {
      logOperation(`操作失败: ${error.message}`);
    }
  };

  const checkPermission = (type: SearchType, permissions: UserPermissions): boolean => {
    switch (type) {
      case SearchType.USER:
        return permissions.canViewProfile;
      case SearchType.GROUP:
        return permissions.canJoinGroup;
      case SearchType.MESSAGE:
      case SearchType.CHAT_MESSAGE:
        return permissions.canViewMessages;
      default:
        return false;
    }
  };

  const handleUserAction = async (data: any) => {
    logOperation(`正在查看用户: ${data.profile?.nick || data.profile?.userID}`);
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 500));
    logOperation('用户资料加载完成');
  };

  const handleGroupAction = async (data: any) => {
    logOperation(`正在申请加入群组: ${data.groupInfo?.name || data.groupInfo?.groupID}`);
    await new Promise(resolve => setTimeout(resolve, 1000));
    logOperation('群组申请已发送');
  };

  const handleMessageAction = async (data: any) => {
    logOperation(`正在打开会话: ${data.conversation?.conversationID}`);
    await new Promise(resolve => setTimeout(resolve, 300));
    logOperation('会话已打开');
  };

  const handleChatMessageAction = async (data: any) => {
    logOperation(`正在定位到消息: ${data.ID}`);
    await new Promise(resolve => setTimeout(resolve, 200));
    logOperation('消息定位完成');
  };

  const getTypeLabel = (type: ISearchType): string => {
    const labels = {
      [SearchType.USER]: '用户',
      [SearchType.GROUP]: '群组',
      [SearchType.MESSAGE]: '消息',
      [SearchType.CHAT_MESSAGE]: '聊天消息'
    };
    return labels[type] || '未知';
  };

  const mockData = {
    profile: {
      userID: 'user456',
      nick: '高级用户',
      avatar: 'https://example.com/avatar2.jpg'
    }
  };

  return (
    <div style={{ padding: '20px' }}>
      <div style={{ marginBottom: '16px' }}>
        <h4 style={{ fontSize: '14px', margin: '0 0 8px 0' }}>用户权限:</h4>
        <div style={{ fontSize: '12px', color: '#666' }}>
          查看资料: {userPermissions.canViewProfile ? '✅' : '❌'} | 
          发起聊天: {userPermissions.canStartChat ? '✅' : '❌'} | 
          加入群组: {userPermissions.canJoinGroup ? '✅' : '❌'} | 
          查看消息: {userPermissions.canViewMessages ? '✅' : '❌'}
        </div>
      </div>

      <SearchResultsItem
        keyword="高级"
        data={mockData}
        type={ISearchType.USER}
        onClick={handleAdvancedClick}
        style={{ border: '1px solid #e0e0e0', borderRadius: '4px' }}
      />

      {/* 操作日志 */}
      {operationLog.length > 0 && (
        <div style={{ marginTop: '16px' }}>
          <h4 style={{ fontSize: '14px', margin: '0 0 8px 0' }}>操作日志:</h4>
          {operationLog.map((log, index) => (
            <div key={index} style={{
              fontSize: '12px',
              padding: '4px 8px',
              backgroundColor: '#f8f9fa',
              marginBottom: '2px',
              borderLeft: '3px solid #007AFF',
              borderRadius: '2px'
            }}>
              {log}
            </div>
          ))}
        </div>
      )}
    </div>
  );
} 