package tenant_public import ( "quyun/v2/app/errorx" tenant_dto "quyun/v2/app/http/tenant/dto" "quyun/v2/app/requests" "quyun/v2/app/services" "quyun/v2/database/models" "quyun/v2/pkg/consts" "quyun/v2/providers/jwt" "github.com/gofiber/fiber/v3" log "github.com/sirupsen/logrus" ) // content 提供“租户维度的公开只读接口”(不要求租户成员)。 // // @provider type content struct{} func viewerUserID(ctx fiber.Ctx) int64 { claims, ok := ctx.Locals(consts.CtxKeyClaims).(*jwt.Claims) if !ok || claims == nil { return 0 } return claims.UserID } // list // // @Summary 公开内容列表(已发布 + public) // @Tags TenantPublic // @Accept json // @Produce json // @Param tenantCode path string true "Tenant Code" // @Param filter query tenant_dto.ContentListFilter true "Filter" // @Success 200 {object} requests.Pager{items=tenant_dto.ContentItem} // // @Router /t/:tenantCode/v1/public/contents [get] // @Bind tenant local key(tenant) // @Bind filter query func (*content) list( ctx fiber.Ctx, tenant *models.Tenant, filter *tenant_dto.ContentListFilter, ) (*requests.Pager, error) { uid := viewerUserID(ctx) log.WithFields(log.Fields{ "tenant_id": tenant.ID, "user_id": uid, }).Info("tenant_public.contents.list") if filter == nil { filter = &tenant_dto.ContentListFilter{} } filter.Pagination.Format() return services.Content.ListPublicPublished(ctx, tenant.ID, uid, filter) } // show // // @Summary 公开内容详情(已发布 + public) // @Tags TenantPublic // @Accept json // @Produce json // @Param tenantCode path string true "Tenant Code" // @Param contentID path int64 true "ContentID" // @Success 200 {object} tenant_dto.ContentDetail // // @Router /t/:tenantCode/v1/public/contents/:contentID [get] // @Bind tenant local key(tenant) // @Bind contentID path func (*content) show(ctx fiber.Ctx, tenant *models.Tenant, contentID int64) (*tenant_dto.ContentDetail, error) { uid := viewerUserID(ctx) log.WithFields(log.Fields{ "tenant_id": tenant.ID, "user_id": uid, "content_id": contentID, }).Info("tenant_public.contents.show") item, err := services.Content.PublicDetail(ctx, tenant.ID, uid, contentID) if err != nil { return nil, err } return &tenant_dto.ContentDetail{ Content: item.Content, Price: item.Price, HasAccess: item.HasAccess, }, nil } // previewAssets // // @Summary 获取公开试看资源(preview role) // @Tags TenantPublic // @Accept json // @Produce json // @Param tenantCode path string true "Tenant Code" // @Param contentID path int64 true "ContentID" // @Success 200 {object} tenant_dto.ContentAssetsResponse // // @Router /t/:tenantCode/v1/public/contents/:contentID/preview [get] // @Bind tenant local key(tenant) // @Bind contentID path func (*content) previewAssets( ctx fiber.Ctx, tenant *models.Tenant, contentID int64, ) (*tenant_dto.ContentAssetsResponse, error) { uid := viewerUserID(ctx) log.WithFields(log.Fields{ "tenant_id": tenant.ID, "user_id": uid, "content_id": contentID, }).Info("tenant_public.contents.preview_assets") detail, err := services.Content.PublicDetail(ctx, tenant.ID, uid, contentID) if err != nil { return nil, err } assets, err := services.Content.AssetsByRole(ctx, tenant.ID, contentID, consts.ContentAssetRolePreview) if err != nil { return nil, err } previewSeconds := int32(detail.Content.PreviewSeconds) if previewSeconds <= 0 { previewSeconds = consts.DefaultContentPreviewSeconds } return &tenant_dto.ContentAssetsResponse{ Content: detail.Content, Assets: assets, PreviewSeconds: previewSeconds, }, nil } // mainAssets // // @Summary 获取公开正片资源(main role;免费/作者/已购) // @Tags TenantPublic // @Accept json // @Produce json // @Param tenantCode path string true "Tenant Code" // @Param contentID path int64 true "ContentID" // @Success 200 {object} tenant_dto.ContentAssetsResponse // // @Router /t/:tenantCode/v1/public/contents/:contentID/assets [get] // @Bind tenant local key(tenant) // @Bind contentID path func (*content) mainAssets( ctx fiber.Ctx, tenant *models.Tenant, contentID int64, ) (*tenant_dto.ContentAssetsResponse, error) { uid := viewerUserID(ctx) log.WithFields(log.Fields{ "tenant_id": tenant.ID, "user_id": uid, "content_id": contentID, }).Info("tenantpublic.contents.main_assets") detail, err := services.Content.PublicDetail(ctx, tenant.ID, uid, contentID) if err != nil { return nil, err } if !detail.HasAccess { return nil, errorx.ErrPermissionDenied.WithMsg("未购买或无权限访问") } assets, err := services.Content.AssetsByRole(ctx, tenant.ID, contentID, consts.ContentAssetRoleMain) if err != nil { return nil, err } return &tenant_dto.ContentAssetsResponse{ Content: detail.Content, Assets: assets, }, nil }