mi-assessment/server/MiAssessment/src/MiAssessment.Admin.Business/Services/PlannerService.cs
2026-03-18 11:53:46 +08:00

598 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.Planner;
using MiAssessment.Admin.Business.Services.Interfaces;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace MiAssessment.Admin.Business.Services;
/// <summary>
/// 规划师服务实现
/// </summary>
public class PlannerService : IPlannerService
{
private readonly AdminBusinessDbContext _dbContext;
private readonly ILogger<PlannerService> _logger;
/// <summary>
/// 规划师状态名称映射
/// </summary>
private static readonly Dictionary<int, string> PlannerStatusNames = new()
{
{ 0, "禁用" },
{ 1, "启用" }
};
/// <summary>
/// 预约状态名称映射
/// </summary>
private static readonly Dictionary<int, string> BookingStatusNames = new()
{
{ 1, "待联系" },
{ 2, "已联系" },
{ 3, "已完成" },
{ 4, "已取消" }
};
/// <summary>
/// 性别名称映射
/// </summary>
private static readonly Dictionary<int, string> GenderNames = new()
{
{ 1, "男" },
{ 2, "女" }
};
/// <summary>
/// 年级名称映射
/// </summary>
private static readonly Dictionary<int, string> GradeNames = new()
{
{ 1, "一年级" },
{ 2, "二年级" },
{ 3, "三年级" },
{ 4, "四年级" },
{ 5, "五年级" },
{ 6, "六年级" },
{ 7, "初一" },
{ 8, "初二" },
{ 9, "初三" },
{ 10, "高一" },
{ 11, "高二" },
{ 12, "高三" }
};
/// <summary>
/// 订单状态名称映射
/// </summary>
private static readonly Dictionary<int, string> OrderStatusNames = new()
{
{ 1, "待支付" },
{ 2, "已支付" },
{ 3, "已完成" },
{ 4, "退款中" },
{ 5, "已退款" },
{ 6, "已取消" }
};
/// <summary>
/// 构造函数
/// </summary>
/// <param name="dbContext">数据库上下文</param>
/// <param name="logger">日志记录器</param>
public PlannerService(
AdminBusinessDbContext dbContext,
ILogger<PlannerService> logger)
{
_dbContext = dbContext;
_logger = logger;
}
#region
/// <inheritdoc />
public async Task<PagedResult<PlannerDto>> GetPlannerListAsync(PlannerQueryRequest request)
{
// 构建查询,过滤软删除记录
var query = _dbContext.Planners
.AsNoTracking()
.Where(p => !p.IsDeleted);
// 应用过滤条件
if (!string.IsNullOrWhiteSpace(request.Name))
{
query = query.Where(p => p.Name.Contains(request.Name));
}
if (request.Status.HasValue)
{
query = query.Where(p => p.Status == request.Status.Value);
}
// 获取总数
var total = await query.CountAsync();
// 分页查询,按排序字段降序排列
var plannerIds = await query
.OrderByDescending(p => p.Sort)
.ThenByDescending(p => p.CreateTime)
.Skip(request.Skip)
.Take(request.PageSize)
.Select(p => p.Id)
.ToListAsync();
// 获取预约数量
var bookingCounts = await _dbContext.PlannerBookings
.AsNoTracking()
.Where(b => plannerIds.Contains(b.PlannerId) && !b.IsDeleted)
.GroupBy(b => b.PlannerId)
.Select(g => new { PlannerId = g.Key, Count = g.Count() })
.ToDictionaryAsync(x => x.PlannerId, x => x.Count);
// 获取规划师详情
var items = await query
.OrderByDescending(p => p.Sort)
.ThenByDescending(p => p.CreateTime)
.Skip(request.Skip)
.Take(request.PageSize)
.Select(p => new PlannerDto
{
Id = p.Id,
Name = p.Name,
Avatar = p.Avatar,
Title = p.Title,
Introduction = p.Introduction,
Tags = p.Tags,
Price = p.Price,
Sort = p.Sort,
Status = p.Status,
StatusName = GetPlannerStatusName(p.Status),
BookingCount = 0, // 稍后填充
CreateTime = p.CreateTime,
UpdateTime = p.UpdateTime
})
.ToListAsync();
// 填充预约数量
foreach (var item in items)
{
item.BookingCount = bookingCounts.TryGetValue(item.Id, out var count) ? count : 0;
}
return PagedResult<PlannerDto>.Create(items, total, request.Page, request.PageSize);
}
/// <inheritdoc />
public async Task<long> CreatePlannerAsync(CreatePlannerRequest request)
{
var planner = new Planner
{
Name = request.Name,
Avatar = request.Avatar,
Title = request.Title,
Introduction = request.Introduction,
Tags = request.Tags,
Price = request.Price,
Sort = request.Sort,
Status = request.Status,
CreateTime = DateTime.Now,
UpdateTime = DateTime.Now,
IsDeleted = false
};
_dbContext.Planners.Add(planner);
await _dbContext.SaveChangesAsync();
_logger.LogInformation("创建规划师成功ID: {PlannerId}, 姓名: {Name}", planner.Id, planner.Name);
return planner.Id;
}
/// <inheritdoc />
public async Task<bool> UpdatePlannerAsync(UpdatePlannerRequest request)
{
var planner = await _dbContext.Planners
.Where(p => p.Id == request.Id && !p.IsDeleted)
.FirstOrDefaultAsync();
if (planner == null)
{
throw new BusinessException(ErrorCodes.PlannerNotFound, "规划师不存在");
}
// 验证价格
if (request.Price <= 0)
{
throw new BusinessException(ErrorCodes.ParamError, "价格必须大于0");
}
planner.Name = request.Name;
planner.Avatar = request.Avatar;
planner.Title = request.Title;
planner.Introduction = request.Introduction;
planner.Tags = request.Tags;
planner.Price = request.Price;
planner.Sort = request.Sort;
planner.Status = request.Status;
planner.UpdateTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("更新规划师成功ID: {PlannerId}", request.Id);
return true;
}
/// <inheritdoc />
public async Task<bool> DeletePlannerAsync(long id)
{
var planner = await _dbContext.Planners
.Where(p => p.Id == id && !p.IsDeleted)
.FirstOrDefaultAsync();
if (planner == null)
{
throw new BusinessException(ErrorCodes.PlannerNotFound, "规划师不存在");
}
// 软删除
planner.IsDeleted = true;
planner.UpdateTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("删除规划师成功ID: {PlannerId}", id);
return true;
}
/// <inheritdoc />
public async Task<bool> UpdatePlannerStatusAsync(long id, int status)
{
var planner = await _dbContext.Planners
.Where(p => p.Id == id && !p.IsDeleted)
.FirstOrDefaultAsync();
if (planner == null)
{
throw new BusinessException(ErrorCodes.PlannerNotFound, "规划师不存在");
}
planner.Status = status;
planner.UpdateTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("更新规划师状态成功ID: {PlannerId}, 状态: {Status}", id, status);
return true;
}
/// <inheritdoc />
public async Task<bool> UpdatePlannerSortAsync(List<SortItem> items)
{
if (items == null || items.Count == 0)
{
return true;
}
var ids = items.Select(i => i.Id).ToList();
var planners = await _dbContext.Planners
.Where(p => ids.Contains(p.Id) && !p.IsDeleted)
.ToListAsync();
foreach (var planner in planners)
{
var sortItem = items.FirstOrDefault(i => i.Id == planner.Id);
if (sortItem != null)
{
planner.Sort = sortItem.Sort;
planner.UpdateTime = DateTime.Now;
}
}
await _dbContext.SaveChangesAsync();
_logger.LogInformation("更新规划师排序成功,数量: {Count}", items.Count);
return true;
}
#endregion
#region
/// <inheritdoc />
public async Task<PagedResult<BookingDto>> GetBookingListAsync(BookingQueryRequest request)
{
// 构建查询,过滤软删除记录
var query = _dbContext.PlannerBookings
.AsNoTracking()
.Include(b => b.User)
.Include(b => b.Planner)
.Include(b => b.Order)
.Where(b => !b.IsDeleted);
// 应用过滤条件
query = ApplyBookingQueryFilters(query, request);
// 获取总数
var total = await query.CountAsync();
// 分页查询,按创建时间降序排列
var items = await query
.OrderByDescending(b => b.CreateTime)
.Skip(request.Skip)
.Take(request.PageSize)
.Select(b => new BookingDto
{
Id = b.Id,
UserId = b.UserId,
UserNickname = b.User != null ? b.User.Nickname : null,
UserPhone = b.User != null ? b.User.Phone : null,
OrderId = b.OrderId,
OrderNo = b.Order != null ? b.Order.OrderNo : null,
PlannerId = b.PlannerId,
PlannerName = b.Planner != null ? b.Planner.Name : null,
BookingDate = b.BookingDate,
BookingTime = b.BookingTime,
Name = b.Name,
Phone = b.Phone,
Gender = b.Gender,
GenderName = GetGenderName(b.Gender),
Grade = b.Grade,
GradeName = GetGradeName(b.Grade),
Status = b.Status,
StatusName = GetBookingStatusName(b.Status),
CreateTime = b.CreateTime
})
.ToListAsync();
return PagedResult<BookingDto>.Create(items, total, request.Page, request.PageSize);
}
/// <inheritdoc />
public async Task<BookingDetailDto?> GetBookingDetailAsync(long id)
{
var booking = await _dbContext.PlannerBookings
.AsNoTracking()
.Include(b => b.User)
.Include(b => b.Planner)
.Include(b => b.Order)
.Where(b => b.Id == id && !b.IsDeleted)
.FirstOrDefaultAsync();
if (booking == null)
{
return null;
}
return new BookingDetailDto
{
Id = booking.Id,
UserId = booking.UserId,
UserNickname = booking.User?.Nickname,
UserPhone = booking.User?.Phone,
OrderId = booking.OrderId,
OrderNo = booking.Order?.OrderNo,
PlannerId = booking.PlannerId,
PlannerName = booking.Planner?.Name,
PlannerAvatar = booking.Planner?.Avatar,
PlannerIntroduction = booking.Planner?.Introduction,
BookingDate = booking.BookingDate,
BookingTime = booking.BookingTime,
Name = booking.Name,
Phone = booking.Phone,
Gender = booking.Gender,
GenderName = GetGenderName(booking.Gender),
Grade = booking.Grade,
GradeName = GetGradeName(booking.Grade),
MajorName = booking.MajorName,
ScoreChinese = booking.ScoreChinese,
ScoreMath = booking.ScoreMath,
ScoreEnglish = booking.ScoreEnglish,
ScorePhysics = booking.ScorePhysics,
ScoreChemistry = booking.ScoreChemistry,
ScoreBiology = booking.ScoreBiology,
ScoreGeography = booking.ScoreGeography,
ScorePolitics = booking.ScorePolitics,
Status = booking.Status,
StatusName = GetBookingStatusName(booking.Status),
OrderAmount = booking.Order?.Amount,
OrderStatus = booking.Order?.Status,
OrderStatusName = booking.Order != null ? GetOrderStatusName(booking.Order.Status) : null,
CreateTime = booking.CreateTime,
UpdateTime = booking.UpdateTime
};
}
/// <inheritdoc />
public async Task<bool> UpdateBookingStatusAsync(long id, int status, string? remark)
{
var booking = await _dbContext.PlannerBookings
.Where(b => b.Id == id && !b.IsDeleted)
.FirstOrDefaultAsync();
if (booking == null)
{
throw new BusinessException(ErrorCodes.BookingNotFound, "预约记录不存在");
}
// 验证状态值
if (status < 1 || status > 4)
{
throw new BusinessException(ErrorCodes.ParamError, "状态值无效");
}
booking.Status = status;
booking.UpdateTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("更新预约状态成功ID: {BookingId}, 状态: {Status}", id, status);
return true;
}
/// <inheritdoc />
public async Task<List<BookingDto>> ExportBookingsAsync(BookingQueryRequest request)
{
// 构建查询,过滤软删除记录
var query = _dbContext.PlannerBookings
.AsNoTracking()
.Include(b => b.User)
.Include(b => b.Planner)
.Include(b => b.Order)
.Where(b => !b.IsDeleted);
// 应用过滤条件
query = ApplyBookingQueryFilters(query, request);
// 查询所有匹配的记录(不分页)
var items = await query
.OrderByDescending(b => b.CreateTime)
.Select(b => new BookingDto
{
Id = b.Id,
UserId = b.UserId,
UserNickname = b.User != null ? b.User.Nickname : null,
UserPhone = b.User != null ? b.User.Phone : null,
OrderId = b.OrderId,
OrderNo = b.Order != null ? b.Order.OrderNo : null,
PlannerId = b.PlannerId,
PlannerName = b.Planner != null ? b.Planner.Name : null,
BookingDate = b.BookingDate,
BookingTime = b.BookingTime,
Name = b.Name,
Phone = b.Phone,
Gender = b.Gender,
GenderName = GetGenderName(b.Gender),
Grade = b.Grade,
GradeName = GetGradeName(b.Grade),
Status = b.Status,
StatusName = GetBookingStatusName(b.Status),
CreateTime = b.CreateTime
})
.ToListAsync();
_logger.LogInformation("导出预约记录成功,数量: {Count}", items.Count);
return items;
}
#endregion
#region
/// <summary>
/// 应用预约查询过滤条件
/// </summary>
/// <param name="query">查询</param>
/// <param name="request">请求</param>
/// <returns>过滤后的查询</returns>
private IQueryable<PlannerBooking> ApplyBookingQueryFilters(IQueryable<PlannerBooking> query, BookingQueryRequest request)
{
// 按规划师ID筛选
if (request.PlannerId.HasValue)
{
query = query.Where(b => b.PlannerId == request.PlannerId.Value);
}
// 按用户ID筛选
if (request.UserId.HasValue)
{
query = query.Where(b => b.UserId == request.UserId.Value);
}
// 按预约日期范围筛选
if (request.BookingDateStart.HasValue)
{
query = query.Where(b => b.BookingDate >= request.BookingDateStart.Value);
}
if (request.BookingDateEnd.HasValue)
{
var endDate = request.BookingDateEnd.Value.AddDays(1);
query = query.Where(b => b.BookingDate < endDate);
}
// 按状态筛选
if (request.Status.HasValue)
{
query = query.Where(b => b.Status == request.Status.Value);
}
// 按姓名模糊搜索
if (!string.IsNullOrWhiteSpace(request.Name))
{
query = query.Where(b => b.Name.Contains(request.Name));
}
// 按手机号模糊搜索
if (!string.IsNullOrWhiteSpace(request.Phone))
{
query = query.Where(b => b.Phone.Contains(request.Phone));
}
return query;
}
/// <summary>
/// 获取规划师状态名称
/// </summary>
/// <param name="status">状态值</param>
/// <returns>状态名称</returns>
private static string GetPlannerStatusName(int status)
{
return PlannerStatusNames.TryGetValue(status, out var name) ? name : "未知";
}
/// <summary>
/// 获取预约状态名称
/// </summary>
/// <param name="status">状态值</param>
/// <returns>状态名称</returns>
private static string GetBookingStatusName(int status)
{
return BookingStatusNames.TryGetValue(status, out var name) ? name : "未知";
}
/// <summary>
/// 获取性别名称
/// </summary>
/// <param name="gender">性别值</param>
/// <returns>性别名称</returns>
private static string GetGenderName(int gender)
{
return GenderNames.TryGetValue(gender, out var name) ? name : "未知";
}
/// <summary>
/// 获取年级名称
/// </summary>
/// <param name="grade">年级值</param>
/// <returns>年级名称</returns>
private static string GetGradeName(int grade)
{
return GradeNames.TryGetValue(grade, out var name) ? name : "未知";
}
/// <summary>
/// 获取订单状态名称
/// </summary>
/// <param name="status">状态值</param>
/// <returns>状态名称</returns>
private static string GetOrderStatusName(int status)
{
return OrderStatusNames.TryGetValue(status, out var name) ? name : "未知";
}
#endregion
}