初步版本251204

This commit is contained in:
2025-12-04 18:39:34 +08:00
parent cd1ec78a11
commit 9dd458ae8b
17 changed files with 1089 additions and 522 deletions

View File

@@ -0,0 +1,92 @@
using CsvHelper;
using CsvHelper.Configuration;
using FATrace.Com;
using FATrace.OEMApp.Model;
using NLog;
using System.Globalization;
using System.Text;
namespace FATrace.OEMApp.Services
{
public class CsvService
{
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public CsvService()
{
RawUseCsvPath = ConfigHelper.GetValue("RawUseCsvPath");
}
/// <summary>
/// 原料使用信息CSV文件路径
/// </summary>
public string RawUseCsvPath { get; set; }
/// <summary>
/// 将一条原料使用记录导出为单独CSV文件包含表头
/// 文件保存目录来自 RawUseCsvPath文件名包含时间戳与内袋二维码若有
/// </summary>
/// <param name="data">原料使用记录</param>
/// <returns>生成的CSV完整路径</returns>
/// <exception cref="ArgumentNullException">当 data 为空时抛出</exception>
/// <exception cref="InvalidOperationException">当 RawUseCsvPath 未配置时抛出</exception>
/// <exception cref="IOException">当写入文件失败时抛出</exception>
public string ExportSingle(RawUseCsvDto data)
{
if (data == null) throw new ArgumentNullException(nameof(data));
if (string.IsNullOrWhiteSpace(RawUseCsvPath))
{
const string msg = "RawUseCsvPath 未配置无法导出CSV。";
_logger.Error(msg);
throw new InvalidOperationException(msg);
}
try
{
// 确保目录存在
Directory.CreateDirectory(RawUseCsvPath);
// 构建安全文件名时间戳_内袋二维码.csv若二维码为空则用RawUse代替
var safeCode = SanitizeFileName(string.IsNullOrWhiteSpace(data.InBagCode) ? "RawUse" : data.InBagCode!.Trim());
var fileName = $"{safeCode}.csv";
var fullPath = Path.Combine(RawUseCsvPath, fileName);
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
HasHeaderRecord = true,
};
using (var writer = new StreamWriter(fullPath, false, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)))
using (var csv = new CsvWriter(writer, config))
{
csv.Context.RegisterClassMap<RawUseCsvDtoMap>();
csv.WriteHeader<RawUseCsvDto>();
csv.NextRecord();
csv.WriteRecord(data);
csv.NextRecord();
}
_logger.Info($"CSV 导出成功: {fullPath}");
return fullPath;
}
catch (Exception ex)
{
_logger.Error(ex, "导出原料使用CSV失败。");
throw new IOException("导出原料使用CSV失败。", ex);
}
}
private static string SanitizeFileName(string name)
{
var invalid = Path.GetInvalidFileNameChars();
var sb = new StringBuilder(name.Length);
foreach (var ch in name)
{
sb.Append(invalid.Contains(ch) ? '_' : ch);
}
var result = sb.ToString();
return string.IsNullOrWhiteSpace(result) ? "RawUse" : result;
}
}
}