646 lines
27 KiB
C#
646 lines
27 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using NPP.SmartSchedue.Api.Core.Repositories;
|
|
using NPP.SmartSchedue.Api.Contracts.Domain.Integration;
|
|
using ZhonTai.Admin.Core.Db.Transaction;
|
|
using FreeSql;
|
|
|
|
namespace NPP.SmartSchedue.Api.Repositories.Integration
|
|
{
|
|
/// <summary>
|
|
/// 任务变更事件仓储实现类
|
|
///
|
|
/// 业务思考:
|
|
/// 1. 事件数据具有时序性特点,重点优化时间范围查询性能
|
|
/// 2. 支持事件状态流转和批量处理,提高系统吞吐量
|
|
/// 3. 实现智能事件优先级排序,确保重要事件及时处理
|
|
/// 4. 提供丰富的统计分析功能,支持变更监控和趋势分析
|
|
/// </summary>
|
|
public class TaskChangeEventRepository : AppRepositoryBase<TaskChangeEventEntity>, ITaskChangeEventRepository
|
|
{
|
|
public TaskChangeEventRepository(UnitOfWorkManagerCloud unitOfWorkManager) : base(unitOfWorkManager)
|
|
{
|
|
}
|
|
|
|
#region 基础查询方法
|
|
|
|
/// <summary>
|
|
/// 根据任务ID获取变更事件
|
|
/// 利用任务ID索引优化查询性能
|
|
/// </summary>
|
|
public async Task<List<TaskChangeEventEntity>> GetByTaskIdAsync(long taskId)
|
|
{
|
|
return await Select
|
|
.Where(e => e.TaskId == taskId)
|
|
.OrderByDescending(e => e.EventTime)
|
|
.ToListAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据整合记录ID获取相关变更事件
|
|
/// 用于查看特定整合记录的所有变更历史
|
|
/// </summary>
|
|
public async Task<List<TaskChangeEventEntity>> GetByIntegrationRecordIdAsync(long integrationRecordId)
|
|
{
|
|
return await Select
|
|
.Where(e => e.IntegrationRecordId == integrationRecordId)
|
|
.OrderByDescending(e => e.EventTime)
|
|
.ToListAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取待处理的变更事件
|
|
/// 按优先级和时间排序,支持事件处理队列
|
|
/// </summary>
|
|
public async Task<List<TaskChangeEventEntity>> GetPendingEventsAsync(int limit = 100)
|
|
{
|
|
return await Select
|
|
.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Pending)
|
|
.Where(e => !e.NextRetryTime.HasValue || e.NextRetryTime.Value <= DateTime.Now) // 排除还在等待重试的事件
|
|
.OrderByDescending(e => e.EventPriority) // 优先级降序
|
|
.OrderBy(e => e.EventTime) // 时间升序(优先处理早期事件)
|
|
.Take(limit)
|
|
.ToListAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取超时未处理的事件
|
|
/// 支持事件监控和告警机制
|
|
/// </summary>
|
|
public async Task<List<TaskChangeEventEntity>> GetOverdueEventsAsync()
|
|
{
|
|
var now = DateTime.Now;
|
|
|
|
return await Select
|
|
.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Pending ||
|
|
e.ProcessingStatus == TaskChangeEventProcessingStatus.Processing)
|
|
.ToListAsync()
|
|
.ContinueWith(task =>
|
|
{
|
|
var events = task.Result;
|
|
return events.Where(e => e.IsOverdue).ToList();
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 复合查询方法
|
|
|
|
/// <summary>
|
|
/// 多条件综合查询变更事件
|
|
/// 支持灵活的业务查询需求
|
|
/// </summary>
|
|
public async Task<(List<TaskChangeEventEntity> Events, long Total)> GetByMultipleConditionsAsync(
|
|
long? integrationRecordId = null,
|
|
long? rootIntegrationRecordId = null,
|
|
List<long>? taskIds = null,
|
|
List<string>? eventTypes = null,
|
|
List<string>? processingStatuses = null,
|
|
DateTime? startTime = null,
|
|
DateTime? endTime = null,
|
|
List<long>? triggeredByUserIds = null,
|
|
int? minPriority = null,
|
|
int? minImpactScore = null,
|
|
bool includeTestEvents = false,
|
|
int pageIndex = 1,
|
|
int pageSize = 20,
|
|
string sortBy = "EventTime",
|
|
string sortDirection = "Desc")
|
|
{
|
|
var query = Select;
|
|
|
|
// 动态添加查询条件
|
|
if (integrationRecordId.HasValue)
|
|
query = query.Where(e => e.IntegrationRecordId == integrationRecordId.Value);
|
|
|
|
if (rootIntegrationRecordId.HasValue)
|
|
query = query.Where(e => e.RootIntegrationRecordId == rootIntegrationRecordId.Value);
|
|
|
|
if (taskIds?.Any() == true)
|
|
query = query.Where(e => taskIds.Contains(e.TaskId));
|
|
|
|
if (eventTypes?.Any() == true)
|
|
query = query.Where(e => eventTypes.Contains(e.EventType));
|
|
|
|
if (processingStatuses?.Any() == true)
|
|
query = query.Where(e => processingStatuses.Contains(e.ProcessingStatus));
|
|
|
|
if (startTime.HasValue)
|
|
query = query.Where(e => e.EventTime >= startTime.Value);
|
|
|
|
if (endTime.HasValue)
|
|
query = query.Where(e => e.EventTime <= endTime.Value);
|
|
|
|
if (triggeredByUserIds?.Any() == true)
|
|
query = query.Where(e => e.TriggeredByUserId.HasValue && triggeredByUserIds.Contains(e.TriggeredByUserId.Value));
|
|
|
|
if (minPriority.HasValue)
|
|
query = query.Where(e => e.EventPriority >= minPriority.Value);
|
|
|
|
if (minImpactScore.HasValue)
|
|
query = query.Where(e => e.ImpactAssessmentScore >= minImpactScore.Value);
|
|
|
|
if (!includeTestEvents)
|
|
query = query.Where(e => !e.IsTestEvent);
|
|
|
|
// 排序
|
|
var sortField = sortBy.ToLower() switch
|
|
{
|
|
"priority" => nameof(TaskChangeEventEntity.EventPriority),
|
|
"impactscore" => nameof(TaskChangeEventEntity.ImpactAssessmentScore),
|
|
"status" => nameof(TaskChangeEventEntity.ProcessingStatus),
|
|
"taskid" => nameof(TaskChangeEventEntity.TaskId),
|
|
_ => nameof(TaskChangeEventEntity.EventTime)
|
|
};
|
|
|
|
ISelect<TaskChangeEventEntity> orderedQuery;
|
|
if (sortDirection.ToUpper() == "ASC")
|
|
{
|
|
orderedQuery = sortField switch
|
|
{
|
|
nameof(TaskChangeEventEntity.EventTime) => query.OrderBy(e => e.EventTime),
|
|
nameof(TaskChangeEventEntity.TaskId) => query.OrderBy(e => e.TaskId),
|
|
nameof(TaskChangeEventEntity.EventPriority) => query.OrderBy(e => e.EventPriority),
|
|
nameof(TaskChangeEventEntity.ImpactAssessmentScore) => query.OrderBy(e => e.ImpactAssessmentScore),
|
|
_ => query.OrderBy(e => e.EventTime)
|
|
};
|
|
}
|
|
else
|
|
{
|
|
orderedQuery = sortField switch
|
|
{
|
|
nameof(TaskChangeEventEntity.EventTime) => query.OrderByDescending(e => e.EventTime),
|
|
nameof(TaskChangeEventEntity.TaskId) => query.OrderByDescending(e => e.TaskId),
|
|
nameof(TaskChangeEventEntity.EventPriority) => query.OrderByDescending(e => e.EventPriority),
|
|
nameof(TaskChangeEventEntity.ImpactAssessmentScore) => query.OrderByDescending(e => e.ImpactAssessmentScore),
|
|
_ => query.OrderByDescending(e => e.EventTime)
|
|
};
|
|
}
|
|
|
|
var total = await orderedQuery.CountAsync();
|
|
var events = await orderedQuery
|
|
.Page(pageIndex, pageSize)
|
|
.ToListAsync();
|
|
|
|
return (events, total);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取指定时间段内的高影响事件
|
|
/// 支持重要事件监控和分析
|
|
/// </summary>
|
|
public async Task<List<TaskChangeEventEntity>> GetHighImpactEventsAsync(
|
|
DateTime startTime,
|
|
DateTime endTime,
|
|
int minImpactScore = 80,
|
|
int limit = 50)
|
|
{
|
|
return await Select
|
|
.Where(e => e.EventTime >= startTime && e.EventTime <= endTime)
|
|
.Where(e => e.ImpactAssessmentScore >= minImpactScore)
|
|
.Where(e => !e.IsTestEvent)
|
|
.OrderByDescending(e => e.ImpactAssessmentScore)
|
|
.OrderByDescending(e => e.EventPriority)
|
|
.Take(limit)
|
|
.ToListAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取批量处理的事件组
|
|
/// 支持事件分组批量处理机制
|
|
/// </summary>
|
|
public async Task<List<TaskChangeEventEntity>> GetBatchProcessingEventsAsync(long eventGroupId)
|
|
{
|
|
return await Select
|
|
.Where(e => e.EventGroupId == eventGroupId)
|
|
.OrderBy(e => e.EventGroupSequence)
|
|
.ToListAsync();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 状态管理方法
|
|
|
|
/// <summary>
|
|
/// 批量更新事件处理状态
|
|
/// 高效的批量状态更新操作
|
|
/// </summary>
|
|
public async Task<int> BatchUpdateProcessingStatusAsync(
|
|
List<long> eventIds,
|
|
string newStatus,
|
|
long? processedByUserId = null,
|
|
string? processedByUserName = null,
|
|
string? resultSummary = null)
|
|
{
|
|
if (!eventIds.Any())
|
|
return 0;
|
|
|
|
var updateQuery = UpdateDiy
|
|
.Set(e => e.ProcessingStatus, newStatus)
|
|
.Set(e => e.ProcessingCompletedTime, DateTime.Now)
|
|
.Where(e => eventIds.Contains(e.Id));
|
|
|
|
if (processedByUserId.HasValue)
|
|
updateQuery = updateQuery.Set(e => e.ProcessedByUserId, processedByUserId.Value);
|
|
|
|
if (!string.IsNullOrEmpty(processedByUserName))
|
|
updateQuery = updateQuery.Set(e => e.ProcessedByUserName, processedByUserName);
|
|
|
|
if (!string.IsNullOrEmpty(resultSummary))
|
|
updateQuery = updateQuery.Set(e => e.ProcessingResultSummary, resultSummary);
|
|
|
|
return await updateQuery.ExecuteAffrowsAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 标记事件开始处理
|
|
/// 设置处理开始时间和处理人员信息
|
|
/// </summary>
|
|
public async Task<bool> MarkEventProcessingAsync(
|
|
long eventId,
|
|
long processedByUserId,
|
|
string processedByUserName)
|
|
{
|
|
var affectedRows = await UpdateDiy
|
|
.Set(e => e.ProcessingStatus, TaskChangeEventProcessingStatus.Processing)
|
|
.Set(e => e.ProcessingStartTime, DateTime.Now)
|
|
.Set(e => e.ProcessedByUserId, processedByUserId)
|
|
.Set(e => e.ProcessedByUserName, processedByUserName)
|
|
.Where(e => e.Id == eventId)
|
|
.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Pending) // 确保只有待处理的事件才能开始处理
|
|
.ExecuteAffrowsAsync();
|
|
|
|
return affectedRows > 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 完成事件处理
|
|
/// 设置处理完成状态和结果信息
|
|
/// </summary>
|
|
public async Task<bool> CompleteEventProcessingAsync(
|
|
long eventId,
|
|
string resultSummary,
|
|
bool triggeredReallocation = false,
|
|
long? createdVersionId = null,
|
|
string? detailsJson = null)
|
|
{
|
|
var updateQuery = UpdateDiy
|
|
.Set(e => e.ProcessingStatus, TaskChangeEventProcessingStatus.Completed)
|
|
.Set(e => e.ProcessingCompletedTime, DateTime.Now)
|
|
.Set(e => e.ProcessingResultSummary, resultSummary)
|
|
.Set(e => e.TriggeredReallocation, triggeredReallocation)
|
|
.Where(e => e.Id == eventId)
|
|
.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Processing);
|
|
|
|
if (createdVersionId.HasValue)
|
|
updateQuery = updateQuery.Set(e => e.CreatedNewVersionId, createdVersionId.Value);
|
|
|
|
if (!string.IsNullOrEmpty(detailsJson))
|
|
updateQuery = updateQuery.Set(e => e.ProcessingDetailsJson, detailsJson);
|
|
|
|
var affectedRows = await updateQuery.ExecuteAffrowsAsync();
|
|
return affectedRows > 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 标记事件处理失败
|
|
/// 设置失败状态和错误信息,支持重试机制
|
|
/// </summary>
|
|
public async Task<bool> FailEventProcessingAsync(
|
|
long eventId,
|
|
string errorMessage,
|
|
bool shouldRetry = true)
|
|
{
|
|
var eventEntity = await GetAsync(eventId);
|
|
if (eventEntity == null)
|
|
return false;
|
|
|
|
// 使用实体方法处理失败逻辑(包含重试机制)
|
|
eventEntity.FailProcessing(errorMessage);
|
|
|
|
await UpdateAsync(eventEntity);
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 统计分析方法
|
|
|
|
/// <summary>
|
|
/// 获取事件处理统计数据
|
|
/// 支持监控面板和性能分析
|
|
/// </summary>
|
|
public async Task<EventProcessingStatistics> GetProcessingStatisticsAsync(
|
|
DateTime startTime,
|
|
DateTime endTime)
|
|
{
|
|
var events = await Select
|
|
.Where(e => e.EventTime >= startTime && e.EventTime <= endTime)
|
|
.Where(e => !e.IsTestEvent)
|
|
.ToListAsync();
|
|
|
|
if (!events.Any())
|
|
{
|
|
return new EventProcessingStatistics
|
|
{
|
|
StartTime = startTime,
|
|
EndTime = endTime
|
|
};
|
|
}
|
|
|
|
var completedEvents = events.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Completed).ToList();
|
|
var failedEvents = events.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Failed).ToList();
|
|
var pendingEvents = events.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Pending).ToList();
|
|
var overdueEvents = events.Where(e => e.IsOverdue).ToList();
|
|
|
|
return new EventProcessingStatistics
|
|
{
|
|
StartTime = startTime,
|
|
EndTime = endTime,
|
|
TotalEvents = events.Count,
|
|
CompletedEvents = completedEvents.Count,
|
|
FailedEvents = failedEvents.Count,
|
|
PendingEvents = pendingEvents.Count,
|
|
OverdueEvents = overdueEvents.Count,
|
|
AverageProcessingTime = completedEvents.Any()
|
|
? (long)completedEvents.Average(e => e.ProcessingElapsedMilliseconds)
|
|
: 0,
|
|
AverageImpactScore = events.Any()
|
|
? Math.Round((decimal)events.Average(e => e.ImpactAssessmentScore), 1)
|
|
: 0,
|
|
SuccessRate = events.Count > 0
|
|
? Math.Round((decimal)completedEvents.Count / events.Count * 100, 2)
|
|
: 0,
|
|
ReallocationTriggerCount = events.Count(e => e.TriggeredReallocation),
|
|
UniqueTaskCount = events.Select(e => e.TaskId).Distinct().Count(),
|
|
UniqueOperatorCount = events.Where(e => e.TriggeredByUserId.HasValue)
|
|
.Select(e => e.TriggeredByUserId.Value).Distinct().Count()
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取事件类型分布统计
|
|
/// 分析不同事件类型的发生频率和处理效果
|
|
/// </summary>
|
|
public async Task<List<EventTypeStatistics>> GetEventTypeStatisticsAsync(
|
|
DateTime startTime,
|
|
DateTime endTime)
|
|
{
|
|
var events = await Select
|
|
.Where(e => e.EventTime >= startTime && e.EventTime <= endTime)
|
|
.Where(e => !e.IsTestEvent)
|
|
.ToListAsync();
|
|
|
|
var typeGroups = events
|
|
.GroupBy(e => e.EventType)
|
|
.Select(g => new EventTypeStatistics
|
|
{
|
|
EventType = g.Key,
|
|
TotalCount = g.Count(),
|
|
CompletedCount = g.Count(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Completed),
|
|
FailedCount = g.Count(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Failed),
|
|
PendingCount = g.Count(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Pending),
|
|
AverageImpactScore = Math.Round((decimal)g.Average(e => e.ImpactAssessmentScore), 1),
|
|
AverageProcessingTime = g.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Completed).Any()
|
|
? (long)g.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Completed)
|
|
.Average(e => e.ProcessingElapsedMilliseconds)
|
|
: 0,
|
|
ReallocationTriggerRate = g.Count() > 0
|
|
? Math.Round((decimal)g.Count(e => e.TriggeredReallocation) / g.Count() * 100, 2)
|
|
: 0
|
|
})
|
|
.OrderByDescending(s => s.TotalCount)
|
|
.ToList();
|
|
|
|
return typeGroups;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取事件处理趋势数据
|
|
/// 生成趋势图表数据,支持性能监控
|
|
/// </summary>
|
|
public async Task<List<EventProcessingTrend>> GetProcessingTrendAsync(int days = 30)
|
|
{
|
|
var startDate = DateTime.Today.AddDays(-days + 1);
|
|
var endDate = DateTime.Today.AddDays(1);
|
|
|
|
var events = await Select
|
|
.Where(e => e.EventTime >= startDate && e.EventTime < endDate)
|
|
.Where(e => !e.IsTestEvent)
|
|
.ToListAsync();
|
|
|
|
var trends = events
|
|
.GroupBy(e => e.EventTime.Date)
|
|
.Select(g => new EventProcessingTrend
|
|
{
|
|
Date = g.Key,
|
|
TotalEvents = g.Count(),
|
|
CompletedEvents = g.Count(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Completed),
|
|
FailedEvents = g.Count(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Failed),
|
|
AverageImpactScore = Math.Round((decimal)g.Average(e => e.ImpactAssessmentScore), 1),
|
|
ReallocationTriggeredEvents = g.Count(e => e.TriggeredReallocation)
|
|
})
|
|
.OrderBy(t => t.Date)
|
|
.ToList();
|
|
|
|
// 填充没有数据的日期
|
|
var allDates = Enumerable.Range(0, days)
|
|
.Select(i => startDate.AddDays(i))
|
|
.ToList();
|
|
|
|
var completeTrends = allDates
|
|
.Select(date => trends.FirstOrDefault(t => t.Date == date) ?? new EventProcessingTrend
|
|
{
|
|
Date = date,
|
|
TotalEvents = 0,
|
|
CompletedEvents = 0,
|
|
FailedEvents = 0,
|
|
AverageImpactScore = 0,
|
|
ReallocationTriggeredEvents = 0
|
|
})
|
|
.ToList();
|
|
|
|
return completeTrends;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 业务专用方法
|
|
|
|
/// <summary>
|
|
/// 创建任务变更事件
|
|
/// 便捷的事件创建方法,自动设置基础信息
|
|
/// </summary>
|
|
public async Task<TaskChangeEventEntity> CreateTaskChangeEventAsync(
|
|
long taskId,
|
|
string taskCode,
|
|
string eventType,
|
|
long? integrationRecordId = null,
|
|
long? rootIntegrationRecordId = null,
|
|
string changedFields = "",
|
|
Dictionary<string, object>? beforeValues = null,
|
|
Dictionary<string, object>? afterValues = null,
|
|
long? triggeredByUserId = null,
|
|
string triggeredByUserName = "",
|
|
string eventSource = "Manual",
|
|
int eventPriority = 5)
|
|
{
|
|
var eventEntity = new TaskChangeEventEntity
|
|
{
|
|
TaskId = taskId,
|
|
TaskCode = taskCode,
|
|
IntegrationRecordId = integrationRecordId,
|
|
RootIntegrationRecordId = rootIntegrationRecordId,
|
|
EventType = eventType,
|
|
ChangedFields = changedFields,
|
|
EventTime = DateTime.Now,
|
|
TriggeredByUserId = triggeredByUserId,
|
|
TriggeredByUserName = triggeredByUserName,
|
|
EventSource = eventSource,
|
|
EventPriority = eventPriority,
|
|
ProcessingStatus = TaskChangeEventProcessingStatus.Pending,
|
|
RequiresNotification = true,
|
|
NotificationStatus = "NotSent"
|
|
};
|
|
|
|
// 设置变更前后值
|
|
if (beforeValues?.Any() == true)
|
|
eventEntity.SetBeforeValues(beforeValues);
|
|
|
|
if (afterValues?.Any() == true)
|
|
eventEntity.SetAfterValues(afterValues);
|
|
|
|
// 计算影响评估评分
|
|
eventEntity.ImpactAssessmentScore = eventEntity.CalculateImpactScore();
|
|
|
|
return await InsertAsync(eventEntity);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取可重试的失败事件
|
|
/// 支持自动重试机制
|
|
/// </summary>
|
|
public async Task<List<TaskChangeEventEntity>> GetRetryableFailedEventsAsync(int limit = 50)
|
|
{
|
|
return await Select
|
|
.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Pending) // 失败后重置为Pending状态
|
|
.Where(e => e.RetryCount < e.MaxRetryCount)
|
|
.Where(e => !e.NextRetryTime.HasValue || e.NextRetryTime.Value <= DateTime.Now)
|
|
.OrderByDescending(e => e.EventPriority)
|
|
.OrderBy(e => e.NextRetryTime)
|
|
.Take(limit)
|
|
.ToListAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清理过期的已完成事件
|
|
/// 定期数据清理,保持系统性能
|
|
/// </summary>
|
|
public async Task<int> ArchiveCompletedEventsAsync(DateTime beforeDate)
|
|
{
|
|
// 这里可以实现将完成的事件迁移到历史表的逻辑
|
|
// 暂时使用软删除处理
|
|
var archivedCount = await UpdateDiy
|
|
.Set(e => e.IsDeleted, true)
|
|
.Set(e => e.ModifiedTime, DateTime.Now)
|
|
.Where(e => e.ProcessingStatus == TaskChangeEventProcessingStatus.Completed)
|
|
.Where(e => e.ProcessingCompletedTime.HasValue && e.ProcessingCompletedTime.Value < beforeDate)
|
|
.Where(e => !e.IsDeleted)
|
|
.ExecuteAffrowsAsync();
|
|
|
|
return archivedCount;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>
|
|
/// 任务变更事件仓储接口
|
|
/// </summary>
|
|
public interface ITaskChangeEventRepository : ZhonTai.Admin.Core.Repositories.IRepositoryBase<TaskChangeEventEntity>
|
|
{
|
|
Task<List<TaskChangeEventEntity>> GetByTaskIdAsync(long taskId);
|
|
Task<List<TaskChangeEventEntity>> GetByIntegrationRecordIdAsync(long integrationRecordId);
|
|
Task<List<TaskChangeEventEntity>> GetPendingEventsAsync(int limit = 100);
|
|
Task<List<TaskChangeEventEntity>> GetOverdueEventsAsync();
|
|
Task<(List<TaskChangeEventEntity> Events, long Total)> GetByMultipleConditionsAsync(
|
|
long? integrationRecordId = null,
|
|
long? rootIntegrationRecordId = null,
|
|
List<long>? taskIds = null,
|
|
List<string>? eventTypes = null,
|
|
List<string>? processingStatuses = null,
|
|
DateTime? startTime = null,
|
|
DateTime? endTime = null,
|
|
List<long>? triggeredByUserIds = null,
|
|
int? minPriority = null,
|
|
int? minImpactScore = null,
|
|
bool includeTestEvents = false,
|
|
int pageIndex = 1,
|
|
int pageSize = 20,
|
|
string sortBy = "EventTime",
|
|
string sortDirection = "Desc");
|
|
Task<List<TaskChangeEventEntity>> GetHighImpactEventsAsync(DateTime startTime, DateTime endTime, int minImpactScore = 80, int limit = 50);
|
|
Task<List<TaskChangeEventEntity>> GetBatchProcessingEventsAsync(long eventGroupId);
|
|
Task<int> BatchUpdateProcessingStatusAsync(List<long> eventIds, string newStatus, long? processedByUserId = null, string? processedByUserName = null, string? resultSummary = null);
|
|
Task<bool> MarkEventProcessingAsync(long eventId, long processedByUserId, string processedByUserName);
|
|
Task<bool> CompleteEventProcessingAsync(long eventId, string resultSummary, bool triggeredReallocation = false, long? createdVersionId = null, string? detailsJson = null);
|
|
Task<bool> FailEventProcessingAsync(long eventId, string errorMessage, bool shouldRetry = true);
|
|
Task<TaskChangeEventEntity> CreateTaskChangeEventAsync(long taskId, string taskCode, string eventType, long? integrationRecordId = null, long? rootIntegrationRecordId = null, string changedFields = "", Dictionary<string, object>? beforeValues = null, Dictionary<string, object>? afterValues = null, long? triggeredByUserId = null, string triggeredByUserName = "", string eventSource = "Manual", int eventPriority = 5);
|
|
Task<List<TaskChangeEventEntity>> GetRetryableFailedEventsAsync(int limit = 50);
|
|
Task<int> ArchiveCompletedEventsAsync(DateTime beforeDate);
|
|
}
|
|
|
|
#region 统计数据DTO类
|
|
|
|
/// <summary>
|
|
/// 事件处理统计数据
|
|
/// </summary>
|
|
public class EventProcessingStatistics
|
|
{
|
|
public DateTime StartTime { get; set; }
|
|
public DateTime EndTime { get; set; }
|
|
public int TotalEvents { get; set; }
|
|
public int CompletedEvents { get; set; }
|
|
public int FailedEvents { get; set; }
|
|
public int PendingEvents { get; set; }
|
|
public int OverdueEvents { get; set; }
|
|
public long AverageProcessingTime { get; set; }
|
|
public decimal AverageImpactScore { get; set; }
|
|
public decimal SuccessRate { get; set; }
|
|
public int ReallocationTriggerCount { get; set; }
|
|
public int UniqueTaskCount { get; set; }
|
|
public int UniqueOperatorCount { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 事件类型统计数据
|
|
/// </summary>
|
|
public class EventTypeStatistics
|
|
{
|
|
public string EventType { get; set; } = string.Empty;
|
|
public int TotalCount { get; set; }
|
|
public int CompletedCount { get; set; }
|
|
public int FailedCount { get; set; }
|
|
public int PendingCount { get; set; }
|
|
public decimal AverageImpactScore { get; set; }
|
|
public long AverageProcessingTime { get; set; }
|
|
public decimal ReallocationTriggerRate { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 事件处理趋势数据
|
|
/// </summary>
|
|
public class EventProcessingTrend
|
|
{
|
|
public DateTime Date { get; set; }
|
|
public int TotalEvents { get; set; }
|
|
public int CompletedEvents { get; set; }
|
|
public int FailedEvents { get; set; }
|
|
public decimal AverageImpactScore { get; set; }
|
|
public int ReallocationTriggeredEvents { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
} |