新增生产-前缫看台记录,并导入车头工/挡车工看台记录历史数据
功能: - 后端新增 KtjlCtgs / KtjlDcgs 两张表、KtjlService 与 api/prod/ktjl 接口 (按日期+车间+班次查询、整组先删后建保存、整组删除、按看台排班带出默认记录、工种下拉) - 挡车数按 F9 口径自动重算(与他人接壤的边界车位各扣 0.5),机组由车位反查机组车台 - 前端新增 /prod/qianxian/ktjl 看台记录页:挡车工/车头工双页签、删除、录入(新增)、录入(指定日期) - 录入弹窗校验对齐 F9:个人时长不超标准、挡车数/看台时长匹配、车头工每机组≥2 人且时长为标准时长整数倍 - 生产-前缫菜单新增「看台记录」,权限 prod:ktjl:list 数据导入: - 新增内嵌资源 biz_prod_qs_ktjl_ctg.csv / biz_prod_qs_ktjl_dcg.csv(约 5 万行,采用紧凑 CSV) - 剔除软删除行、日期异常行、部门无法映射与职工不存在的行;日期由 Excel 序列号转换 - 车头工 12693 行、挡车工 38048 行入库,日期范围 2025-12-16 ~ 2026-09-11 - 表内已有数据则整体跳过,分批 1000 行插入 其他:同步工作进度-13 文档与开发数据库快照
This commit is contained in:
@@ -737,14 +737,16 @@ public static class DbSeeder
|
||||
("机组车台", "/prod/qianxian/jizuchetai", "base/jizuchetai/index", "prod:jizuchetai:list", "SetUp", 1),
|
||||
("落丝记录", "/prod/qianxian/lsjl", "prod/lsjl/index", "prod:lsjl:list", "Document", 2),
|
||||
("车间班次", "/prod/qianxian/chejianbanci", "base/chejianbanci/index", "prod:chejianbanci:list", "Timer", 3),
|
||||
("看台排班", "/prod/qianxian/ktpb", "prod/ktpb/index", "prod:ktpb:list", "Grid", 4)
|
||||
("看台排班", "/prod/qianxian/ktpb", "prod/ktpb/index", "prod:ktpb:list", "Grid", 4),
|
||||
("看台记录", "/prod/qianxian/ktjl", "prod/ktjl/index", "prod:ktjl:list", "Tickets", 5)
|
||||
});
|
||||
|
||||
// 子菜单顺序归一(EnsureTopMenuWithChildren 只补新菜单,不调整已存在菜单的排序)
|
||||
foreach (var (path, sort) in new (string Path, int Sort)[]
|
||||
{
|
||||
("/prod/qianxian/jizuchetai", 1), ("/prod/qianxian/lsjl", 2),
|
||||
("/prod/qianxian/chejianbanci", 3), ("/prod/qianxian/ktpb", 4)
|
||||
("/prod/qianxian/chejianbanci", 3), ("/prod/qianxian/ktpb", 4),
|
||||
("/prod/qianxian/ktjl", 5)
|
||||
})
|
||||
{
|
||||
fsql.Update<SysMenu>()
|
||||
|
||||
@@ -8,6 +8,7 @@ using F9WebAiTest.Domain.Entities.Prod;
|
||||
using F9WebAiTest.Domain.Enums.SYS.Employees;
|
||||
using SysDept = F9WebAiTest.Domain.Entities.SYS.Departments;
|
||||
using SysEmp = F9WebAiTest.Domain.Entities.SYS.Employees;
|
||||
using SysWt = F9WebAiTest.Domain.Entities.SYS.WorkTypes;
|
||||
|
||||
namespace F9WebAiTest.Infrastructure.Data;
|
||||
|
||||
@@ -24,6 +25,8 @@ public static class ProdSeedData
|
||||
private const string KtpbCtgResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_prod_qs_ktpb_ctg.json";
|
||||
private const string KtpbDcgResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_prod_qs_ktpb_dcg.json";
|
||||
private const string KtpbZbzResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_prod_qs_ktpb_zbz.json";
|
||||
private const string KtjlCtgResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_prod_qs_ktjl_ctg.csv";
|
||||
private const string KtjlDcgResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_prod_qs_ktjl_dcg.csv";
|
||||
|
||||
private static readonly JsonSerializerOptions JsonOpts = new()
|
||||
{
|
||||
@@ -39,6 +42,9 @@ public static class ProdSeedData
|
||||
SeedKtpbCtg(fsql);
|
||||
SeedKtpbDcg(fsql);
|
||||
SeedKtpbZbz(fsql);
|
||||
// 看台记录(历史流水,一次性导入)
|
||||
SeedKtjlCtg(fsql);
|
||||
SeedKtjlDcg(fsql);
|
||||
}
|
||||
|
||||
// ==================== 机组车台 ====================
|
||||
@@ -310,6 +316,146 @@ public static class ProdSeedData
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 看台记录 ====================
|
||||
|
||||
/// <summary>
|
||||
/// 车头工看台记录(历史流水):一次性导入,表内已有数据则跳过。
|
||||
/// 数据格式:date|depId|banci|jizu|hours|employeeId|employeeDepId|worktypeId|noChanliang
|
||||
/// </summary>
|
||||
private static void SeedKtjlCtg(IFreeSql fsql)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (fsql.Select<KtjlCtg>().Any()) { return; }
|
||||
var lines = LoadCsv(KtjlCtgResource);
|
||||
if (lines.Count == 0) return;
|
||||
|
||||
var deptMap = BuildDeptMap(fsql);
|
||||
var empIds = BuildEmpIdSet(fsql);
|
||||
var wtNames = fsql.Select<SysWt.WorkType>().ToList().ToDictionary(w => w.Id, w => w.WorkName);
|
||||
|
||||
var batch = new List<KtjlCtg>(1000);
|
||||
int added = 0, skipped = 0;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var f = line.Split('|');
|
||||
if (f.Length < 9) { skipped++; continue; }
|
||||
if (!DateTime.TryParse(f[0], out var date)) { skipped++; continue; }
|
||||
if (!deptMap.TryGetValue(long.Parse(f[1]), out var depId)) { skipped++; continue; }
|
||||
if (!empIds.Contains(long.Parse(f[5]))) { skipped++; continue; }
|
||||
|
||||
var wtId = long.Parse(f[7]);
|
||||
batch.Add(new KtjlCtg
|
||||
{
|
||||
Date = date.Date,
|
||||
DeptId = depId,
|
||||
Banci = (Prod_Banci_Enum)int.Parse(f[2]),
|
||||
Jizu = int.Parse(f[3]),
|
||||
Hours = decimal.Parse(f[4]),
|
||||
EmployeeId = long.Parse(f[5]),
|
||||
EmployeeDepId = deptMap.TryGetValue(long.Parse(f[6]), out var ed) ? ed : depId,
|
||||
WorktypeId = wtId,
|
||||
WorktypeName = wtNames.GetValueOrDefault(wtId, ""),
|
||||
NoChanliang = f[8] == "1" || f[8].Equals("true", StringComparison.OrdinalIgnoreCase)
|
||||
});
|
||||
if (batch.Count >= 1000)
|
||||
{
|
||||
fsql.Insert(batch).ExecuteAffrows();
|
||||
added += batch.Count;
|
||||
batch.Clear();
|
||||
}
|
||||
}
|
||||
if (batch.Count > 0)
|
||||
{
|
||||
fsql.Insert(batch).ExecuteAffrows();
|
||||
added += batch.Count;
|
||||
}
|
||||
Console.WriteLine($"[ProdSeed] 车头工看台记录:来源 {lines.Count} 行,导入 {added} 行,跳过 {skipped} 行");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[ProdSeed] 车头工看台记录导入跳过:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 挡车工看台记录(历史流水):一次性导入,表内已有数据则跳过。
|
||||
/// 数据格式:date|depId|banci|jizu|chetaiStart|chetaiEnd|dangcheNum|hours|employeeId|employeeDepId|worktypeId|noChanliang
|
||||
/// </summary>
|
||||
private static void SeedKtjlDcg(IFreeSql fsql)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (fsql.Select<KtjlDcg>().Any()) { return; }
|
||||
var lines = LoadCsv(KtjlDcgResource);
|
||||
if (lines.Count == 0) return;
|
||||
|
||||
var deptMap = BuildDeptMap(fsql);
|
||||
var empIds = BuildEmpIdSet(fsql);
|
||||
var wtNames = fsql.Select<SysWt.WorkType>().ToList().ToDictionary(w => w.Id, w => w.WorkName);
|
||||
|
||||
var batch = new List<KtjlDcg>(1000);
|
||||
int added = 0, skipped = 0;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var f = line.Split('|');
|
||||
if (f.Length < 12) { skipped++; continue; }
|
||||
if (!DateTime.TryParse(f[0], out var date)) { skipped++; continue; }
|
||||
if (!deptMap.TryGetValue(long.Parse(f[1]), out var depId)) { skipped++; continue; }
|
||||
if (!empIds.Contains(long.Parse(f[8]))) { skipped++; continue; }
|
||||
|
||||
var wtId = long.Parse(f[10]);
|
||||
batch.Add(new KtjlDcg
|
||||
{
|
||||
Date = date.Date,
|
||||
DeptId = depId,
|
||||
Banci = (Prod_Banci_Enum)int.Parse(f[2]),
|
||||
Jizu = int.Parse(f[3]),
|
||||
ChetaiStart = int.Parse(f[4]),
|
||||
ChetaiEnd = int.Parse(f[5]),
|
||||
DangcheNum = decimal.Parse(f[6]),
|
||||
Hours = decimal.Parse(f[7]),
|
||||
EmployeeId = long.Parse(f[8]),
|
||||
EmployeeDepId = deptMap.TryGetValue(long.Parse(f[9]), out var ed) ? ed : depId,
|
||||
WorktypeId = wtId,
|
||||
WorktypeName = wtNames.GetValueOrDefault(wtId, ""),
|
||||
NoChanliang = f[11] == "1" || f[11].Equals("true", StringComparison.OrdinalIgnoreCase)
|
||||
});
|
||||
if (batch.Count >= 1000)
|
||||
{
|
||||
fsql.Insert(batch).ExecuteAffrows();
|
||||
added += batch.Count;
|
||||
batch.Clear();
|
||||
}
|
||||
}
|
||||
if (batch.Count > 0)
|
||||
{
|
||||
fsql.Insert(batch).ExecuteAffrows();
|
||||
added += batch.Count;
|
||||
}
|
||||
Console.WriteLine($"[ProdSeed] 挡车工看台记录:来源 {lines.Count} 行,导入 {added} 行,跳过 {skipped} 行");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[ProdSeed] 挡车工看台记录导入跳过:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static List<string> LoadCsv(string resourceName)
|
||||
{
|
||||
var asm = Assembly.GetExecutingAssembly();
|
||||
using var stream = asm.GetManifestResourceStream(resourceName);
|
||||
if (stream == null) return new List<string>();
|
||||
using var reader = new StreamReader(stream);
|
||||
var list = new List<string>();
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
var line = reader.ReadLine();
|
||||
if (!string.IsNullOrWhiteSpace(line)) list.Add(line);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// ==================== 公共 ====================
|
||||
|
||||
/// <summary>本系统存在的职工 Id 集合(F9 职工导出时保留了原始雪花 Id,可直接比对)</summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user