xiangyixiangqin/server/src/XiangYi.Application/Services/AdminMemberService.cs
2026-02-06 17:58:15 +08:00

271 lines
9.4 KiB
C#

using Microsoft.Extensions.Logging;
using XiangYi.Application.DTOs.Requests;
using XiangYi.Application.DTOs.Responses;
using XiangYi.Application.Interfaces;
using XiangYi.Core.Constants;
using XiangYi.Core.Entities.Biz;
using XiangYi.Core.Exceptions;
using XiangYi.Core.Interfaces;
namespace XiangYi.Application.Services;
/// <summary>
/// 后台会员管理服务实现
/// </summary>
public class AdminMemberService : IAdminMemberService
{
private readonly IRepository<Member> _memberRepository;
private readonly IRepository<MemberFamily> _memberFamilyRepository;
private readonly IRepository<User> _userRepository;
private readonly IRepository<Order> _orderRepository;
private readonly ILogger<AdminMemberService> _logger;
/// <summary>
/// 会员等级名称
/// </summary>
private static readonly Dictionary<int, string> MemberLevelNames = new()
{
{ 1, "不限时会员" },
{ 2, "诚意会员" },
{ 3, "家庭版会员" },
{ 4, "限时会员" }
};
/// <summary>
/// 会员状态名称
/// </summary>
private static readonly Dictionary<int, string> MemberStatusNames = new()
{
{ 1, "生效中" },
{ 2, "已过期" }
};
public AdminMemberService(
IRepository<Member> memberRepository,
IRepository<MemberFamily> memberFamilyRepository,
IRepository<User> userRepository,
IRepository<Order> orderRepository,
ILogger<AdminMemberService> logger)
{
_memberRepository = memberRepository;
_memberFamilyRepository = memberFamilyRepository;
_userRepository = userRepository;
_orderRepository = orderRepository;
_logger = logger;
}
/// <inheritdoc />
public async Task<PagedResult<AdminMemberListDto>> GetMemberListAsync(AdminMemberQueryRequest request)
{
// Get all members
var members = await _memberRepository.GetAllAsync();
var query = members.AsQueryable();
// Filter by member level
if (request.MemberLevel.HasValue)
{
query = query.Where(m => m.MemberLevel == request.MemberLevel.Value);
}
// Filter by status
if (request.Status.HasValue)
{
query = query.Where(m => m.Status == request.Status.Value);
}
// Filter by start time range
if (request.StartTimeBegin.HasValue)
{
query = query.Where(m => m.StartTime >= request.StartTimeBegin.Value);
}
if (request.StartTimeEnd.HasValue)
{
var endTime = request.StartTimeEnd.Value.Date.AddDays(1);
query = query.Where(m => m.StartTime < endTime);
}
// Get user IDs for keyword search
var memberList = query.ToList();
var userIds = memberList.Select(m => m.UserId).Distinct().ToList();
var users = await _userRepository.GetListAsync(u => userIds.Contains(u.Id));
var userDict = users.ToDictionary(u => u.Id);
// Filter by keyword (XiangQinNo, Nickname, Phone)
if (!string.IsNullOrWhiteSpace(request.Keyword))
{
var keyword = request.Keyword.Trim();
var matchedUserIds = users
.Where(u =>
(u.XiangQinNo != null && u.XiangQinNo.Contains(keyword)) ||
(u.Nickname != null && u.Nickname.Contains(keyword)) ||
(u.Phone != null && u.Phone.Contains(keyword)))
.Select(u => u.Id)
.ToHashSet();
memberList = memberList.Where(m => matchedUserIds.Contains(m.UserId)).ToList();
}
var total = memberList.Count;
// Order by CreateTime descending and paginate
var items = memberList
.OrderByDescending(m => m.CreateTime)
.Skip((request.PageIndex - 1) * request.PageSize)
.Take(request.PageSize)
.ToList();
// Get order IDs for order info lookup
var orderIds = items.Select(m => m.OrderId).Distinct().ToList();
var orders = await _orderRepository.GetListAsync(o => orderIds.Contains(o.Id));
var orderDict = orders.ToDictionary(o => o.Id);
// Get family bind counts for family members
var memberIds = items.Where(m => m.MemberLevel == 3).Select(m => m.Id).ToList();
var familyBinds = await _memberFamilyRepository.GetListAsync(f => memberIds.Contains(f.MemberId));
var familyBindCountDict = familyBinds.GroupBy(f => f.MemberId).ToDictionary(g => g.Key, g => g.Count());
// Map to DTOs - 过滤掉没有关联用户的会员记录
var dtos = items
.Where(m => userDict.ContainsKey(m.UserId)) // 只保留有关联用户的会员
.Select(m =>
{
userDict.TryGetValue(m.UserId, out var user);
orderDict.TryGetValue(m.OrderId, out var order);
familyBindCountDict.TryGetValue(m.Id, out var familyBindCount);
return MapToMemberListDto(m, user, order, familyBindCount);
}).ToList();
return new PagedResult<AdminMemberListDto>
{
Items = dtos,
Total = total,
PageIndex = request.PageIndex,
PageSize = request.PageSize
};
}
/// <inheritdoc />
public async Task<AdminMemberDetailDto> GetMemberDetailAsync(long memberId)
{
var member = await _memberRepository.GetByIdAsync(memberId);
if (member == null)
{
throw new BusinessException(ErrorCodes.UserNotFound, "会员记录不存在");
}
// Get user info
var user = await _userRepository.GetByIdAsync(member.UserId);
// Get order info
var order = await _orderRepository.GetByIdAsync(member.OrderId);
// Get family members if family version
List<AdminFamilyMemberDto>? familyMembers = null;
if (member.MemberLevel == 3)
{
var familyBinds = await _memberFamilyRepository.GetListAsync(f => f.MemberId == memberId);
if (familyBinds.Any())
{
var bindUserIds = familyBinds.Select(f => f.BindUserId).ToList();
var bindUsers = await _userRepository.GetListAsync(u => bindUserIds.Contains(u.Id));
var bindUserDict = bindUsers.ToDictionary(u => u.Id);
familyMembers = familyBinds.Select(f =>
{
bindUserDict.TryGetValue(f.BindUserId, out var bindUser);
return new AdminFamilyMemberDto
{
BindId = f.Id,
UserId = f.BindUserId,
XiangQinNo = bindUser?.XiangQinNo,
Nickname = bindUser?.Nickname,
Avatar = bindUser?.Avatar,
BindTime = f.CreateTime
};
}).ToList();
}
}
return MapToMemberDetailDto(member, user, order, familyMembers);
}
#region Private Helper Methods
private static AdminMemberListDto MapToMemberListDto(Member member, User? user, Order? order, int familyBindCount)
{
return new AdminMemberListDto
{
MemberId = member.Id,
UserId = member.UserId,
XiangQinNo = user?.XiangQinNo,
Nickname = user?.Nickname,
Avatar = user?.Avatar,
Phone = MaskPhone(user?.Phone),
MemberLevel = member.MemberLevel,
MemberLevelText = GetMemberLevelText(member.MemberLevel),
OrderId = member.OrderId,
OrderNo = order?.OrderNo,
StartTime = member.StartTime,
ExpireTime = member.ExpireTime,
Status = member.Status,
StatusText = GetMemberStatusText(member.Status),
FamilyBindCount = familyBindCount,
CreateTime = member.CreateTime
};
}
private static AdminMemberDetailDto MapToMemberDetailDto(
Member member,
User? user,
Order? order,
List<AdminFamilyMemberDto>? familyMembers)
{
return new AdminMemberDetailDto
{
MemberId = member.Id,
UserId = member.UserId,
XiangQinNo = user?.XiangQinNo,
Nickname = user?.Nickname,
Avatar = user?.Avatar,
Phone = MaskPhone(user?.Phone),
MemberLevel = member.MemberLevel,
MemberLevelText = GetMemberLevelText(member.MemberLevel),
OrderId = member.OrderId,
OrderNo = order?.OrderNo,
OrderAmount = order?.PayAmount,
PayTime = order?.PayTime,
StartTime = member.StartTime,
ExpireTime = member.ExpireTime,
Status = member.Status,
StatusText = GetMemberStatusText(member.Status),
FamilyMembers = familyMembers,
CreateTime = member.CreateTime
};
}
/// <summary>
/// 手机号脱敏
/// </summary>
private static string? MaskPhone(string? phone)
{
return phone;
}
/// <summary>
/// 获取会员等级文本
/// </summary>
private static string GetMemberLevelText(int memberLevel)
{
return MemberLevelNames.TryGetValue(memberLevel, out var name) ? name : "未知";
}
/// <summary>
/// 获取会员状态文本
/// </summary>
private static string GetMemberStatusText(int status)
{
return MemberStatusNames.TryGetValue(status, out var name) ? name : "未知";
}
#endregion
}