paiban/NPP.SmartSchedue.Api/Repositories/Integration/IntegrationRecordRepository.cs
Asoka.Wang 21f044712c 1
2025-08-27 18:39:19 +08:00

524 lines
20 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FreeSql;
using NPP.SmartSchedue.Api.Core.Repositories;
using NPP.SmartSchedue.Api.Contracts.Domain.Integration;
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
using ZhonTai.Admin.Core.Db.Transaction;
namespace NPP.SmartSchedue.Api.Repositories.Integration
{
/// <summary>
/// 智能整合记录仓储实现类
///
/// 业务实现思考:
/// 1. 充分利用FreeSql的强大功能包括分页、索引优化、JSON查询等
/// 2. 考虑查询性能,合理使用索引和查询优化策略
/// 3. 实现完整的统计分析功能,为业务决策提供数据支持
/// 4. 处理大数据量场景,提供高效的分页和聚合查询
/// </summary>
public class IntegrationRecordRepository : AppRepositoryBase<IntegrationRecordEntity>, IIntegrationRecordRepository
{
public IntegrationRecordRepository(UnitOfWorkManagerCloud unitOfWorkManager) : base(unitOfWorkManager)
{
}
#region
/// <summary>
/// 根据批次编码获取整合记录
/// 利用唯一索引,确保查询性能
/// </summary>
public async Task<IntegrationRecordEntity?> GetByBatchCodeAsync(string batchCode)
{
if (string.IsNullOrWhiteSpace(batchCode))
return null;
return await Select
.Where(r => r.IntegrationBatchCode == batchCode)
.FirstAsync();
}
/// <summary>
/// 获取指定时间范围内的整合记录
/// 使用时间索引优化查询性能
/// </summary>
public async Task<(List<IntegrationRecordEntity> Records, long Total)> GetByTimeRangeAsync(
DateTime startTime,
DateTime endTime,
int pageIndex = 1,
int pageSize = 20)
{
var query = Select
.Where(r => r.IntegrationTime >= startTime && r.IntegrationTime <= endTime)
.OrderByDescending(r => r.IntegrationTime);
var total = await query.CountAsync();
var records = await query
.Page(pageIndex, pageSize)
.ToListAsync();
return (records, total);
}
/// <summary>
/// 根据操作人员获取整合记录
/// 使用操作员索引优化查询
/// </summary>
public async Task<(List<IntegrationRecordEntity> Records, long Total)> GetByOperatorAsync(
long operatorUserId,
int pageIndex = 1,
int pageSize = 20)
{
var query = Select
.Where(r => r.OperatorUserId == operatorUserId)
.OrderByDescending(r => r.IntegrationTime);
var total = await query.CountAsync();
var records = await query
.Page(pageIndex, pageSize)
.ToListAsync();
return (records, total);
}
/// <summary>
/// 根据项目编号获取相关整合记录
/// 使用字符串包含查询,注意性能优化
/// </summary>
public async Task<(List<IntegrationRecordEntity> Records, long Total)> GetByProjectNumberAsync(
string projectNumber,
int pageIndex = 1,
int pageSize = 20)
{
if (string.IsNullOrWhiteSpace(projectNumber))
return (new List<IntegrationRecordEntity>(), 0);
var query = Select
.Where(r => r.ProjectNumbers.Contains(projectNumber))
.OrderByDescending(r => r.IntegrationTime);
var total = await query.CountAsync();
var records = await query
.Page(pageIndex, pageSize)
.ToListAsync();
return (records, total);
}
#endregion
#region
/// <summary>
/// 多维度综合查询整合记录
/// 动态构建查询条件,支持灵活的业务查询需求
/// </summary>
public async Task<(List<IntegrationRecordEntity> Records, long Total)> GetByMultipleConditionsAsync(
long? operatorUserId = null,
string? projectNumber = null,
string? integrationType = null,
DateTime? startTime = null,
DateTime? endTime = null,
decimal? minSuccessRate = null,
int pageIndex = 1,
int pageSize = 20)
{
var query = Select;
// 动态添加查询条件
if (operatorUserId.HasValue)
{
query = query.Where(r => r.OperatorUserId == operatorUserId.Value);
}
if (!string.IsNullOrWhiteSpace(projectNumber))
{
query = query.Where(r => r.ProjectNumbers.Contains(projectNumber));
}
if (!string.IsNullOrWhiteSpace(integrationType))
{
query = query.Where(r => r.IntegrationType == integrationType);
}
if (startTime.HasValue)
{
query = query.Where(r => r.IntegrationTime >= startTime.Value);
}
if (endTime.HasValue)
{
query = query.Where(r => r.IntegrationTime <= endTime.Value);
}
if (minSuccessRate.HasValue)
{
// 使用计算字段进行筛选
query = query.Where(r => r.SuccessTaskCount + r.FailedTaskCount > 0)
.Where(r => (decimal)r.SuccessTaskCount / (r.SuccessTaskCount + r.FailedTaskCount) * 100 >= minSuccessRate.Value);
}
var orderedQuery = query.OrderByDescending(r => r.IntegrationTime);
var total = await orderedQuery.CountAsync();
var records = await orderedQuery
.Page(pageIndex, pageSize)
.ToListAsync();
return (records, total);
}
/// <summary>
/// 获取包含指定任务的整合记录
/// 使用JSON查询功能在TaskIdsJson中搜索任务ID
/// </summary>
public async Task<List<IntegrationRecordEntity>> GetRecordsContainingTaskAsync(long taskId)
{
// 使用FreeSql的JSON查询功能支持JSON数组格式
return await Select
.Where(r => r.TaskIdsJson.Contains($"\"{taskId}\"") || r.TaskIdsJson.Contains($"{taskId}"))
.OrderByDescending(r => r.IntegrationTime)
.ToListAsync();
}
#endregion
#region
/// <summary>
/// 获取指定时间段的整合统计数据
/// 使用聚合查询生成统计报表
/// </summary>
public async Task<IntegrationStatistics> GetIntegrationStatisticsAsync(DateTime startTime, DateTime endTime)
{
var records = await Select
.Where(r => r.IntegrationTime >= startTime && r.IntegrationTime <= endTime)
.Where(r => !r.IsTestData) // 排除测试数据
.ToListAsync();
if (!records.Any())
{
return new IntegrationStatistics
{
StartTime = startTime,
EndTime = endTime
};
}
var totalTasks = records.Sum(r => r.SuccessTaskCount + r.FailedTaskCount);
var successfulTasks = records.Sum(r => r.SuccessTaskCount);
var failedTasks = records.Sum(r => r.FailedTaskCount);
return new IntegrationStatistics
{
StartTime = startTime,
EndTime = endTime,
TotalIntegrations = records.Count,
TotalTasks = totalTasks,
SuccessfulTasks = successfulTasks,
FailedTasks = failedTasks,
AverageSuccessRate = totalTasks > 0 ? Math.Round((decimal)successfulTasks / totalTasks * 100, 2) : 0,
AverageElapsedTime = records.Any() ? (long)records.Average(r => r.ElapsedMilliseconds) : 0,
AveragePersonnelFairnessScore = records.Any() ? Math.Round((decimal)records.Average(r => r.PersonnelFairnessScore), 1) : 0,
AverageEquipmentUtilizationRate = records.Any() ? Math.Round(records.Average(r => r.EquipmentUtilizationRate), 1) : 0,
ActiveOperatorCount = records.Select(r => r.OperatorUserId).Distinct().Count(),
InvolvedProjectCount = records
.Where(r => !string.IsNullOrWhiteSpace(r.ProjectNumbers))
.SelectMany(r => r.GetProjectNumbers())
.Distinct()
.Count()
};
}
/// <summary>
/// 获取操作员整合统计数据
/// 针对特定操作员的详细统计分析
/// </summary>
public async Task<OperatorIntegrationStats> GetOperatorStatisticsAsync(
long operatorUserId,
DateTime startTime,
DateTime endTime)
{
var records = await Select
.Where(r => r.OperatorUserId == operatorUserId)
.Where(r => r.IntegrationTime >= startTime && r.IntegrationTime <= endTime)
.Where(r => !r.IsTestData)
.OrderByDescending(r => r.IntegrationTime)
.ToListAsync();
if (!records.Any())
{
var operatorInfo = await Select
.Where(r => r.OperatorUserId == operatorUserId)
.OrderByDescending(r => r.IntegrationTime)
.FirstAsync();
return new OperatorIntegrationStats
{
OperatorUserId = operatorUserId,
OperatorUserName = operatorInfo?.OperatorUserName ?? "",
OperatorRealName = operatorInfo?.OperatorRealName ?? ""
};
}
var totalTasks = records.Sum(r => r.SuccessTaskCount + r.FailedTaskCount);
var successfulTasks = records.Sum(r => r.SuccessTaskCount);
return new OperatorIntegrationStats
{
OperatorUserId = operatorUserId,
OperatorUserName = records.First().OperatorUserName,
OperatorRealName = records.First().OperatorRealName,
IntegrationCount = records.Count,
TotalTasks = totalTasks,
AverageSuccessRate = totalTasks > 0 ? Math.Round((decimal)successfulTasks / totalTasks * 100, 2) : 0,
TotalElapsedTime = records.Sum(r => r.ElapsedMilliseconds),
AverageIntegrationTime = records.Any() ? (long)records.Average(r => r.ElapsedMilliseconds) : 0,
LastOperationTime = records.Max(r => r.IntegrationTime)
};
}
/// <summary>
/// 获取策略效果分析数据
/// 分析不同分配策略的效果,支持策略优化决策
/// </summary>
public async Task<List<StrategyEffectivenessStats>> GetStrategyEffectivenessAsync(
DateTime startTime,
DateTime endTime)
{
var records = await Select
.Where(r => r.IntegrationTime >= startTime && r.IntegrationTime <= endTime)
.Where(r => !r.IsTestData)
.ToListAsync();
if (!records.Any())
return new List<StrategyEffectivenessStats>();
// 解析策略配置并进行分组统计
var strategyGroups = records
.Where(r => !string.IsNullOrWhiteSpace(r.StrategyConfigJson))
.GroupBy(r => r.StrategyConfigJson) // 按策略配置JSON分组
.Select(g => new StrategyEffectivenessStats
{
PersonnelStrategy = ExtractPersonnelStrategyFromJson(g.Key),
EquipmentStrategy = ExtractEquipmentStrategyFromJson(g.Key),
UsageCount = g.Count(),
AverageSuccessRate = CalculateGroupSuccessRate(g.ToList()),
AveragePersonnelFairnessScore = Math.Round((decimal)g.Average(r => r.PersonnelFairnessScore), 1),
AverageEquipmentUtilizationRate = Math.Round(g.Average(r => r.EquipmentUtilizationRate), 1),
AverageElapsedTime = (long)g.Average(r => r.ElapsedMilliseconds)
})
.OrderByDescending(s => s.UsageCount)
.ToList();
return strategyGroups;
}
/// <summary>
/// 获取整合性能趋势数据
/// 生成性能趋势图表数据,支持性能监控
/// </summary>
public async Task<List<IntegrationPerformanceTrend>> GetPerformanceTrendAsync(int days = 30)
{
var startDate = DateTime.Today.AddDays(-days + 1);
var endDate = DateTime.Today.AddDays(1);
var records = await Select
.Where(r => r.IntegrationTime >= startDate && r.IntegrationTime < endDate)
.Where(r => !r.IsTestData)
.ToListAsync();
var trends = records
.GroupBy(r => r.IntegrationTime.Date)
.Select(g => new IntegrationPerformanceTrend
{
Date = g.Key,
IntegrationCount = g.Count(),
AverageSuccessRate = CalculateGroupSuccessRate(g.ToList()),
AverageElapsedTime = (long)g.Average(r => r.ElapsedMilliseconds),
TotalTasks = g.Sum(r => r.SuccessTaskCount + r.FailedTaskCount)
})
.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 IntegrationPerformanceTrend
{
Date = date,
IntegrationCount = 0,
AverageSuccessRate = 0,
AverageElapsedTime = 0,
TotalTasks = 0
})
.ToList();
return completeTrends;
}
#endregion
#region
/// <summary>
/// 检查批次编码是否已存在
/// 利用唯一索引快速查询
/// </summary>
public async Task<bool> BatchCodeExistsAsync(string batchCode)
{
if (string.IsNullOrWhiteSpace(batchCode))
return false;
return await Select
.Where(r => r.IntegrationBatchCode == batchCode)
.AnyAsync();
}
/// <summary>
/// 获取最近的整合记录
/// 支持监控面板和快速状态查看
/// </summary>
public async Task<List<IntegrationRecordEntity>> GetRecentRecordsAsync(int count = 10)
{
return await Select
.Where(r => !r.IsTestData)
.OrderByDescending(r => r.IntegrationTime)
.Take(count)
.ToListAsync();
}
/// <summary>
/// 获取失败率高的整合记录
/// 支持质量监控和问题识别
/// </summary>
public async Task<List<IntegrationRecordEntity>> GetHighFailureRateRecordsAsync(
decimal minFailureRate,
DateTime startTime,
DateTime endTime,
int count = 50)
{
return await Select
.Where(r => r.IntegrationTime >= startTime && r.IntegrationTime <= endTime)
.Where(r => !r.IsTestData)
.Where(r => r.SuccessTaskCount + r.FailedTaskCount > 0) // 确保有任务数据
.ToListAsync()
.ContinueWith(task =>
{
var records = task.Result;
return records
.Where(r =>
{
var totalTasks = r.SuccessTaskCount + r.FailedTaskCount;
var failureRate = totalTasks > 0 ? (decimal)r.FailedTaskCount / totalTasks * 100 : 0;
return failureRate >= minFailureRate;
})
.OrderByDescending(r => (decimal)r.FailedTaskCount / (r.SuccessTaskCount + r.FailedTaskCount))
.Take(count)
.ToList();
});
}
/// <summary>
/// 软删除过期的测试数据
/// 定期数据清理,保持系统性能
/// </summary>
public async Task<int> SoftDeleteExpiredTestDataAsync(DateTime beforeDate)
{
var expiredRecords = await Select
.Where(r => r.IsTestData && r.CreatedTime < beforeDate)
.Where(r => !r.IsDeleted)
.ToListAsync();
if (!expiredRecords.Any())
return 0;
// 批量软删除
var deletedCount = await UpdateDiy
.Set(r => r.IsDeleted, true)
.Set(r => r.ModifiedTime, DateTime.Now)
.Where(r => expiredRecords.Select(er => er.Id).Contains(r.Id))
.ExecuteAffrowsAsync();
return deletedCount;
}
#endregion
#region
/// <summary>
/// 从策略JSON中提取人员策略
/// </summary>
private string ExtractPersonnelStrategyFromJson(string strategyConfigJson)
{
try
{
if (string.IsNullOrWhiteSpace(strategyConfigJson))
return "未知";
using var document = System.Text.Json.JsonDocument.Parse(strategyConfigJson);
var root = document.RootElement;
if (root.TryGetProperty("PersonnelStrategy", out var personnelStrategyProp))
{
return personnelStrategyProp.GetString() ?? "未知";
}
return "未知";
}
catch
{
return "未知";
}
}
/// <summary>
/// 从策略JSON中提取设备策略
/// </summary>
private string ExtractEquipmentStrategyFromJson(string strategyConfigJson)
{
try
{
if (string.IsNullOrWhiteSpace(strategyConfigJson))
return "未知";
using var document = System.Text.Json.JsonDocument.Parse(strategyConfigJson);
var root = document.RootElement;
if (root.TryGetProperty("EquipmentStrategy", out var equipmentStrategyProp))
{
return equipmentStrategyProp.GetString() ?? "未知";
}
return "未知";
}
catch
{
return "未知";
}
}
/// <summary>
/// 计算分组的平均成功率
/// </summary>
private decimal CalculateGroupSuccessRate(List<IntegrationRecordEntity> records)
{
if (!records.Any())
return 0;
var totalTasks = records.Sum(r => r.SuccessTaskCount + r.FailedTaskCount);
var successfulTasks = records.Sum(r => r.SuccessTaskCount);
return totalTasks > 0 ? Math.Round((decimal)successfulTasks / totalTasks * 100, 2) : 0;
}
#endregion
}
}