整体调整了功能
This commit is contained in:
@@ -30,13 +30,13 @@ namespace FATrace.WPLApp.Services
|
||||
IsParent = true,
|
||||
ChildrenNavItemDtos = new ObservableCollection<NavItemDto>()
|
||||
{
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "报表数据",
|
||||
CmdPar = "报表数据",
|
||||
Icon = "\uec55",
|
||||
IsParent = false,
|
||||
},
|
||||
//new NavItemDto()
|
||||
//{
|
||||
// Name = "报表数据",
|
||||
// CmdPar = "报表数据",
|
||||
// Icon = "\uec55",
|
||||
// IsParent = false,
|
||||
//},
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "原料使用查询",
|
||||
@@ -52,6 +52,13 @@ namespace FATrace.WPLApp.Services
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "文件导入日志",
|
||||
CmdPar = "文件导入日志",
|
||||
Icon = "\ue792",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "历史报警",
|
||||
CmdPar = "历史报警",
|
||||
@@ -87,6 +94,13 @@ namespace FATrace.WPLApp.Services
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "用户管理",
|
||||
CmdPar = "用户管理",
|
||||
Icon = "\uec46",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "使用手册",
|
||||
CmdPar = "使用手册",
|
||||
@@ -95,6 +109,104 @@ namespace FATrace.WPLApp.Services
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 工厂/OEM 数据查询(单独的菜单目录节点)
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "工厂/OEM 数据查询",
|
||||
CmdPar = string.Empty,
|
||||
Icon = "\ue650",
|
||||
IsParent = true,
|
||||
ChildrenNavItemDtos = new ObservableCollection<NavItemDto>()
|
||||
{
|
||||
// 工厂节点
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "工厂",
|
||||
CmdPar = string.Empty,
|
||||
Icon = "\ue962",
|
||||
IsParent = true,
|
||||
ChildrenNavItemDtos = new ObservableCollection<NavItemDto>()
|
||||
{
|
||||
new NavItemDto
|
||||
{
|
||||
Name = "工厂-入库",
|
||||
CmdPar = "工厂-入库",
|
||||
Icon = "\uea25",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto
|
||||
{
|
||||
Name = "工厂-领料",
|
||||
CmdPar = "工厂-领料",
|
||||
Icon = "\uea25",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto
|
||||
{
|
||||
Name = "工厂-出入库",
|
||||
CmdPar = "工厂-出入库",
|
||||
Icon = "\uea25",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto
|
||||
{
|
||||
Name = "工厂-原料生产信息",
|
||||
CmdPar = "工厂-原料生产信息",
|
||||
Icon = "\uea25",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto
|
||||
{
|
||||
Name = "工厂-成品出库",
|
||||
CmdPar = "工厂-成品出库",
|
||||
Icon = "\uea25",
|
||||
IsParent = false,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// OEM 节点
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "OEM",
|
||||
CmdPar = string.Empty,
|
||||
Icon = "\ued08",
|
||||
IsParent = true,
|
||||
ChildrenNavItemDtos = new ObservableCollection<NavItemDto>()
|
||||
{
|
||||
new NavItemDto
|
||||
{
|
||||
Name = "OEM-入库",
|
||||
CmdPar = "OEM-入库",
|
||||
Icon = "\ueab4",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto
|
||||
{
|
||||
Name = "OEM-出库",
|
||||
CmdPar = "OEM-出库",
|
||||
Icon = "\ueab4",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto
|
||||
{
|
||||
Name = "OEM-出入库",
|
||||
CmdPar = "OEM-出入库",
|
||||
Icon = "\ueab4",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto
|
||||
{
|
||||
Name = "OEM-原料使用信息",
|
||||
CmdPar = "OEM-原料使用信息",
|
||||
Icon = "\ueab4",
|
||||
IsParent = false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//// 生产管理导航项(父级) - 新增测试导航
|
||||
//new NavItemDto()
|
||||
|
||||
679
FATrace.WPLApp/Services/ReadFileServices.cs
Normal file
679
FATrace.WPLApp/Services/ReadFileServices.cs
Normal file
@@ -0,0 +1,679 @@
|
||||
using FATrace.Com;
|
||||
using FATrace.Model;
|
||||
using NPOI.SS.UserModel;
|
||||
using NPOI.XSSF.UserModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using FreeSql;
|
||||
|
||||
namespace FATrace.WPLApp.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Excel 文件读取与定时导入服务
|
||||
/// - 每小时扫描一次源目录中的 *.xlsx 文件(文件名: yyyyMMddHHmmss.xlsx,每天一个)
|
||||
/// - 按 Sheet 名映射到对应的 FileModel 实体表
|
||||
/// - 使用 FreeSql 批量插入数据
|
||||
/// - 导入完成后将文件移动到归档目录,并在 FileImportLog 中记录详细信息
|
||||
/// </summary>
|
||||
public class ReadFileServices : IDisposable
|
||||
{
|
||||
private readonly ILogService _log;
|
||||
private readonly IFreeSql _fsql;
|
||||
|
||||
private readonly System.Timers.Timer _timer;
|
||||
private readonly string _sourceDirectory;
|
||||
private readonly string _archiveDirectory;
|
||||
|
||||
private bool _disposed;
|
||||
private volatile bool _isRunning;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数:初始化路径配置与定时器
|
||||
/// </summary>
|
||||
public ReadFileServices(ILogService logService, IFreeSql freeSql)
|
||||
{
|
||||
_log = logService;
|
||||
_fsql = freeSql;
|
||||
|
||||
// 路径从 App.config 读取,支持相对路径(相对于应用程序根目录)
|
||||
var sourceSetting = FATrace.Com.ConfigHelper.GetStringOrDefault("ExcelImportSourceDir", "ExcelFile");
|
||||
var archiveSetting = FATrace.Com.ConfigHelper.GetStringOrDefault("ExcelImportArchiveDir", Path.Combine("ExcelFile", "Archive"));
|
||||
|
||||
_sourceDirectory = ResolvePath(sourceSetting);
|
||||
_archiveDirectory = ResolvePath(archiveSetting);
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(_sourceDirectory);
|
||||
Directory.CreateDirectory(_archiveDirectory);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"创建 Excel 导入目录失败: src={_sourceDirectory}, archive={_archiveDirectory}, ex={ex.Message}");
|
||||
}
|
||||
|
||||
// 每小时扫描一次(3600000 ms),如有需要可后续改为配置项
|
||||
_timer = new System.Timers.Timer(TimeSpan.FromMinutes(1).TotalMilliseconds)//TimeSpan.FromHours(1).TotalMilliseconds
|
||||
{
|
||||
AutoReset = true,
|
||||
Enabled = true
|
||||
};
|
||||
_timer.Elapsed += async (s, e) => await OnTimerElapsedAsync().ConfigureAwait(false);
|
||||
|
||||
// 启动后立即执行一次检查,避免必须等一小时
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await OnTimerElapsedAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"Excel 首次导入检查异常: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将配置中的路径转换为绝对路径(支持相对路径)
|
||||
/// </summary>
|
||||
private static string ResolvePath(string pathSetting)
|
||||
{
|
||||
var path = (pathSetting ?? string.Empty).Trim();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return AppDomain.CurrentDomain.BaseDirectory;
|
||||
}
|
||||
|
||||
// 兼容配置中写成 "C:\Dir" 或 'C:\Dir' 的情况
|
||||
if (path.Length >= 2)
|
||||
{
|
||||
if ((path.StartsWith("\"") && path.EndsWith("\"")) || (path.StartsWith("'") && path.EndsWith("'")))
|
||||
{
|
||||
path = path.Substring(1, path.Length - 2).Trim();
|
||||
}
|
||||
}
|
||||
|
||||
// 支持环境变量:%USERPROFILE%\xxx
|
||||
path = Environment.ExpandEnvironmentVariables(path);
|
||||
|
||||
// 支持 ~ 作为用户目录(主要用于开发/测试环境)
|
||||
if (path.StartsWith("~", StringComparison.Ordinal))
|
||||
{
|
||||
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
var tail = path.Substring(1).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
path = Path.Combine(home, tail);
|
||||
}
|
||||
|
||||
// 仅当不是绝对路径时,才基于程序目录做相对路径拼接
|
||||
if (!Path.IsPathRooted(path))
|
||||
{
|
||||
path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
|
||||
}
|
||||
return Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时器回调:避免重入,统一调度导入任务
|
||||
/// </summary>
|
||||
private async Task OnTimerElapsedAsync()
|
||||
{
|
||||
if (_isRunning) return;
|
||||
_isRunning = true;
|
||||
try
|
||||
{
|
||||
await CheckAndImportAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"Excel 导入定时任务异常: {ex}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对外公开的手动触发方法,方便调试与单元测试
|
||||
/// </summary>
|
||||
public Task TriggerImportOnceAsync()
|
||||
{
|
||||
return CheckAndImportAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 扫描源目录,按文件执行导入
|
||||
/// </summary>
|
||||
private async Task CheckAndImportAsync()
|
||||
{
|
||||
if (!Directory.Exists(_sourceDirectory))
|
||||
{
|
||||
_log.Warn($"Excel 导入目录不存在: {_sourceDirectory}");
|
||||
return;
|
||||
}
|
||||
|
||||
string[] files;
|
||||
try
|
||||
{
|
||||
files = Directory.GetFiles(_sourceDirectory, "*.xlsx", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"扫描 Excel 导入目录失败: dir={_sourceDirectory}, ex={ex.Message}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (files.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 按文件名排序,确保按时间顺序处理
|
||||
foreach (var filePath in files.OrderBy(f => Path.GetFileName(f)))
|
||||
{
|
||||
try
|
||||
{
|
||||
await ImportSingleFileAsync(filePath).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"导入 Excel 文件失败: {filePath}, ex={ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入单个 Excel 文件:按 Sheet 写入各表、记录日志并移动文件
|
||||
/// </summary>
|
||||
private async Task ImportSingleFileAsync(string filePath)
|
||||
{
|
||||
var fileName = Path.GetFileName(filePath);
|
||||
if (string.IsNullOrWhiteSpace(fileName)) return;
|
||||
|
||||
// 若已存在成功记录,则不再重复导入
|
||||
var alreadySuccess = await _fsql.Select<FileImportLog>()
|
||||
.Where(x => x.FileName == fileName && x.Status == "Success")
|
||||
.AnyAsync().ConfigureAwait(false);
|
||||
if (alreadySuccess)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var log = new FileImportLog
|
||||
{
|
||||
FileName = fileName,
|
||||
SourcePath = filePath,
|
||||
StartTime = DateTime.Now,
|
||||
Status = "Running"
|
||||
};
|
||||
|
||||
var sheetStats = new Dictionary<string, int>();
|
||||
|
||||
try
|
||||
{
|
||||
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
IWorkbook workbook = new XSSFWorkbook(fs);
|
||||
var formatter = new DataFormatter();
|
||||
|
||||
sheetStats["FactoryInbound"] = ImportFactoryInbound(workbook, formatter);
|
||||
sheetStats["FactoryMaterialWithdrawal"] = ImportFactoryMaterialWithdrawal(workbook, formatter);
|
||||
sheetStats["FactoryInventoryTransaction"] = ImportFactoryInventoryTransaction(workbook, formatter);
|
||||
sheetStats["FactoryProductionRecord"] = ImportFactoryProductionRecord(workbook, formatter);
|
||||
sheetStats["FactoryOutbound"] = ImportFactoryOutbound(workbook, formatter);
|
||||
sheetStats["OEMInbound"] = ImportOEMInbound(workbook, formatter);
|
||||
sheetStats["OEMOutbound"] = ImportOEMOutbound(workbook, formatter);
|
||||
sheetStats["OEMInventoryTransaction"] = ImportOEMInventoryTransaction(workbook, formatter);
|
||||
sheetStats["OEMRawUsageInfo"] = ImportOEMRawUsageInfo(workbook, formatter);
|
||||
}
|
||||
|
||||
// 构造统计摘要
|
||||
log.SheetRowStats = string.Join(";", sheetStats.Select(kv => $"{kv.Key}={kv.Value}"));
|
||||
|
||||
// 移动文件到归档目录
|
||||
var archivePath = Path.Combine(_archiveDirectory, fileName);
|
||||
try
|
||||
{
|
||||
if (File.Exists(archivePath))
|
||||
{
|
||||
var newName = $"{Path.GetFileNameWithoutExtension(fileName)}_{DateTime.Now:HHmmss}{Path.GetExtension(fileName)}";
|
||||
archivePath = Path.Combine(_archiveDirectory, newName);
|
||||
}
|
||||
|
||||
File.Move(filePath, archivePath);
|
||||
log.ArchivePath = archivePath;
|
||||
}
|
||||
catch (Exception moveEx)
|
||||
{
|
||||
log.ArchivePath = archivePath;
|
||||
_log.Error($"移动 Excel 文件到归档目录失败: src={filePath}, dest={archivePath}, ex={moveEx.Message}");
|
||||
// 视为部分成功
|
||||
}
|
||||
|
||||
log.Status = "Success";
|
||||
log.Message = "OK";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Status = "Failed";
|
||||
log.Message = ex.Message;
|
||||
|
||||
if (sheetStats.Count > 0 && string.IsNullOrEmpty(log.SheetRowStats))
|
||||
{
|
||||
log.SheetRowStats = string.Join(";", sheetStats.Select(kv => $"{kv.Key}={kv.Value}"));
|
||||
}
|
||||
|
||||
_log.Error($"导入 Excel 文件过程中出现异常: {filePath}, ex={ex}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
log.EndTime = DateTime.Now;
|
||||
try
|
||||
{
|
||||
await _fsql.Insert(log).ExecuteAffrowsAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"写入 FileImportLog 失败: file={fileName}, ex={ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region 各 Sheet 导入实现
|
||||
|
||||
private static bool IsRowEmpty(IRow? row, DataFormatter formatter)
|
||||
{
|
||||
if (row == null) return true;
|
||||
for (int i = row.FirstCellNum; i < row.LastCellNum; i++)
|
||||
{
|
||||
var cell = row.GetCell(i);
|
||||
if (cell != null && !string.IsNullOrWhiteSpace(formatter.FormatCellValue(cell)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string GetCellString(IRow row, int columnIndex, DataFormatter formatter)
|
||||
{
|
||||
var cell = row.GetCell(columnIndex);
|
||||
return cell == null ? string.Empty : formatter.FormatCellValue(cell).Trim();
|
||||
}
|
||||
|
||||
private int ImportFactoryInbound(IWorkbook workbook, DataFormatter formatter)
|
||||
{
|
||||
var sheet = workbook.GetSheet("工厂-入库");
|
||||
if (sheet == null) return 0;
|
||||
|
||||
var list = new List<FactoryInbound>();
|
||||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
var row = sheet.GetRow(i);
|
||||
if (IsRowEmpty(row, formatter)) continue;
|
||||
|
||||
var entity = new FactoryInbound
|
||||
{
|
||||
Origin = GetCellString(row, 0, formatter),
|
||||
RawCode = GetCellString(row, 1, formatter),
|
||||
RawName = GetCellString(row, 2, formatter),
|
||||
Weight = GetCellString(row, 3, formatter),
|
||||
LoginDate = GetCellString(row, 4, formatter),
|
||||
LoginTime = GetCellString(row, 5, formatter),
|
||||
LoginDateTime = GetCellString(row, 6, formatter)
|
||||
};
|
||||
|
||||
if (IsAllEmpty(entity.Origin, entity.RawCode, entity.RawName, entity.Weight, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||||
continue;
|
||||
|
||||
list.Add(entity);
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
_fsql.Insert(list).ExecuteAffrows();
|
||||
}
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
private int ImportFactoryMaterialWithdrawal(IWorkbook workbook, DataFormatter formatter)
|
||||
{
|
||||
var sheet = workbook.GetSheet("工厂-领料");
|
||||
if (sheet == null) return 0;
|
||||
|
||||
var list = new List<FactoryMaterialWithdrawal>();
|
||||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
var row = sheet.GetRow(i);
|
||||
if (IsRowEmpty(row, formatter)) continue;
|
||||
|
||||
var entity = new FactoryMaterialWithdrawal
|
||||
{
|
||||
Origin = GetCellString(row, 0, formatter),
|
||||
RawCode = GetCellString(row, 1, formatter),
|
||||
RawName = GetCellString(row, 2, formatter),
|
||||
Weight = GetCellString(row, 3, formatter),
|
||||
LoginDate = GetCellString(row, 4, formatter),
|
||||
LoginTime = GetCellString(row, 5, formatter),
|
||||
LoginDateTime = GetCellString(row, 6, formatter)
|
||||
};
|
||||
|
||||
if (IsAllEmpty(entity.Origin, entity.RawCode, entity.RawName, entity.Weight, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||||
continue;
|
||||
|
||||
list.Add(entity);
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
_fsql.Insert(list).ExecuteAffrows();
|
||||
}
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
private int ImportFactoryInventoryTransaction(IWorkbook workbook, DataFormatter formatter)
|
||||
{
|
||||
var sheet = workbook.GetSheet("工厂-出入库");
|
||||
if (sheet == null) return 0;
|
||||
|
||||
var list = new List<FactoryInventoryTransaction>();
|
||||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
var row = sheet.GetRow(i);
|
||||
if (IsRowEmpty(row, formatter)) continue;
|
||||
|
||||
var entity = new FactoryInventoryTransaction
|
||||
{
|
||||
InTime = GetCellString(row, 0, formatter),
|
||||
OutTime = GetCellString(row, 1, formatter),
|
||||
Origin = GetCellString(row, 2, formatter),
|
||||
RawCode = GetCellString(row, 3, formatter),
|
||||
RawName = GetCellString(row, 4, formatter),
|
||||
TotalInWeightKg = GetCellString(row, 5, formatter),
|
||||
TotalOutWeightKg = GetCellString(row, 6, formatter),
|
||||
RemainWeightKg = GetCellString(row, 7, formatter)
|
||||
};
|
||||
|
||||
if (IsAllEmpty(entity.InTime, entity.OutTime, entity.Origin, entity.RawCode, entity.RawName, entity.TotalInWeightKg, entity.TotalOutWeightKg, entity.RemainWeightKg))
|
||||
continue;
|
||||
|
||||
list.Add(entity);
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
_fsql.Insert(list).ExecuteAffrows();
|
||||
}
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
private int ImportFactoryProductionRecord(IWorkbook workbook, DataFormatter formatter)
|
||||
{
|
||||
var sheet = workbook.GetSheet("工厂-原料生产信息");
|
||||
if (sheet == null) return 0;
|
||||
|
||||
var list = new List<FactoryProductionRecord>();
|
||||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
var row = sheet.GetRow(i);
|
||||
if (IsRowEmpty(row, formatter)) continue;
|
||||
|
||||
var entity = new FactoryProductionRecord
|
||||
{
|
||||
RawCode = GetCellString(row, 0, formatter),
|
||||
RawName = GetCellString(row, 1, formatter),
|
||||
Origin = GetCellString(row, 2, formatter),
|
||||
InBagCode = GetCellString(row, 3, formatter),
|
||||
BoxCode = GetCellString(row, 4, formatter),
|
||||
Batch = GetCellString(row, 5, formatter),
|
||||
ShelfLife = GetCellString(row, 6, formatter),
|
||||
Weight = GetCellString(row, 7, formatter),
|
||||
DeliveryDate = GetCellString(row, 8, formatter),
|
||||
RemainWeight = GetCellString(row, 9, formatter),
|
||||
StockWeight = GetCellString(row, 10, formatter),
|
||||
WeightTime = GetCellString(row, 11, formatter),
|
||||
OpUser = GetCellString(row, 12, formatter),
|
||||
CheckUser = GetCellString(row, 13, formatter),
|
||||
BoxScanTime = GetCellString(row, 14, formatter)
|
||||
};
|
||||
|
||||
if (IsAllEmpty(entity.RawCode, entity.RawName, entity.Origin, entity.InBagCode, entity.BoxCode, entity.Batch,
|
||||
entity.ShelfLife, entity.Weight, entity.DeliveryDate, entity.RemainWeight, entity.StockWeight,
|
||||
entity.WeightTime, entity.OpUser, entity.CheckUser, entity.BoxScanTime))
|
||||
continue;
|
||||
|
||||
list.Add(entity);
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
_fsql.Insert(list).ExecuteAffrows();
|
||||
}
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
private int ImportFactoryOutbound(IWorkbook workbook, DataFormatter formatter)
|
||||
{
|
||||
var sheet = workbook.GetSheet("工厂-成品出库");
|
||||
if (sheet == null) return 0;
|
||||
|
||||
var list = new List<FactoryOutbound>();
|
||||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
var row = sheet.GetRow(i);
|
||||
if (IsRowEmpty(row, formatter)) continue;
|
||||
|
||||
var entity = new FactoryOutbound
|
||||
{
|
||||
Batch = GetCellString(row, 0, formatter),
|
||||
Weight = GetCellString(row, 1, formatter),
|
||||
ShelfLife = GetCellString(row, 2, formatter),
|
||||
Origin = GetCellString(row, 3, formatter),
|
||||
RawCode = GetCellString(row, 4, formatter),
|
||||
RawName = GetCellString(row, 5, formatter),
|
||||
SequenceNo = GetCellString(row, 6, formatter),
|
||||
LoginDate = GetCellString(row, 7, formatter),
|
||||
LoginTime = GetCellString(row, 8, formatter),
|
||||
LoginDateTime = GetCellString(row, 9, formatter)
|
||||
};
|
||||
|
||||
if (IsAllEmpty(entity.Batch, entity.Weight, entity.ShelfLife, entity.Origin, entity.RawCode, entity.RawName,
|
||||
entity.SequenceNo, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||||
continue;
|
||||
|
||||
list.Add(entity);
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
_fsql.Insert(list).ExecuteAffrows();
|
||||
}
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
private int ImportOEMInbound(IWorkbook workbook, DataFormatter formatter)
|
||||
{
|
||||
var sheet = workbook.GetSheet("OEM-入库");
|
||||
if (sheet == null) return 0;
|
||||
|
||||
var list = new List<OEMInbound>();
|
||||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
var row = sheet.GetRow(i);
|
||||
if (IsRowEmpty(row, formatter)) continue;
|
||||
|
||||
var entity = new OEMInbound
|
||||
{
|
||||
Batch = GetCellString(row, 0, formatter),
|
||||
Weight = GetCellString(row, 1, formatter),
|
||||
ShelfLife = GetCellString(row, 2, formatter),
|
||||
Origin = GetCellString(row, 3, formatter),
|
||||
RawCode = GetCellString(row, 4, formatter),
|
||||
RawName = GetCellString(row, 5, formatter),
|
||||
SequenceNo = GetCellString(row, 6, formatter),
|
||||
LoginDate = GetCellString(row, 7, formatter),
|
||||
LoginTime = GetCellString(row, 8, formatter),
|
||||
LoginDateTime = GetCellString(row, 9, formatter)
|
||||
};
|
||||
|
||||
if (IsAllEmpty(entity.Batch, entity.Weight, entity.ShelfLife, entity.Origin, entity.RawCode, entity.RawName,
|
||||
entity.SequenceNo, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||||
continue;
|
||||
|
||||
list.Add(entity);
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
_fsql.Insert(list).ExecuteAffrows();
|
||||
}
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
private int ImportOEMOutbound(IWorkbook workbook, DataFormatter formatter)
|
||||
{
|
||||
var sheet = workbook.GetSheet("OEM-出库");
|
||||
if (sheet == null) return 0;
|
||||
|
||||
var list = new List<OEMOutbound>();
|
||||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
var row = sheet.GetRow(i);
|
||||
if (IsRowEmpty(row, formatter)) continue;
|
||||
|
||||
var entity = new OEMOutbound
|
||||
{
|
||||
Batch = GetCellString(row, 0, formatter),
|
||||
Weight = GetCellString(row, 1, formatter),
|
||||
ShelfLife = GetCellString(row, 2, formatter),
|
||||
Origin = GetCellString(row, 3, formatter),
|
||||
RawCode = GetCellString(row, 4, formatter),
|
||||
RawName = GetCellString(row, 5, formatter),
|
||||
SequenceNo = GetCellString(row, 6, formatter),
|
||||
LoginDate = GetCellString(row, 7, formatter),
|
||||
LoginTime = GetCellString(row, 8, formatter),
|
||||
LoginDateTime = GetCellString(row, 9, formatter)
|
||||
};
|
||||
|
||||
if (IsAllEmpty(entity.Batch, entity.Weight, entity.ShelfLife, entity.Origin, entity.RawCode, entity.RawName,
|
||||
entity.SequenceNo, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||||
continue;
|
||||
|
||||
list.Add(entity);
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
_fsql.Insert(list).ExecuteAffrows();
|
||||
}
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
private int ImportOEMInventoryTransaction(IWorkbook workbook, DataFormatter formatter)
|
||||
{
|
||||
var sheet = workbook.GetSheet("OEM-出入库");
|
||||
if (sheet == null) return 0;
|
||||
|
||||
var list = new List<OEMInventoryTransaction>();
|
||||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
var row = sheet.GetRow(i);
|
||||
if (IsRowEmpty(row, formatter)) continue;
|
||||
|
||||
var entity = new OEMInventoryTransaction
|
||||
{
|
||||
InTime = GetCellString(row, 0, formatter),
|
||||
OutTime = GetCellString(row, 1, formatter),
|
||||
Origin = GetCellString(row, 2, formatter),
|
||||
RawCode = GetCellString(row, 3, formatter),
|
||||
RawName = GetCellString(row, 4, formatter),
|
||||
TotalInWeightKg = GetCellString(row, 5, formatter),
|
||||
TotalOutWeightKg = GetCellString(row, 6, formatter),
|
||||
RemainWeightKg = GetCellString(row, 7, formatter)
|
||||
};
|
||||
|
||||
if (IsAllEmpty(entity.InTime, entity.OutTime, entity.Origin, entity.RawCode, entity.RawName,
|
||||
entity.TotalInWeightKg, entity.TotalOutWeightKg, entity.RemainWeightKg))
|
||||
continue;
|
||||
|
||||
list.Add(entity);
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
_fsql.Insert(list).ExecuteAffrows();
|
||||
}
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
private int ImportOEMRawUsageInfo(IWorkbook workbook, DataFormatter formatter)
|
||||
{
|
||||
var sheet = workbook.GetSheet("OEM-原料使用信息");
|
||||
if (sheet == null) return 0;
|
||||
|
||||
var list = new List<OEMRawUsageInfo>();
|
||||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
var row = sheet.GetRow(i);
|
||||
if (IsRowEmpty(row, formatter)) continue;
|
||||
|
||||
var entity = new OEMRawUsageInfo
|
||||
{
|
||||
RawUseTime = GetCellString(row, 0, formatter),
|
||||
InBagCode = GetCellString(row, 1, formatter),
|
||||
Origin = GetCellString(row, 2, formatter),
|
||||
RawName = GetCellString(row, 3, formatter),
|
||||
RawCode = GetCellString(row, 4, formatter),
|
||||
VideoUrl = GetCellString(row, 5, formatter)
|
||||
};
|
||||
|
||||
if (IsAllEmpty(entity.RawUseTime, entity.InBagCode, entity.Origin, entity.RawName, entity.RawCode, entity.VideoUrl))
|
||||
continue;
|
||||
|
||||
list.Add(entity);
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
{
|
||||
_fsql.Insert(list).ExecuteAffrows();
|
||||
}
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
private static bool IsAllEmpty(params string?[] values)
|
||||
{
|
||||
if (values == null || values.Length == 0) return true;
|
||||
foreach (var v in values)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(v)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 释放定时器等资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
|
||||
try
|
||||
{
|
||||
_timer?.Stop();
|
||||
_timer?.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 忽略定时器释放异常
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,7 @@ namespace FATrace.WPLApp.Services
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
IsLogin = false;
|
||||
CurAccessLevel = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -94,6 +95,23 @@ namespace FATrace.WPLApp.Services
|
||||
}
|
||||
}
|
||||
|
||||
private string? _CurAccessLevel;
|
||||
/// <summary>
|
||||
/// 当前用户等级(管理员/操作员/访客)
|
||||
/// </summary>
|
||||
public string? CurAccessLevel
|
||||
{
|
||||
get { return _CurAccessLevel; }
|
||||
set
|
||||
{
|
||||
if (_CurAccessLevel != value)
|
||||
{
|
||||
_CurAccessLevel = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _IsLogin;
|
||||
/// <summary>
|
||||
/// 登录
|
||||
|
||||
Reference in New Issue
Block a user