Skip to content

Feed/Chatter 组件:补充测试 + Console 集成 + 完成收尾工作 #727

@hotlong

Description

@hotlong

背景

#706P0/P1/P2 核心组件代码已全部完成,放置在 packages/plugin-detail/src/,Roadmap P1.5 已更新标记完成。

但经评估发现三个关键收尾缺口:

  1. 新组件缺少专项单元测试
  2. Console 未集成新组件(仍使用旧版 CommentThread
  3. P3 增强项未实现

本 Issue 跟踪所有需要开展的细项工作。


任务清单

🔴 Task 1 — 补充新组件单元测试

现有测试覆盖的是旧版 ActivityTimelineRecordComments,新的消费 @objectstack/spec Feed 协议的 6 个核心组件均无专项测试。

  • RecordActivityTimeline.test.tsxpackages/plugin-detail/src/__tests__/

    • 渲染基本 feed items(comment / field_change / task / event / system / email / call)
    • 各 item type 显示正确的图标和颜色样式
    • Actor 头像 + 名称 + 来源 + 时间戳正确渲染
    • unifiedTimeline 模式:评论与字段变更混排
    • filterMode 切换:all / comments_only / changes_only / tasks_only
    • 受控 filterMode 和非受控内部 filter 两种模式
    • 空列表显示 "No activity recorded"
    • showFilter 可通过 config.showFilterToggle 控制隐藏
    • CommentInput 渲染(当 onAddComment 提供时)
    • CommentInput 不渲染(当 onAddComment 未提供时或 config.showCommentInput === false
    • 提交评论:点击按钮 + Ctrl+Enter 快捷键
    • 提交后清空输入框
    • 提交期间禁用输入和按钮
    • 分页:hasMore=true 时显示 "Load more" 按钮
    • 加载更多时显示 loading spinner
    • edited 标记显示 "(edited)"
    • pinned 标记显示 "📌 Pinned"
    • source 字段显示 "via {source}"
    • SubscriptionToggleconfig.showSubscriptionToggle=truesubscription 存在时渲染
    • Reactions 在 config.enableReactions=true 时渲染
    • Threading 在 config.enableThreading=true 时按 parentId 分组
  • RecordChatterPanel.test.tsxpackages/plugin-detail/src/__tests__/

    • Sidebar 模式(position='right'):正确宽度、border-l 样式
    • Sidebar 模式(position='left'):border-r 样式
    • Inline 模式(position='bottom'):无 border 样式
    • 可折叠:collapsible=true + defaultCollapsed=true 初始折叠
    • 折叠态显示 "Open discussion panel" 按钮(sidebar)
    • 折叠态显示 "Show Discussion (N)" 按钮(inline)
    • 展开后显示 "Close discussion panel" / "Hide discussion" 按钮
    • 点击折叠/展开按钮切换状态
    • collapsible=false 时不显示折叠按钮
    • 内嵌 RecordActivityTimeline 正确传递 config.feed 配置
    • Sidebar 模式下 Timeline 有 border-0 shadow-none class
    • 所有回调 props 正确透传(onAddComment, onAddReply, onToggleReaction, onToggleSubscription)
  • FieldChangeItem.test.tsxpackages/plugin-detail/src/__tests__/

    • 渲染字段名(自动 capitalize + 下划线替换空格)
    • 使用 fieldLabel 优先于自动生成
    • 渲染旧值(删除线样式)和新值
    • 使用 oldDisplayValue / newDisplayValue 优先于原始值
    • 旧值/新值为 null 时显示 "(empty)"
    • 中间箭头图标渲染
  • ReactionPicker.test.tsxpackages/plugin-detail/src/__tests__/

    • 渲染已有 reactions:emoji + count
    • 已 reacted 的 reaction 显示高亮样式(bg-primary/10)
    • 未 reacted 的 reaction 显示普通样式(bg-muted)
    • 点击已有 reaction 调用 onToggleReaction(emoji)
    • "Add reaction" 按钮(SmilePlus 图标)
    • 点击 "Add reaction" 展开 emoji picker
    • 选择 emoji 调用 onToggleReaction(emoji) 并关闭 picker
    • onToggleReaction 时不显示 "Add reaction" 按钮
    • onToggleReaction 时已有 reaction 按钮 disabled
    • 自定义 emojiOptions 渲染对应 emoji
    • aria-label 包含 emoji + count
  • ThreadedReplies.test.tsxpackages/plugin-detail/src/__tests__/

    • 渲染折叠态:显示 "N replies" / "1 reply"
    • 点击展开按钮显示所有回复
    • 展开态每条回复:头像(avatarUrl 或首字母)+ actor + 时间戳 + body
    • 收起态 aria-expanded=false,展开态 aria-expanded=true
    • Reply 输入框渲染(当 showReplyInput=trueonAddReply 存在)
    • 输入文本并点击 Send 按钮调用 onAddReply(parentId, text)
    • Ctrl+Enter 快捷键提交回复
    • 提交后清空输入框
    • 空输入时 Send 按钮 disabled
    • 提交期间输入和按钮 disabled
    • replies=[]showReplyInput=false 时返回 null
  • SubscriptionToggle.test.tsxpackages/plugin-detail/src/__tests__/

    • subscribed=true 显示 Bell 图标(text-primary 样式)
    • subscribed=false 显示 BellOff 图标(text-muted-foreground 样式)
    • 点击调用 onToggle(!subscription.subscribed)
    • 点击后 loading 状态 disabled
    • onToggle 时按钮 disabled
    • aria-label 随 subscribed 状态变化
    • title 随 subscribed 状态变化

🔴 Task 2 — Console RecordDetailView 集成

当前 apps/console/src/components/RecordDetailView.tsx 使用旧版 CommentThread(来自 @object-ui/collaboration)。需要替换为新的 spec 协议组件。

  • 替换 CommentThread → RecordChatterPanel

    • @object-ui/plugin-detail 导入 RecordChatterPanel
    • 移除 CommentThread 导入
    • <CommentThread> 替换为 <RecordChatterPanel> 并传入 RecordChatterPanelProps
    • 配置 position: 'bottom'(保持当前内联布局)或改为 position: 'right'(Airtable 风格侧边栏)
  • 接入 FeedItem 数据模型

    • 将现有 comments state 从 Comment[] 改为 FeedItem[]
    • 适配 FeedItem 接口字段:id, type, actor, actorAvatarUrl, body, createdAt, reactions, parentId, replyCount
    • 添加字段变更历史获取逻辑(调用 dataSource.find('sys_audit_log', ...)client.feed.list()
    • 合并 comments + field changes 为统一 FeedItem[] 数组
  • 接入 RecordSubscription

    • 添加 subscription state(RecordSubscription 类型)
    • 获取当前用户对该 record 的订阅状态
    • 实现 onToggleSubscription 回调
  • 接入分页

    • 添加 hasMore / onLoadMore 逻辑
    • 初始加载 limit 设为 20,后续分页 cursor-based
  • 接入 Reactions

    • 将现有 handleReaction 适配为 onToggleReaction(itemId, emoji) 签名
    • Reactions 数据从 { [emoji]: string[] } 格式映射为 Reaction[]{ emoji, count, reacted }
  • 接入 Threading

    • handleAddCommentparentId 适配为 onAddReply(parentId, text) 签名
    • 设置 config.enableThreading = true

🟡 Task 3 — Console ActivityFeed 升级(头部通知)

apps/console/src/components/ActivityFeed.tsx 是 Phase 17 L1 的本地状态组件,未消费 Feed 协议。

  • 评估是否将 ActivityFeed(Sheet 铃铛通知面板)替换为 RecordActivityTimeline
  • 如需替换:将 ActivityItem 数据模型迁移为 FeedItem
  • 如需替换:接入 client.feed.list() API 获取全局 activity feed

🟡 Task 4 — RichTextCommentInput 集成

RichTextCommentInput 已开发但未被 RecordActivityTimeline 的 CommentInput 区域使用(当前 Timeline 使用普通 <textarea>)。

  • 评估是否将 RecordActivityTimeline 内嵌的 <textarea> 升级为 RichTextCommentInput
  • 如升级:传入 mentionSuggestions(用户列表)作为 MentionAutocomplete 数据源
  • 如升级:onSubmit 回调对接 onAddComment

🟢 Task 5 — P3 增强项(可后续迭代)

  • Comment 编辑功能(edit 按钮 + 内联编辑模式)
  • Comment 删除功能(delete 确认对话框)
  • 文件附件集成(CommentAttachment 已存在,需接入到 CommentInput 流程)
  • 富文本渲染(将 Markdown body 渲染为 HTML,目前仅 preview 模式可用)

🟢 Task 6 — 运行测试 & 确认无回归

  • 运行 pnpm test 确认所有新增测试通过
  • 运行 pnpm build 确认 42/42 构建通过
  • 确认 Console 集成后 RecordDetailView 页面功能正常
  • 更新 Roadmap 中测试计数(当前 5,177+)

协议参考

协议文件 位置 说明
FeedItem / FieldChangeEntry / Reaction / RecordSubscription @object-ui/types 类型定义
RecordActivityTimeline packages/plugin-detail/src/RecordActivityTimeline.tsx 统一时间线
RecordChatterPanel packages/plugin-detail/src/RecordChatterPanel.tsx 侧边面板
FieldChangeItem packages/plugin-detail/src/FieldChangeItem.tsx 字段变更条目
ReactionPicker packages/plugin-detail/src/ReactionPicker.tsx Emoji 选择器
ThreadedReplies packages/plugin-detail/src/ThreadedReplies.tsx 回复线程
SubscriptionToggle packages/plugin-detail/src/SubscriptionToggle.tsx 订阅开关
RichTextCommentInput packages/plugin-detail/src/RichTextCommentInput.tsx 富文本输入
Console RecordDetailView apps/console/src/components/RecordDetailView.tsx 集成目标
Console ActivityFeed apps/console/src/components/ActivityFeed.tsx 通知面板

关联

  • 上游 Issue: #706 — UI 实现:Airtable 风格的 Comments & Activity Timeline 渲染组件
  • 上游协议: objectstack-ai/spec#731 — Feed/Comment/Chatter 协议定义

建议开发流程

  1. Task 1 先行 — 补测试,确保现有组件实现正确
  2. Task 2 — Console 集成,切换到新组件
  3. Task 3-4 — 评估 + 可选升级
  4. Task 6 — 全量测试验证
  5. 每步完成后 pnpm test 确认无回归

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions