协同办公

Odoo Discuss 频道为什么不是“成员都一样收消息”:channel member、mentions only、mute 和 web push 矩阵讲透

很多人以为 Discuss 频道里只要是成员,就会按同一种方式收通知。源码其实分得非常细:成员不是 follower,频道通知还要看 custom_notifications、mute、busy 状态和 web push 分流。

协同办公
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 4 阅读

先说结论

很多人把 Discuss 频道通知理解成一个很简单的逻辑:

  • 是成员
  • 就会收到频道消息

addons/mail/models/discuss/discuss_channel.pydiscuss_channel_member.py 告诉我们的现实要复杂得多。

在 Discuss 里,通知不是“成员统一广播”,而是一张条件矩阵:

  • 频道成员是谁
  • 频道类型是什么
  • 用户是否静音
  • 用户是否只想收 mentions
  • 用户当前是否是 busy
  • 这条消息是不是把某人显式拉进 partner_ids
  • 最后走 inbox、email 还是 web push

所以更准确的说法是:

Discuss 的协作通知不是“成员名单”,而是“成员状态 × 频道类型 × 消息上下文”的计算结果。


一、频道成员为什么不是 follower

discuss.channel_notify_get_recipients() 里写得很直接:

  • channel 不是标准意义上的 mail.thread 文档
  • 它没有 followers 这一套收件基础
  • 它依赖的是 discuss.channel.member

这点特别重要。

因为很多人看到 Odoo 全站都有 Chatter,就会下意识套用“followers 决定收件人”的思路。

但 Discuss 频道不是业务对象页面下的一段消息区, 它本身就是即时协作空间。

因此它的基础单位不是 follower,而是 member

这意味着 Discuss 更关心的是:

  • 你是不是这个空间的成员
  • 你对这个空间现在采用什么通知策略

而不是“你是否订阅某条业务记录”。


二、为什么同样是成员,收件策略却不同

discuss.channel.member 上有几个很关键的字段:

  • custom_notifications
  • mute_until_dt
  • seen_message_id
  • new_message_separator
  • last_interest_dt
  • unpin_dt

其中最直接影响通知策略的是 custom_notifications

源码给出的取值有:

  • all
  • mentions
  • no_notif

而且帮助文案还明确说:

  • 这套定制设置主要应用在频道(channel)上
  • 如果没指定,就回退到用户设置里的默认值

也就是说,Discuss 不是“同一频道,同一提醒方式”。

它允许成员按自己的工作方式调节噪音密度。

这很符合真实办公场景:

  • 有人要盯全量频道
  • 有人只要被点名时再进来
  • 有人这段时间临时不想被打断

三、为什么 mentions only 不是前端小开关,而是后端路由条件

discuss.channel._notify_get_recipients() 里,频道通知筛成员时写得相当细。

对于 channel_type='channel' 的公共/团队频道,系统会判断:

  • 成员自定义是否是 all
  • 若成员没自定义,看用户设置里 channel_notifications 是否是 all
  • 若成员自定义是 mentions,则只有当该成员出现在 partner_ids 时才会被算进来
  • 若成员没自定义且用户默认也不是全量,也会回到“必须在 partner_ids 里”这个条件

这说明 “mentions only” 并不是 UI 上写着好看的一行字。

它实际改变了后端的收件人筛选逻辑。

所以你可以把它理解成:

成员仍然在频道里,但默认不进入每条消息的通知收件集;只有被显式点名时,才重新进入。

这和简单静音还不一样。


四、为什么静音和 busy 也会改变通知结果

很多人以为静音只是前端不弹红点。

但 Discuss 在后端选收件人时,直接排除了:

  • mute_until_dt 仍然生效的成员
  • manual_im_status = busy 的内部用户

这透露出 Odoo 的一个很务实的设计判断:

  • 通知不只是“系统能不能送”
  • 还要考虑“此刻是否适合打扰”

也就是说,Discuss 并没有把“成员关系”和“通知资格”画等号。

成员资格只是基础, 真正能不能被推送,还要看当前状态。

这正是即时协作和普通 Chatter 的差异之一。


五、为什么 partner_ids 在频道里仍然很重要

虽然频道没有 followers, 但 partner_ids 仍然在 Discuss 通知中扮演关键角色。

原因很简单:

  • partner_ids 代表这条消息被显式点到的人
  • mentions only 策略最终就靠它来判断“这次是不是轮到你”

所以在频道场景里,partner_ids 的意义不是“持久订阅”,而更像:

  • 本条消息的精确命中名单

这也是为什么 mention 功能和频道通知偏好能自然接到一起。

一个成员平时可以不接收全量频道广播, 但只要本条消息明确点了他,后端仍能把他拉回通知路径。


六、为什么 web push 要和 inbox 分开算

discuss.channel._notify_thread_by_web_push() 里有一段很关键的注释:

  • Discuss 频道里,只对 notif == 'web_push' 的收件人发 web push
  • 要排除 inbox recipients
  • 因为 inbox 和 web push 在频道场景里可能是互斥的

这段设计很值得品。

它说明 Odoo 没把“通知”抽象成一条单路通道, 而是承认:

  • 有的用户想在 Discuss 里看未读
  • 有的用户更依赖系统级推送
  • 两者不能机械叠加,否则会重复打扰

所以频道通知不是“先确定人,再把所有渠道都打一遍”, 而是:

  • 先分类成员
  • 再根据分类决定走哪条路

这比很多 IM 集成做法成熟得多。


七、为什么频道类型不同,通知心智也不同

同一个 _notify_get_recipients() 里还能看到 Odoo 对频道类型的不同处理:

  • chat
  • group
  • channel

尤其 channel 类型最强调成员偏好设置, 因为它更像团队公共空间,天然更容易产生噪音。

而一对一聊天、临时小组聊天的通知逻辑通常更直接。

这背后的产品判断很合理:

  • 空间越公共,越要允许成员自己调噪
  • 空间越私密、越临时,越接近强提醒

所以 Discuss 的通知模型并不是单一算法,而是跟空间性质耦合的。


八、这套设计对协同办公意味着什么

这意味着 Odoo Discuss 并不把“协作”理解成无差别广播。

它更像在做两件事:

1. 让成员关系足够清楚

你属于哪个频道,决定你有没有资格参与。

2. 让打扰强度足够可调

你怎样被打扰、在什么情况下被拉进来,则由成员设置和消息上下文共同决定。

这种设计比“要么全收、要么退群”更适合企业协作。

因为真实团队里,很多频道本来就应该:

  • 低频盯着
  • 必要时被点名
  • 特殊时段暂时静音

Odoo 把这些现实工作方式直接写进了模型结构里。


九、实战里最容易踩的坑

1. 把 Discuss 频道误当成普通 Chatter 线程

结果设计时只会想 followers,不会想 members。

2. 只测“成员能不能收到”,不测“mentions only 是否只在 partner_ids 命中时触发”

最后以为通知随机。

3. 忽略 mute 与 busy 状态

以为系统漏推,其实是故意不打扰。

4. 同时堆 inbox 和 web push

容易把频道体验做成双重轰炸。

5. 不区分 chat / group / channel 的通知语义

把所有空间做成一套规则,体验通常会很差。


一句话记忆法

Odoo Discuss 的频道通知不是“成员统一收消息”,而是“成员资格 + 频道偏好 + 当前状态 + 本条消息是否点名”的联合计算。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。