整体调整了功能

This commit is contained in:
2026-01-13 15:03:02 +08:00
parent 63a768bd80
commit f1a892281b
82 changed files with 11226 additions and 291 deletions

View File

@@ -10,4 +10,8 @@
<PackageReference Include="FreeSql" Version="3.5.213" />
</ItemGroup>
<ItemGroup>
<Folder Include="FileModel\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,52 @@
using FreeSql.DataAnnotations;
namespace FATrace.Model
{
/// <summary>
/// 工厂-入库Excel 导入数据,仅展示用)
/// </summary>
[Table(Name = "FactoryInbound")]
public class FactoryInbound
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 产地
/// </summary>
public string? Origin { get; set; }
/// <summary>
/// 原料代码
/// </summary>
public string? RawCode { get; set; }
/// <summary>
/// 原料名称
/// </summary>
public string? RawName { get; set; }
/// <summary>
/// 重量
/// </summary>
public string? Weight { get; set; }
/// <summary>
/// 登录日
/// </summary>
public string? LoginDate { get; set; }
/// <summary>
/// 登录时间
/// </summary>
public string? LoginTime { get; set; }
/// <summary>
/// 登录日期时间
/// </summary>
public string? LoginDateTime { get; set; }
}
}

View File

@@ -0,0 +1,57 @@
using FreeSql.DataAnnotations;
namespace FATrace.Model
{
/// <summary>
/// 工厂-出入库Excel 导入数据,仅展示用)
/// </summary>
[Table(Name = "FactoryInventoryTransaction")]
public class FactoryInventoryTransaction
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 入库时间
/// </summary>
public string? InTime { get; set; }
/// <summary>
/// 出库时间
/// </summary>
public string? OutTime { get; set; }
/// <summary>
/// 产地
/// </summary>
public string? Origin { get; set; }
/// <summary>
/// 原料代码
/// </summary>
public string? RawCode { get; set; }
/// <summary>
/// 原料名称
/// </summary>
public string? RawName { get; set; }
/// <summary>
/// 入库总重量 KG
/// </summary>
public string? TotalInWeightKg { get; set; }
/// <summary>
/// 出库总重量 KG
/// </summary>
public string? TotalOutWeightKg { get; set; }
/// <summary>
/// 剩余重量 KG
/// </summary>
public string? RemainWeightKg { get; set; }
}
}

View File

@@ -0,0 +1,52 @@
using FreeSql.DataAnnotations;
namespace FATrace.Model
{
/// <summary>
/// 工厂-领料Excel 导入数据,仅展示用)
/// </summary>
[Table(Name = "FactoryMaterialWithdrawal")]
public class FactoryMaterialWithdrawal
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 产地
/// </summary>
public string? Origin { get; set; }
/// <summary>
/// 原料代码
/// </summary>
public string? RawCode { get; set; }
/// <summary>
/// 原料名称
/// </summary>
public string? RawName { get; set; }
/// <summary>
/// 重量
/// </summary>
public string? Weight { get; set; }
/// <summary>
/// 登录日
/// </summary>
public string? LoginDate { get; set; }
/// <summary>
/// 登录时间
/// </summary>
public string? LoginTime { get; set; }
/// <summary>
/// 登录日期时间
/// </summary>
public string? LoginDateTime { get; set; }
}
}

View File

@@ -0,0 +1,67 @@
using FreeSql.DataAnnotations;
namespace FATrace.Model
{
/// <summary>
/// 工厂-成品出库Excel 导入数据,仅展示用)
/// </summary>
[Table(Name = "FactoryOutbound")]
public class FactoryOutbound
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 批号
/// </summary>
public string? Batch { get; set; }
/// <summary>
/// 重量
/// </summary>
public string? Weight { get; set; }
/// <summary>
/// 保质期
/// </summary>
public string? ShelfLife { get; set; }
/// <summary>
/// 产地
/// </summary>
public string? Origin { get; set; }
/// <summary>
/// 原料代码
/// </summary>
public string? RawCode { get; set; }
/// <summary>
/// 原料名称
/// </summary>
public string? RawName { get; set; }
/// <summary>
/// 序号
/// </summary>
public string? SequenceNo { get; set; }
/// <summary>
/// 登录日
/// </summary>
public string? LoginDate { get; set; }
/// <summary>
/// 登录时间
/// </summary>
public string? LoginTime { get; set; }
/// <summary>
/// 登录日期时间
/// </summary>
public string? LoginDateTime { get; set; }
}
}

View File

