using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using DotNext; namespace server.Controllers; /// /// 实验控制器 /// [ApiController] [Route("api/[controller]")] public class ExamController : ControllerBase { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 实验信息类 /// public class ExamInfo { /// /// 实验的唯一标识符 /// public required string ID { get; set; } /// /// 实验名称 /// public required string Name { get; set; } /// /// 实验描述 /// public required string Description { get; set; } /// /// 实验创建时间 /// public DateTime CreatedTime { get; set; } /// /// 实验最后更新时间 /// public DateTime UpdatedTime { get; set; } /// /// 实验标签 /// public string[] Tags { get; set; } = Array.Empty(); /// /// 实验难度(1-5) /// public int Difficulty { get; set; } = 1; /// /// 普通用户是否可见 /// public bool IsVisibleToUsers { get; set; } = true; } /// /// 实验简要信息类(用于列表显示) /// public class ExamSummary { /// /// 实验的唯一标识符 /// public required string ID { get; set; } /// /// 实验名称 /// public required string Name { get; set; } /// /// 实验创建时间 /// public DateTime CreatedTime { get; set; } /// /// 实验最后更新时间 /// public DateTime UpdatedTime { get; set; } /// /// 实验标签 /// public string[] Tags { get; set; } = Array.Empty(); /// /// 实验难度(1-5) /// public int Difficulty { get; set; } = 1; /// /// 普通用户是否可见 /// public bool IsVisibleToUsers { get; set; } = true; } /// /// 创建实验请求类 /// public class CreateExamRequest { /// /// 实验ID /// public required string ID { get; set; } /// /// 实验名称 /// public required string Name { get; set; } /// /// 实验描述 /// public required string Description { get; set; } /// /// 实验标签 /// public string[] Tags { get; set; } = Array.Empty(); /// /// 实验难度(1-5) /// public int Difficulty { get; set; } = 1; /// /// 普通用户是否可见 /// public bool IsVisibleToUsers { get; set; } = true; } /// /// 获取所有实验列表 /// /// 实验列表 [Authorize] [HttpGet("list")] [EnableCors("Users")] [ProducesResponseType(typeof(ExamSummary[]), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult GetExamList() { try { using var db = new Database.AppDataConnection(); var exams = db.GetAllExams(); var examSummaries = exams.Select(exam => new ExamSummary { ID = exam.ID, Name = exam.Name, CreatedTime = exam.CreatedTime, UpdatedTime = exam.UpdatedTime, Tags = exam.GetTagsList(), Difficulty = exam.Difficulty, IsVisibleToUsers = exam.IsVisibleToUsers }).ToArray(); logger.Info($"成功获取实验列表,共 {examSummaries.Length} 个实验"); return Ok(examSummaries); } catch (Exception ex) { logger.Error($"获取实验列表时出错: {ex.Message}"); return StatusCode(StatusCodes.Status500InternalServerError, $"获取实验列表失败: {ex.Message}"); } } /// /// 根据实验ID获取实验详细信息 /// /// 实验ID /// 实验详细信息 [Authorize] [HttpGet("{examId}")] [EnableCors("Users")] [ProducesResponseType(typeof(ExamInfo), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult GetExam(string examId) { if (string.IsNullOrWhiteSpace(examId)) return BadRequest("实验ID不能为空"); try { using var db = new Database.AppDataConnection(); var result = db.GetExamByID(examId); if (!result.IsSuccessful) { logger.Error($"获取实验时出错: {result.Error.Message}"); return StatusCode(StatusCodes.Status500InternalServerError, $"获取实验失败: {result.Error.Message}"); } if (!result.Value.HasValue) { logger.Warn($"实验不存在: {examId}"); return NotFound($"实验 {examId} 不存在"); } var exam = result.Value.Value; var examInfo = new ExamInfo { ID = exam.ID, Name = exam.Name, Description = exam.Description, CreatedTime = exam.CreatedTime, UpdatedTime = exam.UpdatedTime, Tags = exam.GetTagsList(), Difficulty = exam.Difficulty, IsVisibleToUsers = exam.IsVisibleToUsers }; logger.Info($"成功获取实验信息: {examId}"); return Ok(examInfo); } catch (Exception ex) { logger.Error($"获取实验 {examId} 时出错: {ex.Message}"); return StatusCode(StatusCodes.Status500InternalServerError, $"获取实验失败: {ex.Message}"); } } /// /// 创建新实验 /// /// 创建实验请求 /// 创建结果 [Authorize("Admin")] [HttpPost] [EnableCors("Users")] [ProducesResponseType(typeof(ExamInfo), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status409Conflict)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult CreateExam([FromBody] CreateExamRequest request) { if (string.IsNullOrWhiteSpace(request.ID) || string.IsNullOrWhiteSpace(request.Name) || string.IsNullOrWhiteSpace(request.Description)) return BadRequest("实验ID、名称和描述不能为空"); try { using var db = new Database.AppDataConnection(); var result = db.CreateExam(request.ID, request.Name, request.Description, request.Tags, request.Difficulty, request.IsVisibleToUsers); if (!result.IsSuccessful) { if (result.Error.Message.Contains("已存在")) return Conflict(result.Error.Message); logger.Error($"创建实验时出错: {result.Error.Message}"); return StatusCode(StatusCodes.Status500InternalServerError, $"创建实验失败: {result.Error.Message}"); } var exam = result.Value; var examInfo = new ExamInfo { ID = exam.ID, Name = exam.Name, Description = exam.Description, CreatedTime = exam.CreatedTime, UpdatedTime = exam.UpdatedTime, Tags = exam.GetTagsList(), Difficulty = exam.Difficulty, IsVisibleToUsers = exam.IsVisibleToUsers }; logger.Info($"成功创建实验: {request.ID}"); return CreatedAtAction(nameof(GetExam), new { examId = request.ID }, examInfo); } catch (Exception ex) { logger.Error($"创建实验 {request.ID} 时出错: {ex.Message}"); return StatusCode(StatusCodes.Status500InternalServerError, $"创建实验失败: {ex.Message}"); } } }