先说结论
在 Odoo Discuss 里,很多人以为:
- chat 就是私聊,
- group 就是群聊,
- channel 就是频道。
这当然没错,但太浅了。
从 discuss_channel.py 和 res_partner.py 的源码看,三者真正的区别不是名字,而是协作边界的设计:
- 谁能加入;
- 是否可以公开授权;
- 成员数量怎么约束;
- 父子频道能不能继承边界;
- 邀请建议能不能越权。
一句话说:
Odoo Discuss 的频道类型,本质上是在定义不同协作空间的成员治理规则,而不是做三个外观不同的聊天盒子。
这篇主要看哪里
核心源码在:
addons/mail/models/discuss/discuss_channel.pyaddons/mail/models/discuss/res_partner.py
重点可以看:
channel_type_constraint_partners_chat()_constraint_group_id_channel()_compute_group_public_id()_compute_is_member()search_for_channel_invite()_search_for_channel_invite()get_mention_suggestions_from_channel()
第一层:三种频道类型不是名字差异,而是权限模型差异
源码里 channel_type 有三种:
chatgroupchannel
字段 help 写得很清楚:
- Chat:私密且唯一地存在于两个人之间;
- Group:受邀成员之间的私密空间;
- Channel:可自由加入,但仍取决于配置。
这几句话其实已经透露了 Odoo 的基本治理思想:
chat
重点是一对一唯一性,不追求扩张。
group
重点是受邀制私密协作。
channel
重点是可管理的公开协作面。
所以你看到的不是聊天形态分类,而是协作开放程度分层。
第二层:为什么 chat 被硬限制为最多两人
_constraint_partners_chat() 直接限制:
channel_type == 'chat'时,成员不能超过两人。
这不是 UI 约束,而是数据层约束。
这意味着 Odoo 不允许“本来是私聊,后来慢慢拉成小群”这种语义漂移。
为什么这很重要?
因为如果允许 chat 任意加人:
- 历史权限语义会变脏;
- 私聊期待会被破坏;
- 前端很多关于直聊的假设会失效;
- 后续邀请、显示名、成员可见性都难以解释。
Odoo 选择在模型层把这件事卡死,实际上是在保护协作预期。
第三层:为什么只有 channel 能做公开组授权和自动订阅
源码里有两个非常关键的限制:
group_public_idgroup_ids
并且 _constraint_group_id_channel() 明确要求:
- 只有
channel_type == 'channel'才能使用基于用户组的授权或自动订阅。
也就是说:
group虽然也是多人空间,但它不是面向公开加入治理的;- 真正承接“面向某个组织范围开放”的,是
channel。
这非常合理。
因为一旦你允许 group 也同时拥有公开授权和自动订阅,它就会在“私密受邀空间”和“受治理开放空间”之间语义混乱。
Odoo 明确把两者切开了。
第四层:父子频道不是任意嵌套,且类型要一致
_constraint_parent_channel_id() 里有几个很强的约束:
- 父频道不能本身还是子频道;
- 父频道类型只能是
channel或group; - 子频道必须和父频道同类型。
这说明 Odoo 不希望频道树无限乱长。
它更像是在支持有限层级的协作分区,而不是要做一个复杂社区论坛。
更关键的是“类型必须一致”这条。
因为如果你允许:
- 公开 channel 下面挂私密 group;
- 或 group 下面再挂另一套完全不同公开语义的 channel;
成员边界、授权继承、邀请能力都会变得很难解释。
所以 Odoo 直接在模型层面把这种复杂度砍掉了。
第五层:邀请候选并不是想搜谁就能加谁
search_for_channel_invite() 和 _search_for_channel_invite() 也很值得看。
源码会在邀请候选阶段就限制:
- 不能邀请自己;
- 对方必须是活跃内部用户;
- 如果当前频道有
group_public_id,候选人还必须属于该授权组; - 已经在频道里的成员不会重复出现。
这说明 Odoo 的邀请搜索不是“全局搜人”,而是“在当前频道治理边界内搜可合法加入的人”。
这跟很多聊天产品的“先搜到再说”不同。
Odoo 把可邀请性提前到候选计算阶段,减少了后置报错和权限歧义。
第六层:必要时还允许按邮箱邀请,但也有限制
如果搜索不到匹配伙伴,且输入看起来像邮箱,源码会进一步判断:
- 当前频道是否允许通过邮箱邀请;
- 这个邮箱对应的人是否已经在频道成员里;
- 是否曾经向这个邮箱发过邀请邮件。
这说明 Odoo 在“开放协作”上也不是一刀切:
- 它允许把组织外的人拉进来;
- 但不是无条件开放;
- 仍然要求频道本身声明“我支持这种邀请方式”。
这正是一个企业协同产品应有的克制。
第七层:提及建议也会继承频道边界
get_mention_suggestions_from_channel() 里,提及候选不仅看搜索词,还会限制在:
- 当前频道或父频道范围内的成员;
- 如果有授权组,还得满足
allowed_group。
这意味着 Odoo 的设计很一致:
- 你不能把一个本来无权进入该协作空间的人,仅仅通过“@一下”拉进来;
- mention 也要服从频道成员和授权边界。
这点非常关键。
否则频道治理会被编辑器提及功能偷偷绕开。
一句话记住
Odoo Discuss 里的 chat、group、channel,不是三种视觉组件,而是三套协作治理规则:
chat 保护一对一直聊,group 保护受邀私密协作,channel 承接受治理的开放协作。
理解这层以后,你再看成员约束、邀请建议、公开授权、父子频道和 mention 边界,就会发现它们其实都在服务同一件事:
让协作空间既能扩展,又不失控。
DISCUSSION
评论区