@@ -0,0 +1,92 @@
using FreeSql.DataAnnotations;
namespace FATrace.Model
{
/// <summary>
/// 工厂-原料生产信息Excel 导入数据,仅展示用)
/// </summary>
[Table(Name = "FactoryProductionRecord")]
public class FactoryProductionRecord
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 原料编号
/// </summary>
public string? RawCode { get; set; }
/// <summary>
/// 原料名称
/// </summary>
public string? RawName { get; set; }
/// <summary>
/// 产地
/// </summary>
public string? Origin { get; set; }
/// <summary>
/// 内袋二维码
/// </summary>
public string? InBagCode { get; set; }
/// <summary>
/// 外箱二维码
/// </summary>
public string? BoxCode { get; set; }
/// <summary>
/// 批号
/// </summary>
public string? Batch { get; set; }
/// <summary>
/// 保质期
/// </summary>
public string? ShelfLife { get; set; }
/// <summary>
/// 称重重量 (g)
/// </summary>
public string? Weight { get; set; }
/// <summary>
/// 配料日期
/// </summary>
public string? DeliveryDate { get; set; }
/// <summary>
/// 剩余重量 (Kg)
/// </summary>
public string? RemainWeight { get; set; }
/// <summary>
/// 入库总重量 (Kg)
/// </summary>
public string? StockWeight { get; set; }
/// <summary>
/// 称重时间
/// </summary>
public string? WeightTime { get; set; }
/// <summary>
/// 操作者
/// </summary>
public string? OpUser { get; set; }
/// <summary>
/// 确认者
/// </summary>
public string? CheckUser { get; set; }
/// <summary>
/// 外箱扫码时间
/// </summary>
public string? BoxScanTime { get; set; }
}
}

View File

@@ -0,0 +1,64 @@
using FreeSql.DataAnnotations;
using System;
namespace FATrace.Model
{
/// <summary>
/// Excel 文件导入日志,用于追踪每次导入结果与行数统计
/// </summary>
[Table(Name = "FileImportLog")]
public class FileImportLog
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 文件名包含时间戳例如20251218161818.xlsx
/// </summary>
[Column(StringLength = 260)]
public string? FileName { get; set; }
/// <summary>
/// 源文件完整路径
/// </summary>
[Column(StringLength = 500)]
public string? SourcePath { get; set; }
/// <summary>
/// 归档后完整路径
/// </summary>
[Column(StringLength = 500)]
public string? ArchivePath { get; set; }
/// <summary>
/// 导入开始时间
/// </summary>
public DateTime StartTime { get; set; }
/// <summary>
/// 导入结束时间
/// </summary>
public DateTime EndTime { get; set; }
/// <summary>
/// 导入状态Success / Failed / Partial 等
/// </summary>
[Column(StringLength = 20)]
public string? Status { get; set; }
/// <summary>
/// 错误或摘要信息
/// </summary>
[Column(StringLength = 1000)]
public string? Message { get; set; }
/// <summary>
/// 每个 Sheet 的行数统计摘要例如FactoryInbound=100;FactoryOutbound=50
/// </summary>
[Column(StringLength = 1000)]
public string? SheetRowStats { get; set; }
}
}

View File

@@ -0,0 +1,67 @@
using FreeSql.DataAnnotations;
namespace FATrace.Model
{
/// <summary>
/// OEM-入库Excel 导入数据,仅展示用)
/// </summary>
[Table(Name = "OEMInbound")]
public class OEMInbound
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 批号
/// </summary>
public string? Batch { get; set; }
/// <summary>
/// 重量
/// </summary>
public string? Weight { get; set; }
/// <summary>
/// 保质期
/// </summary>
public string? ShelfLife { get; set; }
/// <summary>
/// 产地
/// </summary>
public string? Origin { get; set; }
/// <summary>
/// 原料代码
/// </summary>
public string? RawCode { get; set; }
/// <summary>
/// 原料名称
/// </summary>
public string? RawName { get; set; }
/// <summary>
/// 序号
/// </summary>
public string? SequenceNo { get; set; }
/// <summary>
/// 登录日
/// </summary>
public string? LoginDate { get; set; }
/// <summary>
/// 登录时间
/// </summary>
public string? LoginTime { get; set; }
/// <summary>
/// 登录日期时间
/// </summary>
public string? LoginDateTime { get; set; }
}
}

View File

@@ -0,0 +1,57 @@
using FreeSql.DataAnnotations;
namespace FATrace.Model
{
/// <summary>
/// OEM-出入库Excel 导入数据,仅展示用)
/// </summary>
[Table(Name = "OEMInventoryTransaction")]
public class OEMInventoryTransaction
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 入库时间
/// </summary>
public string? InTime { get; set; }
/// <summary>
/// 出库时间
/// </summary>
public string? OutTime { get; set; }
/// <summary>
/// 产地
/// </summary>
public string? Origin { get; set; }
/// <summary>
/// 原料代码
/// </summary>
public string? RawCode { get; set; }
/// <summary>
/// 原料名称
/// </summary>
public string? RawName { get; set; }
/// <summary>
/// 入库总重量 KG
/// </summary>
public string? TotalInWeightKg { get; set; }
/// <summary>
/// 出库总重量 KG
/// </summary>
public string? TotalOutWeightKg { get; set; }
/// <summary>
/// 剩余重量 KG
/// </summary>
public string? RemainWeightKg { get; set; }
}
}

View File

