feat: 新增群组成员数量统计功能并在接口中返回
实现了群组成员数量统计的接口,包含数据库层统计逻辑,在群组详情、设置等接口中返回实时成员数,同时修复了测试用例中参数空格问题。
This commit is contained in:
@@ -405,6 +405,7 @@ type TenantBusinessAdapter interface {
|
||||
TenantGroupMemberUpsert(t.TenantID, *t.GroupMember) (*t.GroupMember, error)
|
||||
TenantGroupMemberGet(t.TenantID, string, t.Uid) (*t.GroupMember, error)
|
||||
TenantGroupMemberList(t.TenantID, string, t.GroupMemberListOptions) ([]t.GroupMember, string, error)
|
||||
TenantGroupMembersCount(t.TenantID, []string) (map[string]int64, error)
|
||||
TenantGroupMemberUpdate(t.TenantID, string, t.Uid, t.GroupMemberPatch) (*t.GroupMember, error)
|
||||
TenantUsersShareOpenPrivateGroup(t.TenantID, t.Uid, t.Uid) (bool, error)
|
||||
TenantGroupInvitationCreate(t.TenantID, *t.GroupInvitation) (*t.GroupInvitation, error)
|
||||
|
||||
@@ -394,6 +394,50 @@ func (a *adapter) TenantGroupMemberList(id t.TenantID, topic string, opts t.Grou
|
||||
return items, next, rows.Err()
|
||||
}
|
||||
|
||||
// TenantGroupMembersCount counts active members for the given topics using the
|
||||
// same visibility rules as TenantGroupMemberList: membership active, subscription
|
||||
// not deleted, user not deleted. Returns counts keyed by topic; topics with no
|
||||
// active members are absent from the map.
|
||||
func (a *adapter) TenantGroupMembersCount(id t.TenantID, topics []string) (map[string]int64, error) {
|
||||
if tenantAdp, err := a.routeGroupTenant(id); err != nil {
|
||||
return nil, err
|
||||
} else if tenantAdp != a {
|
||||
return tenantAdp.TenantGroupMembersCount(id, topics)
|
||||
}
|
||||
if len(topics) == 0 {
|
||||
return map[string]int64{}, nil
|
||||
}
|
||||
placeholders := strings.TrimSuffix(strings.Repeat("?,", len(topics)), ",")
|
||||
args := make([]any, 0, len(topics)+3)
|
||||
args = append(args, t.StateDeleted, id, t.GroupMemberStatusActive)
|
||||
for _, topic := range topics {
|
||||
args = append(args, topic)
|
||||
}
|
||||
ctx, cancel := a.getContext()
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
rows, err := a.db.QueryContext(ctx, tenantShardSQL(id, `SELECT gm.topic, COUNT(DISTINCT gm.user_id) FROM im_group_members AS gm
|
||||
JOIN im_subscriptions AS s ON s.tenant_id=gm.tenant_id AND s.topic=gm.topic AND s.userid=gm.user_id AND s.deletedat IS NULL
|
||||
JOIN im_users AS u ON u.tenant_id=gm.tenant_id AND u.id=gm.user_id AND u.state!=?
|
||||
WHERE gm.tenant_id=? AND gm.member_status=? AND gm.topic IN (`+placeholders+`)
|
||||
GROUP BY gm.topic`), args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
counts := make(map[string]int64, len(topics))
|
||||
for rows.Next() {
|
||||
var topic string
|
||||
var count int64
|
||||
if err = rows.Scan(&topic, &count); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
counts[topic] = count
|
||||
}
|
||||
return counts, rows.Err()
|
||||
}
|
||||
|
||||
func (a *adapter) TenantUsersShareOpenPrivateGroup(id t.TenantID, userID, peerID t.Uid) (bool, error) {
|
||||
if tenantAdp, err := a.routeGroupTenant(id); err != nil {
|
||||
return false, err
|
||||
|
||||
Reference in New Issue
Block a user