一、开发概述

适用场景

对话页面功能增强,新增对话搜索(模糊匹配) 、时间分组展示核心功能,同步解决开发中常见问题。

技术依赖

  • 组件复用:系统内置 Input 组件(保证样式统一)
  • 核心文件:web/src/components/sidebar/ConversationList.tsx(搜索框)、web/src/components/sidebar/ConversationGroup.tsx(时间分组)

二、核心功能实现(可直接复制使用)

1. 对话搜索框(ConversationList.tsx)

tsx

import Input from '@/components/ui/input/Input';
import { useState } from 'react';

const ConversationList = ({ conversations }) => {
  // 搜索关键词状态
  const [searchKeyword, setSearchKeyword] = useState('');

  // 实时筛选:匹配对话名称/摘要(支持模糊搜索)
  const filteredConversations = conversations.filter(conversation => 
    conversation.name.includes(searchKeyword) || 
    (conversation.summary && conversation.summary.includes(searchKeyword))
  );

  return (
    <div className="max-w-[280px] flex-1">
      {/* 搜索框组件(优化垂直居中样式) */}
      <Input
        type="text"
        className="!py-2 mb-4 line-height-1"
        showLeftIcon={true}
        showClearIcon={true}
        placeholder="搜索对话"
        value={searchKeyword}
        onChange={e => setSearchKeyword(e.target.value)} // 实时更新关键词
        onClear={() => setSearchKeyword('')} // 清空搜索
        wrapperClassName="w-full"
      />
      {/* 渲染筛选后的对话列表 */}
      <ConversationGroup filteredConversations={filteredConversations} />
    </div>
  );
};

export default ConversationList;

2. 时间分类功能(ConversationGroup.tsx)

tsx

const ConversationGroup = ({ filteredConversations }) => {
  // 时间分组工具函数:按「今天/昨天/最近7天/更早」分类
  const getTimeGroup = (time: string) => {
    const conversationTime = new Date(time);
    const now = new Date();
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);
    const recent7Days = new Date(today);
    recent7Days.setDate(recent7Days.getDate() - 7);

    if (conversationTime >= today) return 'today';
    if (conversationTime >= yesterday) return 'yesterday';
    if (conversationTime >= recent7Days) return 'recent7';
    return 'earlier';
  };

  // 按时间分组处理(修复新对话无updated_at问题)
  const groupedConversations = filteredConversations.reduce((groups, item) => {
    const updatedAt = item.updated_at || Math.floor(Date.now() / 1000); // 兜底当前时间
    const groupKey = getTimeGroup(new Date(updatedAt * 1000).toISOString());
    groups[groupKey] = groups[groupKey] || [];
    groups[groupKey].push(item);
    return groups;
  }, {} as Record<string, typeof filteredConversations>);

  // 分组渲染(按时间倒序展示)
  const groupOrder = ['today', 'yesterday', 'recent7', 'earlier'];
  return (
    <div>
      {groupOrder.map(key => {
        const conversations = groupedConversations[key];
        if (!conversations?.length) return null;
        return (
          <div key={key} className="mb-4">
            <h3 className="text-sm font-medium text-text-tertiary mb-2">
              {key === 'today' ? '今天' : 
               key === 'yesterday' ? '昨天' : 
               key === 'recent7' ? '最近7天' : '更早'}
            </h3>
            {conversations.map(conversation => (
              <ConversationItem key={conversation.id} conversation={conversation} />
            ))}
          </div>
        );
      })}
    </div>
  );
};

export default ConversationGroup;

三、常见问题解决方案(问题 - 原因 - 解决)

问题描述 原因分析 解决方案
搜索图标贴底,不垂直居中 Tailwind 类名错误 + 行高偏移 补充 line-height-1,删除拆分的 -translate-y 类名,统一样式控制
新对话默认显示在「更早」 新对话 updated_at 为 undefined,分组误判 给 updated_at 加兜底:`item.updated_at Math.floor(Date.now() / 1000)`
搜索无实时筛选效果 未绑定 onChange 或筛选逻辑不全 绑定 onChange 实时更新 searchKeyword,筛选条件包含 name 和 summary
收藏状态刷新后丢失 仅本地维护状态,未从接口获取初始值 组件挂载时调用 /api/conversations/${id}/status,用 is_collected 初始化
反馈提交后数据库无数据 未关联 message_feedbacks 表,接口未写入 后端接口添加表插入逻辑,确保 message_idrating 等字段存储

四、功能验证清单

  1. 搜索验证:输入关键词,对话列表实时筛选,结果匹配名称 / 摘要;清空关键词后显示全部
  2. 分类验证:新创建对话显示在「今天」分组,历史对话按时间正确归类(昨天 / 最近 7 天 / 更早)
  3. 样式验证:搜索图标垂直居中,分组标题样式统一,无布局错乱
  4. 边界验证:无 summary 的对话仅匹配名称,无 updated_at 的新对话正常归类

欢迎评论私信讨论Dify相关的问题,需要源码私我

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