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.Compensation;
using QYZH.InteractiveMagazine.Models.Entity;
using QYZH.InteractiveMagazine.Models.Enum;
using QYZH.InteractiveMagazine.Repository;
using SqlSugar;
namespace QYZH.InteractiveMagazine.Service;
///
/// 补偿任务管理服务实现
///
public class CompensationManageService(
BaseRepository compensationTaskRepository,
IOperationLogService operationLogService,
ILogger logger)
: BaseRepository, ICompensationManageService
{
///
/// 分页查询补偿任务(含用户昵称)
///
public async Task> GetListAsync(CompensationTaskQueryInput input)
{
if (input.PageIndex <= 0)
input.PageIndex = 1;
if (input.PageSize <= 0 || input.PageSize > 100)
input.PageSize = 10;
RefAsync totalNumber = 0;
var pageResult = await compensationTaskRepository.Queryable()
.LeftJoin((t, u) => t.UserId == u.Id)
.WhereIF(input.UserId.HasValue, (t, u) => t.UserId == input.UserId.Value)
.WhereIF(input.TaskType.HasValue, (t, u) => t.TaskType == (int)input.TaskType.Value)
.WhereIF(input.Status.HasValue, (t, u) => t.Status == (int)input.Status)
.WhereIF(!string.IsNullOrWhiteSpace(input.BusinessSource), (t, u) => t.BusinessSource == input.BusinessSource)
.OrderByDescending((t, u) => t.CreatedAt)
.Select((t, u) => new CompensationManageOutput
{
Id = t.Id,
TaskType = (CompensationTaskTypeEnum)t.TaskType,
BusinessSource = t.BusinessSource,
BusinessId = t.BusinessId,
UserId = t.UserId,
UserName = u.Name,
Payload = t.Payload,
ErrorMessage = t.ErrorMessage,
ErrorSource = t.ErrorSource,
RetryCount = t.RetryCount,
MaxRetries = t.MaxRetries,
Status = (CompensationTaskStatusEnum)t.Status,
ProcessedAt = t.ProcessedAt,
ScheduledAt = t.ScheduledAt,
ResultMessage = t.ResultMessage,
CreatedAt = t.CreatedAt
})
.ToPageListAsync(input.PageIndex, input.PageSize, totalNumber);
return new PageListModel(pageResult, input.PageIndex, input.PageSize, totalNumber);
}
///
/// 手动重试补偿任务
///
public async Task RetryAsync(long taskId, long operatorId, string operatorName, CompensationRetryInput input, string? ipAddress = null)
{
logger.LogInformation("手动重试补偿任务,TaskId: {TaskId}, Operator: {Operator}", taskId, operatorName);
var task = await compensationTaskRepository.GetByIdAsync(taskId);
if (task == null)
throw new BusinessException("补偿任务不存在", 404);
if (task.Status != (int)CompensationTaskStatusEnum.Failed && task.Status != (int)CompensationTaskStatusEnum.Cancelled)
throw new BusinessException($"只有失败或已取消的任务才能重试,当前状态: {task.Status}", 400);
// 重置任务状态为 Pending,清零重试次数,设置立即执行
await compensationTaskRepository.Context.Updateable()
.SetColumns(t => t.Status == (int)CompensationTaskStatusEnum.Pending)
.SetColumns(t => t.RetryCount == 0)
.SetColumns(t => t.ScheduledAt == DateTime.Now)
.SetColumns(t => t.ResultMessage == $"管理员手动重试: {input.Reason}")
.SetColumns(t => t.UpdatedBy == operatorName)
.SetColumns(t => t.UpdatedAt == DateTime.Now)
.Where(t => t.Id == taskId && !t.IsDeleted)
.ExecuteCommandAsync();
// 记录操作日志
var detail = JsonConvert.SerializeObject(new
{
OriginalStatus = task.Status,
Reason = input.Reason,
TaskType = task.TaskType,
UserId = task.UserId
});
await operationLogService.LogAsync(
operatorId, operatorName,
OperationLogActionType.CompensationRetry,
OperationLogTargetType.CompensationTask,
taskId, null, detail, ipAddress);
logger.LogInformation("补偿任务手动重试成功,TaskId: {TaskId}", taskId);
}
///
/// 标记补偿任务为已解决
///
public async Task ResolveAsync(long taskId, long operatorId, string operatorName, CompensationResolveInput input, string? ipAddress = null)
{
logger.LogInformation("标记补偿任务已解决,TaskId: {TaskId}, Operator: {Operator}", taskId, operatorName);
var task = await compensationTaskRepository.GetByIdAsync(taskId);
if (task == null)
throw new BusinessException("补偿任务不存在", 404);
if (task.Status == (int)CompensationTaskStatusEnum.Success)
throw new BusinessException("该任务已经是成功状态,无需标记", 400);
// 标记为 Success
await compensationTaskRepository.Context.Updateable()
.SetColumns(t => t.Status == (int)CompensationTaskStatusEnum.Success)
.SetColumns(t => t.ResultMessage == $"管理员手动标记已解决: {input.ResolveNote}")
.SetColumns(t => t.ProcessedAt == DateTime.Now)
.SetColumns(t => t.UpdatedBy == operatorName)
.SetColumns(t => t.UpdatedAt == DateTime.Now)
.Where(t => t.Id == taskId && !t.IsDeleted)
.ExecuteCommandAsync();
// 记录操作日志
var detail = JsonConvert.SerializeObject(new
{
OriginalStatus = task.Status,
ResolveNote = input.ResolveNote,
TaskType = task.TaskType,
UserId = task.UserId
});
await operationLogService.LogAsync(
operatorId, operatorName,
OperationLogActionType.CompensationResolve,
OperationLogTargetType.CompensationTask,
taskId, null, detail, ipAddress);
logger.LogInformation("补偿任务标记已解决成功,TaskId: {TaskId}", taskId);
}
///
/// 获取补偿任务详情
///
public async Task GetDetailAsync(long taskId)
{
logger.LogInformation("获取补偿任务详情,TaskId: {TaskId}", taskId);
var result = await compensationTaskRepository.Queryable()
.LeftJoin((t, u) => t.UserId == u.Id)
.Where((t, u) => t.Id == taskId && !t.IsDeleted)
.Select((t, u) => new CompensationManageDetailOutput
{
Id = t.Id,
TaskType = (CompensationTaskTypeEnum)t.TaskType,
BusinessSource = t.BusinessSource,
BusinessId = t.BusinessId,
UserId = t.UserId,
UserName = u.Name,
Payload = t.Payload,
ErrorMessage = t.ErrorMessage,
ErrorSource = t.ErrorSource,
RetryCount = t.RetryCount,
MaxRetries = t.MaxRetries,
Status = (CompensationTaskStatusEnum)t.Status,
ProcessedAt = t.ProcessedAt,
ScheduledAt = t.ScheduledAt,
ResultMessage = t.ResultMessage,
CreatedAt = t.CreatedAt,
CreatedBy = t.CreatedBy,
UpdatedBy = t.UpdatedBy,
UpdatedAt = t.UpdatedAt
})
.FirstAsync();
if (result == null)
throw new BusinessException("补偿任务不存在", 404);
return result;
}
}