前端给AI消息做日期分组与时间线

先说结论:把一长条 AI 对话消息变成清爽的时间线,核心就两步------按会话(session)分组 、再按日期(今天/昨天/更早)打标签 。数据层用 reduce 归并,渲染层做粘性日期头,不用引第三方库。下面是我前两周真踩过的活儿,代码能直接抄。

起因

我在给一个自己搭的 AI 小助手做 web 端聊天界面。后端把消息一股脑按时间正序吐回来,前端就一条接一条往下堆。测了两天,消息攒到三百多条的时候,整个面板糊成一坨------你根本分不清哪句是今早问的,哪句是上周那次会话留下的。产品同事(其实就是我自己兼)看了一眼说:太脏了。

行吧。

第一步:数据先分好组,别在 JSX 里硬塞

我见过有人直接在模板里 if (上一条日期 !== 这条日期) 插分隔线,能跑,但乱。先在数据层把扁平数组捏成分组结构。

scss 复制代码
// 假设每条 msg: { id, sessionId, content, role, createdAt }
function groupBySession(messages) {
  const map = new Map();
  for (const m of messages) {
    if (!map.has(m.sessionId)) map.set(m.sessionId, []);
    map.get(m.sessionId).push(m);
  }
  // Map 保插入顺序,会话天然按首次出现排好
  return [...map.entries()].map(([sessionId, list]) => ({
    sessionId,
    list,
    startAt: list[0].createdAt,
  }));
}

会话内再不用动,组与组之间按 startAt 倒序就是最近的会话在最上面。

第二步:日期标签,别去算"几天前"

这步是我栽过的坑。一开始我吭哧吭哧写 Math.floor((now - t) / 86400000) 去算差几天,结果跨午夜就错------晚上23:50和凌晨0:10明明隔了20分钟,算出来"0天",可它俩分属两天,得分到两组。

正解是比日历日,不是比时间差:

ini 复制代码
function dayLabel(ts) {
  const d = new Date(ts);
  const today = new Date();
  const ymd = x => x.getFullYear() * 10000 + (x.getMonth() + 1) * 100 + x.getDate();
  const diff = ymd(today) - ymd(d);
  if (diff === 0) return '今天';
  if (diff === 1) return '昨天';
  if (diff < 7) return d.toLocaleDateString('zh-CN', { weekday: 'long' }); // 周三
  return `${d.getMonth() + 1}月${d.getDate()}日`;
}

把日期戳压成 年*10000+月*100+日 这个整数再相减,天数差就稳了,不受具体几点几分干扰。

第三步:粘性日期头,滚动时吸顶

时间线的"清爽感"一大半来自滚动时那个日期标签会黏在顶上。纯 CSS 就够:

css 复制代码
.day-label {
  position: sticky;
  top: 0;
  z-index: 2;
  /* 别忘了背景色,不然下面的消息会透上来糊一起 */
  background: #f7f8fa;
}

background 那行我忘了写,调了十分钟以为是 z-index 的事,结果是文字和下面气泡叠透了。记一下。

一点真实的取舍

会话分组我没做"自动归并相近时间的消息"那种智能合并------比如隔了2小时的两次提问算不算一个会话。试过,阈值定多少都有人觉得不对,干脆老老实实信后端给的 sessionId,前端只管展示。少做一点反而稳。

另外说句实话,难看的不是布局,是内容本身。我那个 AI 小助手第一版回答又干又短,时间线做得再漂亮,点开每条都是两行废话也白搭。后来我给它配了点私有资料喂进去(RAG 那套),回答才有了血肉,时间线翻起来才像回事。

对了,搭这个小助手我基本没写后端------拖一拖配一配,挂个现成模型、传几份文档当知识库,发布成一个 API,前端直接调。我一个偏前端的人,零代码就把"智能体"那部分糊出来了,省下的精力全砸在这个时间线交互上了。

收尾

分组的活儿听着小,做到"一眼就清爽"挺费心思的------比 ymd 那个整数 trick 还琐碎的细节有七八处。但用户滑动时那个日期标签稳稳吸在顶上的瞬间,值。

你们做聊天记录的日期分组,是信后端 sessionId 还是前端自己按时间切?评论区聊聊,我那套阈值方案就是被同行劝退的。

(背后那个智能体我挂的是讯飞的 MaaS,现成大模型直接调 API,没自己部署算力,省心。)

相关推荐
u130130几秒前
GitHub 热榜项目:日榜(2026-10-14)
人工智能·github
Raas1001 分钟前
AI网关怎么选?MAI Gateway(魔芋企业级AI网关)入选2026年企业级AI网关推荐清单
大数据·网络·人工智能·gateway·mai gateway
晨间晓2 分钟前
两张图片哪里不一样?用 OpenCV 做图像差异检测工具
人工智能·opencv·计算机视觉
逸A6 分钟前
携程app逆向那些事(ai agent能力偏弱时)
人工智能·python·安全
汇智信科10 分钟前
基于 SMS 体系的民航安全管理平台架构,危险源与事件闭环管理
人工智能·安全·汇智信科·hsim·fastclaw·汇智龙虾
数据皮皮侠12 分钟前
中国产品级二氧化碳排放数据集
大数据·人工智能·搜索引擎·智慧城市·制造
旋生万物17 分钟前
螺旋数不是玄学:Python 实现广义复数与等角螺线
开发语言·人工智能·python·云原生·aigc·软件工程·后端开发
边界智能18 分钟前
国庆假期 AI Agent 行业复盘|智能体的考核标准被改写
人工智能·ai·智能体
李福春19 分钟前
技术思考问题16:AI智能体模型Meta-Muse-Wonder越聪明,刹车应该谁来踩?
人工智能·agent安全·幂等设计·深圳同盟·腾讯云架构师技术同盟·智能体权限·工具授权分级
素男22 分钟前
不够好,正好:便利贴那管「失败」的胶
人工智能·agent·self-becoming·ai长期记忆·ai自我介绍