Files
QYZH.InteractiveMagazine/QYZH.InteractiveMagazine.Service/UsersService.cs
glz 0126c6b097 refactor: 完善枚举系统与状态类型转换,新增枚举管理接口
1. 为所有枚举添加Description特性用于中文描述
2. 移除实体类中冗余的状态字段注释与定义
3. 将所有枚举状态参数改为int类型转换,统一数据交互格式
4. 新增系统管理枚举查询接口与实现,支持获取所有枚举元数据
5. 调整宠物服务模板状态更新接口参数类型
2026-06-08 17:54:36 +08:00

290 lines
10 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 Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using QYZH.InteractiveMagazine.IService;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using QYZH.InteractiveMagazine.Models.Dto.CheckIn;
using QYZH.InteractiveMagazine.Models.Dto.Compensation;
using QYZH.InteractiveMagazine.Models.Dto.Points;
using QYZH.InteractiveMagazine.Models.Entity;
using QYZH.InteractiveMagazine.Models.Enum;
using QYZH.InteractiveMagazine.Repository;
using SqlSugar;
namespace QYZH.InteractiveMagazine.Service;
public class UsersService(
BaseRepository<Users> usersRepository,
ILogger<UsersService> _logger,
IPointsService pointsService,
ICheckInService checkInService,
ICompensationTaskService compensationTaskService,
IUserJournalService userJournalService,
IOperationLogService operationLogService) : BaseRepository<Users>, IUsersService
{
/// <summary>
/// 分页查询用户列表
/// </summary>
public async Task<BaseResponse<PageListModel<UsersOutput>>> GetListAsync(UsersQueryInput input)
{
var page = Queryable()
.WhereIF(!string.IsNullOrEmpty(input.WxUserId), u => u.OpenId == input.WxUserId)
.OrderBy(u => u.Id, OrderByType.Desc)
.ToPage<Users, UsersOutput>(input);
return BaseResponse<PageListModel<UsersOutput>>.Success(page);
}
/// <summary>
/// 获取用户详情(包含积分记录、签到记录、补偿任务、期刊列表)
/// </summary>
public async Task<BaseResponse<UserDetailOutput>> GetDetailAsync(long id)
{
var user = await GetByIdAsync<UsersOutput>(u => u.Id == id);
if (user == null)
{
return BaseResponse<UserDetailOutput>.Fail("用户不存在");
}
// 并行查询关联数据
var pointsTask = GetPointsRecordsAsync(id);
var checkInTask = GetCheckInRecordsAsync(id);
var compensationTask = GetFailedCompensationTasksAsync(id);
var journalsTask = GetUserJournalsWithDetailAsync(id);
await Task.WhenAll(pointsTask, checkInTask, compensationTask, journalsTask);
return BaseResponse<UserDetailOutput>.Success(new UserDetailOutput
{
BasicInfo = user,
PointsRecords = await pointsTask,
CheckInRecords = await checkInTask,
FailedCompensationTasks = await compensationTask,
Journals = await journalsTask
});
}
/// <summary>
/// 获取用户积分记录最近20条
/// </summary>
private async Task<List<PointsRecordOutput>> GetPointsRecordsAsync(long userId)
{
try
{
var result = await pointsService.GetPointsRecordsAsync(new PointsRecordQueryInput
{
UserId = userId,
PageIndex = 1,
PageSize = 20
});
return result.Result ?? [];
}
catch (Exception ex)
{
_logger.LogWarning(ex, "获取用户积分记录失败UserId: {UserId}", userId);
return [];
}
}
/// <summary>
/// 获取用户签到记录
/// </summary>
private async Task<List<CheckInRecordOutput>> GetCheckInRecordsAsync(long userId)
{
try
{
var info = await checkInService.GetCheckInInfoAsync(userId);
return info.RecentRecords ?? [];
}
catch (Exception ex)
{
_logger.LogWarning(ex, "获取用户签到记录失败UserId: {UserId}", userId);
return [];
}
}
/// <summary>
/// 获取用户失败的补偿任务(需要手动处理)
/// </summary>
private async Task<List<CompensationTaskOutput>> GetFailedCompensationTasksAsync(long userId)
{
try
{
var tasks = await compensationTaskService.GetTasksAsync(new GetCompensationTasksInput
{
Status = CompensationTaskStatusEnum.Failed,
Limit = 50
});
return tasks.Where(t => t.UserId == userId).ToList();
}
catch (Exception ex)
{
_logger.LogWarning(ex, "获取用户失败补偿任务失败UserId: {UserId}", userId);
return [];
}
}
/// <summary>
/// 获取用户拥有的期刊列表(含期刊详情)
/// </summary>
private async Task<List<UserJournalItemOutput>> GetUserJournalsWithDetailAsync(long userId)
{
try
{
var userJournals = await Context.Queryable<UserJournal>()
.Where(uj => uj.UserId == userId && !uj.IsDeleted)
.OrderByDescending(uj => uj.CreatedAt)
.ToListAsync();
var result = new List<UserJournalItemOutput>();
foreach (var uj in userJournals)
{
var journal = await Context.Queryable<Journal>()
.Where(j => j.Id == uj.JournalId && !j.IsDeleted)
.FirstAsync();
if (journal != null)
{
result.Add(new UserJournalItemOutput
{
BindId = uj.Id,
JournalId = uj.JournalId,
JournalTitle = journal.Title,
CoverImageUrl = journal.CoverImageUrl,
Type = uj.Type.ToString(),
Status = uj.Status.ToString(),
CreatedAt = uj.CreatedAt
});
}
}
return result;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "获取用户期刊列表失败UserId: {UserId}", userId);
return [];
}
}
/// <summary>
/// 更新用户状态
/// </summary>
public async Task<BaseResponse> UpdateStatusAsync(long id, UpdateUserStatusInput input)
{
var exists = await Queryable().AnyAsync(u => u.Id == id);
if (!exists)
{
return BaseResponse.Fail("用户不存在");
}
var statusValue = input.Status == 1 ? UserStatusEnum.Active : UserStatusEnum.Disabled;
var result = await UpdateAsync(
u => new Users { Status = (int)statusValue },
u => u.Id == id
);
return result ? BaseResponse.Success() : BaseResponse.Fail("更新失败");
}
/// <summary>
/// 手动增加用户积分
/// </summary>
public async Task<ManualPointsOutput> ManualAddPointsAsync(long userId, ManualAddPointsInput input, long operatorId, string operatorName, string? ipAddress = null)
{
_logger.LogInformation("管理员手动增加积分UserId: {UserId}, Amount: {Amount}, Operator: {Operator}",
userId, input.Amount, operatorName);
// 校验用户是否存在
var user = await Queryable().Where(u => u.Id == userId && !u.IsDeleted).FirstAsync();
if (user == null)
throw new BusinessException("用户不存在", 404);
// 调用积分服务增加积分
var result = await pointsService.AddPointsAsync(new AddPointsInput
{
UserId = userId,
Amount = input.Amount,
ChangeType = PointsChangeTypeEnum.ManualAdjust,
Description = $"管理员手动增加: {input.Reason}",
OperatorName = operatorName
});
// 记录操作日志
var detail = JsonConvert.SerializeObject(new
{
Amount = input.Amount,
Reason = input.Reason,
PreviousBalance = result.PreviousBalance,
NewBalance = result.NewBalance,
RecordId = result.RecordId
});
await operationLogService.LogAsync(
operatorId, operatorName,
OperationLogActionType.ManualAddPoints,
OperationLogTargetType.User,
userId, user.Name, detail, ipAddress);
return new ManualPointsOutput
{
RecordId = result.RecordId,
PreviousBalance = result.PreviousBalance,
NewBalance = result.NewBalance,
ChangeAmount = input.Amount,
OperatorName = operatorName,
OperatedAt = DateTime.Now
};
}
/// <summary>
/// 手动扣除用户积分
/// </summary>
public async Task<ManualPointsOutput> ManualDeductPointsAsync(long userId, ManualDeductPointsInput input, long operatorId, string operatorName, string? ipAddress = null)
{
_logger.LogInformation("管理员手动扣除积分UserId: {UserId}, Amount: {Amount}, Operator: {Operator}",
userId, input.Amount, operatorName);
// 校验用户是否存在
var user = await Queryable().Where(u => u.Id == userId && !u.IsDeleted).FirstAsync();
if (user == null)
throw new BusinessException("用户不存在", 404);
// 调用积分服务扣除积分
var result = await pointsService.DeductPointsAsync(new DeductPointsInput
{
UserId = userId,
Amount = input.Amount,
ChangeType = PointsChangeTypeEnum.ManualAdjust,
Description = $"管理员手动扣除: {input.Reason}",
OperatorName = operatorName
});
// 记录操作日志
var detail = JsonConvert.SerializeObject(new
{
Amount = input.Amount,
Reason = input.Reason,
PreviousBalance = result.PreviousBalance,
NewBalance = result.NewBalance,
RecordId = result.RecordId
});
await operationLogService.LogAsync(
operatorId, operatorName,
OperationLogActionType.ManualDeductPoints,
OperationLogTargetType.User,
userId, user.Name, detail, ipAddress);
return new ManualPointsOutput
{
RecordId = result.RecordId,
PreviousBalance = result.PreviousBalance,
NewBalance = result.NewBalance,
ChangeAmount = -input.Amount,
OperatorName = operatorName,
OperatedAt = DateTime.Now
};
}
}