feat(channels): 管理面板消息日志——chat_messages 加 adapter_id + 配置级/平台/总览三粒度端点
后端: - 迁移 0007:chat_messages 加 adapter_id 列 + 索引 - history.Message 加 AdapterID;persistToMain/persistIsolated 传适配器名(a.Name()) - channelbridge: 4 个持久化点 + registerSilenced 传 a;light.go registerSilenced 签名加 a - Store 新增 ListAdapterLog(?adapter=, 不排除主会话)/ListAllLog(adapter_id!='', 总览);ListPlatformLog 保留 - 新端点 GET /api/v1/admin/channels/messages:?adapter= 配置级 / ?platform= 平台 / 无参=总览,historyMessage 加 adapterId - 测试:ListAdapterLog/ListAllLog 过滤用例 + 端点粒度用例 + 桥接持久化断言 前端:渠道管理每配置(账号)「消息日志」按钮 + 页顶「适配器总览日志」入口 + ChannelLogPanel 弹窗(总览/配置级),Miuix 风格,build 绿。
This commit is contained in:
1 parent
c1bd740f7c
commit
2e044d1d19
15 files changed
+560
-41
No files matched your search
@@ -50,17 +50,19 @@ func (b *Bridge) notifyPersisted(msg history.Message) {
|
||||
// platform and client deviceID, then notifies the transport hook so Web clients receive
|
||||
// a `message_persisted` event without a refresh (design/16 §4.4). deviceID is the
|
||||
// concrete client that sent the message (design/16 §4.5) — e.g. "weixin-ilink:conf0:wx_uid"
|
||||
// for IM. It is a no-op when no history store is wired, so the bridge runs unchanged
|
||||
// without storage.
|
||||
func (b *Bridge) persistToMain(ctx context.Context, role, content, platform, deviceID string) {
|
||||
// for IM. adapterID is the account adapter registration name that received the message
|
||||
// (e.g. "kook:3bef..."), so the admin log can query a per-adapter send/receive stream;
|
||||
// it is empty for Web-originated messages. It is a no-op when no history store is wired,
|
||||
// so the bridge runs unchanged without storage.
|
||||
func (b *Bridge) persistToMain(ctx context.Context, role, content, platform, deviceID, adapterID string) {
|
||||
if b.history == nil {
|
||||
return
|
||||
}
|
||||
full, err := b.history.AppendFull(ctx, history.Message{
|
||||
SessionID: history.MainSessionID, Role: role, Content: content, Platform: platform, DeviceID: deviceID,
|
||||
SessionID: history.MainSessionID, Role: role, Content: content, Platform: platform, DeviceID: deviceID, AdapterID: adapterID,
|
||||
})
|
||||
if err != nil {
|
||||
b.log.Warn("persist main session", "err", err, "role", role, "platform", platform, "device_id", deviceID)
|
||||
b.log.Warn("persist main session", "err", err, "role", role, "platform", platform, "device_id", deviceID, "adapter", adapterID)
|
||||
return
|
||||
}
|
||||
b.notifyPersisted(full)
|
||||
@@ -69,21 +71,22 @@ func (b *Bridge) persistToMain(ctx context.Context, role, content, platform, dev
|
||||
// persistIsolated writes one message into a restricted (group / stranger) session's
|
||||
// own platform log (design/16 §4.6 §4): the message lands in the isolated sess-xxx
|
||||
// session (NOT the main web session) and carries the channel platform, the client
|
||||
// deviceID and the sender's display name, so the IM adapter log page can render the
|
||||
// non-owner message stream. It is deliberately NOT broadcast to the Web main session
|
||||
// (only owner-private messages mirror to the Web). It is a no-op when no history
|
||||
// store is wired, so the bridge runs unchanged without storage.
|
||||
func (b *Bridge) persistIsolated(ctx context.Context, role, content, deviceID string, sess session.Session, platform, senderName string) {
|
||||
// deviceID, the sender's display name and the account adapter registration name, so
|
||||
// the IM adapter log page can render the non-owner message stream per adapter config.
|
||||
// It is deliberately NOT broadcast to the Web main session (only owner-private
|
||||
// messages mirror to the Web). It is a no-op when no history store is wired, so the
|
||||
// bridge runs unchanged without storage.
|
||||
func (b *Bridge) persistIsolated(ctx context.Context, role, content, deviceID string, sess session.Session, platform, senderName, adapterID string) {
|
||||
if b.history == nil {
|
||||
return
|
||||
}
|
||||
full, err := b.history.AppendFull(ctx, history.Message{
|
||||
SessionID: sess.SessionID, Role: role, Content: content, Platform: platform,
|
||||
DeviceID: deviceID, SenderName: senderName,
|
||||
DeviceID: deviceID, SenderName: senderName, AdapterID: adapterID,
|
||||
})
|
||||
if err != nil {
|
||||
b.log.Warn("persist isolated session", "err", err, "role", role,
|
||||
"session", sess.SessionID, "platform", platform, "sender_name", senderName)
|
||||
"session", sess.SessionID, "platform", platform, "sender_name", senderName, "adapter", adapterID)
|
||||
return
|
||||
}
|
||||
// No broadcast: third-party messages must not reach the Web main session (design/16 §4.6 §3).
|
||||
|
||||
Reference in new issue
Block a user