649 lines
27 KiB
C#
649 lines
27 KiB
C#
using Microsoft.Extensions.Logging;
|
||
using OrpaonVision.Core.Abstractions;
|
||
using OrpaonVision.Core.Results;
|
||
using OrpaonVision.Model.Production;
|
||
using System.Collections.Concurrent;
|
||
|
||
namespace OrpaonVision.Core.Services;
|
||
|
||
/// <summary>
|
||
/// 产品会话记录服务实现。
|
||
/// </summary>
|
||
public sealed class ProductionSessionService : IProductionSessionService
|
||
{
|
||
private readonly ILogger<ProductionSessionService> _logger;
|
||
private readonly ConcurrentDictionary<Guid, ProductionSessionModel> _sessions = new();
|
||
private readonly object _lock = new object();
|
||
|
||
/// <summary>
|
||
/// 构造函数。
|
||
/// </summary>
|
||
public ProductionSessionService(ILogger<ProductionSessionService> logger)
|
||
{
|
||
_logger = logger;
|
||
InitializeSampleData();
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<ProductionSessionModel> CreateSession(CreateProductionSessionRequest request)
|
||
{
|
||
try
|
||
{
|
||
_logger.LogInformation("正在创建产品会话,产品类型: {ProductType}, 工位: {Station}, 操作员: {Operator}",
|
||
request.ProductTypeCode, request.StationId, request.OperatorId);
|
||
|
||
// 检查当前是否已有活动会话
|
||
var currentSession = GetCurrentSession(request.StationId);
|
||
if (currentSession.Succeeded && currentSession.Data != null)
|
||
{
|
||
return Result<ProductionSessionModel>.Fail("ACTIVE_SESSION_EXISTS",
|
||
$"工位 {request.StationId} 已存在活动会话。");
|
||
}
|
||
|
||
var session = new ProductionSessionModel
|
||
{
|
||
SessionId = Guid.NewGuid(),
|
||
ProductTypeCode = request.ProductTypeCode,
|
||
ProductTypeName = request.ProductTypeName,
|
||
StationId = request.StationId,
|
||
StationName = request.StationName,
|
||
OperatorId = request.OperatorId,
|
||
OperatorName = request.OperatorName,
|
||
ShiftId = request.ShiftId,
|
||
ShiftName = request.ShiftName,
|
||
StartedAtUtc = DateTime.UtcNow,
|
||
Status = ProductionSessionStatus.InProgress,
|
||
Result = ProductionSessionResult.Pending,
|
||
CurrentLayer = 1,
|
||
TotalLayers = request.TotalLayers,
|
||
Remark = request.Remark,
|
||
CreatedAtUtc = DateTime.UtcNow,
|
||
UpdatedAtUtc = DateTime.UtcNow,
|
||
CreatedBy = request.CreatedBy,
|
||
UpdatedBy = request.CreatedBy
|
||
};
|
||
|
||
_sessions.TryAdd(session.SessionId, session);
|
||
|
||
_logger.LogInformation("产品会话创建成功,会话ID: {SessionId}", session.SessionId);
|
||
return Result<ProductionSessionModel>.Success(session, message: "产品会话创建成功。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "创建产品会话失败。TraceId: {TraceId}", traceId);
|
||
var errorResult = Result.FromException(ex, "CREATE_SESSION_FAILED", "创建产品会话失败。", traceId);
|
||
return Result<ProductionSessionModel>.FailWithTrace(errorResult.Code, errorResult.Message, errorResult.TraceId ?? traceId, errorResult.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result UpdateSessionStatus(Guid sessionId, ProductionSessionStatus status, string? reason = null)
|
||
{
|
||
try
|
||
{
|
||
if (!_sessions.TryGetValue(sessionId, out var session))
|
||
{
|
||
return Result.Fail("SESSION_NOT_FOUND", $"会话 {sessionId} 不存在。");
|
||
}
|
||
|
||
lock (_lock)
|
||
{
|
||
session.Status = status;
|
||
session.UpdatedAtUtc = DateTime.UtcNow;
|
||
session.UpdatedBy = "System";
|
||
|
||
if (status == ProductionSessionStatus.CompletedNg && !string.IsNullOrEmpty(reason))
|
||
{
|
||
session.NgReason = reason;
|
||
}
|
||
|
||
if (status == ProductionSessionStatus.CompletedOk || status == ProductionSessionStatus.CompletedNg || status == ProductionSessionStatus.Cancelled)
|
||
{
|
||
session.EndedAtUtc = DateTime.UtcNow;
|
||
}
|
||
}
|
||
|
||
_logger.LogInformation("会话状态更新成功,会话ID: {SessionId}, 状态: {Status}", sessionId, status);
|
||
return Result.Success("会话状态更新成功。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "更新会话状态失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "UPDATE_SESSION_STATUS_FAILED", "更新会话状态失败。", traceId);
|
||
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result UpdateSessionProgress(Guid sessionId, int currentLayer)
|
||
{
|
||
try
|
||
{
|
||
if (!_sessions.TryGetValue(sessionId, out var session))
|
||
{
|
||
return Result.Fail("SESSION_NOT_FOUND", $"会话 {sessionId} 不存在。");
|
||
}
|
||
|
||
lock (_lock)
|
||
{
|
||
session.CurrentLayer = currentLayer;
|
||
session.UpdatedAtUtc = DateTime.UtcNow;
|
||
session.UpdatedBy = "System";
|
||
}
|
||
|
||
_logger.LogDebug("会话进度更新成功,会话ID: {SessionId}, 当前层: {CurrentLayer}", sessionId, currentLayer);
|
||
return Result.Success("会话进度更新成功。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "更新会话进度失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "UPDATE_SESSION_PROGRESS_FAILED", "更新会话进度失败。", traceId);
|
||
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result CompleteSession(Guid sessionId, ProductionSessionResult result, string? ngReason = null, string? remark = null)
|
||
{
|
||
try
|
||
{
|
||
if (!_sessions.TryGetValue(sessionId, out var session))
|
||
{
|
||
return Result.Fail("SESSION_NOT_FOUND", $"会话 {sessionId} 不存在。");
|
||
}
|
||
|
||
lock (_lock)
|
||
{
|
||
session.Result = result;
|
||
session.Status = result == ProductionSessionResult.Ok ? ProductionSessionStatus.CompletedOk : ProductionSessionStatus.CompletedNg;
|
||
session.EndedAtUtc = DateTime.UtcNow;
|
||
session.UpdatedAtUtc = DateTime.UtcNow;
|
||
session.UpdatedBy = "System";
|
||
|
||
if (result == ProductionSessionResult.Ng && !string.IsNullOrEmpty(ngReason))
|
||
{
|
||
session.NgReason = ngReason;
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(remark))
|
||
{
|
||
session.Remark = remark;
|
||
}
|
||
}
|
||
|
||
_logger.LogInformation("会话完成,会话ID: {SessionId}, 结果: {Result}", sessionId, result);
|
||
return Result.Success("会话完成。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "完成会话失败。TraceId: {TraceId}", traceId);
|
||
var errorResult = Result.FromException(ex, "COMPLETE_SESSION_FAILED", "完成会话失败。", traceId);
|
||
return Result.FailWithTrace(errorResult.Code, errorResult.Message, errorResult.TraceId ?? traceId, errorResult.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result CancelSession(Guid sessionId, string? reason = null)
|
||
{
|
||
try
|
||
{
|
||
if (!_sessions.TryGetValue(sessionId, out var session))
|
||
{
|
||
return Result.Fail("SESSION_NOT_FOUND", $"会话 {sessionId} 不存在。");
|
||
}
|
||
|
||
lock (_lock)
|
||
{
|
||
session.Status = ProductionSessionStatus.Cancelled;
|
||
session.EndedAtUtc = DateTime.UtcNow;
|
||
session.UpdatedAtUtc = DateTime.UtcNow;
|
||
session.UpdatedBy = "System";
|
||
|
||
if (!string.IsNullOrEmpty(reason))
|
||
{
|
||
session.Remark = reason;
|
||
}
|
||
}
|
||
|
||
_logger.LogInformation("会话取消,会话ID: {SessionId}, 原因: {Reason}", sessionId, reason);
|
||
return Result.Success("会话取消。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "取消会话失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "CANCEL_SESSION_FAILED", "取消会话失败。", traceId);
|
||
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<ProductionSessionModel?> GetSession(Guid sessionId)
|
||
{
|
||
try
|
||
{
|
||
_sessions.TryGetValue(sessionId, out var session);
|
||
|
||
if (session == null)
|
||
{
|
||
_logger.LogWarning("会话不存在,会话ID: {SessionId}", sessionId);
|
||
return Result<ProductionSessionModel?>.Success(null, message: "会话不存在。");
|
||
}
|
||
|
||
_logger.LogDebug("获取会话成功,会话ID: {SessionId}", sessionId);
|
||
return Result<ProductionSessionModel?>.Success(session, message: "获取会话成功。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "获取会话失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "GET_SESSION_FAILED", "获取会话失败。", traceId);
|
||
return Result<ProductionSessionModel?>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<PagedResult<ProductionSessionModel>> GetSessions(GetProductionSessionsRequest request)
|
||
{
|
||
try
|
||
{
|
||
_logger.LogInformation("正在获取会话列表,产品类型: {ProductType}, 工位: {Station}, 页码: {PageIndex}",
|
||
request.ProductTypeCode, request.StationId, request.PageIndex);
|
||
|
||
var query = _sessions.Values.AsQueryable();
|
||
|
||
// 应用筛选条件
|
||
if (!string.IsNullOrEmpty(request.ProductTypeCode))
|
||
{
|
||
query = query.Where(s => s.ProductTypeCode.Equals(request.ProductTypeCode, StringComparison.OrdinalIgnoreCase));
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(request.StationId))
|
||
{
|
||
query = query.Where(s => s.StationId.Equals(request.StationId, StringComparison.OrdinalIgnoreCase));
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(request.OperatorId))
|
||
{
|
||
query = query.Where(s => s.OperatorId.Equals(request.OperatorId, StringComparison.OrdinalIgnoreCase));
|
||
}
|
||
|
||
if (request.Status.HasValue)
|
||
{
|
||
query = query.Where(s => s.Status == request.Status.Value);
|
||
}
|
||
|
||
if (request.Result.HasValue)
|
||
{
|
||
query = query.Where(s => s.Result == request.Result.Value);
|
||
}
|
||
|
||
if (request.StartTimeUtc.HasValue)
|
||
{
|
||
query = query.Where(s => s.StartedAtUtc >= request.StartTimeUtc.Value);
|
||
}
|
||
|
||
if (request.EndTimeUtc.HasValue)
|
||
{
|
||
query = query.Where(s => s.EndedAtUtc <= request.EndTimeUtc.Value);
|
||
}
|
||
|
||
// 排序
|
||
query = query.OrderByDescending(s => s.StartedAtUtc);
|
||
|
||
var totalCount = query.Count();
|
||
var items = query.Skip((request.PageIndex - 1) * request.PageSize).Take(request.PageSize).ToList();
|
||
|
||
var pagedResult = new PagedResult<ProductionSessionModel>
|
||
{
|
||
Items = items,
|
||
TotalCount = totalCount,
|
||
PageIndex = request.PageIndex,
|
||
PageSize = request.PageSize
|
||
};
|
||
|
||
_logger.LogInformation("获取会话列表成功,总数: {TotalCount}, 当前页: {Count}", totalCount, items.Count);
|
||
return Result<PagedResult<ProductionSessionModel>>.Success(pagedResult, message: "获取会话列表成功。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "获取会话列表失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "GET_SESSIONS_FAILED", "获取会话列表失败。", traceId);
|
||
return Result<PagedResult<ProductionSessionModel>>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<ProductionSessionModel?> GetCurrentSession(string stationId)
|
||
{
|
||
try
|
||
{
|
||
var currentSession = _sessions.Values
|
||
.FirstOrDefault(s => s.StationId.Equals(stationId, StringComparison.OrdinalIgnoreCase)
|
||
&& s.Status == ProductionSessionStatus.InProgress);
|
||
|
||
_logger.LogDebug("获取当前会话完成,工位: {StationId}, 会话ID: {SessionId}",
|
||
stationId, currentSession?.SessionId);
|
||
|
||
return Result<ProductionSessionModel?>.Success(currentSession, message: "获取当前会话成功。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "获取当前会话失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "GET_CURRENT_SESSION_FAILED", "获取当前会话失败。", traceId);
|
||
return Result<ProductionSessionModel?>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<ProductionSessionStatistics> GetStatistics(GetProductionSessionStatisticsRequest request)
|
||
{
|
||
try
|
||
{
|
||
_logger.LogInformation("正在获取会话统计信息,时间范围: {StartTime} - {EndTime}",
|
||
request.StartTimeUtc, request.EndTimeUtc);
|
||
|
||
var query = _sessions.Values.Where(s => s.StartedAtUtc >= request.StartTimeUtc && s.StartedAtUtc <= request.EndTimeUtc);
|
||
|
||
// 应用筛选条件
|
||
if (!string.IsNullOrEmpty(request.ProductTypeCode))
|
||
{
|
||
query = query.Where(s => s.ProductTypeCode.Equals(request.ProductTypeCode, StringComparison.OrdinalIgnoreCase));
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(request.StationId))
|
||
{
|
||
query = query.Where(s => s.StationId.Equals(request.StationId, StringComparison.OrdinalIgnoreCase));
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(request.OperatorId))
|
||
{
|
||
query = query.Where(s => s.OperatorId.Equals(request.OperatorId, StringComparison.OrdinalIgnoreCase));
|
||
}
|
||
|
||
var sessions = query.ToList();
|
||
var statistics = CalculateStatistics(sessions, request.StartTimeUtc, request.EndTimeUtc);
|
||
|
||
_logger.LogInformation("获取会话统计信息成功,总会话数: {TotalSessions}, 合格率: {PassRate:P1}",
|
||
statistics.TotalSessions, statistics.PassRate);
|
||
|
||
return Result<ProductionSessionStatistics>.Success(statistics, message: "获取会话统计信息成功。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "获取会话统计信息失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "GET_STATISTICS_FAILED", "获取会话统计信息失败。", traceId);
|
||
return Result<ProductionSessionStatistics>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<byte[]> ExportSessions(ExportProductionSessionsRequest request)
|
||
{
|
||
try
|
||
{
|
||
_logger.LogInformation("正在导出会话记录,格式: {Format}", request.Format);
|
||
|
||
// 获取要导出的会话
|
||
var getSessionsRequest = new GetProductionSessionsRequest
|
||
{
|
||
ProductTypeCode = request.ProductTypeCode,
|
||
StationId = request.StationId,
|
||
OperatorId = request.OperatorId,
|
||
Status = request.Status,
|
||
Result = request.Result,
|
||
StartTimeUtc = request.StartTimeUtc,
|
||
EndTimeUtc = request.EndTimeUtc,
|
||
PageIndex = 1,
|
||
PageSize = int.MaxValue
|
||
};
|
||
|
||
var sessionsResult = GetSessions(getSessionsRequest);
|
||
if (!sessionsResult.Succeeded || sessionsResult.Data == null)
|
||
{
|
||
return Result<byte[]>.Fail("EXPORT_FAILED", "获取要导出的会话失败。");
|
||
}
|
||
|
||
var sessions = sessionsResult.Data.Items.ToList();
|
||
var exportData = GenerateExportData(sessions, request.Format);
|
||
|
||
_logger.LogInformation("导出会话记录成功,记录数: {Count}, 格式: {Format}", sessions.Count, request.Format);
|
||
return Result<byte[]>.Success(exportData, message: "导出会话记录成功。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "导出会话记录失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "EXPORT_SESSIONS_FAILED", "导出会话记录失败。", traceId);
|
||
return Result<byte[]>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
private ProductionSessionStatistics CalculateStatistics(List<ProductionSessionModel> sessions, DateTime startTime, DateTime endTime)
|
||
{
|
||
var statistics = new ProductionSessionStatistics
|
||
{
|
||
TotalSessions = sessions.Count,
|
||
OkSessions = sessions.Count(s => s.Result == ProductionSessionResult.Ok),
|
||
NgSessions = sessions.Count(s => s.Result == ProductionSessionResult.Ng),
|
||
InProgressSessions = sessions.Count(s => s.Status == ProductionSessionStatus.InProgress),
|
||
CancelledSessions = sessions.Count(s => s.Status == ProductionSessionStatus.Cancelled),
|
||
PausedSessions = sessions.Count(s => s.Status == ProductionSessionStatus.Paused)
|
||
};
|
||
|
||
statistics.PassRate = statistics.TotalSessions > 0 ? (double)statistics.OkSessions / statistics.TotalSessions : 0;
|
||
|
||
// 计算平均处理时间
|
||
var completedSessions = sessions.Where(s => s.EndedAtUtc.HasValue).ToList();
|
||
if (completedSessions.Any())
|
||
{
|
||
statistics.AverageProcessingTimeSeconds = completedSessions
|
||
.Average(s => (s.EndedAtUtc!.Value - s.StartedAtUtc).TotalSeconds);
|
||
}
|
||
|
||
// 计算每小时处理量
|
||
var totalHours = (endTime - startTime).TotalHours;
|
||
if (totalHours > 0)
|
||
{
|
||
statistics.ThroughputPerHour = statistics.TotalSessions / totalHours;
|
||
}
|
||
|
||
// 按产品类型分组统计
|
||
statistics.ByProductType = sessions
|
||
.GroupBy(s => new { s.ProductTypeCode, s.ProductTypeName })
|
||
.Select(g => new ProductTypeStatistics
|
||
{
|
||
ProductTypeCode = g.Key.ProductTypeCode,
|
||
ProductTypeName = g.Key.ProductTypeName,
|
||
TotalSessions = g.Count(),
|
||
OkSessions = g.Count(s => s.Result == ProductionSessionResult.Ok),
|
||
NgSessions = g.Count(s => s.Result == ProductionSessionResult.Ng),
|
||
PassRate = g.Count() > 0 ? (double)g.Count(s => s.Result == ProductionSessionResult.Ok) / g.Count() : 0
|
||
})
|
||
.ToList();
|
||
|
||
// 按工位分组统计
|
||
statistics.ByStation = sessions
|
||
.GroupBy(s => new { s.StationId, s.StationName })
|
||
.Select(g => new StationStatistics
|
||
{
|
||
StationId = g.Key.StationId,
|
||
StationName = g.Key.StationName,
|
||
TotalSessions = g.Count(),
|
||
OkSessions = g.Count(s => s.Result == ProductionSessionResult.Ok),
|
||
NgSessions = g.Count(s => s.Result == ProductionSessionResult.Ng),
|
||
PassRate = g.Count() > 0 ? (double)g.Count(s => s.Result == ProductionSessionResult.Ok) / g.Count() : 0
|
||
})
|
||
.ToList();
|
||
|
||
// 按操作员分组统计
|
||
statistics.ByOperator = sessions
|
||
.GroupBy(s => new { s.OperatorId, s.OperatorName })
|
||
.Select(g => new OperatorStatistics
|
||
{
|
||
OperatorId = g.Key.OperatorId,
|
||
OperatorName = g.Key.OperatorName,
|
||
TotalSessions = g.Count(),
|
||
OkSessions = g.Count(s => s.Result == ProductionSessionResult.Ok),
|
||
NgSessions = g.Count(s => s.Result == ProductionSessionResult.Ng),
|
||
PassRate = g.Count() > 0 ? (double)g.Count(s => s.Result == ProductionSessionResult.Ok) / g.Count() : 0
|
||
})
|
||
.ToList();
|
||
|
||
// 按日期分组统计
|
||
statistics.ByDate = sessions
|
||
.GroupBy(s => s.StartedAtUtc.Date)
|
||
.Select(g => new DailyStatistics
|
||
{
|
||
DateUtc = g.Key,
|
||
TotalSessions = g.Count(),
|
||
OkSessions = g.Count(s => s.Result == ProductionSessionResult.Ok),
|
||
NgSessions = g.Count(s => s.Result == ProductionSessionResult.Ng),
|
||
PassRate = g.Count() > 0 ? (double)g.Count(s => s.Result == ProductionSessionResult.Ok) / g.Count() : 0
|
||
})
|
||
.OrderBy(d => d.DateUtc)
|
||
.ToList();
|
||
|
||
return statistics;
|
||
}
|
||
|
||
private byte[] GenerateExportData(List<ProductionSessionModel> sessions, ExportFormat format)
|
||
{
|
||
return format switch
|
||
{
|
||
ExportFormat.Csv => GenerateCsvExport(sessions),
|
||
ExportFormat.Json => GenerateJsonExport(sessions),
|
||
ExportFormat.Excel => GenerateExcelExport(sessions),
|
||
_ => GenerateCsvExport(sessions)
|
||
};
|
||
}
|
||
|
||
private byte[] GenerateCsvExport(List<ProductionSessionModel> sessions)
|
||
{
|
||
using var ms = new System.IO.MemoryStream();
|
||
using var writer = new System.IO.StreamWriter(ms, System.Text.Encoding.UTF8);
|
||
|
||
// 写入CSV头部
|
||
writer.WriteLine("会话ID,产品类型,工位,操作员,开始时间,结束时间,状态,结果,当前层,总层数,NG原因,备注");
|
||
|
||
// 写入数据行
|
||
foreach (var session in sessions)
|
||
{
|
||
writer.WriteLine($"{session.SessionId},{session.ProductTypeCode},{session.StationId},{session.OperatorName}," +
|
||
$"{session.StartedAtUtc:yyyy-MM-dd HH:mm:ss},{session.EndedAtUtc:yyyy-MM-dd HH:mm:ss}," +
|
||
$"{session.Status},{session.Result},{session.CurrentLayer},{session.TotalLayers}," +
|
||
$"{session.NgReason ?? ""},{session.Remark ?? ""}");
|
||
}
|
||
|
||
writer.Flush();
|
||
return ms.ToArray();
|
||
}
|
||
|
||
private byte[] GenerateJsonExport(List<ProductionSessionModel> sessions)
|
||
{
|
||
var json = System.Text.Json.JsonSerializer.Serialize(sessions, new System.Text.Json.JsonSerializerOptions
|
||
{
|
||
WriteIndented = true,
|
||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||
});
|
||
|
||
return System.Text.Encoding.UTF8.GetBytes(json);
|
||
}
|
||
|
||
private byte[] GenerateExcelExport(List<ProductionSessionModel> sessions)
|
||
{
|
||
// 简化的Excel导出实现,实际项目中可以使用EPPlus等库
|
||
// 这里暂时返回CSV格式
|
||
return GenerateCsvExport(sessions);
|
||
}
|
||
|
||
private void InitializeSampleData()
|
||
{
|
||
_logger.LogInformation("正在初始化示例产品会话数据");
|
||
|
||
var sampleSessions = new List<ProductionSessionModel>
|
||
{
|
||
new()
|
||
{
|
||
SessionId = Guid.NewGuid(),
|
||
ProductTypeCode = "VFD-001",
|
||
ProductTypeName = "变频器V1.0",
|
||
StationId = "ST-001",
|
||
StationName = "装配工位1",
|
||
OperatorId = "OP-001",
|
||
OperatorName = "张三",
|
||
ShiftId = "SH-001",
|
||
ShiftName = "白班",
|
||
StartedAtUtc = DateTime.UtcNow.AddHours(-2),
|
||
EndedAtUtc = DateTime.UtcNow.AddHours(-1.8),
|
||
Status = ProductionSessionStatus.CompletedOk,
|
||
Result = ProductionSessionResult.Ok,
|
||
CurrentLayer = 3,
|
||
TotalLayers = 3,
|
||
CreatedAtUtc = DateTime.UtcNow.AddHours(-2),
|
||
UpdatedAtUtc = DateTime.UtcNow.AddHours(-1.8),
|
||
CreatedBy = "System",
|
||
UpdatedBy = "System"
|
||
},
|
||
new()
|
||
{
|
||
SessionId = Guid.NewGuid(),
|
||
ProductTypeCode = "VFD-001",
|
||
ProductTypeName = "变频器V1.0",
|
||
StationId = "ST-001",
|
||
StationName = "装配工位1",
|
||
OperatorId = "OP-002",
|
||
OperatorName = "李四",
|
||
ShiftId = "SH-001",
|
||
ShiftName = "白班",
|
||
StartedAtUtc = DateTime.UtcNow.AddHours(-1.5),
|
||
EndedAtUtc = DateTime.UtcNow.AddHours(-1.2),
|
||
Status = ProductionSessionStatus.CompletedNg,
|
||
Result = ProductionSessionResult.Ng,
|
||
CurrentLayer = 2,
|
||
TotalLayers = 3,
|
||
NgReason = "第2层检测到缺陷",
|
||
CreatedAtUtc = DateTime.UtcNow.AddHours(-1.5),
|
||
UpdatedAtUtc = DateTime.UtcNow.AddHours(-1.2),
|
||
CreatedBy = "System",
|
||
UpdatedBy = "System"
|
||
},
|
||
new()
|
||
{
|
||
SessionId = Guid.NewGuid(),
|
||
ProductTypeCode = "VFD-002",
|
||
ProductTypeName = "变频器V2.0",
|
||
StationId = "ST-002",
|
||
StationName = "装配工位2",
|
||
OperatorId = "OP-003",
|
||
OperatorName = "王五",
|
||
ShiftId = "SH-002",
|
||
ShiftName = "夜班",
|
||
StartedAtUtc = DateTime.UtcNow.AddMinutes(-30),
|
||
Status = ProductionSessionStatus.InProgress,
|
||
Result = ProductionSessionResult.Pending,
|
||
CurrentLayer = 1,
|
||
TotalLayers = 4,
|
||
CreatedAtUtc = DateTime.UtcNow.AddMinutes(-30),
|
||
UpdatedAtUtc = DateTime.UtcNow.AddMinutes(-30),
|
||
CreatedBy = "System",
|
||
UpdatedBy = "System"
|
||
}
|
||
};
|
||
|
||
foreach (var session in sampleSessions)
|
||
{
|
||
_sessions.TryAdd(session.SessionId, session);
|
||
}
|
||
|
||
_logger.LogInformation("示例产品会话数据初始化完成,共 {Count} 条记录", sampleSessions.Count);
|
||
}
|
||
}
|