using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using MiAssessment.Admin.Business.Data; using MiAssessment.Admin.Business.Entities; using MiAssessment.Admin.Business.Models; using MiAssessment.Admin.Business.Models.Common; using MiAssessment.Admin.Business.Models.Content; using MiAssessment.Admin.Business.Services.Interfaces; namespace MiAssessment.Admin.Business.Services; /// /// 内容管理服务实现 /// public class ContentService : IContentService { private readonly AdminBusinessDbContext _dbContext; private readonly ILogger _logger; /// /// 跳转类型名称映射 /// private static readonly Dictionary LinkTypeNames = new() { { 0, "无" }, { 1, "内部页面" }, { 2, "外部链接" }, { 3, "小程序" } }; /// /// 状态名称映射 /// private static readonly Dictionary StatusNames = new() { { 0, "禁用" }, { 1, "启用" } }; /// /// 宣传图位置名称映射 /// private static readonly Dictionary PositionNames = new() { { 1, "首页底部" }, { 2, "团队页" } }; /// /// 构造函数 /// /// 数据库上下文 /// 日志记录器 public ContentService( AdminBusinessDbContext dbContext, ILogger logger) { _dbContext = dbContext; _logger = logger; } #region Banner 轮播图操作 /// public async Task> GetBannerListAsync(BannerQueryRequest request) { // 构建查询,过滤软删除记录 var query = _dbContext.Banners .AsNoTracking() .Where(b => !b.IsDeleted); // 状态筛选 if (request.Status.HasValue) { query = query.Where(b => b.Status == request.Status.Value); } // 获取总数 var total = await query.CountAsync(); // 分页查询,按 Sort 降序排列 var items = await query .OrderByDescending(b => b.Sort) .ThenByDescending(b => b.CreateTime) .Skip(request.Skip) .Take(request.PageSize) .Select(b => new BannerDto { Id = b.Id, Title = b.Title, ImageUrl = b.ImageUrl, LinkType = b.LinkType, LinkTypeName = GetLinkTypeName(b.LinkType), LinkUrl = b.LinkUrl, AppId = b.AppId, Sort = b.Sort, Status = b.Status, StatusName = GetStatusName(b.Status), CreateTime = b.CreateTime }) .ToListAsync(); return PagedResult.Create(items, total, request.Page, request.PageSize); } /// public async Task GetBannerByIdAsync(long id) { var banner = await _dbContext.Banners .AsNoTracking() .Where(b => b.Id == id && !b.IsDeleted) .Select(b => new BannerDto { Id = b.Id, Title = b.Title, ImageUrl = b.ImageUrl, LinkType = b.LinkType, LinkTypeName = GetLinkTypeName(b.LinkType), LinkUrl = b.LinkUrl, AppId = b.AppId, Sort = b.Sort, Status = b.Status, StatusName = GetStatusName(b.Status), CreateTime = b.CreateTime }) .FirstOrDefaultAsync(); if (banner == null) { throw new BusinessException(ErrorCodes.BannerNotFound, "轮播图不存在"); } return banner; } /// public async Task CreateBannerAsync(CreateBannerRequest request) { // 验证图片URL必填 if (string.IsNullOrWhiteSpace(request.ImageUrl)) { throw new BusinessException(ErrorCodes.BannerImageRequired, "图片URL不能为空"); } // 验证 LinkType 和对应字段 ValidateLinkType(request.LinkType, request.LinkUrl, request.AppId); // 创建实体 var banner = new Banner { Title = request.Title, ImageUrl = request.ImageUrl, LinkType = request.LinkType, LinkUrl = request.LinkUrl, AppId = request.AppId, Sort = request.Sort, Status = request.Status, CreateTime = DateTime.Now, UpdateTime = DateTime.Now, IsDeleted = false }; _dbContext.Banners.Add(banner); await _dbContext.SaveChangesAsync(); _logger.LogInformation("创建轮播图成功,ID: {BannerId}, 标题: {Title}", banner.Id, banner.Title); return banner.Id; } /// public async Task UpdateBannerAsync(UpdateBannerRequest request) { // 查找轮播图 var banner = await _dbContext.Banners .Where(b => b.Id == request.Id && !b.IsDeleted) .FirstOrDefaultAsync(); if (banner == null) { throw new BusinessException(ErrorCodes.BannerNotFound, "轮播图不存在"); } // 验证图片URL必填 if (string.IsNullOrWhiteSpace(request.ImageUrl)) { throw new BusinessException(ErrorCodes.BannerImageRequired, "图片URL不能为空"); } // 验证 LinkType 和对应字段 ValidateLinkType(request.LinkType, request.LinkUrl, request.AppId); // 更新字段 banner.Title = request.Title; banner.ImageUrl = request.ImageUrl; banner.LinkType = request.LinkType; banner.LinkUrl = request.LinkUrl; banner.AppId = request.AppId; banner.Sort = request.Sort; banner.Status = request.Status; banner.UpdateTime = DateTime.Now; await _dbContext.SaveChangesAsync(); _logger.LogInformation("更新轮播图成功,ID: {BannerId}", banner.Id); return true; } /// public async Task DeleteBannerAsync(long id) { // 查找轮播图 var banner = await _dbContext.Banners .Where(b => b.Id == id && !b.IsDeleted) .FirstOrDefaultAsync(); if (banner == null) { throw new BusinessException(ErrorCodes.BannerNotFound, "轮播图不存在"); } // 软删除 banner.IsDeleted = true; banner.UpdateTime = DateTime.Now; await _dbContext.SaveChangesAsync(); _logger.LogInformation("删除轮播图成功,ID: {BannerId}", id); return true; } /// public async Task UpdateBannerStatusAsync(long id, int status) { // 查找轮播图 var banner = await _dbContext.Banners .Where(b => b.Id == id && !b.IsDeleted) .FirstOrDefaultAsync(); if (banner == null) { throw new BusinessException(ErrorCodes.BannerNotFound, "轮播图不存在"); } // 更新状态 banner.Status = status; banner.UpdateTime = DateTime.Now; await _dbContext.SaveChangesAsync(); _logger.LogInformation("更新轮播图状态成功,ID: {BannerId}, 状态: {Status}", id, status); return true; } /// public async Task UpdateBannerSortAsync(List items) { if (items == null || items.Count == 0) { return true; } // 获取所有需要更新的轮播图ID var ids = items.Select(i => i.Id).ToList(); // 批量查询轮播图 var banners = await _dbContext.Banners .Where(b => ids.Contains(b.Id) && !b.IsDeleted) .ToListAsync(); // 更新排序 foreach (var item in items) { var banner = banners.FirstOrDefault(b => b.Id == item.Id); if (banner != null) { banner.Sort = item.Sort; banner.UpdateTime = DateTime.Now; } } await _dbContext.SaveChangesAsync(); _logger.LogInformation("批量更新轮播图排序成功,更新数量: {Count}", items.Count); return true; } #endregion #region Promotion 宣传图操作 /// public async Task> GetPromotionListAsync(PromotionQueryRequest request) { // 构建查询,过滤软删除记录 var query = _dbContext.Promotions .AsNoTracking() .Where(p => !p.IsDeleted); // 位置筛选 if (request.Position.HasValue) { query = query.Where(p => p.Position == request.Position.Value); } // 状态筛选 if (request.Status.HasValue) { query = query.Where(p => p.Status == request.Status.Value); } // 获取总数 var total = await query.CountAsync(); // 分页查询,按 Sort 降序排列 var items = await query .OrderByDescending(p => p.Sort) .ThenByDescending(p => p.CreateTime) .Skip(request.Skip) .Take(request.PageSize) .Select(p => new PromotionDto { Id = p.Id, Title = p.Title, ImageUrl = p.ImageUrl, Position = p.Position, PositionName = GetPositionName(p.Position), Sort = p.Sort, Status = p.Status, StatusName = GetStatusName(p.Status), CreateTime = p.CreateTime }) .ToListAsync(); return PagedResult.Create(items, total, request.Page, request.PageSize); } /// public async Task GetPromotionByIdAsync(long id) { var promotion = await _dbContext.Promotions .AsNoTracking() .Where(p => p.Id == id && !p.IsDeleted) .Select(p => new PromotionDto { Id = p.Id, Title = p.Title, ImageUrl = p.ImageUrl, Position = p.Position, PositionName = GetPositionName(p.Position), Sort = p.Sort, Status = p.Status, StatusName = GetStatusName(p.Status), CreateTime = p.CreateTime }) .FirstOrDefaultAsync(); if (promotion == null) { throw new BusinessException(ErrorCodes.PromotionNotFound, "宣传图不存在"); } return promotion; } /// public async Task CreatePromotionAsync(CreatePromotionRequest request) { // 验证图片URL必填 if (string.IsNullOrWhiteSpace(request.ImageUrl)) { throw new BusinessException(ErrorCodes.PromotionImageRequired, "图片URL不能为空"); } // 验证 Position 值 ValidatePosition(request.Position); // 创建实体 var promotion = new Promotion { Title = request.Title, ImageUrl = request.ImageUrl, Position = request.Position, Sort = request.Sort, Status = request.Status, CreateTime = DateTime.Now, UpdateTime = DateTime.Now, IsDeleted = false }; _dbContext.Promotions.Add(promotion); await _dbContext.SaveChangesAsync(); _logger.LogInformation("创建宣传图成功,ID: {PromotionId}, 标题: {Title}, 位置: {Position}", promotion.Id, promotion.Title, promotion.Position); return promotion.Id; } /// public async Task UpdatePromotionAsync(UpdatePromotionRequest request) { // 查找宣传图 var promotion = await _dbContext.Promotions .Where(p => p.Id == request.Id && !p.IsDeleted) .FirstOrDefaultAsync(); if (promotion == null) { throw new BusinessException(ErrorCodes.PromotionNotFound, "宣传图不存在"); } // 验证图片URL必填 if (string.IsNullOrWhiteSpace(request.ImageUrl)) { throw new BusinessException(ErrorCodes.PromotionImageRequired, "图片URL不能为空"); } // 验证 Position 值 ValidatePosition(request.Position); // 更新字段 promotion.Title = request.Title; promotion.ImageUrl = request.ImageUrl; promotion.Position = request.Position; promotion.Sort = request.Sort; promotion.Status = request.Status; promotion.UpdateTime = DateTime.Now; await _dbContext.SaveChangesAsync(); _logger.LogInformation("更新宣传图成功,ID: {PromotionId}", promotion.Id); return true; } /// public async Task DeletePromotionAsync(long id) { // 查找宣传图 var promotion = await _dbContext.Promotions .Where(p => p.Id == id && !p.IsDeleted) .FirstOrDefaultAsync(); if (promotion == null) { throw new BusinessException(ErrorCodes.PromotionNotFound, "宣传图不存在"); } // 软删除 promotion.IsDeleted = true; promotion.UpdateTime = DateTime.Now; await _dbContext.SaveChangesAsync(); _logger.LogInformation("删除宣传图成功,ID: {PromotionId}", id); return true; } /// public async Task UpdatePromotionStatusAsync(long id, int status) { // 查找宣传图 var promotion = await _dbContext.Promotions .Where(p => p.Id == id && !p.IsDeleted) .FirstOrDefaultAsync(); if (promotion == null) { throw new BusinessException(ErrorCodes.PromotionNotFound, "宣传图不存在"); } // 更新状态 promotion.Status = status; promotion.UpdateTime = DateTime.Now; await _dbContext.SaveChangesAsync(); _logger.LogInformation("更新宣传图状态成功,ID: {PromotionId}, 状态: {Status}", id, status); return true; } #endregion #region 私有方法 /// /// 验证 LinkType 和对应字段 /// /// 跳转类型 /// 跳转地址 /// 小程序AppId private void ValidateLinkType(int linkType, string? linkUrl, string? appId) { switch (linkType) { case 0: // 无跳转,不需要验证 break; case 1: case 2: // 内部页面或外部链接,LinkUrl 必填 if (string.IsNullOrWhiteSpace(linkUrl)) { throw new BusinessException(ErrorCodes.BannerLinkUrlRequired, "跳转地址不能为空"); } break; case 3: // 小程序,LinkUrl 和 AppId 都必填 if (string.IsNullOrWhiteSpace(linkUrl)) { throw new BusinessException(ErrorCodes.BannerLinkUrlRequired, "跳转地址不能为空"); } if (string.IsNullOrWhiteSpace(appId)) { throw new BusinessException(ErrorCodes.BannerLinkUrlRequired, "小程序AppId不能为空"); } break; } } /// /// 获取跳转类型名称 /// /// 跳转类型 /// 类型名称 private static string GetLinkTypeName(int linkType) { return LinkTypeNames.TryGetValue(linkType, out var name) ? name : "未知"; } /// /// 获取状态名称 /// /// 状态值 /// 状态名称 private static string GetStatusName(int status) { return StatusNames.TryGetValue(status, out var name) ? name : "未知"; } /// /// 获取位置名称 /// /// 位置值 /// 位置名称 private static string GetPositionName(int position) { return PositionNames.TryGetValue(position, out var name) ? name : "未知"; } /// /// 验证 Position 值 /// /// 位置值 private void ValidatePosition(int position) { if (position != 1 && position != 2) { throw new BusinessException(ErrorCodes.ParamError, "位置值必须为1(首页底部)或2(团队页)"); } } #endregion }