package store import ( "context" "time" ) // 全平台空间观测(管理端「空间管理」页)。系统级口径:跨租户看所有 Space, // 走 WithoutTenant 旁路租户插件。 // AdminSpaceRow 是管理端空间一行:空间 + 租户名 + 建者邮箱 + 成员数。 type AdminSpaceRow struct { ID string `json:"id"` TenantID string `json:"tenant_id"` TenantName string `json:"tenant_name"` Name string `json:"name"` Kind string `json:"kind"` // personal / project / tenant Creator string `json:"creator"` CreatorEmail string `json:"creator_email"` Archived bool `json:"archived"` Members int64 `json:"members"` CreatedAt time.Time `json:"created_at"` } // AllSpaces 全平台空间流(管理端观测;跨租户)。倒序,翻页。 func (p *Postgres) AllSpaces(ctx context.Context, limit int) []AdminSpaceRow { if p.db == nil { return nil } if limit <= 0 || limit > 500 { limit = 200 } ctx = WithoutTenant(ctx) // 系统级:看所有租户的空间 var out []AdminSpaceRow p.db.WithContext(ctx).Table("sundynix_space as s"). Select("s.id, s.tenant_id, s.name, s.kind, s.creator, s.archived, s.created_at, " + "coalesce(tn.name,'') as tenant_name, coalesce(u.email,'') as creator_email, " + "(select count(*) from sundynix_space_member m where m.space_id = s.id and m.deleted_at is null) as members"). Joins("left join sundynix_tenant tn on tn.id = s.tenant_id"). Joins("left join sundynix_user u on u.id = s.creator"). Where("s.deleted_at is null"). Order("s.created_at desc").Limit(limit).Scan(&out) return out }