@@ -0,0 +1,67 @@
using FreeSql.DataAnnotations;
namespace FATrace.Model
{
/// <summary>
/// OEM-出库Excel 导入数据,仅展示用)
/// </summary>
[Table(Name = "OEMOutbound")]
public class OEMOutbound
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 批号
/// </summary>
public string? Batch { get; set; }
/// <summary>
/// 重量
/// </summary>
public string? Weight { get; set; }
/// <summary>
/// 保质期
/// </summary>
public string? ShelfLife { get; set; }
/// <summary>
/// 产地
/// </summary>
public string? Origin { get; set; }
/// <summary>
/// 原料代码
/// </summary>
public string? RawCode { get; set; }
/// <summary>
/// 原料名称
/// </summary>
public string? RawName { get; set; }
/// <summary>
/// 序号
/// </summary>
public string? SequenceNo { get; set; }
/// <summary>
/// 登录日
/// </summary>
public string? LoginDate { get; set; }
/// <summary>
/// 登录时间
/// </summary>
public string? LoginTime { get; set; }
/// <summary>
/// 登录日期时间
/// </summary>
public string? LoginDateTime { get; set; }
}
}

View File

@@ -0,0 +1,47 @@
using FreeSql.DataAnnotations;
namespace FATrace.Model
{
/// <summary>
/// OEM-原料使用信息Excel 导入数据,仅展示用)
/// </summary>
[Table(Name = "OEMRawUsageInfo")]
public class OEMRawUsageInfo
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 原料使用时间
/// </summary>
public string? RawUseTime { get; set; }
/// <summary>
/// 内袋二维码
/// </summary>
public string? InBagCode { get; set; }
/// <summary>
/// 原料产地
/// </summary>
public string? Origin { get; set; }
/// <summary>
/// 原料名称
/// </summary>
public string? RawName { get; set; }
/// <summary>
/// 原料代码
/// </summary>
public string? RawCode { get; set; }
/// <summary>
/// 视频链接
/// </summary>
public string? VideoUrl { get; set; }
}
}

113
FATrace.Model/QRModel.cs Normal file
View File

@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FATrace.Model
{
/// <summary>
/// 二维码模型信息
/// 示例DYG05030013,20250923,802,3,01,0001
/// 1段产品编码
/// 2段批号/生产日期,格式 yyyyMMdd例如 20250923
/// 3段重量编码3/4 位数字,末位为小数位,例如 802 表示 80.2g
/// 4段保质期月数1 位数字
/// 5段国家代码01=国内02=日本
/// 6段当日产量计数4 位,从 0001 开始)
/// </summary>
public class QRModel
{
/// <summary>
/// 原始二维码字符串
/// </summary>
public string RawText { get; set; } = string.Empty;
/// <summary>
/// 原料编号(第一段)
/// </summary>
public string RawCode { get; set; } = string.Empty;
/// <summary>
/// 批号
/// </summary>
public string Batch { get; set; }
/// <summary>
/// 重量(第三段解析后的实际数值,比如 802 -> 80.2
/// 单位:克(如有需要可在业务层自行换算)
/// </summary>
public decimal Weight { get; set; }
/// <summary>
/// 保质期(月数,来自第四段)
/// </summary>
public int ShelfLife { get; set; }
/// <summary>
/// 国家代码(第五段,例如 01=国内02=日本)
/// </summary>
public string RawSource { get; set; } = string.Empty;
/// <summary>
/// 当日生产序号第六段4 位,从 1 开始)
/// </summary>
public int DailySequence { get; set; }
/// <summary>
/// 解析二维码字符串为 QRModel。
/// 预期格式:"产品编码,yyyyMMdd,重量编码,保质期(月),国家代码,当日序号"。
/// </summary>
/// <param name="text">二维码原始字符串</param>
/// <returns>解析成功的 QRModel 实例</returns>
/// <exception cref="ArgumentException">当格式不正确时抛出</exception>
public static QRModel Parse(string text)
{
if (string.IsNullOrWhiteSpace(text))
{
throw new ArgumentException("二维码内容不能为空。", nameof(text));
}
var parts = text.Split(',');
if (parts.Length != 6)
{
throw new ArgumentException($"二维码格式不正确,预期 6 段,实际为 {parts.Length} 段。内容:{text}", nameof(text));
}
var model = new QRModel
{
RawText = text.Trim(),
RawCode = parts[0].Trim(),
Batch = parts[1].Trim(),
RawSource = parts[4].Trim()
};
// 重量3/4 位数字,末位为小数位,例如 802 -> 80.2
var weightCode = parts[2].Trim();
if (!int.TryParse(weightCode, out var weightInt))
{
throw new ArgumentException($"重量段不是有效数字:{weightCode}", nameof(text));
}
// 按 1 位小数解析80.2g),如需其他规则可在此调整
model.Weight = weightInt / 10m;
// 保质期(月)
var shelfText = parts[3].Trim();
if (!int.TryParse(shelfText, out var shelfMonths) || shelfMonths < 0)
{
throw new ArgumentException($"保质期(月)不是有效数字:{shelfText}", nameof(text));
}
model.ShelfLife = shelfMonths;
// 当日序号
var seqText = parts[5].Trim();
if (!int.TryParse(seqText, out var seq) || seq < 0)
{
throw new ArgumentException($"当日生产序号不是有效数字:{seqText}", nameof(text));
}
model.DailySequence = seq;
return model;
}
}
}