using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Tiku.Api.Contracts; using Tiku.Api.Security; using Tiku.Application.Learning; using Tiku.Application.Security; namespace Tiku.Api.Controllers; [ApiController] [Tags("学生端-学习")] [Authorize(Policy = TikuPolicies.CurrentTenantMember)] [RequireSaasFeature(SaasFeatureCatalog.Practice)] [Produces("application/json")] [Route("api/student/learning")] public sealed class WordLearningController( IWordLearningService service, LearningActorResolver actorResolver) : ControllerBase { [HttpGet("vocabulary/progress")] [EndpointSummary("查询单词学习进度")] [ProducesResponseType>(StatusCodes.Status200OK)] public async Task>> GetWordProgress( [FromQuery] LearningLimitQueryDto query, CancellationToken cancellationToken) { return Ok(await service.GetWordProgressAsync( actorResolver.Resolve(), query.ToFilter(), cancellationToken)); } [HttpGet("vocabulary/review-plan")] [EndpointSummary("生成单词复习计划")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetWordReviewPlan( [FromQuery] LearningLimitQueryDto query, CancellationToken cancellationToken) { return Ok(await service.GetWordReviewPlanAsync( actorResolver.Resolve(), query.ToFilter(), cancellationToken)); } [HttpPost("vocabulary/progress")] [EndpointSummary("更新单词学习进度")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> UpdateWordProgress( WordProgressDto request, CancellationToken cancellationToken) { return Ok(await service.UpdateWordProgressAsync( actorResolver.Resolve(), request.ToCommand(), cancellationToken)); } [HttpPost("vocabulary/review")] [EndpointSummary("提交单词复习结果")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> ReviewWord( WordReviewDto request, CancellationToken cancellationToken) { return Ok(await service.ReviewWordAsync( actorResolver.Resolve(), request.ToCommand(), cancellationToken)); } [HttpGet("vocabulary/stats")] [EndpointSummary("查询单词学习统计")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetWordStats( [FromQuery] LearningLimitQueryDto query, CancellationToken cancellationToken) { return Ok(await service.GetWordStatsAsync( actorResolver.Resolve(), query.ToFilter(), cancellationToken)); } [HttpGet("vocabulary/favorites")] [EndpointSummary("查询收藏单词")] [ProducesResponseType>(StatusCodes.Status200OK)] public async Task>> GetFavoriteWords( [FromQuery] LearningLimitQueryDto query, CancellationToken cancellationToken) { return Ok(await service.GetFavoriteWordsAsync( actorResolver.Resolve(), query.ToFilter(), cancellationToken)); } [HttpPost("vocabulary/favorites")] [EndpointSummary("收藏或取消收藏单词")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> ToggleFavoriteWord( FavoriteWordDto request, CancellationToken cancellationToken) { return Ok(await service.ToggleFavoriteWordAsync( actorResolver.Resolve(), request.ToCommand(), cancellationToken)); } }