package services import ( "context" "strings" tenantdto "quyun/v2/app/http/tenant/dto" "quyun/v2/app/requests" "quyun/v2/database" "quyun/v2/database/models" "github.com/pkg/errors" "github.com/samber/lo" log "github.com/sirupsen/logrus" "go.ipao.vip/gen" "go.ipao.vip/gen/field" ) // AdminContentPage returns contents list for tenant admin (includes drafts/unpublished/etc). func (s *content) AdminContentPage(ctx context.Context, tenantID int64, filter *tenantdto.AdminContentListFilter) (*requests.Pager, error) { if tenantID <= 0 { return nil, errors.New("tenant_id must be > 0") } if filter == nil { filter = &tenantdto.AdminContentListFilter{} } log.WithFields(log.Fields{ "tenant_id": tenantID, "page": filter.Page, "limit": filter.Limit, "user_id": lo.FromPtr(filter.UserID), "keyword": filter.KeywordTrimmed(), "status": lo.FromPtr(filter.Status), }).Info("services.content.admin.page") filter.Pagination.Format() cTbl, query := models.ContentQuery.QueryContext(ctx) query = query.Select(cTbl.ALL) conds := []gen.Condition{ cTbl.TenantID.Eq(tenantID), cTbl.DeletedAt.IsNull(), } if filter.ID != nil && *filter.ID > 0 { conds = append(conds, cTbl.ID.Eq(*filter.ID)) } if filter.UserID != nil && *filter.UserID > 0 { conds = append(conds, cTbl.UserID.Eq(*filter.UserID)) } if kw := strings.TrimSpace(filter.KeywordTrimmed()); kw != "" { conds = append(conds, cTbl.Title.Like(database.WrapLike(kw))) } if filter.Status != nil { conds = append(conds, cTbl.Status.Eq(*filter.Status)) } if filter.Visibility != nil { conds = append(conds, cTbl.Visibility.Eq(*filter.Visibility)) } if filter.PublishedAtFrom != nil { conds = append(conds, cTbl.PublishedAt.Gte(*filter.PublishedAtFrom)) } if filter.PublishedAtTo != nil { conds = append(conds, cTbl.PublishedAt.Lte(*filter.PublishedAtTo)) } if filter.CreatedAtFrom != nil { conds = append(conds, cTbl.CreatedAt.Gte(*filter.CreatedAtFrom)) } if filter.CreatedAtTo != nil { conds = append(conds, cTbl.CreatedAt.Lte(*filter.CreatedAtTo)) } orderBys := make([]field.Expr, 0, 6) allowedAsc := map[string]field.Expr{ "id": cTbl.ID.Asc(), "title": cTbl.Title.Asc(), "user_id": cTbl.UserID.Asc(), "status": cTbl.Status.Asc(), "visibility": cTbl.Visibility.Asc(), "published_at": cTbl.PublishedAt.Asc(), "created_at": cTbl.CreatedAt.Asc(), "updated_at": cTbl.UpdatedAt.Asc(), } allowedDesc := map[string]field.Expr{ "id": cTbl.ID.Desc(), "title": cTbl.Title.Desc(), "user_id": cTbl.UserID.Desc(), "status": cTbl.Status.Desc(), "visibility": cTbl.Visibility.Desc(), "published_at": cTbl.PublishedAt.Desc(), "created_at": cTbl.CreatedAt.Desc(), "updated_at": cTbl.UpdatedAt.Desc(), } for _, f := range filter.AscFields() { f = strings.TrimSpace(f) if f == "" { continue } if ob, ok := allowedAsc[f]; ok { orderBys = append(orderBys, ob) } } for _, f := range filter.DescFields() { f = strings.TrimSpace(f) if f == "" { continue } if ob, ok := allowedDesc[f]; ok { orderBys = append(orderBys, ob) } } if len(orderBys) == 0 { orderBys = append(orderBys, cTbl.ID.Desc()) } else { orderBys = append(orderBys, cTbl.ID.Desc()) } items, total, err := query.Where(conds...).Order(orderBys...).FindByPage(int(filter.Offset()), int(filter.Limit)) if err != nil { return nil, err } contentIDs := lo.Uniq(lo.FilterMap(items, func(item *models.Content, _ int) (int64, bool) { if item == nil || item.ID <= 0 { return 0, false } return item.ID, true })) ownerIDs := lo.Uniq(lo.FilterMap(items, func(item *models.Content, _ int) (int64, bool) { if item == nil || item.UserID <= 0 { return 0, false } return item.UserID, true })) priceByContent, err := s.contentPriceMapping(ctx, tenantID, contentIDs) if err != nil { return nil, err } ownerMap := map[int64]*tenantdto.AdminContentOwnerLite{} if len(ownerIDs) > 0 { uTbl, uQuery := models.UserQuery.QueryContext(ctx) users, err := uQuery.Where(uTbl.ID.In(ownerIDs...)).Find() if err != nil { return nil, err } for _, u := range users { if u == nil { continue } ownerMap[u.ID] = &tenantdto.AdminContentOwnerLite{ ID: u.ID, Username: u.Username, Status: u.Status, Roles: u.Roles, } } } respItems := lo.Map(items, func(model *models.Content, _ int) *tenantdto.AdminContentItem { if model == nil { return nil } return &tenantdto.AdminContentItem{ Content: model, Price: priceByContent[model.ID], Owner: ownerMap[model.UserID], StatusDescription: model.Status.Description(), VisibilityDescription: model.Visibility.Description(), } }) return &requests.Pager{ Pagination: filter.Pagination, Total: total, Items: respItems, }, nil }