群系统事件消息改为居中纯文本渲染,不再走普通气泡+作者名的展示逻辑

根因:群里的系统事件消息(成员加入、角色变更、公告发布等,x-im-type=system_action/
system_notice)服务端并不带真实的 `from`,但 messages-view.jsx 一直把它们和普通消息
一样交给 ChatMessage 渲染——chat-message.jsx 的 fullDisplay 逻辑会在气泡下方额外画一行
发送者名字,解析不到发送者时回退显示"未找到"。对照参考图 内容沟通对话3-开启进群验证与
拉人状态.png,这类系统事件应该是居中的纯灰字提示,不带头像、不带气泡、不带作者名——现状
既不符合参考图,也让"未找到"这种内部占位文案暴露给了用户。

怎么修:meta-message.jsx 新增 systemText 分支,复用日期分隔条同一套"居中提示"视觉语言
(.meta .bubble.system,无背景、纯居中灰字);messages-view.jsx 在消息渲染分支里识别
system_action/system_notice 且不带可操作按钮(group_invitation_created 那种带
"立即加入"按钮的除外,仍走完整气泡展示)的消息,改为渲染 MetaMessage 而不是 ChatMessage。

验证:用真实群(3 个真实账号)走了两遍"扫码申请入群→通过审批",会话里"有成员通过审批
加入了群聊。"正确显示为居中灰字,不再出现气泡、头像和"未找到"作者名;带按钮的
group_invitation_created 消息不受影响,仍是完整气泡+"立即加入"按钮。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-09-06 13:39:35 +08:00
co-authored by Claude Sonnet 5
parent e53af93409
commit e6e51f625e
3 changed files with 40 additions and 0 deletions
+6
View File
@@ -4391,9 +4391,15 @@ button.full-screen .material-icons {
width: 10rem;
height: 10rem;
z-index: 2;
/* Draggable while in a fullscreen connected video call (call-panel.jsx's dragStart); the grab
cursor is the only hint of that before a viewer ever tries, since unlike the minimized bubble
there's no other affordance. Not shown while [disabled] (audio-only calls / minimized, where
dragging this box does nothing -- see call-panel.jsx). */
cursor: grab;
}
.call-party.self[disabled] {
cursor: unset;
display: none;
}
+26
View File
@@ -2350,6 +2350,16 @@ class MessagesView extends React.Component {
replyToSeq = null;
}
// group_invitation_created is the one system_action template with a real, backend-honored
// action button (see chat-message.jsx's renderGroupInvitationCard) -- it still needs the
// full ChatMessage bubble treatment. Every other system_action/system_notice template is
// purely informational and belongs in the plain centered style below.
const systemActions = msg.content && typeof msg.content == 'object' && Array.isArray(msg.content.actions) ?
msg.content.actions : null;
const isActionableSystemMessage = systemActions && systemActions.some(a => a && a.type == 'group_invitation_accept');
const isPlainSystemMessage = msg.head && (msg.head['x-im-type'] == 'system_notice' || msg.head['x-im-type'] == 'system_action') &&
!isActionableSystemMessage && msg.content && typeof msg.content == 'object' && typeof msg.content.text == 'string';
if (msg.hi) {
// Deleted message.
messageNodes.push(
@@ -2358,6 +2368,22 @@ class MessagesView extends React.Component {
deletedText={this.props.intl.formatMessage(messages.message_deleted)}
key={msg.seq} />
);
} else if (isPlainSystemMessage) {
const thisDate = new Date(msg.ts);
if (!prevDate || prevDate.toDateString() != thisDate.toDateString()) {
messageNodes.push(
<MetaMessage
date={relativeDateFormat(msg.ts)}
locale={this.props.intl.locale}
key={'date-' + msg.seq} />
);
prevDate = thisDate;
}
messageNodes.push(
<MetaMessage
systemText={msg.content.text}
key={msg.seq} />
);
} else {
const thisDate = new Date(msg.ts);
// This message was sent on a different date than the previous.
+8
View File
@@ -20,6 +20,14 @@ export default class MetaMessage extends React.PureComponent {
// 什么都不剩,看不出这里曾经有过一条消息。文案复用已有的 message_deleted("消息已删除")。
content = <i className="gray">{this.props.deletedText || '消息已删除'}</i>;
bubbleClass += ' deleted';
} else if (this.props.systemText) {
// docs/images/内容沟通对话3-开启进群验证与拉人状态.png:群系统事件(成员加入/退出/角色变更/
// 群公告发布等)在参考图里是居中的纯灰字,不带头像、不带气泡、不带发送者名字——跟这里的
// 日期分隔条是同一种视觉语言。这类消息之前是当成普通消息交给 ChatMessage 渲染的(服务端
// 这类消息没有真实的 `from`,chat-message.jsx 的 fullDisplay 逻辑因此在系统消息下方多画出
// 一行解析不到发送者、回退成"未找到"的作者名,明显不该出现)。
content = <span className="gray">{this.props.systemText}</span>;
bubbleClass += ' system';
}
if (!content) {