using System.Security.Claims; using AgriculturalPlatform.Api.Data; using AgriculturalPlatform.Api.Dtos; using AgriculturalPlatform.Api.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace AgriculturalPlatform.Api.Controllers; /// 通知公告 [ApiController] [Route("api/announcements")] [Authorize] public class AnnouncementsController(AppDbContext db) : ControllerBase { private int UserId => int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? "0"); /// 我的公告列表(含已读状态、未读数) [HttpGet("my")] public async Task My([FromQuery] int page = 1, [FromQuery] int pageSize = 10) { var uid = UserId; var query = db.Announcements.AsNoTracking(); // 范围过滤:空范围=全员可见;含本人组织 var orgId = await db.Users.Where(u => u.Id == uid).Select(u => u.OrgId).FirstOrDefaultAsync(); var queryFiltered = query.Where(a => a.ScopeOrgIds == "" || (orgId != null && a.ScopeOrgIds.Split(',', StringSplitOptions.RemoveEmptyEntries).Contains(orgId.ToString()))); var total = await queryFiltered.CountAsync(); var items = await queryFiltered.OrderByDescending(a => a.IsPinned).ThenByDescending(a => a.PublishedAt) .Skip((page - 1) * pageSize).Take(pageSize) .Select(a => new { a.Id, a.Title, a.Content, a.Type, a.ScopeOrgIds, a.IsPinned, PublisherName = a.Publisher != null ? a.Publisher.RealName : "", a.PublishedAt, a.CreatedAt, IsRead = db.AnnouncementReads.Any(r => r.AnnouncementId == a.Id && r.UserId == uid) }) .ToListAsync(); var unread = await queryFiltered .CountAsync(a => !db.AnnouncementReads.Any(r => r.AnnouncementId == a.Id && r.UserId == uid)); return Ok(new { items, total, unread }); } /// 未读公告数(顶栏徽标) [HttpGet("unread-count")] public async Task UnreadCount() { var uid = UserId; var orgId = await db.Users.Where(u => u.Id == uid).Select(u => u.OrgId).FirstOrDefaultAsync(); var count = await db.Announcements.CountAsync(a => (a.ScopeOrgIds == "" || (orgId != null && a.ScopeOrgIds.Split(',', StringSplitOptions.RemoveEmptyEntries).Contains(orgId.ToString()))) && !db.AnnouncementReads.Any(r => r.AnnouncementId == a.Id && r.UserId == uid)); return Ok(new { count }); } /// 公告详情(标记已读) [HttpGet("{id:int}")] public async Task Get(int id) { var uid = UserId; var a = await db.Announcements.Include(x => x.Publisher).FirstOrDefaultAsync(x => x.Id == id); if (a is null) return NotFound(); // 标记已读 if (!await db.AnnouncementReads.AnyAsync(r => r.AnnouncementId == id && r.UserId == uid)) { db.AnnouncementReads.Add(new AnnouncementRead { AnnouncementId = id, UserId = uid, ReadAt = DateTime.Now }); await db.SaveChangesAsync(); } var dto = new AnnouncementDto(a.Id, a.Title, a.Content, a.Type, a.ScopeOrgIds, a.IsPinned, a.Publisher?.RealName ?? "", a.PublishedAt, a.CreatedAt, true); return Ok(dto); } /// 全部公告(管理端) [HttpGet] public async Task>> List(string? keyword, string? type, [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { var uid = UserId; var query = db.Announcements.AsNoTracking(); if (!string.IsNullOrWhiteSpace(keyword)) query = query.Where(a => a.Title.Contains(keyword) || a.Content.Contains(keyword)); if (!string.IsNullOrWhiteSpace(type)) query = query.Where(a => a.Type == type); var total = await query.CountAsync(); var items = await query.OrderByDescending(a => a.PublishedAt) .Skip((page - 1) * pageSize).Take(pageSize) .Select(a => new AnnouncementDto( a.Id, a.Title, a.Content, a.Type, a.ScopeOrgIds, a.IsPinned, a.Publisher != null ? a.Publisher.RealName : "", a.PublishedAt, a.CreatedAt, db.AnnouncementReads.Any(r => r.AnnouncementId == a.Id && r.UserId == uid))) .ToListAsync(); return Ok(new PagedResult(items, total)); } /// 发布公告 [HttpPost] public async Task Create(AnnouncementSaveRequest req) { if (string.IsNullOrWhiteSpace(req.Title)) return BadRequest(new { message = "标题不能为空" }); var a = new Announcement { Title = req.Title, Content = req.Content ?? "", Type = req.Type, ScopeOrgIds = req.ScopeOrgIds ?? "", IsPinned = req.IsPinned, PublisherId = UserId, PublishedAt = DateTime.Now, CreatedAt = DateTime.Now }; db.Announcements.Add(a); await db.SaveChangesAsync(); return Ok(new { message = "发布成功", id = a.Id }); } /// 修改公告 [HttpPut("{id:int}")] public async Task Update(int id, AnnouncementSaveRequest req) { var a = await db.Announcements.FindAsync(id); if (a is null) return NotFound(); a.Title = req.Title; a.Content = req.Content ?? ""; a.Type = req.Type; a.ScopeOrgIds = req.ScopeOrgIds ?? ""; a.IsPinned = req.IsPinned; await db.SaveChangesAsync(); return Ok(new { message = "保存成功" }); } /// 删除公告 [HttpDelete("{id:int}")] public async Task Delete(int id) { var a = await db.Announcements.FindAsync(id); if (a is null) return NotFound(); db.Announcements.Remove(a); await db.SaveChangesAsync(); return Ok(new { message = "删除成功" }); } }