package services import ( "context" "errors" "fmt" "quyun/v2/app/errorx" "quyun/v2/app/http/v1/dto" "quyun/v2/app/requests" "quyun/v2/database/models" "quyun/v2/pkg/consts" "github.com/spf13/cast" "go.ipao.vip/gen/types" "gorm.io/gorm" ) // @provider type tenant struct{} func (s *tenant) List(ctx context.Context, filter *dto.TenantListFilter) (*requests.Pager, error) { tbl, q := models.TenantQuery.QueryContext(ctx) q = q.Where(tbl.Status.Eq(consts.TenantStatusVerified)) if filter.Keyword != nil && *filter.Keyword != "" { q = q.Where(tbl.Name.Like("%" + *filter.Keyword + "%")) } filter.Pagination.Format() total, err := q.Count() if err != nil { return nil, errorx.ErrDatabaseError.WithCause(err) } list, err := q.Offset(int(filter.Pagination.Offset())).Limit(int(filter.Pagination.Limit)).Find() if err != nil { return nil, errorx.ErrDatabaseError.WithCause(err) } var data []dto.TenantProfile for _, t := range list { followers, _ := models.TenantUserQuery.WithContext(ctx).Where(models.TenantUserQuery.TenantID.Eq(t.ID)).Count() contents, _ := models.ContentQuery.WithContext(ctx). Where(models.ContentQuery.TenantID.Eq(t.ID), models.ContentQuery.Status.Eq(consts.ContentStatusPublished)). Count() cfg := t.Config.Data() data = append(data, dto.TenantProfile{ ID: cast.ToString(t.ID), Name: t.Name, Avatar: cfg.Avatar, Bio: cfg.Bio, Stats: dto.Stats{ Followers: int(followers), Contents: int(contents), }, }) } return &requests.Pager{ Pagination: filter.Pagination, Total: total, Items: data, }, nil } func (s *tenant) GetPublicProfile(ctx context.Context, userID int64, id string) (*dto.TenantProfile, error) { tid := cast.ToInt64(id) t, err := models.TenantQuery.WithContext(ctx).Where(models.TenantQuery.ID.Eq(tid)).First() if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errorx.ErrRecordNotFound } return nil, errorx.ErrDatabaseError.WithCause(err) } // Stats followers, _ := models.TenantUserQuery.WithContext(ctx).Where(models.TenantUserQuery.TenantID.Eq(tid)).Count() contents, _ := models.ContentQuery.WithContext(ctx). Where(models.ContentQuery.TenantID.Eq(tid), models.ContentQuery.Status.Eq(consts.ContentStatusPublished)). Count() // Following status isFollowing := false if userID > 0 { uid := userID isFollowing, _ = models.TenantUserQuery.WithContext(ctx). Where(models.TenantUserQuery.TenantID.Eq(tid), models.TenantUserQuery.UserID.Eq(uid)). Exists() } cfg := t.Config.Data() fmt.Printf("DEBUG: Tenant Config: %+v\n", cfg) return &dto.TenantProfile{ ID: cast.ToString(t.ID), Name: t.Name, Avatar: cfg.Avatar, Cover: cfg.Cover, Bio: cfg.Bio, Description: cfg.Description, Stats: dto.Stats{ Followers: int(followers), Contents: int(contents), }, IsFollowing: isFollowing, }, nil } func (s *tenant) Follow(ctx context.Context, userID int64, id string) error { if userID == 0 { return errorx.ErrUnauthorized } uid := userID tid := cast.ToInt64(id) // Check if tenant exists t, err := models.TenantQuery.WithContext(ctx).Where(models.TenantQuery.ID.Eq(tid)).First() if err != nil { return errorx.ErrRecordNotFound } tu := &models.TenantUser{ TenantID: tid, UserID: uid, Role: types.Array[consts.TenantUserRole]{consts.TenantUserRoleMember}, Status: consts.UserStatusVerified, } if err := models.TenantUserQuery.WithContext(ctx).Save(tu); err != nil { return errorx.ErrDatabaseError.WithCause(err) } if Notification != nil { _ = Notification.Send(ctx, t.UserID, "interaction", "新增粉丝", "有人关注了您的店铺: "+t.Name) } return nil } func (s *tenant) Unfollow(ctx context.Context, userID int64, id string) error { if userID == 0 { return errorx.ErrUnauthorized } uid := userID tid := cast.ToInt64(id) _, err := models.TenantUserQuery.WithContext(ctx). Where(models.TenantUserQuery.TenantID.Eq(tid), models.TenantUserQuery.UserID.Eq(uid)). Delete() if err != nil { return errorx.ErrDatabaseError.WithCause(err) } return nil } func (s *tenant) ListFollowed(ctx context.Context, userID int64) ([]dto.TenantProfile, error) { if userID == 0 { return nil, errorx.ErrUnauthorized } uid := userID tbl, q := models.TenantUserQuery.QueryContext(ctx) list, err := q.Where(tbl.UserID.Eq(uid)).Find() if err != nil { return nil, errorx.ErrDatabaseError.WithCause(err) } var data []dto.TenantProfile for _, tu := range list { // Fetch Tenant t, err := models.TenantQuery.WithContext(ctx).Where(models.TenantQuery.ID.Eq(tu.TenantID)).First() if err != nil { continue } // Stats followers, _ := models.TenantUserQuery.WithContext(ctx). Where(models.TenantUserQuery.TenantID.Eq(tu.TenantID)). Count() contents, _ := models.ContentQuery.WithContext(ctx). Where(models.ContentQuery.TenantID.Eq(tu.TenantID), models.ContentQuery.Status.Eq(consts.ContentStatusPublished)). Count() data = append(data, dto.TenantProfile{ ID: cast.ToString(t.ID), Name: t.Name, Avatar: "", Stats: dto.Stats{ Followers: int(followers), Contents: int(contents), }, IsFollowing: true, }) } return data, nil } // GetModelByID 获取指定 ID 的model func (s *tenant) GetModelByID(ctx context.Context, id int64) (*models.Tenant, error) { tbl, query := models.TenantQuery.QueryContext(ctx) u, err := query.Where(tbl.ID.Eq(id)).First() if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errorx.ErrRecordNotFound } return nil, errorx.ErrDatabaseError.WithCause(err) } return u, nil }