basePath: /t/{tenantCode}/v1 definitions: consts.ContentAssetRole: enum: - main - cover - preview type: string x-enum-varnames: - ContentAssetRoleMain - ContentAssetRoleCover - ContentAssetRolePreview consts.ContentStatus: enum: - draft - reviewing - published - unpublished - blocked type: string x-enum-varnames: - ContentStatusDraft - ContentStatusReviewing - ContentStatusPublished - ContentStatusUnpublished - ContentStatusBlocked consts.ContentVisibility: enum: - public - tenant_only - private type: string x-enum-varnames: - ContentVisibilityPublic - ContentVisibilityTenantOnly - ContentVisibilityPrivate consts.Currency: enum: - CNY type: string x-enum-varnames: - CurrencyCNY consts.DiscountType: enum: - none - percent - amount type: string x-enum-varnames: - DiscountTypeNone - DiscountTypePercent - DiscountTypeAmount consts.MediaAssetStatus: enum: - uploaded - processing - ready - failed - deleted type: string x-enum-varnames: - MediaAssetStatusUploaded - MediaAssetStatusProcessing - MediaAssetStatusReady - MediaAssetStatusFailed - MediaAssetStatusDeleted consts.MediaAssetType: enum: - video - audio - image type: string x-enum-varnames: - MediaAssetTypeVideo - MediaAssetTypeAudio - MediaAssetTypeImage consts.Role: enum: - user - super_admin type: string x-enum-varnames: - RoleUser - RoleSuperAdmin consts.TenantStatus: enum: - pending_verify - verified - banned type: string x-enum-varnames: - TenantStatusPendingVerify - TenantStatusVerified - TenantStatusBanned consts.TenantUserRole: enum: - member - tenant_admin type: string x-enum-varnames: - TenantUserRoleMember - TenantUserRoleTenantAdmin consts.UserStatus: enum: - pending_verify - verified - banned type: string x-enum-varnames: - UserStatusPendingVerify - UserStatusVerified - UserStatusBanned dto.ContentAssetAttachForm: properties: asset_id: description: AssetID is the media asset id to attach. type: integer role: allOf: - $ref: '#/definitions/consts.ContentAssetRole' description: Role indicates how this asset is used (main/cover/preview). sort: description: Sort controls ordering under the same role. type: integer type: object dto.ContentAssetsResponse: properties: assets: description: Assets is the list of media assets for the requested role (preview/main). items: $ref: '#/definitions/models.MediaAsset' type: array content: allOf: - $ref: '#/definitions/models.Content' description: Content is the content entity. preview_seconds: description: PreviewSeconds indicates the max preview duration (only meaningful for preview response). type: integer type: object dto.ContentCreateForm: properties: description: description: Description is the content description. type: string preview_seconds: description: PreviewSeconds controls preview duration (defaults to 60 when omitted). type: integer title: description: Title is the content title. type: string visibility: allOf: - $ref: '#/definitions/consts.ContentVisibility' description: Visibility controls who can view the content detail (main assets still require free/purchase). type: object dto.ContentDetail: properties: content: allOf: - $ref: '#/definitions/models.Content' description: Content is the content entity. has_access: description: HasAccess indicates whether current user can access main assets (free/owner/purchased). type: boolean price: allOf: - $ref: '#/definitions/models.ContentPrice' description: Price is the current price settings for the content (may be nil if not set). type: object dto.ContentItem: properties: content: allOf: - $ref: '#/definitions/models.Content' description: Content is the content entity. has_access: description: HasAccess indicates whether current user can access main assets (free/owner/purchased). type: boolean price: allOf: - $ref: '#/definitions/models.ContentPrice' description: Price is the current price settings for the content (may be nil if not set). type: object dto.ContentPriceUpsertForm: properties: currency: allOf: - $ref: '#/definitions/consts.Currency' description: Currency is fixed to CNY for now. discount_end_at: description: DiscountEndAt disables discount after this time (optional). type: string discount_start_at: description: DiscountStartAt enables discount from this time (optional). type: string discount_type: allOf: - $ref: '#/definitions/consts.DiscountType' description: DiscountType defines the discount algorithm (none/percent/amount). discount_value: description: DiscountValue is interpreted based on DiscountType. type: integer price_amount: description: PriceAmount is the base price in cents (CNY 分). type: integer type: object dto.ContentUpdateForm: properties: description: description: Description updates the description when provided. type: string preview_seconds: description: PreviewSeconds updates preview duration when provided (must be > 0). type: integer status: allOf: - $ref: '#/definitions/consts.ContentStatus' description: Status updates the content status when provided (e.g. publish/unpublish). title: description: Title updates the title when provided. type: string visibility: allOf: - $ref: '#/definitions/consts.ContentVisibility' description: Visibility updates the visibility when provided. type: object dto.LoginForm: properties: password: type: string username: type: string type: object dto.LoginResponse: properties: token: type: string type: object dto.MeResponse: properties: tenant: allOf: - $ref: '#/definitions/models.Tenant' description: Tenant is the resolved tenant by `tenantCode`. tenant_user: allOf: - $ref: '#/definitions/models.TenantUser' description: TenantUser is the membership record of the authenticated user within the tenant. user: allOf: - $ref: '#/definitions/models.User' description: User is the authenticated user derived from JWT `user_id`. type: object dto.TenantExpireUpdateForm: properties: duration: enum: - 7 - 30 - 90 - 180 - 365 type: integer required: - duration type: object dto.TenantItem: properties: code: type: string config: items: type: integer type: array created_at: type: string expired_at: type: string id: type: integer name: type: string status: $ref: '#/definitions/consts.TenantStatus' status_description: type: string updated_at: type: string user_balance: type: integer user_count: type: integer user_id: type: integer users: items: $ref: '#/definitions/models.User' type: array uuid: type: string type: object dto.TenantStatusUpdateForm: properties: status: allOf: - $ref: '#/definitions/consts.TenantStatus' enum: - normal - disabled required: - status type: object dto.UserItem: properties: created_at: type: string deleted_at: $ref: '#/definitions/gorm.DeletedAt' id: type: integer metas: items: type: integer type: array owned: $ref: '#/definitions/models.Tenant' password: type: string roles: items: $ref: '#/definitions/consts.Role' type: array status: $ref: '#/definitions/consts.UserStatus' status_description: type: string tenants: items: $ref: '#/definitions/models.Tenant' type: array updated_at: type: string username: type: string verified_at: type: string type: object dto.UserStatistics: properties: count: type: integer status: $ref: '#/definitions/consts.UserStatus' status_description: type: string type: object dto.UserStatusUpdateForm: properties: status: allOf: - $ref: '#/definitions/consts.UserStatus' enum: - normal - disabled required: - status type: object gorm.DeletedAt: properties: time: type: string valid: description: Valid is true if Time is not NULL type: boolean type: object models.Content: properties: created_at: type: string deleted_at: $ref: '#/definitions/gorm.DeletedAt' description: type: string id: type: integer preview_downloadable: type: boolean preview_seconds: type: integer published_at: type: string status: $ref: '#/definitions/consts.ContentStatus' tenant_id: type: integer title: type: string updated_at: type: string user_id: type: integer visibility: $ref: '#/definitions/consts.ContentVisibility' type: object models.ContentAsset: properties: asset_id: type: integer content_id: type: integer created_at: type: string id: type: integer role: $ref: '#/definitions/consts.ContentAssetRole' sort: type: integer tenant_id: type: integer updated_at: type: string user_id: type: integer type: object models.ContentPrice: properties: content_id: type: integer created_at: type: string currency: $ref: '#/definitions/consts.Currency' discount_end_at: type: string discount_start_at: type: string discount_type: $ref: '#/definitions/consts.DiscountType' discount_value: type: integer id: type: integer price_amount: type: integer tenant_id: type: integer updated_at: type: string user_id: type: integer type: object models.MediaAsset: properties: bucket: type: string created_at: type: string deleted_at: $ref: '#/definitions/gorm.DeletedAt' id: type: integer meta: items: type: integer type: array object_key: type: string provider: type: string status: $ref: '#/definitions/consts.MediaAssetStatus' tenant_id: type: integer type: $ref: '#/definitions/consts.MediaAssetType' updated_at: type: string user_id: type: integer type: object models.Tenant: properties: code: type: string config: items: type: integer type: array created_at: type: string expired_at: type: string id: type: integer name: type: string status: $ref: '#/definitions/consts.TenantStatus' updated_at: type: string user_id: type: integer users: items: $ref: '#/definitions/models.User' type: array uuid: type: string type: object models.TenantUser: properties: balance: type: integer created_at: type: string id: type: integer role: items: $ref: '#/definitions/consts.TenantUserRole' type: array status: $ref: '#/definitions/consts.UserStatus' tenant_id: type: integer updated_at: type: string user_id: type: integer type: object models.User: properties: created_at: type: string deleted_at: $ref: '#/definitions/gorm.DeletedAt' id: type: integer metas: items: type: integer type: array owned: $ref: '#/definitions/models.Tenant' password: type: string roles: items: $ref: '#/definitions/consts.Role' type: array status: $ref: '#/definitions/consts.UserStatus' tenants: items: $ref: '#/definitions/models.Tenant' type: array updated_at: type: string username: type: string verified_at: type: string type: object requests.KV: properties: key: description: Key is a machine-readable value, usually an enum string. type: string value: description: Value is the label payload, often a human-readable string. type: object requests.Pager: properties: items: description: Items is the paged result list; concrete type depends on endpoint. limit: description: Limit is page size; only values in {10,20,50,100} are accepted (otherwise defaults to 10). type: integer page: description: Page is 1-based page index; values <= 0 are normalized to 1. type: integer total: description: Total is the total number of items matching current filter (before paging). type: integer type: object externalDocs: description: OpenAPI url: https://swagger.io/resources/open-api/ host: localhost:8080 info: contact: email: support@swagger.io name: UserName url: http://www.swagger.io/support description: Multi-tenant media platform backend API. license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html termsOfService: http://swagger.io/terms/ title: ApiDoc version: "1.0" paths: /super/v1/auth/login: post: consumes: - application/json parameters: - description: form in: body name: form required: true schema: $ref: '#/definitions/dto.LoginForm' produces: - application/json responses: "200": description: 成功 schema: $ref: '#/definitions/dto.LoginResponse' tags: - Super /super/v1/auth/token: get: consumes: - application/json produces: - application/json responses: "200": description: 成功 schema: $ref: '#/definitions/dto.LoginResponse' tags: - Super /super/v1/tenants: get: consumes: - application/json parameters: - description: Asc specifies comma-separated field names to sort ascending by. in: query name: asc type: string - description: Desc specifies comma-separated field names to sort descending by. in: query name: desc type: string - description: Limit is page size; only values in {10,20,50,100} are accepted (otherwise defaults to 10). in: query name: limit type: integer - in: query name: name type: string - description: Page is 1-based page index; values <= 0 are normalized to 1. in: query name: page type: integer - enum: - pending_verify - verified - banned in: query name: status type: string x-enum-varnames: - TenantStatusPendingVerify - TenantStatusVerified - TenantStatusBanned produces: - application/json responses: "200": description: OK schema: allOf: - $ref: '#/definitions/requests.Pager' - properties: items: $ref: '#/definitions/dto.TenantItem' type: object summary: 租户列表 tags: - Super /super/v1/tenants/{tenantID}: patch: consumes: - application/json parameters: - description: TenantID format: int64 in: path name: tenantID required: true type: integer - description: Form in: body name: form required: true schema: $ref: '#/definitions/dto.TenantExpireUpdateForm' produces: - application/json responses: {} summary: 更新过期时间 tags: - Super /super/v1/tenants/{tenantID}/status: patch: consumes: - application/json parameters: - description: TenantID format: int64 in: path name: tenantID required: true type: integer - description: Form in: body name: form required: true schema: $ref: '#/definitions/dto.TenantStatusUpdateForm' produces: - application/json responses: {} summary: 更新租户状态 tags: - Super /super/v1/tenants/statuses: get: consumes: - application/json produces: - application/json responses: "200": description: OK schema: items: $ref: '#/definitions/requests.KV' type: array summary: 租户状态列表 tags: - Super /super/v1/users: get: consumes: - application/json parameters: - description: Asc specifies comma-separated field names to sort ascending by. in: query name: asc type: string - description: Desc specifies comma-separated field names to sort descending by. in: query name: desc type: string - description: Limit is page size; only values in {10,20,50,100} are accepted (otherwise defaults to 10). in: query name: limit type: integer - description: Page is 1-based page index; values <= 0 are normalized to 1. in: query name: page type: integer - enum: - pending_verify - verified - banned in: query name: status type: string x-enum-varnames: - UserStatusPendingVerify - UserStatusVerified - UserStatusBanned - in: query name: tenantID type: integer - in: query name: username type: string produces: - application/json responses: "200": description: OK schema: allOf: - $ref: '#/definitions/requests.Pager' - properties: items: $ref: '#/definitions/dto.UserItem' type: object summary: 租户列表 tags: - Super /super/v1/users/{userID}/status: patch: consumes: - application/json parameters: - description: UserID format: int64 in: path name: userID required: true type: integer - description: Form in: body name: form required: true schema: $ref: '#/definitions/dto.UserStatusUpdateForm' produces: - application/json responses: {} summary: 更新用户状态 tags: - Super /super/v1/users/statistics: get: consumes: - application/json produces: - application/json responses: "200": description: OK schema: items: $ref: '#/definitions/dto.UserStatistics' type: array summary: 用户统计信息 tags: - Super /super/v1/users/statuses: get: consumes: - application/json produces: - application/json responses: "200": description: OK schema: items: $ref: '#/definitions/requests.KV' type: array summary: 用户状态列表 tags: - Super /t/{tenantCode}/v1/admin/contents: post: consumes: - application/json parameters: - description: Tenant Code in: path name: tenantCode required: true type: string - description: Form in: body name: form required: true schema: $ref: '#/definitions/dto.ContentCreateForm' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/models.Content' summary: 创建内容(草稿) tags: - Tenant /t/{tenantCode}/v1/admin/contents/{contentID}: patch: consumes: - application/json parameters: - description: Tenant Code in: path name: tenantCode required: true type: string - description: ContentID format: int64 in: path name: contentID required: true type: integer - description: Form in: body name: form required: true schema: $ref: '#/definitions/dto.ContentUpdateForm' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/models.Content' summary: 更新内容(标题/描述/状态等) tags: - Tenant /t/{tenantCode}/v1/admin/contents/{contentID}/assets: post: consumes: - application/json parameters: - description: Tenant Code in: path name: tenantCode required: true type: string - description: ContentID format: int64 in: path name: contentID required: true type: integer - description: Form in: body name: form required: true schema: $ref: '#/definitions/dto.ContentAssetAttachForm' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/models.ContentAsset' summary: 绑定媒体资源到内容(main/cover/preview) tags: - Tenant /t/{tenantCode}/v1/admin/contents/{contentID}/price: put: consumes: - application/json parameters: - description: Tenant Code in: path name: tenantCode required: true type: string - description: ContentID format: int64 in: path name: contentID required: true type: integer - description: Form in: body name: form required: true schema: $ref: '#/definitions/dto.ContentPriceUpsertForm' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/models.ContentPrice' summary: 设置内容价格与折扣 tags: - Tenant /t/{tenantCode}/v1/contents: get: consumes: - application/json parameters: - description: Tenant Code in: path name: tenantCode required: true type: string - description: Keyword filters by title keyword (LIKE). in: query name: keyword type: string - description: Limit is page size; only values in {10,20,50,100} are accepted (otherwise defaults to 10). in: query name: limit type: integer - description: Page is 1-based page index; values <= 0 are normalized to 1. in: query name: page type: integer produces: - application/json responses: "200": description: OK schema: allOf: - $ref: '#/definitions/requests.Pager' - properties: items: $ref: '#/definitions/dto.ContentItem' type: object summary: 内容列表(已发布) tags: - Tenant /t/{tenantCode}/v1/contents/{contentID}: get: consumes: - application/json parameters: - description: Tenant Code in: path name: tenantCode required: true type: string - description: ContentID format: int64 in: path name: contentID required: true type: integer produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/dto.ContentDetail' summary: 内容详情(可见性+权益校验) tags: - Tenant /t/{tenantCode}/v1/contents/{contentID}/assets: get: consumes: - application/json parameters: - description: Tenant Code in: path name: tenantCode required: true type: string - description: ContentID format: int64 in: path name: contentID required: true type: integer produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/dto.ContentAssetsResponse' summary: 获取正片资源(main role,需要已购或免费) tags: - Tenant /t/{tenantCode}/v1/contents/{contentID}/preview: get: consumes: - application/json parameters: - description: Tenant Code in: path name: tenantCode required: true type: string - description: ContentID format: int64 in: path name: contentID required: true type: integer produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/dto.ContentAssetsResponse' summary: 获取试看资源(preview role) tags: - Tenant /t/{tenantCode}/v1/me: get: consumes: - application/json parameters: - description: Tenant Code in: path name: tenantCode required: true type: string produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/dto.MeResponse' summary: 当前租户上下文信息 tags: - Tenant securityDefinitions: BasicAuth: type: basic swagger: "2.0"