Files
OrpaonVision/OrpaonVision.SiteApp/Runtime/Services/ManualOverrideService.cs
2026-04-12 22:34:46 +08:00

2099 lines
90 KiB
C#
Raw Permalink 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 Microsoft.Extensions.Options;
using OrpaonVision.Core.ManualOverride;
using OrpaonVision.Core.Results;
using OrpaonVision.Core.Common;
using System.Collections.Concurrent;
using System.Text.Json;
using CoreAuditLevel = OrpaonVision.Core.ManualOverride.AuditLevel;
using OrpaonVision.SiteApp.Runtime.Services;
using RuntimeOptions = OrpaonVision.SiteApp.Runtime.Options.RuntimeOptions;
namespace OrpaonVision.SiteApp.Runtime.Services;
/// <summary>
/// 人工复位放行服务实现,集成状态机和审计功能。
/// </summary>
public sealed class ManualOverrideService : IManualOverrideService
{
private readonly ILogger<ManualOverrideService> _logger;
private readonly IRuntimeStateMachineService _stateMachineService;
private readonly RuntimeOptions _options;
private readonly ConcurrentDictionary<string, object> _overrideCache = new();
private readonly object _lock = new();
public ManualOverrideService(
ILogger<ManualOverrideService> logger,
IOptions<RuntimeOptions> options,
IRuntimeStateMachineService stateMachineService)
{
_logger = logger;
_options = options.Value;
_stateMachineService = stateMachineService;
_logger.LogInformation("人工复位放行服务已初始化");
}
public Task<Result<IReadOnlyList<OverrideableSession>>> GetOverrideableSessionsAsync(DateTime startTime, DateTime endTime, string? productTypeCode = null, OverrideStatus? overrideStatus = null, CancellationToken cancellationToken = default)
{
IReadOnlyList<OverrideableSession> sessions = Array.Empty<OverrideableSession>();
return Task.FromResult(Result<IReadOnlyList<OverrideableSession>>.Success(sessions));
}
public Task<Result<OverridePermission>> GetOverridePermissionAsync(Guid sessionId, string operatorId, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("获取会话复位放行权限会话ID={SessionId}操作员ID={OperatorId}", sessionId, operatorId);
// 检查当前状态机状态是否允许人工干预
var currentState = _stateMachineService.GetCurrentState();
var canIntervene = _stateMachineService.CanExecuteOperation(StateTrigger.ManualIntervention);
if (!canIntervene)
{
var permission = new OverridePermission
{
PermissionId = Guid.NewGuid(),
SessionId = sessionId,
OperatorId = operatorId,
OperatorName = operatorId,
OperatorPermissionLevel = OperatorPermissionLevel.Operator,
HasPermission = false,
PermissionReason = $"当前状态 {currentState} 不允许人工干预"
};
return Task.FromResult(Result<OverridePermission>.Success(permission));
}
// 检查操作员权限级别
var permissionLevel = GetOperatorPermissionLevel(operatorId);
var hasPermission = CheckOverridePermission(sessionId, operatorId, permissionLevel);
var result = new OverridePermission
{
PermissionId = Guid.NewGuid(),
SessionId = sessionId,
OperatorId = operatorId,
OperatorName = operatorId,
OperatorPermissionLevel = permissionLevel,
HasPermission = hasPermission,
PermissionReason = hasPermission
? $"权限检查通过,当前状态 {currentState} 允许干预"
: $"权限不足,需要 {OperatorPermissionLevel.Administrator} 级别权限"
};
_logger.LogInformation("复位放行权限获取完成会话ID={SessionId}操作员ID={OperatorId},是否有权限={HasPermission},权限级别={PermissionLevel},当前状态={CurrentState}",
sessionId, operatorId, result.HasPermission, permissionLevel, currentState);
return Task.FromResult(Result<OverridePermission>.Success(result));
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取复位放行权限失败。TraceId: {TraceId}", traceId);
return Task.FromResult(Result<OverridePermission>.FailWithTrace("GET_OVERRIDE_PERMISSION_FAILED", "获取复位放行权限失败", traceId));
}
}
public Task<Result<OverrideValidationResult>> ValidateOverrideConditionsAsync(Guid sessionId, ManualOverrideRequest overrideRequest, CancellationToken cancellationToken = default)
{
var result = new OverrideValidationResult
{
ValidationId = Guid.NewGuid(),
SessionId = sessionId,
RequestId = overrideRequest.RequestId,
IsValid = true,
ValidationResult = ValidationResult.Pass,
ValidationMessage = "最小实现:验证通过",
ValidationTimeUtc = DateTime.UtcNow,
ValidationElapsedMs = 0
};
return Task.FromResult(Result<OverrideValidationResult>.Success(result));
}
public async Task<Result<ManualOverrideResult>> ExecuteManualOverrideAsync(ManualOverrideRequest overrideRequest, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("执行人工复位放行请求ID={RequestId}会话ID={SessionId}操作员ID={OperatorId},干预类型={OverrideType}",
overrideRequest.RequestId, overrideRequest.SessionId, overrideRequest.OperatorId, overrideRequest.OverrideType);
var startTime = DateTime.UtcNow;
// 步骤1权限校验
var permissionResult = await GetOverridePermissionAsync(overrideRequest.SessionId, overrideRequest.OperatorId, cancellationToken);
if (!permissionResult.IsSuccess)
{
return Result<ManualOverrideResult>.FailWithTrace(permissionResult.Code, permissionResult.Message, permissionResult.TraceId);
}
if (!permissionResult.Data.HasPermission)
{
return Result<ManualOverrideResult>.Fail("PERMISSION_DENIED", permissionResult.Data.PermissionReason);
}
// 步骤2条件验证
var validationResult = await ValidateOverrideConditionsAsync(overrideRequest.SessionId, overrideRequest, cancellationToken);
if (!validationResult.IsSuccess)
{
return Result<ManualOverrideResult>.FailWithTrace(validationResult.Code, validationResult.Message, validationResult.TraceId);
}
if (!validationResult.Data.IsValid)
{
return Result<ManualOverrideResult>.Fail("VALIDATION_FAILED", validationResult.Data.ValidationMessage);
}
// 步骤3状态迁移
var stateTransitionResult = await ExecuteStateTransitionAsync(overrideRequest, cancellationToken);
if (!stateTransitionResult.IsSuccess)
{
return Result<ManualOverrideResult>.FailWithTrace(stateTransitionResult.Code, stateTransitionResult.Message, stateTransitionResult.TraceId);
}
// 步骤4执行具体干预操作
var overrideResult = await ExecuteOverrideOperationAsync(overrideRequest, cancellationToken);
// 步骤5审计记录
await LogOverrideAuditAsync(overrideRequest, overrideResult, startTime, cancellationToken);
var elapsed = DateTime.UtcNow - startTime;
var result = new ManualOverrideResult
{
OverrideId = Guid.NewGuid(),
RequestId = overrideRequest.RequestId,
SessionId = overrideRequest.SessionId,
OverrideResult = overrideResult,
OverrideStatus = overrideResult == OverrideResult.Success ? OverrideStatus.Overridden : OverrideStatus.Pending,
OverrideMessage = GetOverrideMessage(overrideResult),
ExecutionTimeUtc = DateTime.UtcNow,
ExecutionElapsedMs = (long)elapsed.TotalMilliseconds,
Executor = overrideRequest.OperatorName,
AffectedSessionStatus = GetSessionStatusAfterOverride(overrideRequest.OverrideType)
};
_logger.LogInformation("人工复位放行执行完成请求ID={RequestId},干预类型={OverrideType},结果={OverrideResult},耗时={ElapsedMs}ms",
overrideRequest.RequestId, overrideRequest.OverrideType, overrideResult, elapsed.TotalMilliseconds);
return Result<ManualOverrideResult>.Success(result);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "执行人工复位放行失败。TraceId: {TraceId}", traceId);
return Result<ManualOverrideResult>.FailWithTrace("EXECUTE_MANUAL_OVERRIDE_FAILED", "执行人工复位放行失败", traceId);
}
}
/// <summary>
/// 执行状态迁移。
/// </summary>
private async Task<Result> ExecuteStateTransitionAsync(ManualOverrideRequest overrideRequest, CancellationToken cancellationToken)
{
try
{
var currentState = _stateMachineService.GetCurrentState();
// 统一触发“人工干预”状态转换
var triggerResult = _stateMachineService.TriggerTransition(
StateTrigger.ManualIntervention,
$"人工干预: {overrideRequest.OverrideType}");
if (!triggerResult.IsSuccess)
{
_logger.LogWarning("状态迁移失败:当前状态={CurrentState},干预类型={OverrideType},错误={Error}",
currentState, overrideRequest.OverrideType, triggerResult.Message);
return Result.Fail("STATE_TRANSITION_FAILED", triggerResult.Message);
}
_logger.LogInformation("状态迁移成功:从 {PreviousState} 迁移到 {NewState},干预类型={OverrideType}",
triggerResult.Data?.PreviousState, triggerResult.Data?.NewState, overrideRequest.OverrideType);
return Result.Success();
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "执行状态迁移失败。TraceId: {TraceId}", traceId);
return Result.FailWithTrace("STATE_TRANSITION_ERROR", "执行状态迁移失败", traceId);
}
}
/// <summary>
/// 执行具体干预操作。
/// </summary>
private async Task<OverrideResult> ExecuteOverrideOperationAsync(ManualOverrideRequest overrideRequest, CancellationToken cancellationToken)
{
try
{
// 根据干预类型执行具体操作
var result = overrideRequest.OverrideType switch
{
OverrideType.ResetAndRelease => await ExecuteResetOperationAsync(overrideRequest, cancellationToken),
OverrideType.ForcePass => await ExecuteReleaseOperationAsync(overrideRequest, cancellationToken),
OverrideType.SkipInspection => await ExecuteSkipLayerOperationAsync(overrideRequest, cancellationToken),
_ => OverrideResult.Success // 默认成功
};
_logger.LogDebug("干预操作执行完成:干预类型={OverrideType},结果={Result}", overrideRequest.OverrideType, result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "干预操作执行失败:干预类型={OverrideType}", overrideRequest.OverrideType);
return OverrideResult.Failed;
}
}
/// <summary>
/// 执行放行操作。
/// </summary>
private async Task<OverrideResult> ExecuteReleaseOperationAsync(ManualOverrideRequest overrideRequest, CancellationToken cancellationToken)
{
// 触发人工干预完成状态转换,返回运行状态
var completionResult = _stateMachineService.TriggerTransition(StateTrigger.ManualInterventionCompleted, "人工放行完成");
if (completionResult.IsSuccess)
{
_logger.LogInformation("放行操作完成会话ID={SessionId},操作员={OperatorId}",
overrideRequest.SessionId, overrideRequest.OperatorId);
return OverrideResult.Success;
}
else
{
_logger.LogWarning("放行操作失败:{Error}", completionResult.Message);
return OverrideResult.Failed;
}
}
/// <summary>
/// 执行复位操作。
/// </summary>
private async Task<OverrideResult> ExecuteResetOperationAsync(ManualOverrideRequest overrideRequest, CancellationToken cancellationToken)
{
// 触发重置状态转换
var resetResult = _stateMachineService.TriggerTransition(StateTrigger.Reset, "人工复位");
if (resetResult.IsSuccess)
{
_logger.LogInformation("复位操作完成会话ID={SessionId},操作员={OperatorId}",
overrideRequest.SessionId, overrideRequest.OperatorId);
return OverrideResult.Success;
}
else
{
_logger.LogWarning("复位操作失败:{Error}", resetResult.Message);
return OverrideResult.Failed;
}
}
/// <summary>
/// 执行跳层操作。
/// </summary>
private async Task<OverrideResult> ExecuteSkipLayerOperationAsync(ManualOverrideRequest overrideRequest, CancellationToken cancellationToken)
{
// 先完成人工干预,然后移动到下一层
var completionResult = _stateMachineService.TriggerTransition(StateTrigger.ManualInterventionCompleted, "人工跳层完成");
if (completionResult.IsSuccess)
{
var nextLayerResult = _stateMachineService.TriggerTransition(StateTrigger.MoveToNextLayer, "人工跳层到下一层");
if (nextLayerResult.IsSuccess)
{
_logger.LogInformation("跳层操作完成会话ID={SessionId},操作员={OperatorId},当前层级={CurrentLayer}",
overrideRequest.SessionId, overrideRequest.OperatorId, _stateMachineService.GetCurrentLayer());
return OverrideResult.Success;
}
else
{
_logger.LogWarning("跳层操作失败:{Error}", nextLayerResult.Message);
return OverrideResult.Failed;
}
}
else
{
_logger.LogWarning("跳层操作失败(人工干预完成阶段):{Error}", completionResult.Message);
return OverrideResult.Failed;
}
}
/// <summary>
/// 记录审计日志。
/// </summary>
private async Task LogOverrideAuditAsync(ManualOverrideRequest request, OverrideResult result, DateTime startTime, CancellationToken cancellationToken)
{
try
{
var currentState = _stateMachineService.GetCurrentState();
var currentLayer = _stateMachineService.GetCurrentLayer();
var auditLog = new OverrideAuditLog
{
LogId = Guid.NewGuid(),
SessionId = request.SessionId,
OverrideId = Guid.NewGuid(),
OperatorId = request.OperatorId,
OperatorName = request.OperatorName,
AuditLevel = result == OverrideResult.Success ? CoreAuditLevel.Info : CoreAuditLevel.Error,
AuditType = AuditType.OverrideExecuted,
AuditMessage = "人工干预执行",
AuditDetails = JsonSerializer.Serialize(new
{
request.RequestId,
request.OverrideType,
request.TargetStatus,
result,
elapsed_ms = (long)(DateTime.UtcNow - startTime).TotalMilliseconds,
state = currentState.ToString(),
layer = currentLayer,
reason = request.OverrideReason
}),
AuditTimeUtc = DateTime.UtcNow,
ExtendedProperties = new Dictionary<string, object>
{
["request_source"] = "ManualOverrideService",
["execution_elapsed_ms"] = (long)(DateTime.UtcNow - startTime).TotalMilliseconds,
["state"] = currentState.ToString(),
["layer"] = currentLayer,
["integration_with_state_machine"] = true
}
};
// 这里应该调用审计服务记录日志
// 暂时只记录到日志文件
_logger.LogInformation("人工干预审计记录审计ID={AuditId}会话ID={SessionId},操作员={OperatorId},干预类型={OverrideType},结果={Result},耗时={ElapsedMs}ms",
auditLog.LogId, auditLog.SessionId, auditLog.OperatorId, request.OverrideType, result, (long)(DateTime.UtcNow - startTime).TotalMilliseconds);
}
catch (Exception ex)
{
_logger.LogError(ex, "记录人工干预审计日志失败");
}
}
public async Task<Result<BatchManualOverrideResult>> ExecuteBatchManualOverrideAsync(IReadOnlyList<ManualOverrideRequest> overrideRequests, CancellationToken cancellationToken = default)
{
var results = new List<ManualOverrideResult>();
foreach (var request in overrideRequests)
{
var one = await ExecuteManualOverrideAsync(request, cancellationToken);
if (one.Data != null)
{
results.Add(one.Data);
}
}
var batch = new BatchManualOverrideResult
{
BatchId = Guid.NewGuid(),
TotalRequestCount = overrideRequests.Count,
SuccessCount = results.Count,
FailureCount = Math.Max(0, overrideRequests.Count - results.Count),
Results = results,
BatchMessage = "最小实现:批量执行完成",
BatchExecutionTimeUtc = DateTime.UtcNow,
BatchExecutionElapsedMs = 0
};
return Result<BatchManualOverrideResult>.Success(batch);
}
public Task<Result<IReadOnlyList<ManualOverrideHistory>>> GetOverrideHistoryAsync(DateTime startTime, DateTime endTime, string? operatorId = null, OverrideResult? overrideResult = null, CancellationToken cancellationToken = default)
{
IReadOnlyList<ManualOverrideHistory> history = Array.Empty<ManualOverrideHistory>();
return Task.FromResult(Result<IReadOnlyList<ManualOverrideHistory>>.Success(history));
}
public Task<Result<ManualOverrideDetail>> GetOverrideDetailAsync(Guid overrideId, CancellationToken cancellationToken = default)
{
var detail = new ManualOverrideDetail
{
OverrideId = overrideId,
OverrideResult = new ManualOverrideResult
{
OverrideId = overrideId,
RequestId = Guid.Empty,
SessionId = Guid.Empty,
OverrideResult = OverrideResult.Success,
OverrideStatus = OverrideStatus.Overridden,
OverrideMessage = "最小实现",
ExecutionTimeUtc = DateTime.UtcNow,
ExecutionElapsedMs = 0,
Executor = string.Empty,
AffectedSessionStatus = SessionStatus.Completed
},
OverrideRequest = new ManualOverrideRequest()
};
return Task.FromResult(Result<ManualOverrideDetail>.Success(detail));
}
public Task<Result<OverrideRevokeResult>> RevokeManualOverrideAsync(Guid overrideId, string revokeReason, string operatorId, CancellationToken cancellationToken = default)
{
var result = new OverrideRevokeResult
{
RevokeId = Guid.NewGuid(),
OverrideId = overrideId,
RevokeResult = RevokeResult.Success,
RevokeReason = revokeReason,
RevokeTimeUtc = DateTime.UtcNow,
Revoker = operatorId,
RevokeMessage = "最小实现:撤销成功"
};
return Task.FromResult(Result<OverrideRevokeResult>.Success(result));
}
public Task<Result<ManualOverrideStatistics>> GetOverrideStatisticsAsync(DateTime startTime, DateTime endTime, string? productTypeCode = null, CancellationToken cancellationToken = default)
{
var statistics = new ManualOverrideStatistics
{
TimeRange = new TimeRange { StartTime = startTime, EndTime = endTime },
ProductTypeCode = productTypeCode ?? string.Empty,
TotalOverrideCount = 0,
SuccessfulOverrideCount = 0,
FailedOverrideCount = 0,
OverridesByType = new Dictionary<OverrideType, int>(),
OverridesByOperator = new Dictionary<string, OperatorOverrideStatistics>(),
ByDate = new Dictionary<DateTime, DailyOverrideStatistics>(),
AverageOverrideElapsedMs = 0,
MaxOverrideElapsedMs = 0,
MinOverrideElapsedMs = 0
};
return Task.FromResult(Result<ManualOverrideStatistics>.Success(statistics));
}
public Task<Result<IReadOnlyList<OverrideAuditLog>>> GetOverrideAuditLogsAsync(Guid? sessionId = null, Guid? overrideId = null, DateTime? startTime = null, DateTime? endTime = null, CoreAuditLevel? auditLevel = null, CancellationToken cancellationToken = default)
{
IReadOnlyList<OverrideAuditLog> logs = Array.Empty<OverrideAuditLog>();
return Task.FromResult(Result<IReadOnlyList<OverrideAuditLog>>.Success(logs));
}
public Task<Result<ManualOverrideReport>> GenerateOverrideReportAsync(OverrideReportRequest reportRequest, CancellationToken cancellationToken = default)
{
var report = new ManualOverrideReport
{
ReportId = Guid.NewGuid(),
ReportType = reportRequest.ReportType,
ReportTitle = "最小实现报告",
TimeRange = reportRequest.TimeRange,
GeneratedAtUtc = DateTime.UtcNow,
ExecutiveSummary = new ReportExecutiveSummary(),
Statistics = new ManualOverrideStatistics(),
TrendAnalysis = new OverrideTrendAnalysis(),
ComplianceAnalysis = new OverrideComplianceAnalysis(),
RiskAnalysis = new OverrideRiskAnalysis(),
ImprovementSuggestions = Array.Empty<OverrideImprovementSuggestion>()
};
return Task.FromResult(Result<ManualOverrideReport>.Success(report));
}
public Task<Result<OverrideComplianceCheck>> CheckOverrideComplianceAsync(Guid sessionId, ManualOverrideRequest overrideRequest, CancellationToken cancellationToken = default)
{
var result = new OverrideComplianceCheck
{
CheckId = Guid.NewGuid(),
SessionId = sessionId,
CheckResult = ComplianceCheckResult.Pass,
ComplianceScore = 1,
CheckItems = Array.Empty<ComplianceCheckItem>(),
Violations = Array.Empty<ComplianceViolation>(),
CheckTimeUtc = DateTime.UtcNow,
CheckElapsedMs = 0
};
return Task.FromResult(Result<OverrideComplianceCheck>.Success(result));
}
public Task<Result<OverrideTemplate>> GetOverrideTemplateAsync(OverrideTemplateType templateType, CancellationToken cancellationToken = default)
{
var template = new OverrideTemplate
{
TemplateId = Guid.NewGuid(),
TemplateType = templateType,
TemplateName = "最小实现模板",
TemplateDescription = string.Empty,
IsEnabled = true,
CreatedAtUtc = DateTime.UtcNow,
Creator = string.Empty,
TemplateContent = string.Empty,
TemplateParameters = Array.Empty<TemplateParameter>(),
ApplicableConditions = Array.Empty<TemplateCondition>()
};
return Task.FromResult(Result<OverrideTemplate>.Success(template));
}
public Task<Result<OverrideTemplateSaveResult>> SaveOverrideTemplateAsync(OverrideTemplate template, CancellationToken cancellationToken = default)
{
var result = new OverrideTemplateSaveResult
{
TemplateId = template.TemplateId,
IsSuccess = true,
SaveMessage = "最小实现:保存成功",
SaveTimeUtc = DateTime.UtcNow
};
_logger.LogDebug("最小实现:保存模板 {TemplateId}", template.TemplateId);
return Task.FromResult(Result<OverrideTemplateSaveResult>.Success(result));
}
#region
/// <summary>
/// 获取操作员权限级别。
/// </summary>
private OperatorPermissionLevel GetOperatorPermissionLevel(string operatorId)
{
// 这里应该从权限系统获取操作员权限级别
// 暂时使用硬编码逻辑
return operatorId.ToLower() switch
{
var id when id.Contains("admin") => OperatorPermissionLevel.Administrator,
var id when id.Contains("supervisor") => OperatorPermissionLevel.Supervisor,
var id when id.Contains("operator") => OperatorPermissionLevel.Operator,
_ => OperatorPermissionLevel.Operator
};
}
/// <summary>
/// 检查覆盖权限。
/// </summary>
private bool CheckOverridePermission(Guid sessionId, string operatorId, OperatorPermissionLevel permissionLevel)
{
// 管理员和主管拥有所有权限
if (permissionLevel == OperatorPermissionLevel.Administrator ||
permissionLevel == OperatorPermissionLevel.Supervisor)
{
return true;
}
// 操作员需要特殊权限检查
if (permissionLevel == OperatorPermissionLevel.Operator)
{
// 这里可以添加更复杂的权限检查逻辑
// 例如:检查会话状态、时间窗口、产品类型等
return true; // 暂时允许
}
return false;
}
/// <summary>
/// 获取干预结果消息。
/// </summary>
private string GetOverrideMessage(OverrideResult result)
{
return result switch
{
OverrideResult.Success => "干预操作成功",
OverrideResult.Failed => "干预操作失败",
OverrideResult.PartialSuccess => "干预操作部分成功",
OverrideResult.Cancelled => "干预操作已取消",
_ => "干预操作状态未知"
};
}
/// <summary>
/// 获取干预后会话状态。
/// </summary>
private SessionStatus GetSessionStatusAfterOverride(OverrideType overrideType)
{
return overrideType switch
{
OverrideType.ResetAndRelease => SessionStatus.Active,
OverrideType.ForcePass => SessionStatus.Completed,
OverrideType.SkipInspection => SessionStatus.Active,
_ => SessionStatus.Active
};
}
#endregion
}
#if false
/// <summary>
/// 人工复位放行服务实现。
/// </summary>
public sealed class ManualOverrideService : IManualOverrideService
{
private readonly ILogger<ManualOverrideService> _logger;
private readonly RuntimeOptions _options;
private readonly ConcurrentDictionary<string, object> _overrideCache = new();
private readonly object _lock = new();
/// <summary>
/// 构造函数。
/// </summary>
public ManualOverrideService(ILogger<ManualOverrideService> logger, IOptions<RuntimeOptions> options)
{
_logger = logger;
_options = options.Value;
_logger.LogInformation("人工复位放行服务已初始化");
}
/// <inheritdoc />
public async Task<Result<IReadOnlyList<OverrideableSession>>> GetOverrideableSessionsAsync(DateTime startTime, DateTime endTime, string? productTypeCode = null, OverrideStatus? overrideStatus = null, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("获取可复位放行的会话列表:开始时间={StartTime},结束时间={EndTime},产品类型={ProductTypeCode},复位状态={OverrideStatus}",
startTime, endTime, productTypeCode, overrideStatus);
var cacheKey = $"overrideable_sessions_{startTime:yyyyMMddHHmm}_{endTime:yyyyMMddHHmm}_{productTypeCode}_{overrideStatus}";
if (_options.EnableHistoryTraceCache && _overrideCache.TryGetValue(cacheKey, out var cached))
{
_logger.LogDebug("从缓存获取可复位放行的会话列表");
return Result.Success((IReadOnlyList<OverrideableSession>)cached);
}
var overrideableSessions = await GenerateOverrideableSessionsAsync(startTime, endTime, productTypeCode, overrideStatus, cancellationToken);
if (_options.EnableHistoryTraceCache)
{
_overrideCache.TryAdd(cacheKey, overrideableSessions);
}
_logger.LogInformation("可复位放行的会话列表获取完成:会话数量={SessionCount}", overrideableSessions.Count);
return Result.Success(overrideableSessions);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取可复位放行的会话列表失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "GET_OVERRIDABLE_SESSIONS_FAILED", "获取可复位放行的会话列表失败", traceId);
return Result.FailWithTrace<IReadOnlyList<OverrideableSession>>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<OverridePermission>> GetOverridePermissionAsync(Guid sessionId, string operatorId, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("获取会话复位放行权限会话ID={SessionId}操作员ID={OperatorId}", sessionId, operatorId);
var cacheKey = $"override_permission_{sessionId}_{operatorId}";
if (_options.EnableHistoryTraceCache && _overrideCache.TryGetValue(cacheKey, out var cached))
{
_logger.LogDebug("从缓存获取复位放行权限");
return Result.Success((OverridePermission)cached);
}
var permission = await GenerateOverridePermissionAsync(sessionId, operatorId, cancellationToken);
if (_options.EnableHistoryTraceCache)
{
_overrideCache.TryAdd(cacheKey, permission);
}
_logger.LogInformation("复位放行权限获取完成会话ID={SessionId}操作员ID={OperatorId},是否有权限={HasPermission}",
sessionId, operatorId, permission.HasPermission);
return Result.Success(permission);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取复位放行权限失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "GET_OVERRIDE_PERMISSION_FAILED", "获取复位放行权限失败", traceId);
return Result.FailWithTrace<OverridePermission>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<OverrideValidationResult>> ValidateOverrideConditionsAsync(Guid sessionId, ManualOverrideRequest overrideRequest, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("验证复位放行条件会话ID={SessionId}请求ID={RequestId}", sessionId, overrideRequest.RequestId);
var validationResult = await GenerateOverrideValidationResultAsync(sessionId, overrideRequest, cancellationToken);
_logger.LogInformation("复位放行条件验证完成会话ID={SessionId},是否通过={IsValid},验证结果={ValidationResult}",
sessionId, validationResult.IsValid, validationResult.ValidationResult);
return Result.Success(validationResult);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "验证复位放行条件失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "VALIDATE_OVERRIDE_CONDITIONS_FAILED", "验证复位放行条件失败", traceId);
return Result.FailWithTrace<OverrideValidationResult>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<ManualOverrideResult>> ExecuteManualOverrideAsync(ManualOverrideRequest overrideRequest, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("执行人工复位放行请求ID={RequestId}会话ID={SessionId}操作员ID={OperatorId}",
overrideRequest.RequestId, overrideRequest.SessionId, overrideRequest.OperatorId);
var startTime = DateTime.UtcNow;
var overrideResult = await GenerateManualOverrideResultAsync(overrideRequest, cancellationToken);
var elapsed = DateTime.UtcNow - startTime;
// 记录审计日志
await LogOverrideAuditAsync(overrideRequest, overrideResult, elapsed, cancellationToken);
_logger.LogInformation("人工复位放行执行完成请求ID={RequestId},复位结果={OverrideResult},耗时={ElapsedMs}ms",
overrideRequest.RequestId, overrideResult.OverrideResult, elapsed.TotalMilliseconds);
return Result.Success(overrideResult);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "执行人工复位放行失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "EXECUTE_MANUAL_OVERRIDE_FAILED", "执行人工复位放行失败", traceId);
return Result.FailWithTrace<ManualOverrideResult>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<BatchManualOverrideResult>> ExecuteBatchManualOverrideAsync(IReadOnlyList<ManualOverrideRequest> overrideRequests, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("执行批量人工复位放行:请求数量={RequestCount}", overrideRequests.Count);
var startTime = DateTime.UtcNow;
var results = new List<ManualOverrideResult>();
var successCount = 0;
var failureCount = 0;
foreach (var request in overrideRequests)
{
try
{
var result = await ExecuteManualOverrideAsync(request, cancellationToken);
if (result.IsSuccess)
{
results.Add(result.Value);
if (result.Value.OverrideResult == OverrideResult.Success)
{
successCount++;
}
else
{
failureCount++;
}
}
else
{
failureCount++;
_logger.LogWarning("批量复位中的单个请求失败请求ID={RequestId},错误={Error}",
request.RequestId, result.Message);
}
}
catch (Exception ex)
{
failureCount++;
_logger.LogError(ex, "批量复位中的单个请求异常请求ID={RequestId}", request.RequestId);
}
}
var elapsed = DateTime.UtcNow - startTime;
var batchResult = new BatchManualOverrideResult
{
BatchId = Guid.NewGuid(),
TotalRequestCount = overrideRequests.Count,
SuccessCount = successCount,
FailureCount = failureCount,
Results = results.AsReadOnly(),
BatchMessage = $"批量操作完成:成功{successCount}个,失败{failureCount}个",
BatchExecutionTimeUtc = DateTime.UtcNow,
BatchExecutionElapsedMs = (long)elapsed.TotalMilliseconds,
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = elapsed.TotalMilliseconds,
["data_source"] = "simulated"
}
};
_logger.LogInformation("批量人工复位放行执行完成:请求数量={RequestCount},成功数={SuccessCount},失败数={FailureCount},耗时={ElapsedMs}ms",
overrideRequests.Count, successCount, failureCount, elapsed.TotalMilliseconds);
return Result.Success(batchResult);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "执行批量人工复位放行失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "EXECUTE_BATCH_MANUAL_OVERRIDE_FAILED", "执行批量人工复位放行失败", traceId);
return Result.FailWithTrace<BatchManualOverrideResult>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<IReadOnlyList<ManualOverrideHistory>>> GetOverrideHistoryAsync(DateTime startTime, DateTime endTime, string? operatorId = null, OverrideResult? overrideResult = null, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("获取复位放行历史记录:开始时间={StartTime},结束时间={EndTime}操作员ID={OperatorId},复位结果={OverrideResult}",
startTime, endTime, operatorId, overrideResult);
var cacheKey = $"override_history_{startTime:yyyyMMddHHmm}_{endTime:yyyyMMddHHmm}_{operatorId}_{overrideResult}";
if (_options.EnableHistoryTraceCache && _overrideCache.TryGetValue(cacheKey, out var cached))
{
_logger.LogDebug("从缓存获取复位放行历史记录");
return Result.Success((IReadOnlyList<ManualOverrideHistory>)cached);
}
var overrideHistory = await GenerateOverrideHistoryAsync(startTime, endTime, operatorId, overrideResult, cancellationToken);
if (_options.EnableHistoryTraceCache)
{
_overrideCache.TryAdd(cacheKey, overrideHistory);
}
_logger.LogInformation("复位放行历史记录获取完成:记录数量={RecordCount}", overrideHistory.Count);
return Result.Success(overrideHistory);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取复位放行历史记录失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "GET_OVERRIDE_HISTORY_FAILED", "获取复位放行历史记录失败", traceId);
return Result.FailWithTrace<IReadOnlyList<ManualOverrideHistory>>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<ManualOverrideDetail>> GetOverrideDetailAsync(Guid overrideId, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("获取复位放行详细信息复位ID={OverrideId}", overrideId);
var cacheKey = $"override_detail_{overrideId}";
if (_options.EnableHistoryTraceCache && _overrideCache.TryGetValue(cacheKey, out var cached))
{
_logger.LogDebug("从缓存获取复位放行详细信息");
return Result.Success((ManualOverrideDetail)cached);
}
var overrideDetail = await GenerateOverrideDetailAsync(overrideId, cancellationToken);
if (_options.EnableHistoryTraceCache)
{
_overrideCache.TryAdd(cacheKey, overrideDetail);
}
_logger.LogInformation("复位放行详细信息获取完成复位ID={OverrideId},复位结果={OverrideResult}",
overrideId, overrideDetail.OverrideResult.OverrideResult);
return Result.Success(overrideDetail);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取复位放行详细信息失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "GET_OVERRIDE_DETAIL_FAILED", "获取复位放行详细信息失败", traceId);
return Result.FailWithTrace<ManualOverrideDetail>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<OverrideRevokeResult>> RevokeManualOverrideAsync(Guid overrideId, string revokeReason, string operatorId, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("撤销人工复位放行复位ID={OverrideId},撤销原因={RevokeReason}操作员ID={OperatorId}",
overrideId, revokeReason, operatorId);
var revokeResult = await GenerateOverrideRevokeResultAsync(overrideId, revokeReason, operatorId, cancellationToken);
// 记录撤销审计日志
await LogRevokeAuditAsync(overrideId, revokeReason, operatorId, revokeResult, cancellationToken);
_logger.LogInformation("人工复位放行撤销完成复位ID={OverrideId},撤销结果={RevokeResult}",
overrideId, revokeResult.RevokeResult);
return Result.Success(revokeResult);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "撤销人工复位放行失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "REVOKE_MANUAL_OVERRIDE_FAILED", "撤销人工复位放行失败", traceId);
return Result.FailWithTrace<OverrideRevokeResult>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<ManualOverrideStatistics>> GetOverrideStatisticsAsync(DateTime startTime, DateTime endTime, string? productTypeCode = null, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("获取复位放行统计信息:开始时间={StartTime},结束时间={EndTime},产品类型={ProductTypeCode}",
startTime, endTime, productTypeCode);
var cacheKey = $"override_statistics_{startTime:yyyyMMddHHmm}_{endTime:yyyyMMddHHmm}_{productTypeCode}";
if (_options.EnableHistoryTraceCache && _overrideCache.TryGetValue(cacheKey, out var cached))
{
_logger.LogDebug("从缓存获取复位放行统计信息");
return Result.Success((ManualOverrideStatistics)cached);
}
var statistics = await GenerateOverrideStatisticsAsync(startTime, endTime, productTypeCode, cancellationToken);
if (_options.EnableHistoryTraceCache)
{
_overrideCache.TryAdd(cacheKey, statistics);
}
_logger.LogInformation("复位放行统计信息获取完成:总复位数={TotalCount},成功率={SuccessRate:F2}%,平均耗时={AvgElapsedMs:F2}ms",
statistics.TotalOverrideCount, statistics.SuccessRate, statistics.AverageOverrideElapsedMs);
return Result.Success(statistics);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取复位放行统计信息失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "GET_OVERRIDE_STATISTICS_FAILED", "获取复位放行统计信息失败", traceId);
return Result.FailWithTrace<ManualOverrideStatistics>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<IReadOnlyList<OverrideAuditLog>>> GetOverrideAuditLogsAsync(Guid? sessionId = null, Guid? overrideId = null, DateTime? startTime = null, DateTime? endTime = null, OrpaonVision.Core.ManualOverride.AuditLevel? auditLevel = null, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("获取复位放行审计日志会话ID={SessionId}复位ID={OverrideId},开始时间={StartTime},结束时间={EndTime},审计级别={AuditLevel}",
sessionId, overrideId, startTime, endTime, auditLevel);
var auditLogs = await GenerateOverrideAuditLogsAsync(sessionId, overrideId, startTime, endTime, auditLevel, cancellationToken);
_logger.LogInformation("复位放行审计日志获取完成:日志数量={LogCount}", auditLogs.Count);
return Result.Success(auditLogs);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取复位放行审计日志失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "GET_OVERRIDE_AUDIT_LOGS_FAILED", "获取复位放行审计日志失败", traceId);
return Result.FailWithTrace<IReadOnlyList<OverrideAuditLog>>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<ManualOverrideReport>> GenerateOverrideReportAsync(OverrideReportRequest reportRequest, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("生成复位放行报告请求ID={RequestId},报告类型={ReportType}",
reportRequest.RequestId, reportRequest.ReportType);
var report = await GenerateManualOverrideReportAsync(reportRequest, cancellationToken);
_logger.LogInformation("复位放行报告生成完成报告ID={ReportId},报告类型={ReportType},评分={OverallScore:F2}",
report.ReportId, report.ReportType, report.ExecutiveSummary.OverallScore);
return Result.Success(report);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "生成复位放行报告失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "GENERATE_OVERRIDE_REPORT_FAILED", "生成复位放行报告失败", traceId);
return Result.FailWithTrace<ManualOverrideReport>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<OverrideComplianceCheck>> CheckOverrideComplianceAsync(Guid sessionId, ManualOverrideRequest overrideRequest, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("检查复位放行合规性会话ID={SessionId}请求ID={RequestId}", sessionId, overrideRequest.RequestId);
var complianceCheck = await GenerateOverrideComplianceCheckAsync(sessionId, overrideRequest, cancellationToken);
_logger.LogInformation("复位放行合规性检查完成会话ID={SessionId},检查结果={CheckResult},合规评分={ComplianceScore:F2}",
sessionId, complianceCheck.CheckResult, complianceCheck.ComplianceScore);
return Result.Success(complianceCheck);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "检查复位放行合规性失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "CHECK_OVERRIDE_COMPLIANCE_FAILED", "检查复位放行合规性失败", traceId);
return Result.FailWithTrace<OverrideComplianceCheck>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<OverrideTemplate>> GetOverrideTemplateAsync(OverrideTemplateType templateType, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("获取复位放行模板:模板类型={TemplateType}", templateType);
var template = await GenerateOverrideTemplateAsync(templateType, cancellationToken);
_logger.LogInformation("复位放行模板获取完成模板ID={TemplateId},模板名称={TemplateName}",
template.TemplateId, template.TemplateName);
return Result.Success(template);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取复位放行模板失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "GET_OVERRIDE_TEMPLATE_FAILED", "获取复位放行模板失败", traceId);
return Result.FailWithTrace<OverrideTemplate>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <inheritdoc />
public async Task<Result<OverrideTemplateSaveResult>> SaveOverrideTemplateAsync(OverrideTemplate template, CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("保存复位放行模板模板ID={TemplateId},模板名称={TemplateName}",
template.TemplateId, template.TemplateName);
var saveResult = await GenerateOverrideTemplateSaveResultAsync(template, cancellationToken);
_logger.LogInformation("复位放行模板保存完成模板ID={TemplateId},保存结果={IsSuccess}",
template.TemplateId, saveResult.IsSuccess);
return Result.Success(saveResult);
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "保存复位放行模板失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "SAVE_OVERRIDE_TEMPLATE_FAILED", "保存复位放行模板失败", traceId);
return Result.FailWithTrace<OverrideTemplateSaveResult>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
#region
/// <summary>
/// 生成可复位放行的会话列表。
/// </summary>
private async Task<IReadOnlyList<OverrideableSession>> GenerateOverrideableSessionsAsync(DateTime startTime, DateTime endTime, string? productTypeCode, OverrideStatus? overrideStatus, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var overrideableSessions = new List<OverrideableSession>();
var current = startTime;
while (current <= endTime)
{
var sessionCount = random.Next(3, 10);
for (int i = 0; i < sessionCount; i++)
{
var status = overrideStatus ?? (OverrideStatus)random.Next(0, 6);
var sessionStartTime = current.AddHours(random.Next(0, 24)).AddMinutes(random.Next(0, 60));
var sessionEndTime = status == OverrideStatus.Overridden ? sessionStartTime.AddMinutes(random.Next(30, 120)) : null;
overrideableSessions.Add(new OverrideableSession
{
SessionId = Guid.NewGuid(),
ProductSerialNumber = $"SN{random.Next(100000, 999999)}",
ProductTypeCode = productTypeCode ?? $"PT{random.Next(1, 10)}",
SessionStatus = SessionStatus.Completed,
FinalJudgmentResult = FinalJudgmentResult.Fail,
SessionStartTimeUtc = sessionStartTime,
SessionEndTimeUtc = sessionEndTime,
OverrideStatus = status,
OverrideReasons = GenerateOverrideReasons(random),
OverridePriority = (OverridePriority)random.Next(0, 4),
RequiredPermissionLevel = (OperatorPermissionLevel)random.Next(1, 6),
OperatorId = $"OP{random.Next(1, 10):D3}",
OperatorName = $"操作员{random.Next(1, 10)}",
StationId = $"ST{random.Next(1, 5):D3}",
StationName = $"工位{random.Next(1, 5)}",
TotalLayerCount = random.Next(3, 8),
CompletedLayerCount = random.Next(0, 8),
NGReasons = GenerateNGReasons(random),
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 25,
["data_source"] = "simulated"
}
});
}
current = current.AddDays(1);
}
return overrideableSessions.AsReadOnly();
}
/// <summary>
/// 生成复位权限。
/// </summary>
private async Task<OverridePermission> GenerateOverridePermissionAsync(Guid sessionId, string operatorId, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var operatorLevel = (OperatorPermissionLevel)random.Next(0, 6);
var hasPermission = operatorLevel >= OperatorPermissionLevel.TeamLeader;
return new OverridePermission
{
PermissionId = Guid.NewGuid(),
SessionId = sessionId,
OperatorId = operatorId,
OperatorName = $"操作员{random.Next(1, 10)}",
OperatorPermissionLevel = operatorLevel,
HasPermission = hasPermission,
PermissionReason = hasPermission ? "权限满足要求" : "权限不足",
PermissionRestrictions = hasPermission ? new List<string>() : new List<string> { "需要班组长或更高级别权限" },
PermissionExpiryUtc = hasPermission ? DateTime.UtcNow.AddHours(8) : null,
RequireSecondaryConfirmation = !hasPermission && operatorLevel == OperatorPermissionLevel.Technician,
RequireApprovalProcess = !hasPermission,
RequiredApprovers = !hasPermission ? new List<string> { $"TL{random.Next(1, 3):D3}" } : new List<string>(),
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 15,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 生成复位验证结果。
/// </summary>
private async Task<OverrideValidationResult> GenerateOverrideValidationResultAsync(Guid sessionId, ManualOverrideRequest overrideRequest, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var isValid = random.NextDouble() > 0.2;
var validationResult = isValid ? ValidationResult.Pass : (random.NextDouble() > 0.5 ? ValidationResult.Warning : ValidationResult.Fail);
return new OverrideValidationResult
{
ValidationId = Guid.NewGuid(),
SessionId = sessionId,
RequestId = overrideRequest.RequestId,
IsValid = isValid,
ValidationResult = validationResult,
ValidationMessage = isValid ? "验证通过" : (validationResult == ValidationResult.Warning ? "验证通过但有警告" : "验证失败"),
ValidationDetails = GenerateValidationDetails(random),
ValidationWarnings = validationResult == ValidationResult.Warning ? new List<string> { "警告1", "警告2" } : new List<string>(),
ValidationErrors = !isValid ? new List<string> { "错误1", "错误2" } : new List<string>(),
ValidationTimeUtc = DateTime.UtcNow,
ValidationElapsedMs = random.Next(100, 1000),
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 20,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 生成复位结果。
/// </summary>
private async Task<ManualOverrideResult> GenerateManualOverrideResultAsync(ManualOverrideRequest overrideRequest, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var isSuccess = random.NextDouble() > 0.1;
var overrideResult = isSuccess ? OverrideResult.Success : (OverrideResult)random.Next(1, 6);
return new ManualOverrideResult
{
OverrideId = Guid.NewGuid(),
RequestId = overrideRequest.RequestId,
SessionId = overrideRequest.SessionId,
OverrideResult = overrideResult,
OverrideStatus = isSuccess ? OverrideStatus.Overridden : (overrideResult == OverrideResult.Rejected ? OverrideStatus.Rejected : OverrideStatus.Pending),
OverrideMessage = isSuccess ? "复位成功" : "复位失败",
ExecutionTimeUtc = DateTime.UtcNow,
ExecutionElapsedMs = random.Next(500, 5000),
Executor = overrideRequest.OperatorName,
ExecutionDetails = GenerateExecutionDetails(random),
AffectedSessionStatus = isSuccess ? SessionStatus.Completed : SessionStatus.Failed,
FollowUpActions = isSuccess ? new List<string> { "记录日志", "通知相关人员" } : new List<string> { "检查失败原因" },
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 30,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 生成复位历史记录。
/// </summary>
private async Task<IReadOnlyList<ManualOverrideHistory>> GenerateOverrideHistoryAsync(DateTime startTime, DateTime endTime, string? operatorId, OverrideResult? overrideResult, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var overrideHistory = new List<ManualOverrideHistory>();
var historyCount = random.Next(10, 50);
for (int i = 0; i < historyCount; i++)
{
var result = overrideResult ?? (OverrideResult)random.Next(0, 6);
var overrideTime = startTime.AddMinutes(random.Next(0, (int)(endTime - startTime).TotalMinutes));
overrideHistory.Add(new ManualOverrideHistory
{
HistoryId = Guid.NewGuid(),
OverrideId = Guid.NewGuid(),
SessionId = Guid.NewGuid(),
RequestId = Guid.NewGuid(),
OverrideType = (OverrideType)random.Next(0, 8),
OverrideResult = result,
OverrideStatus = result == OverrideResult.Success ? OverrideStatus.Overridden : OverrideStatus.Pending,
OperatorId = operatorId ?? $"OP{random.Next(1, 10):D3}",
OperatorName = $"操作员{random.Next(1, 10)}",
OverrideReason = $"复位原因{i + 1}",
OverrideTimeUtc = overrideTime,
OverrideElapsedMs = random.Next(500, 5000),
OverrideMessage = result == OverrideResult.Success ? "复位成功" : "复位失败",
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 18,
["data_source"] = "simulated"
}
});
}
return overrideHistory.AsReadOnly();
}
/// <summary>
/// 生成复位详细信息。
/// </summary>
private async Task<ManualOverrideDetail> GenerateOverrideDetailAsync(Guid overrideId, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var overrideResult = new ManualOverrideResult
{
OverrideId = overrideId,
RequestId = Guid.NewGuid(),
SessionId = Guid.NewGuid(),
OverrideResult = OverrideResult.Success,
OverrideStatus = OverrideStatus.Overridden,
OverrideMessage = "复位成功",
ExecutionTimeUtc = DateTime.UtcNow.AddMinutes(-random.Next(10, 120)),
ExecutionElapsedMs = random.Next(500, 5000),
Executor = $"操作员{random.Next(1, 10)}",
ExecutionDetails = GenerateExecutionDetails(random),
AffectedSessionStatus = SessionStatus.Completed
};
var overrideRequest = new ManualOverrideRequest
{
RequestId = overrideResult.RequestId,
SessionId = overrideResult.SessionId,
OperatorId = $"OP{random.Next(1, 10):D3}",
OperatorName = overrideResult.Executor,
OverrideType = (OverrideType)random.Next(0, 8),
OverrideReason = "复位原因",
OverrideDescription = "复位描述",
OverridePriority = (OverridePriority)random.Next(0, 4),
TargetStatus = SessionStatus.Completed,
RequestTimeUtc = overrideResult.ExecutionTimeUtc.AddMinutes(-random.Next(5, 30)),
IsUrgent = random.NextDouble() > 0.8,
RequireApproval = random.NextDouble() > 0.7
};
return new ManualOverrideDetail
{
OverrideId = overrideId,
OverrideResult = overrideResult,
OverrideRequest = overrideRequest,
ValidationResult = GenerateOverrideValidationResultAsync(overrideResult.SessionId, overrideRequest, cancellationToken).Result,
Permission = GenerateOverridePermissionAsync(overrideResult.SessionId, overrideRequest.OperatorId, cancellationToken).Result,
ApprovalInfos = GenerateApprovalInfos(random),
ImpactAnalysis = GenerateOverrideImpactAnalysis(random),
ComplianceCheck = GenerateOverrideComplianceCheckAsync(overrideResult.SessionId, overrideRequest, cancellationToken).Result,
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 40,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 生成复位撤销结果。
/// </summary>
private async Task<OverrideRevokeResult> GenerateOverrideRevokeResultAsync(Guid overrideId, string revokeReason, string operatorId, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var revokeResult = random.NextDouble() > 0.1 ? RevokeResult.Success : (RevokeResult)random.Next(1, 5);
return new OverrideRevokeResult
{
RevokeId = Guid.NewGuid(),
OverrideId = overrideId,
RevokeResult = revokeResult,
RevokeReason = revokeReason,
RevokeTimeUtc = DateTime.UtcNow,
Revoker = $"操作员{random.Next(1, 10)}",
RevokeMessage = revokeResult == RevokeResult.Success ? "撤销成功" : "撤销失败",
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 25,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 生成复位统计信息。
/// </summary>
private async Task<ManualOverrideStatistics> GenerateOverrideStatisticsAsync(DateTime startTime, DateTime endTime, string? productTypeCode, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var timeRange = new TimeRange { StartTimeUtc = startTime, EndTimeUtc = endTime };
var totalOverrideCount = random.Next(50, 200);
var successfulOverrideCount = (int)(totalOverrideCount * (0.7 + random.NextDouble() * 0.25));
return new ManualOverrideStatistics
{
TimeRange = timeRange,
ProductTypeCode = productTypeCode ?? "default",
TotalOverrideCount = totalOverrideCount,
SuccessfulOverrideCount = successfulOverrideCount,
FailedOverrideCount = totalOverrideCount - successfulOverrideCount,
OverridesByType = GenerateOverridesByType(random, totalOverrideCount),
OverridesByOperator = GenerateOverridesByOperator(random),
ByDate = GenerateDailyOverrideStatistics(startTime, endTime, random),
AverageOverrideElapsedMs = 1000 + random.NextDouble() * 2000,
MaxOverrideElapsedMs = 5000 + random.Next(0, 5000),
MinOverrideElapsedMs = 500 + random.Next(0, 500),
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 35,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 生成审计日志。
/// </summary>
private async Task<IReadOnlyList<OverrideAuditLog>> GenerateOverrideAuditLogsAsync(Guid? sessionId, Guid? overrideId, DateTime? startTime, DateTime? endTime, OrpaonVision.Core.ManualOverride.AuditLevel? auditLevel, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var auditLogs = new List<OverrideAuditLog>();
var logCount = random.Next(20, 100);
for (int i = 0; i < logCount; i++)
{
var level = auditLevel ?? (OrpaonVision.Core.ManualOverride.AuditLevel)random.Next(0, 5);
var auditTime = startTime?.AddMinutes(random.Next(0, (int)(endTime - startTime).Value.TotalMinutes)) ?? DateTime.UtcNow.AddMinutes(-random.Next(10, 1440));
auditLogs.Add(new OverrideAuditLog
{
LogId = Guid.NewGuid(),
SessionId = sessionId,
OverrideId = overrideId,
AuditLevel = level,
AuditType = (AuditType)random.Next(0, 9),
AuditMessage = $"审计消息{i + 1}",
AuditDetails = $"审计详情{i + 1}",
OperatorId = $"OP{random.Next(1, 10):D3}",
OperatorName = $"操作员{random.Next(1, 10)}",
AuditTimeUtc = auditTime,
ClientIp = $"192.168.1.{random.Next(1, 255)}",
UserAgent = $"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 12,
["data_source"] = "simulated"
}
});
}
return auditLogs.AsReadOnly();
}
/// <summary>
/// 生成复位报告。
/// </summary>
private async Task<ManualOverrideReport> GenerateManualOverrideReportAsync(OverrideReportRequest reportRequest, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var statistics = await GenerateOverrideStatisticsAsync(reportRequest.TimeRange.StartTimeUtc, reportRequest.TimeRange.EndTimeUtc, reportRequest.ProductTypeCode, cancellationToken);
return new ManualOverrideReport
{
ReportId = Guid.NewGuid(),
ReportType = reportRequest.ReportType,
ReportTitle = $"{reportRequest.ReportType}复位放行报告",
TimeRange = reportRequest.TimeRange,
GeneratedAtUtc = DateTime.UtcNow,
ExecutiveSummary = GenerateReportExecutiveSummary(random),
Statistics = statistics,
TrendAnalysis = GenerateOverrideTrendAnalysis(random),
ComplianceAnalysis = GenerateOverrideComplianceAnalysis(random),
RiskAnalysis = GenerateOverrideRiskAnalysis(random),
ImprovementSuggestions = GenerateOverrideImprovementSuggestions(random),
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 80,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 生成合规性检查。
/// </summary>
private async Task<OverrideComplianceCheck> GenerateOverrideComplianceCheckAsync(Guid sessionId, ManualOverrideRequest overrideRequest, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var checkResult = random.NextDouble() > 0.2 ? ComplianceCheckResult.Pass : (ComplianceCheckResult)random.Next(1, 4);
return new OverrideComplianceCheck
{
CheckId = Guid.NewGuid(),
SessionId = sessionId,
CheckResult = checkResult,
ComplianceScore = 70 + random.NextDouble() * 25,
CheckItems = GenerateComplianceCheckItems(random),
Violations = checkResult == ComplianceCheckResult.Fail ? GenerateComplianceViolations(random) : new List<ComplianceViolation>(),
CheckTimeUtc = DateTime.UtcNow,
CheckElapsedMs = random.Next(200, 2000),
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 30,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 生成复位模板。
/// </summary>
private async Task<OverrideTemplate> GenerateOverrideTemplateAsync(OverrideTemplateType templateType, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
return new OverrideTemplate
{
TemplateId = Guid.NewGuid(),
TemplateType = templateType,
TemplateName = $"{templateType}模板",
TemplateDescription = $"{templateType}复位模板描述",
TemplateContent = $"{templateType}复位模板内容",
TemplateParameters = GenerateTemplateParameters(random),
ApplicableConditions = GenerateTemplateConditions(random),
CreatedAtUtc = DateTime.UtcNow.AddDays(-random.Next(1, 30)),
Creator = $"创建者{random.Next(1, 5)}",
IsEnabled = random.NextDouble() > 0.1,
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 20,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 生成模板保存结果。
/// </summary>
private async Task<OverrideTemplateSaveResult> GenerateOverrideTemplateSaveResultAsync(OverrideTemplate template, CancellationToken cancellationToken = default)
{
await Task.Delay(1, cancellationToken);
var random = new Random();
var isSuccess = random.NextDouble() > 0.1;
return new OverrideTemplateSaveResult
{
IsSuccess = isSuccess,
TemplateId = template.TemplateId,
SaveMessage = isSuccess ? "保存成功" : "保存失败",
SaveTimeUtc = DateTime.UtcNow,
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 15,
["data_source"] = "simulated"
}
};
}
/// <summary>
/// 记录复位审计日志。
/// </summary>
private async Task LogOverrideAuditAsync(ManualOverrideRequest request, ManualOverrideResult result, TimeSpan elapsed, CancellationToken cancellationToken = default)
{
try
{
var auditLog = new OverrideAuditLog
{
LogId = Guid.NewGuid(),
SessionId = request.SessionId,
OverrideId = result.OverrideId,
AuditLevel = result.OverrideResult == OverrideResult.Success ? OrpaonVision.Core.ManualOverride.AuditLevel.Info : OrpaonVision.Core.ManualOverride.AuditLevel.Warning,
AuditType = AuditType.OverrideExecuted,
AuditMessage = $"执行复位放行:{result.OverrideResult}",
AuditDetails = $"请求ID{request.RequestId},耗时:{elapsed.TotalMilliseconds:F2}ms",
OperatorId = request.OperatorId,
OperatorName = request.OperatorName,
AuditTimeUtc = DateTime.UtcNow,
ClientIp = "127.0.0.1",
UserAgent = "ManualOverrideService",
ExtendedProperties = new Dictionary<string, object>
{
["request_id"] = request.RequestId,
["override_type"] = request.OverrideType,
["elapsed_ms"] = elapsed.TotalMilliseconds
}
};
// 简化处理:在实际实现中,这里应该将审计日志写入数据库或日志文件
_logger.LogInformation("记录复位审计日志:{AuditLog}", JsonSerializer.Serialize(auditLog));
}
catch (Exception ex)
{
_logger.LogError(ex, "记录复位审计日志失败");
}
}
/// <summary>
/// 记录撤销审计日志。
/// </summary>
private async Task LogRevokeAuditAsync(Guid overrideId, string revokeReason, string operatorId, OverrideRevokeResult result, CancellationToken cancellationToken = default)
{
try
{
var auditLog = new OverrideAuditLog
{
LogId = Guid.NewGuid(),
OverrideId = overrideId,
AuditLevel = result.RevokeResult == RevokeResult.Success ? OrpaonVision.Core.ManualOverride.AuditLevel.Info : OrpaonVision.Core.ManualOverride.AuditLevel.Warning,
AuditType = AuditType.OverrideRevoked,
AuditMessage = $"撤销复位放行:{result.RevokeResult}",
AuditDetails = $"撤销原因:{revokeReason}",
OperatorId = operatorId,
OperatorName = $"操作员{operatorId}",
AuditTimeUtc = DateTime.UtcNow,
ClientIp = "127.0.0.1",
UserAgent = "ManualOverrideService",
ExtendedProperties = new Dictionary<string, object>
{
["override_id"] = overrideId,
["revoke_reason"] = revokeReason,
["revoke_result"] = result.RevokeResult
}
};
// 简化处理:在实际实现中,这里应该将审计日志写入数据库或日志文件
_logger.LogInformation("记录撤销审计日志:{AuditLog}", JsonSerializer.Serialize(auditLog));
}
catch (Exception ex)
{
_logger.LogError(ex, "记录撤销审计日志失败");
}
}
#endregion
#region
/// <summary>
/// 生成复位原因列表。
/// </summary>
private IReadOnlyList<OverrideReason> GenerateOverrideReasons(Random random)
{
var reasons = new List<OverrideReason>();
var reasonCount = random.Next(1, 4);
for (int i = 0; i < reasonCount; i++)
{
reasons.Add(new OverrideReason
{
ReasonId = Guid.NewGuid(),
ReasonType = (OverrideReasonType)random.Next(0, 8),
ReasonDescription = $"复位原因{i + 1}",
ReasonSeverity = (OverrideSeverity)random.Next(0, 4),
RecommendedAction = $"建议措施{i + 1}",
ExtendedProperties = new Dictionary<string, object>
{
["reason_index"] = i
}
});
}
return reasons.AsReadOnly();
}
/// <summary>
/// 生成NG原因列表。
/// </summary>
private IReadOnlyList<string> GenerateNGReasons(Random random)
{
var reasons = new List<string>();
var reasonCount = random.Next(0, 5);
for (int i = 0; i < reasonCount; i++)
{
reasons.Add($"NG原因{i + 1}");
}
return reasons.AsReadOnly();
}
/// <summary>
/// 生成验证详情列表。
/// </summary>
private IReadOnlyList<ValidationDetail> GenerateValidationDetails(Random random)
{
var details = new List<ValidationDetail>();
var detailCount = random.Next(3, 8);
for (int i = 0; i < detailCount; i++)
{
details.Add(new ValidationDetail
{
DetailId = Guid.NewGuid(),
ValidationItem = $"验证项{i + 1}",
ValidationResult = random.NextDouble() > 0.2 ? ValidationResult.Pass : ValidationResult.Fail,
ValidationMessage = $"验证消息{i + 1}",
ValidationValue = random.Next(1, 100),
ExpectedValue = random.Next(1, 100),
ExtendedProperties = new Dictionary<string, object>
{
["detail_index"] = i
}
});
}
return details.AsReadOnly();
}
/// <summary>
/// 生成执行详情列表。
/// </summary>
private IReadOnlyList<ExecutionDetail> GenerateExecutionDetails(Random random)
{
var details = new List<ExecutionDetail>();
var detailCount = random.Next(3, 10);
for (int i = 0; i < detailCount; i++)
{
details.Add(new ExecutionDetail
{
DetailId = Guid.NewGuid(),
ExecutionStep = $"执行步骤{i + 1}",
ExecutionResult = random.NextDouble() > 0.1,
ExecutionMessage = $"执行消息{i + 1}",
ExecutionTimeUtc = DateTime.UtcNow.AddSeconds(-random.Next(1, 60)),
ExecutionElapsedMs = random.Next(50, 500),
ExtendedProperties = new Dictionary<string, object>
{
["step_index"] = i
}
});
}
return details.AsReadOnly();
}
/// <summary>
/// 生成审批信息列表。
/// </summary>
private IReadOnlyList<ApprovalInfo> GenerateApprovalInfos(Random random)
{
var approvals = new List<ApprovalInfo>();
var approvalCount = random.Next(0, 3);
for (int i = 0; i < approvalCount; i++)
{
approvals.Add(new ApprovalInfo
{
ApprovalId = Guid.NewGuid(),
ApproverId = $"AP{random.Next(1, 5):D3}",
ApproverName = $"审批人{random.Next(1, 5)}",
ApprovalResult = (ApprovalResult)random.Next(0, 4),
ApprovalComment = $"审批意见{i + 1}",
ApprovalTimeUtc = DateTime.UtcNow.AddMinutes(-random.Next(10, 120)),
ExtendedProperties = new Dictionary<string, object>
{
["approval_index"] = i
}
});
}
return approvals.AsReadOnly();
}
/// <summary>
/// 生成复位影响分析。
/// </summary>
private OverrideImpactAnalysis GenerateOverrideImpactAnalysis(Random random)
{
return new OverrideImpactAnalysis
{
AnalysisId = Guid.NewGuid(),
ImpactLevel = (ImpactLevel)random.Next(0, 5),
ImpactDescription = "影响分析描述",
AffectedSessionCount = random.Next(1, 5),
AffectedLayerCount = random.Next(3, 20),
AffectedDetectionCount = random.Next(10, 100),
RiskAssessment = new RiskAssessment
{
RiskLevel = (RiskLevel)random.Next(0, 5),
RiskDescription = "风险评估描述",
RiskProbability = random.NextDouble(),
RiskImpact = random.NextDouble(),
MitigationMeasures = new List<string> { "缓解措施1", "缓解措施2" },
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 10
}
},
RecommendedActions = new List<string> { "建议措施1", "建议措施2", "建议措施3" },
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 15
}
};
}
/// <summary>
/// 生成按类型分组的复位统计。
/// </summary>
private Dictionary<OverrideType, int> GenerateOverridesByType(Random random, int totalCount)
{
var overridesByType = new Dictionary<OverrideType, int>();
var remainingCount = totalCount;
foreach (OverrideType type in Enum.GetValues<OverrideType>())
{
if (remainingCount <= 0) break;
var count = random.Next(0, remainingCount / 2 + 1);
overridesByType[type] = count;
remainingCount -= count;
}
return overridesByType;
}
/// <summary>
/// 生成按操作员分组的复位统计。
/// </summary>
private Dictionary<string, OperatorOverrideStatistics> GenerateOverridesByOperator(Random random)
{
var operatorStats = new Dictionary<string, OperatorOverrideStatistics>();
for (int i = 1; i <= 5; i++)
{
var overrideCount = random.Next(5, 30);
var successCount = (int)(overrideCount * (0.7 + random.NextDouble() * 0.25));
operatorStats[$"OP{i:D3}"] = new OperatorOverrideStatistics
{
OperatorId = $"OP{i:D3}",
OperatorName = $"操作员{i}",
OverrideCount = overrideCount,
SuccessCount = successCount,
FailureCount = overrideCount - successCount,
AverageElapsedMs = 1000 + random.NextDouble() * 2000,
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 8
}
};
}
return operatorStats;
}
/// <summary>
/// 生成每日复位统计。
/// </summary>
private Dictionary<DateTime, DailyOverrideStatistics> GenerateDailyOverrideStatistics(DateTime startTime, DateTime endTime, Random random)
{
var dailyStats = new Dictionary<DateTime, DailyOverrideStatistics>();
var current = startTime.Date;
while (current <= endTime.Date)
{
var overrideCount = random.Next(5, 20);
var successCount = (int)(overrideCount * (0.7 + random.NextDouble() * 0.25));
dailyStats[current] = new DailyOverrideStatistics
{
Date = current,
OverrideCount = overrideCount,
SuccessCount = successCount,
FailureCount = overrideCount - successCount,
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 6
}
};
current = current.AddDays(1);
}
return dailyStats;
}
/// <summary>
/// 生成报告执行摘要。
/// </summary>
private ReportExecutiveSummary GenerateReportExecutiveSummary(Random random)
{
return new ReportExecutiveSummary
{
OverallScore = 70 + random.NextDouble() * 25,
KeyFindings = new[] { "关键发现1", "关键发现2", "关键发现3" },
MajorIssues = new[] { "主要问题1", "主要问题2" },
ImprovementOpportunities = new[] { "改进机会1", "改进机会2", "改进机会3" },
SummaryDescription = "复位放行报告执行摘要",
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 12
}
};
}
/// <summary>
/// 生成复位趋势分析。
/// </summary>
private OverrideTrendAnalysis GenerateOverrideTrendAnalysis(Random random)
{
return new OverrideTrendAnalysis
{
TrendDirection = (TrendDirection)random.Next(0, 4),
ChangeRate = random.NextDouble() * 10 - 5,
TrendDescription = "复位趋势分析",
PredictedNextOverrideCount = random.Next(10, 50),
Confidence = 0.6 + random.NextDouble() * 0.3,
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 10
}
};
}
/// <summary>
/// 生成复位合规性分析。
/// </summary>
private OverrideComplianceAnalysis GenerateOverrideComplianceAnalysis(Random random)
{
return new OverrideComplianceAnalysis
{
ComplianceScore = 75 + random.NextDouble() * 20,
ComplianceViolationCount = random.Next(0, 10),
Violations = GenerateComplianceViolations(random),
ComplianceRecommendations = new[] { "合规建议1", "合规建议2" },
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 15
}
};
}
/// <summary>
/// 生成复位风险分析。
/// </summary>
private OverrideRiskAnalysis GenerateOverrideRiskAnalysis(Random random)
{
return new OverrideRiskAnalysis
{
RiskScore = 20 + random.NextDouble() * 60,
HighRiskOverrideCount = random.Next(0, 5),
RiskFactors = new List<RiskFactor>
{
new RiskFactor
{
FactorId = Guid.NewGuid(),
FactorName = "风险因素1",
FactorDescription = "风险因素描述1",
RiskLevel = (RiskLevel)random.Next(0, 5),
ImpactLevel = random.NextDouble(),
ExtendedProperties = new Dictionary<string, object>
{
["factor_index"] = 0
}
}
},
RiskMitigationRecommendations = new[] { "风险缓解建议1", "风险缓解建议2" },
ExtendedProperties = new Dictionary<string, object>
{
["generation_time_ms"] = 12
}
};
}
/// <summary>
/// 生成复位改进建议。
/// </summary>
private IReadOnlyList<OverrideImprovementSuggestion> GenerateOverrideImprovementSuggestions(Random random)
{
var suggestions = new List<OverrideImprovementSuggestion>();
for (int i = 0; i < random.Next(3, 8); i++)
{
suggestions.Add(new OverrideImprovementSuggestion
{
SuggestionId = Guid.NewGuid(),
SuggestionCategory = (SuggestionCategory)random.Next(0, 8),
SuggestionTitle = $"改进建议{i + 1}",
SuggestionDescription = $"改进建议描述{i + 1}",
Priority = random.Next(1, 5),
ExpectedImpact = $"预期效果{i + 1}",
ImplementationDifficulty = (ImplementationDifficulty)random.Next(0, 4),
ExtendedProperties = new Dictionary<string, object>
{
["suggestion_index"] = i
}
});
}
return suggestions.AsReadOnly();
}
/// <summary>
/// 生成合规性检查项。
/// </summary>
private IReadOnlyList<ComplianceCheckItem> GenerateComplianceCheckItems(Random random)
{
var items = new List<ComplianceCheckItem>();
var itemCount = random.Next(5, 15);
for (int i = 0; i < itemCount; i++)
{
items.Add(new ComplianceCheckItem
{
ItemId = Guid.NewGuid(),
ItemName = $"检查项{i + 1}",
ItemDescription = $"检查项描述{i + 1}",
CheckResult = random.NextDouble() > 0.2 ? ComplianceCheckResult.Pass : ComplianceCheckResult.Fail,
CheckValue = random.Next(1, 100),
StandardValue = random.Next(1, 100),
CheckMessage = $"检查消息{i + 1}",
ExtendedProperties = new Dictionary<string, object>
{
["item_index"] = i
}
});
}
return items.AsReadOnly();
}
/// <summary>
/// 生成合规违规。
/// </summary>
private IReadOnlyList<ComplianceViolation> GenerateComplianceViolations(Random random)
{
var violations = new List<ComplianceViolation>();
var violationCount = random.Next(0, 5);
for (int i = 0; i < violationCount; i++)
{
violations.Add(new ComplianceViolation
{
ViolationId = Guid.NewGuid(),
ViolationType = $"违规类型{i + 1}",
ViolationDescription = $"违规描述{i + 1}",
ViolationSeverity = (ViolationSeverity)random.Next(0, 4),
ViolationTimeUtc = DateTime.UtcNow.AddMinutes(-random.Next(10, 120)),
ExtendedProperties = new Dictionary<string, object>
{
["violation_index"] = i
}
});
}
return violations.AsReadOnly();
}
/// <summary>
/// 生成模板参数。
/// </summary>
private IReadOnlyList<TemplateParameter> GenerateTemplateParameters(Random random)
{
var parameters = new List<TemplateParameter>();
var parameterCount = random.Next(3, 8);
for (int i = 0; i < parameterCount; i++)
{
parameters.Add(new TemplateParameter
{
ParameterId = Guid.NewGuid(),
ParameterName = $"参数{i + 1}",
ParameterType = "string",
ParameterDescription = $"参数描述{i + 1}",
IsRequired = random.NextDouble() > 0.5,
DefaultValue = $"默认值{i + 1}",
ValidationRule = "required",
ExtendedProperties = new Dictionary<string, object>
{
["parameter_index"] = i
}
});
}
return parameters.AsReadOnly();
}
/// <summary>
/// 生成模板条件。
/// </summary>
private IReadOnlyList<TemplateCondition> GenerateTemplateConditions(Random random)
{
var conditions = new List<TemplateCondition>();
var conditionCount = random.Next(0, 3);
for (int i = 0; i < conditionCount; i++)
{
conditions.Add(new TemplateCondition
{
ConditionId = Guid.NewGuid(),
ConditionName = $"条件{i + 1}",
ConditionExpression = $"condition{i + 1} == true",
ConditionDescription = $"条件描述{i + 1}",
ExtendedProperties = new Dictionary<string, object>
{
["condition_index"] = i
}
});
}
return conditions.AsReadOnly();
}
#endregion
}
#endif