using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Tiku.Api.Contracts; using Tiku.Api.Security; using Tiku.Application.Assets; using Tiku.Application.Catalog; using Tiku.Application.Security; namespace Tiku.Api.Controllers; [ApiController] [Tags("学生端-视频")] [Authorize(Policy = TikuPolicies.CurrentTenantMember)] [RequireSaasFeature(SaasFeatureCatalog.Video)] [Produces("application/json")] [Route("api/student/videos")] public sealed class VideosController( IVideoPlaybackService videoPlaybackService, ICurrentUser currentUser, ITenantContext currentTenant) : ControllerBase { [HttpGet("search")] [EndpointSummary("搜索通用解析视频")] [ProducesResponseType>(StatusCodes.Status200OK)] public async Task>> Search( [FromQuery] VideoSearchQueryDto query, CancellationToken cancellationToken) { return Ok(await videoPlaybackService.SearchAsync(ResolveActor(), query.ToQuery(), cancellationToken)); } [HttpPost("play")] [EndpointSummary("申请视频播放信息")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> Play( VideoPlayDto request, CancellationToken cancellationToken) { return Ok(await videoPlaybackService.PlayAsync(ResolveActor(), request.ToCommand(), cancellationToken)); } [HttpPost("progress")] [EndpointSummary("上报视频播放进度")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> Progress( VideoProgressDto request, CancellationToken cancellationToken) { return Ok( await videoPlaybackService.ReportProgressAsync(ResolveActor(), request.ToCommand(), cancellationToken)); } private VideoPlaybackActor ResolveActor() { if (currentTenant.TenantId is null || currentUser.UserId is null) throw new VideoPlaybackException("Current video actor was not resolved.", "video_access_denied"); return new VideoPlaybackActor(currentTenant.TenantId.Value, currentUser.UserId.Value); } }