using Blahblah.FlowerStory.Server.Data; using Blahblah.FlowerStory.Server.Data.Model; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations; namespace Blahblah.FlowerStory.Server.Controller; /// /// 评论相关 API 服务 /// [ApiController] [Produces("application/json")] [Route("api/comment")] public class CommentApiController(FlowerDatabase database, ILogger? logger = null) : BaseController(database, logger) { static readonly int?[] specialTypes = [1, 2, 3]; /// /// 获取符合条件的评论 /// /// /// 请求示例: /// /// GET /api/comment/query /// Authorization: authorization id /// /// 参数: /// /// rid: int /// t: int? /// from: long? /// to: long? /// size: int? /// /// /// 事件唯一 id /// 评论类型 id /// 起始日期 /// 结束日期 /// 分页大小 /// 会话有效则返回符合条件的评论集 /// 返回符合条件的评论集 /// 未找到登录会话或已过期 /// 用户已禁用 /// 未找到关联用户 [Route("query", Name = "queryComments")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesErrorResponseType(typeof(ErrorResponse))] [HttpGet] [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] public ActionResult GetComments( [FromQuery(Name = "rid")][Required] int recordId, [FromQuery(Name = "t")] int? typeId, [FromQuery] long? from, [FromQuery] long? to, [FromQuery(Name = "size")] int? pageSize = 20) { var (result, user) = CheckPermission(); if (result != null) { return result; } if (user == null) { return NotFound(); } SaveDatabase(); var comments = database.Comments.Where(c => c.RecordId == recordId); if (typeId == null) { comments = comments.Where(c => !specialTypes.Contains(c.CommentCategoryId)); } else { comments = comments.Where(c => c.CommentCategoryId == typeId); } if (from != null) { comments = comments.Where(r => r.DateUnixTime >= from); } if (to != null) { comments = comments.Where(r => r.DateUnixTime <= to); } comments = comments.Select(r => new CommentItem { Id = r.Id, RecordId = r.RecordId, CommentCategoryId = r.CommentCategoryId, OwnerId = r.OwnerId, ByUserId = r.ByUserId, DateUnixTime = r.DateUnixTime, Latitude = r.Latitude, Longitude = r.Longitude, Text = r.Text, ByUserName = string.IsNullOrEmpty(r.ByUserName) && r.ByUserId != null ? database.Users.Single(u => u.Id == r.ByUserId).Name : r.ByUserName }); var size = pageSize ?? 20; comments = comments.OrderByDescending(r => r.DateUnixTime).Take(size); var array = comments.ToArray(); foreach (var r in array) { if (string.IsNullOrEmpty(r.ByUserName)) { r.ByUserName = user.Name; } } return Ok(array); } /// /// 移除用户的评论 /// /// /// 请求示例: /// /// DELETE /api/comment/remove /// Authorization: authorization id /// /// 参数: /// /// id: int /// /// /// 评论唯一 id /// 会话有效则返回操作影响的数据库行数 /// 返回操作影响的数据库行数 /// 未找到登录会话或已过期 /// 用户已禁用 /// 未找到关联用户 [Route("remove", Name = "removeComment")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesErrorResponseType(typeof(ErrorResponse))] [HttpDelete] public ActionResult RemoveComment([FromQuery][Required] int id) { var (result, user) = CheckPermission(); if (result != null) { return result; } if (user == null) { return NotFound(); } var records = database.Records.Where(r => database.Comments.Any(c => c.OwnerId == user.Id && c.Id == id && c.RecordId == r.Id)).ToList(); var count = database.Comments.Where(c => c.OwnerId == user.Id && c.Id == id).ExecuteDelete(); if (count > 0) { foreach (var r in records) { r.LikeCount = database.Comments.Count(c => c.CommentCategoryId == 1 && c.RecordId == r.Id); r.FavoriteCount = database.Comments.Count(c => c.CommentCategoryId == 2 && c.RecordId == r.Id); r.CommentCount = database.Comments.Count(c => !specialTypes.Contains(c.CommentCategoryId) && c.RecordId == r.Id); } } SaveDatabase(); return Ok(count); } /// /// 用户添加评论 /// /// /// 请求示例: /// /// POST /api/comment/add /// Authorization: authorization id /// /// 参数: /// /// recordId: 1 /// typeId: 0 /// text: "这朵花好漂亮" /// byUser: "来宾" /// lon: 29.5462794 /// lat: 106.5380034 /// /// /// 评论参数 /// 添加成功则返回已添加的评论对象 /// 返回已添加的评论对象 /// 未找到登录会话或已过期 /// 用户已禁用 /// 未找到关联用户 [Route("add", Name = "addComment")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesErrorResponseType(typeof(ErrorResponse))] [HttpPost] public ActionResult AddEvent([FromBody] CommentParameter comment) { var (result, user) = CheckPermission(); if (result != null) { return result; } if (user == null) { return NotFound(); } var now = user.ActiveDateUnixTime ?? DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); var item = new CommentItem { RecordId = comment.RecordId, OwnerId = user.Id, CommentCategoryId = comment.TypeId, DateUnixTime = now, ByUserId = comment.ByUser == null ? user.Id : null, ByUserName = comment.ByUser, Text = comment.Text, Latitude = comment.Latitude, Longitude = comment.Longitude }; database.Comments.Add(item); var record = database.Records.SingleOrDefault(r => r.Id == comment.RecordId); if (record != null) { switch (comment.TypeId) { case 1: record.LikeCount = (record.LikeCount ?? 0) + 1; break; case 2: record.FavoriteCount = (record.FavoriteCount ?? 0) + 1; break; case not 3: record.CommentCount = (record.CommentCount ?? 0) + 1; break; } } SaveDatabase(); return Ok(item); } }