343 lines
12 KiB
C#
343 lines
12 KiB
C#
using MiAssessment.Admin.Business.Data;
|
||
using MiAssessment.Admin.Business.Entities;
|
||
using MiAssessment.Admin.Business.Models;
|
||
using MiAssessment.Admin.Business.Models.BusinessPage;
|
||
using MiAssessment.Admin.Business.Models.Common;
|
||
using MiAssessment.Admin.Business.Services.Interfaces;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Logging;
|
||
|
||
namespace MiAssessment.Admin.Business.Services;
|
||
|
||
/// <summary>
|
||
/// 业务介绍页服务实现
|
||
/// </summary>
|
||
public class BusinessPageService : IBusinessPageService
|
||
{
|
||
private readonly AdminBusinessDbContext _dbContext;
|
||
private readonly ILogger<BusinessPageService> _logger;
|
||
|
||
/// <summary>
|
||
/// 状态名称映射
|
||
/// </summary>
|
||
private static readonly Dictionary<int, string> StatusNames = new()
|
||
{
|
||
{ 0, "禁用" },
|
||
{ 1, "启用" }
|
||
};
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
/// <param name="dbContext">数据库上下文</param>
|
||
/// <param name="logger">日志记录器</param>
|
||
public BusinessPageService(
|
||
AdminBusinessDbContext dbContext,
|
||
ILogger<BusinessPageService> logger)
|
||
{
|
||
_dbContext = dbContext;
|
||
_logger = logger;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<PagedResult<BusinessPageDto>> GetPageListAsync(BusinessPageQueryRequest request)
|
||
{
|
||
// 构建查询,过滤软删除记录,使用 AsNoTracking 提高只读查询性能
|
||
var query = _dbContext.BusinessPages
|
||
.AsNoTracking()
|
||
.Where(p => !p.IsDeleted);
|
||
|
||
// 应用过滤条件
|
||
query = ApplyPageQueryFilters(query, request);
|
||
|
||
// 获取总数
|
||
var total = await query.CountAsync();
|
||
|
||
// 分页查询,按 Sort 降序,然后按 CreateTime 降序排列 (Requirements 6.1)
|
||
var items = await query
|
||
.OrderByDescending(p => p.Sort)
|
||
.ThenByDescending(p => p.CreateTime)
|
||
.Skip(request.Skip)
|
||
.Take(request.PageSize)
|
||
.Select(p => new BusinessPageDto
|
||
{
|
||
Id = p.Id,
|
||
Title = p.Title,
|
||
ImageUrl = p.ImageUrl,
|
||
HasActionButton = p.HasActionButton,
|
||
ActionButtonText = p.ActionButtonText,
|
||
ActionButtonLink = p.ActionButtonLink,
|
||
Sort = p.Sort,
|
||
Status = p.Status,
|
||
StatusName = GetStatusName(p.Status),
|
||
CreateTime = p.CreateTime
|
||
})
|
||
.ToListAsync();
|
||
|
||
_logger.LogInformation("查询业务介绍页列表成功,总数: {Total}, 当前页数量: {Count}", total, items.Count);
|
||
|
||
return PagedResult<BusinessPageDto>.Create(items, total, request.Page, request.PageSize);
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<BusinessPageDto?> GetPageByIdAsync(long id)
|
||
{
|
||
// 查询业务介绍页,过滤软删除记录
|
||
var page = await _dbContext.BusinessPages
|
||
.AsNoTracking()
|
||
.Where(p => p.Id == id && !p.IsDeleted)
|
||
.Select(p => new BusinessPageDto
|
||
{
|
||
Id = p.Id,
|
||
Title = p.Title,
|
||
ImageUrl = p.ImageUrl,
|
||
HasActionButton = p.HasActionButton,
|
||
ActionButtonText = p.ActionButtonText,
|
||
ActionButtonLink = p.ActionButtonLink,
|
||
Sort = p.Sort,
|
||
Status = p.Status,
|
||
StatusName = GetStatusName(p.Status),
|
||
CreateTime = p.CreateTime
|
||
})
|
||
.FirstOrDefaultAsync();
|
||
|
||
if (page == null)
|
||
{
|
||
_logger.LogWarning("业务介绍页不存在,ID: {PageId}", id);
|
||
}
|
||
else
|
||
{
|
||
_logger.LogInformation("查询业务介绍页详情成功,ID: {PageId}", id);
|
||
}
|
||
|
||
return page;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<long> CreatePageAsync(CreateBusinessPageRequest request)
|
||
{
|
||
// 验证 Title 和 ImageUrl 必填 (Requirements 5.1)
|
||
ValidatePageRequest(request.Title, request.ImageUrl, request.HasActionButton,
|
||
request.ActionButtonText, request.ActionButtonLink);
|
||
|
||
var now = DateTime.Now;
|
||
|
||
// 创建实体
|
||
var entity = new BusinessPage
|
||
{
|
||
Title = request.Title,
|
||
ImageUrl = request.ImageUrl,
|
||
HasActionButton = request.HasActionButton,
|
||
ActionButtonText = request.ActionButtonText,
|
||
ActionButtonLink = request.ActionButtonLink,
|
||
Sort = request.Sort,
|
||
Status = request.Status, // 默认值为 1(启用)(Requirements 5.4)
|
||
CreateTime = now, // 自动设置创建时间 (Requirements 5.3)
|
||
UpdateTime = now, // 自动设置更新时间 (Requirements 5.3)
|
||
IsDeleted = false // 默认未删除 (Requirements 5.4)
|
||
};
|
||
|
||
_dbContext.BusinessPages.Add(entity);
|
||
await _dbContext.SaveChangesAsync();
|
||
|
||
_logger.LogInformation("创建业务介绍页成功,ID: {PageId}, Title: {Title}", entity.Id, entity.Title);
|
||
|
||
return entity.Id; // 返回自动生成的唯一 Id (Requirements 5.5)
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<bool> UpdatePageAsync(UpdateBusinessPageRequest request)
|
||
{
|
||
// 验证 Title 和 ImageUrl 必填 (Requirements 7.1)
|
||
ValidatePageRequest(request.Title, request.ImageUrl, request.HasActionButton,
|
||
request.ActionButtonText, request.ActionButtonLink);
|
||
|
||
// 查询业务介绍页
|
||
var entity = await _dbContext.BusinessPages
|
||
.Where(p => p.Id == request.Id && !p.IsDeleted)
|
||
.FirstOrDefaultAsync();
|
||
|
||
// 如果不存在或已软删除,抛出业务异常 (Requirements 7.4)
|
||
if (entity == null)
|
||
{
|
||
_logger.LogWarning("业务介绍页不存在,ID: {PageId}", request.Id);
|
||
throw new BusinessException(ErrorCodes.BusinessPageNotFound, "业务介绍页不存在");
|
||
}
|
||
|
||
// 更新字段
|
||
entity.Title = request.Title;
|
||
entity.ImageUrl = request.ImageUrl;
|
||
entity.HasActionButton = request.HasActionButton;
|
||
entity.ActionButtonText = request.ActionButtonText;
|
||
entity.ActionButtonLink = request.ActionButtonLink;
|
||
entity.Sort = request.Sort;
|
||
entity.Status = request.Status;
|
||
entity.UpdateTime = DateTime.Now; // 自动设置更新时间 (Requirements 7.3)
|
||
|
||
await _dbContext.SaveChangesAsync();
|
||
|
||
_logger.LogInformation("更新业务介绍页成功,ID: {PageId}, Title: {Title}", entity.Id, entity.Title);
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<bool> DeletePageAsync(long id)
|
||
{
|
||
// 查询业务介绍页
|
||
var entity = await _dbContext.BusinessPages
|
||
.Where(p => p.Id == id && !p.IsDeleted)
|
||
.FirstOrDefaultAsync();
|
||
|
||
// 如果不存在或已软删除,抛出业务异常 (Requirements 8.3)
|
||
if (entity == null)
|
||
{
|
||
_logger.LogWarning("业务介绍页不存在,ID: {PageId}", id);
|
||
throw new BusinessException(ErrorCodes.BusinessPageNotFound, "业务介绍页不存在");
|
||
}
|
||
|
||
// 软删除:设置 IsDeleted 为 true,更新 UpdateTime (Requirements 8.1)
|
||
entity.IsDeleted = true;
|
||
entity.UpdateTime = DateTime.Now;
|
||
|
||
await _dbContext.SaveChangesAsync();
|
||
|
||
_logger.LogInformation("删除业务介绍页成功(软删除),ID: {PageId}", id);
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<bool> UpdatePageStatusAsync(long id, int status)
|
||
{
|
||
// 查询业务介绍页
|
||
var entity = await _dbContext.BusinessPages
|
||
.Where(p => p.Id == id && !p.IsDeleted)
|
||
.FirstOrDefaultAsync();
|
||
|
||
// 如果不存在或已软删除,抛出业务异常 (Requirements 8.3)
|
||
if (entity == null)
|
||
{
|
||
_logger.LogWarning("业务介绍页不存在,ID: {PageId}", id);
|
||
throw new BusinessException(ErrorCodes.BusinessPageNotFound, "业务介绍页不存在");
|
||
}
|
||
|
||
// 更新状态字段 (Requirements 8.2)
|
||
entity.Status = status;
|
||
entity.UpdateTime = DateTime.Now;
|
||
|
||
await _dbContext.SaveChangesAsync();
|
||
|
||
_logger.LogInformation("更新业务介绍页状态成功,ID: {PageId}, Status: {Status}", id, status);
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<bool> UpdatePageSortAsync(long id, int sort)
|
||
{
|
||
// 查询业务介绍页
|
||
var entity = await _dbContext.BusinessPages
|
||
.Where(p => p.Id == id && !p.IsDeleted)
|
||
.FirstOrDefaultAsync();
|
||
|
||
// 如果不存在或已软删除,抛出业务异常 (Requirements 8.3)
|
||
if (entity == null)
|
||
{
|
||
_logger.LogWarning("业务介绍页不存在,ID: {PageId}", id);
|
||
throw new BusinessException(ErrorCodes.BusinessPageNotFound, "业务介绍页不存在");
|
||
}
|
||
|
||
// 更新排序字段 (Requirements 8.4)
|
||
entity.Sort = sort;
|
||
entity.UpdateTime = DateTime.Now;
|
||
|
||
await _dbContext.SaveChangesAsync();
|
||
|
||
_logger.LogInformation("更新业务介绍页排序成功,ID: {PageId}, Sort: {Sort}", id, sort);
|
||
|
||
return true;
|
||
}
|
||
|
||
#region 私有方法
|
||
|
||
/// <summary>
|
||
/// 应用业务介绍页查询过滤条件
|
||
/// </summary>
|
||
/// <param name="query">查询</param>
|
||
/// <param name="request">请求</param>
|
||
/// <returns>过滤后的查询</returns>
|
||
private static IQueryable<BusinessPage> ApplyPageQueryFilters(
|
||
IQueryable<BusinessPage> query,
|
||
BusinessPageQueryRequest request)
|
||
{
|
||
// 按标题模糊匹配筛选 (Requirements 6.2)
|
||
if (!string.IsNullOrWhiteSpace(request.Title))
|
||
{
|
||
query = query.Where(p => p.Title.Contains(request.Title));
|
||
}
|
||
|
||
// 按状态筛选 (Requirements 6.2)
|
||
if (request.Status.HasValue)
|
||
{
|
||
query = query.Where(p => p.Status == request.Status.Value);
|
||
}
|
||
|
||
return query;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证业务介绍页请求
|
||
/// </summary>
|
||
/// <param name="title">标题</param>
|
||
/// <param name="imageUrl">图片URL</param>
|
||
/// <param name="hasActionButton">是否有操作按钮</param>
|
||
/// <param name="actionButtonText">操作按钮文字</param>
|
||
/// <param name="actionButtonLink">操作按钮链接</param>
|
||
private void ValidatePageRequest(string title, string imageUrl, bool hasActionButton,
|
||
string? actionButtonText, string? actionButtonLink)
|
||
{
|
||
// 验证 Title 必填 (Requirements 5.1, 7.1)
|
||
if (string.IsNullOrWhiteSpace(title))
|
||
{
|
||
_logger.LogWarning("业务介绍页验证失败:标题不能为空");
|
||
throw new BusinessException(ErrorCodes.ParamError, "标题不能为空");
|
||
}
|
||
|
||
// 验证 ImageUrl 必填 (Requirements 5.1, 7.1)
|
||
if (string.IsNullOrWhiteSpace(imageUrl))
|
||
{
|
||
_logger.LogWarning("业务介绍页验证失败:图片URL不能为空");
|
||
throw new BusinessException(ErrorCodes.ParamError, "图片URL不能为空");
|
||
}
|
||
|
||
// 当 HasActionButton 为 true 时,验证 ActionButtonText 和 ActionButtonLink 必填 (Requirements 5.2, 7.2)
|
||
if (hasActionButton)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(actionButtonText))
|
||
{
|
||
_logger.LogWarning("业务介绍页验证失败:启用操作按钮时,按钮文字不能为空");
|
||
throw new BusinessException(ErrorCodes.ParamError, "启用操作按钮时,按钮文字不能为空");
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(actionButtonLink))
|
||
{
|
||
_logger.LogWarning("业务介绍页验证失败:启用操作按钮时,按钮链接不能为空");
|
||
throw new BusinessException(ErrorCodes.ParamError, "启用操作按钮时,按钮链接不能为空");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取状态名称
|
||
/// </summary>
|
||
/// <param name="status">状态值</param>
|
||
/// <returns>状态名称</returns>
|
||
private static string GetStatusName(int status)
|
||
{
|
||
return StatusNames.TryGetValue(status, out var name) ? name : "未知";
|
||
}
|
||
|
||
#endregion
|
||
}
|