完善基础数据

This commit is contained in:
yanpeng200212
2026-10-08 15:44:07 +08:00
parent 8430ba0452
commit 2ffb83830c
95 changed files with 37759 additions and 5 deletions
@@ -18,7 +18,8 @@ public static class BusinessSeedData
}
// ==================== 部门 + 机组车台(真实组织架构) ====================
private static readonly (long Id, string Name, long ParentId, int Sort, string Code)[] DeptData =
/// <summary>F9 原始部门 Id 与名称对照(Id 为 F9 系统的雪花 Id,供工种等模块建立 ID 映射)</summary>
public static readonly (long Id, string Name, long ParentId, int Sort, string Code)[] DeptData =
{
(10920411881541632, "安泰茧丝绸", 0, 0, "123"),
(10929439026188288, "丝业生产中心", 10920411881541632, 100, "100"),
@@ -7,6 +7,7 @@ using F9WebAiTest.Domain.Entities.Base;
using F9WebAiTest.Domain.Entities.Notice;
using F9WebAiTest.Domain.Enums.SYS.RBAC;
using SysMenu = F9WebAiTest.Domain.Entities.SYS.RBAC.Menu;
using SysRole = F9WebAiTest.Domain.Entities.SYS.RBAC.Role;
using SysPermission = F9WebAiTest.Domain.Entities.SYS.RBAC.Permission;
using SysRolePermission = F9WebAiTest.Domain.Entities.SYS.RBAC.RolePermission;
@@ -59,6 +60,21 @@ public static class DbSeeder
// 6.6 F9 风格 RBAC 菜单(用户/角色/菜单/部门管理,写入新 sys_rbac_menus 表)
SeedSysRbacMenus(fsql, snowflake);
// 6.65 基础数据(工种 + 注册表配置 + 原料庄口 + 物资 + 往来单位,F9 导出数据幂等导入)
WorkTypeSeedData.Seed(fsql, snowflake);
RegistrySeedData.Seed(fsql);
YuanliaoZhuangkouSeedData.Seed(fsql);
WuziSeedData.Seed(fsql);
GongyingshangSeedData.Seed(fsql);
// 6.66 基础数据菜单(工种管理、账期管理、注册表、原料庄口、物资目录、往来单位)
SeedWorkTypeMenus(fsql, snowflake);
SeedZhangqiMenus(fsql, snowflake);
SeedRegistryMenus(fsql, snowflake);
SeedYuanliaoZhuangkouMenus(fsql, snowflake);
SeedWuziMenus(fsql, snowflake);
SeedGongyingshangMenus(fsql, snowflake);
// 6.7 为菜单创建权限单元(Permission),并修正旧菜单权限关联(统一权限模型)
FixMenuPermissions(fsql, snowflake);
@@ -429,7 +445,7 @@ public static class DbSeeder
if (sysDir.Rows.Count == 0)
{
sysDirId = snowflake.CreateId();
fsql.Ado.ExecuteNonQuery($"INSERT INTO sys_rbac_menus (id, icon_svg, name, menu_type, parent_id, level, is_active, sort_order, path, component, permission) VALUES ({sysDirId}, 'UserFilled', '系统管理(RBAC)', 1, 0, 1, 0, 6, '/sys', '', '')");
fsql.Ado.ExecuteNonQuery($"INSERT INTO sys_rbac_menus (id, icon_svg, name, menu_type, parent_id, level, is_active, sort_order, path, component, permission, created_at, is_deleted) VALUES ({sysDirId}, 'UserFilled', '系统管理(RBAC)', 1, 0, 1, 0, 6, '/sys', '', '', datetime('now'), 0)");
}
else
{
@@ -441,7 +457,7 @@ public static class DbSeeder
var exist = fsql.Ado.ExecuteDataTable($"SELECT id FROM sys_rbac_menus WHERE path = '{path}'");
if (exist.Rows.Count > 0) return;
var id = snowflake.CreateId();
fsql.Ado.ExecuteNonQuery($"INSERT INTO sys_rbac_menus (id, icon_svg, name, menu_type, parent_id, level, is_active, sort_order, path, component, permission) VALUES ({id}, '{icon}', '{name}', 2, {sysDirId}, 2, 0, {sort}, '{path}', '{component}', '{permission}')");
fsql.Ado.ExecuteNonQuery($"INSERT INTO sys_rbac_menus (id, icon_svg, name, menu_type, parent_id, level, is_active, sort_order, path, component, permission, created_at, is_deleted) VALUES ({id}, '{icon}', '{name}', 2, {sysDirId}, 2, 0, {sort}, '{path}', '{component}', '{permission}', datetime('now'), 0)");
}
AddMenu("用户管理", "/sys/user", "sys/user/index", "User", "sys:user:list", 1);
@@ -461,14 +477,145 @@ public static class DbSeeder
var exist = fsql.Ado.ExecuteDataTable($"SELECT id FROM sys_rbac_role_permissions WHERE role_id = {roleId} AND permission_id = {menuId}");
if (exist.Rows.Count == 0)
{
fsql.Ado.ExecuteNonQuery($"INSERT INTO sys_rbac_role_permissions (id, role_id, permission_id) VALUES ({snowflake.CreateId()}, {roleId}, {menuId})");
fsql.Ado.ExecuteNonQuery($"INSERT INTO sys_rbac_role_permissions (id, role_id, permission_id, created_at, is_deleted) VALUES ({snowflake.CreateId()}, {roleId}, {menuId})");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] RBAC 菜单种子跳过:{ex.Message}");
Console.WriteLine($"[DbSeeder] RBAC 菜单种子跳过:{ex}");
}
}
/// <summary>工种管理菜单(挂在"基础数据"目录下)</summary>
private static void SeedWorkTypeMenus(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
try
{
EnsureBaseDataMenu(fsql, snowflake, "/base/worktype", "工种管理", "base/worktype/index", "base:worktype:list", "Postcard", 5);
Console.WriteLine("[DbSeeder] 工种管理菜单已就绪");
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] 工种菜单种子跳过:{ex}");
}
}
/// <summary>账期管理菜单(挂在"基础数据"目录下)</summary>
private static void SeedZhangqiMenus(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
try
{
EnsureBaseDataMenu(fsql, snowflake, "/base/zhangqi", "账期管理", "base/zhangqi/index", "base:zhangqi:list", "Tickets", 6);
Console.WriteLine("[DbSeeder] 账期管理菜单已就绪");
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] 账期菜单种子跳过:{ex}");
}
}
/// <summary>注册表菜单(挂在"基础数据"目录下)</summary>
private static void SeedRegistryMenus(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
try
{
EnsureBaseDataMenu(fsql, snowflake, "/base/registry", "注册表", "base/registry/index", "base:registry:list", "Setting", 7);
Console.WriteLine("[DbSeeder] 注册表菜单已就绪");
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] 注册表菜单种子跳过:{ex}");
}
}
/// <summary>原料庄口菜单(挂在"基础数据"目录下)</summary>
private static void SeedYuanliaoZhuangkouMenus(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
try
{
EnsureBaseDataMenu(fsql, snowflake, "/base/yuanliaozhuangkou", "原料庄口", "base/yuanliaozhuangkou/index", "base:yuanliaozhuangkou:list", "Box", 8);
Console.WriteLine("[DbSeeder] 原料庄口菜单已就绪");
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] 原料庄口菜单种子跳过:{ex}");
}
}
/// <summary>物资目录菜单(挂在"基础数据"目录下)</summary>
private static void SeedWuziMenus(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
try
{
EnsureBaseDataMenu(fsql, snowflake, "/base/wuzimulu", "物资目录", "base/wuzimulu/index", "base:wuzimulu:list", "Goods", 9);
Console.WriteLine("[DbSeeder] 物资目录菜单已就绪");
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] 物资目录菜单种子跳过:{ex}");
}
}
/// <summary>往来单位菜单(挂在"基础数据"目录下)</summary>
private static void SeedGongyingshangMenus(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
try
{
EnsureBaseDataMenu(fsql, snowflake, "/base/gongyingshang", "往来单位", "base/gongyingshang/index", "base:gongyingshang:list", "Connection", 10);
Console.WriteLine("[DbSeeder] 往来单位菜单已就绪");
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] 往来单位菜单种子跳过:{ex}");
}
}
/// <summary>
/// 确保"基础数据"目录下的菜单存在(含启用状态与图标校正),并给 admin 角色授权。
/// 注意:图标名必须是 Element Plus 图标组件名,前端按图标名渲染菜单图标。
/// </summary>
private static void EnsureBaseDataMenu(IFreeSql fsql, ISnowflakeIdGenerator snowflake,
string path, string name, string component, string permission, string icon, int sort)
{
// 基础数据目录:不存在则创建,已存在则复用
var baseDir = fsql.Select<SysMenu>().Where(m => m.Path == "/base").First();
if (baseDir == null)
{
baseDir = new SysMenu(snowflake.CreateId(), "基础数据", "Files", MenuType_Enum.分组, null, null, 0, 3, 0);
baseDir.SetWebInfo("/base", "", "");
fsql.Insert(baseDir).ExecuteAffrows();
}
var menu = fsql.Select<SysMenu>().Where(m => m.Path == path).First();
if (menu == null)
{
menu = new SysMenu(snowflake.CreateId(), name, icon, MenuType_Enum.页面, null, null, baseDir.Id, sort, 1);
menu.SetWebInfo(path, component, permission);
fsql.Insert(menu).ExecuteAffrows();
}
else if (!menu.IsActive || menu.IconSvg != icon)
{
// 兼容历史数据:补齐启用状态与图标
fsql.Update<SysMenu>()
.Set(x => x.IconSvg, icon)
.Set(x => x.IsActive, true)
.Where(x => x.Id == menu.Id)
.ExecuteAffrows();
}
// admin 角色授权(后续 FixMenuPermissions 会把 permission_id 修正为权限单元 Id)
var adminRole = fsql.Select<SysRole>().Where(r => r.Code == "admin").First();
if (adminRole != null)
{
var any = fsql.Select<SysRolePermission>()
.Where(x => x.RoleId == adminRole.Id && x.PermissionId == menu.Id)
.First();
if (any == null)
{
fsql.Insert(new SysRolePermission(snowflake.CreateId(), adminRole.Id, menu.Id)).ExecuteAffrows();
}
}
}
@@ -0,0 +1,114 @@
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
using FreeSql;
using F9WebAiTest.Domain.Entities.SYS.Gongyingshangs;
using F9WebAiTest.Domain.Enums.SYS.Gongyingshangs;
namespace F9WebAiTest.Infrastructure.Data;
/// <summary>
/// 往来单位(供应商/客户)数据导入:来源于 F9 系统 biz_base_gongyingshang 表导出数据。
/// 幂等:按原始 Id 判重,已存在则跳过;名称 + 业务类型重复的也跳过。
/// </summary>
public static class GongyingshangSeedData
{
private const string Resource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_base_gongyingshang.json";
private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true };
public static void Seed(IFreeSql fsql)
{
try
{
var items = Load();
if (items.Count == 0) return;
var existing = fsql.Select<Gongyingshang>().DisableGlobalFilter("软删除").ToList();
var existIds = existing.Select(x => x.Id).ToHashSet();
var existKeys = existing.Select(x => $"{x.Type}|{x.Name}|{x.BusinessGroup}").ToHashSet();
var inserts = new List<Gongyingshang>();
var duplicate = 0;
foreach (var item in items)
{
if (item.Id <= 0 || existIds.Contains(item.Id)) continue;
if (string.IsNullOrWhiteSpace(item.Name)) continue;
var key = $"{(Gys_Type_Enum)item.BusinessType}|{item.Name.Trim()}|{(Gys_Group_Enum)item.BusinessGroup}";
if (existKeys.Contains(key) || inserts.Any(x => $"{x.Type}|{x.Name}|{x.BusinessGroup}" == key))
{
duplicate++;
continue;
}
inserts.Add(new Gongyingshang(item.Id, (Gys_Type_Enum)item.BusinessType, item.Name.Trim(),
item.Phone ?? string.Empty, item.Lianxiren ?? string.Empty, item.Address ?? string.Empty,
item.Pinyin ?? string.Empty, (Gys_Group_Enum)item.BusinessGroup, (Gys_SaleType_Enum)item.SaleType)
{
CreatedAt = ParseLegacyDate(item.CreatedAt) ?? DateTime.Now,
CreatedBy = item.CreatedBy ?? string.Empty,
UpdatedAt = ParseLegacyDate(item.UpdatedAt)
});
}
if (inserts.Count > 0) fsql.Insert(inserts).ExecuteAffrows();
Console.WriteLine($"[GongyingshangSeed] 往来单位:来源 {items.Count} 条,新增 {inserts.Count} 条,重复 {duplicate} 条");
}
catch (Exception ex)
{
Console.WriteLine($"[GongyingshangSeed] 往来单位数据导入跳过:{ex.Message}");
}
}
private static List<GongyingshangSeedItem> Load()
{
var assembly = typeof(GongyingshangSeedData).Assembly;
using var stream = assembly.GetManifestResourceStream(Resource);
if (stream == null)
{
Console.WriteLine($"[GongyingshangSeed] 未找到内嵌资源:{Resource}");
return new List<GongyingshangSeedItem>();
}
return JsonSerializer.Deserialize<List<GongyingshangSeedItem>>(stream, JsonOptions) ?? new List<GongyingshangSeedItem>();
}
/// <summary>解析 F9 导出的日期(形如 d/M/yyyy H:mm:ss.fff),1970 占位值视为未更新返回 null</summary>
private static readonly string[] LegacyDateFormats =
{
"d/M/yyyy H:mm:ss.fff", "d/M/yyyy H:mm:ss", "d/M/yyyy H:mm",
"M/d/yyyy H:mm:ss.fff", "M/d/yyyy H:mm:ss", "M/d/yyyy H:mm",
"yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss"
};
private static DateTime? ParseLegacyDate(string value)
{
if (string.IsNullOrWhiteSpace(value)) return null;
if (DateTime.TryParseExact(value, LegacyDateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var exact))
return exact.Year <= 1900 ? null : exact;
if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var any))
return any.Year <= 1900 ? null : any;
return null;
}
private sealed class GongyingshangSeedItem
{
[JsonPropertyName("id")] public long Id { get; set; }
[JsonPropertyName("created_by")] public string CreatedBy { get; set; }
[JsonPropertyName("created_at")] public string CreatedAt { get; set; }
[JsonPropertyName("updated_at")] public string UpdatedAt { get; set; }
[JsonPropertyName("businesstype")] public int BusinessType { get; set; }
[JsonPropertyName("name")] public string Name { get; set; }
[JsonPropertyName("phone")] public string Phone { get; set; }
[JsonPropertyName("lianxiren")] public string Lianxiren { get; set; }
[JsonPropertyName("address")] public string Address { get; set; }
[JsonPropertyName("pinyin")] public string Pinyin { get; set; }
[JsonPropertyName("businessgroup")] public int BusinessGroup { get; set; }
/// <summary>F9 导出字段名为 Sale_Type</summary>
[JsonPropertyName("Sale_Type")] public int SaleType { get; set; }
}
}
@@ -0,0 +1,138 @@
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
using FreeSql;
using F9WebAiTest.Domain.Entities.SYS.Registries;
namespace F9WebAiTest.Infrastructure.Data;
/// <summary>
/// 注册表配置导入:来源于 F9 系统 biz_base_registry 表导出数据。
/// 幂等:按原始 Id 判重,已存在则跳过;数据类型归一化为小写。
/// </summary>
public static class RegistrySeedData
{
private const string RegistryResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_base_registry.json";
private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true };
public static void Seed(IFreeSql fsql)
{
try
{
var items = Load(RegistryResource);
if (items.Count == 0) return;
var existIds = fsql.Select<Registry>()
.DisableGlobalFilter("软删除")
.ToList()
.Select(x => x.Id)
.ToHashSet();
// 同命名空间 + 键名也算重复,避免唯一性问题
var existKeys = fsql.Select<Registry>()
.DisableGlobalFilter("软删除")
.ToList()
.Select(x => $"{x.Category}|{x.KeyName}")
.ToHashSet();
var inserts = new List<Registry>();
var duplicate = 0;
foreach (var item in items)
{
if (item.Id <= 0 || existIds.Contains(item.Id)) continue;
if (string.IsNullOrWhiteSpace(item.Category) || string.IsNullOrWhiteSpace(item.KeyName)) continue;
var category = item.Category.Trim();
var keyName = item.KeyName.Trim();
var key = $"{category}|{keyName}";
if (existKeys.Contains(key) || inserts.Any(x => x.Category == category && x.KeyName == keyName))
{
duplicate++;
continue;
}
inserts.Add(new Registry(item.Id, category, keyName, item.Value ?? string.Empty,
(item.DataType ?? "string").Trim().ToLowerInvariant(), item.Description ?? string.Empty,
ParseActive(item.IsActive))
{
CreatedAt = ParseLegacyDate(item.CreatedAt) ?? DateTime.Now,
CreatedBy = item.CreatedBy ?? string.Empty,
UpdatedAt = ParseLegacyDate(item.UpdatedAt)
});
}
if (inserts.Count > 0) fsql.Insert(inserts).ExecuteAffrows();
Console.WriteLine($"[RegistrySeed] 注册表:来源 {items.Count} 条,新增 {inserts.Count} 条,跳过已存在 {items.Count - inserts.Count - duplicate} 条,重复 {duplicate} 条");
}
catch (Exception ex)
{
Console.WriteLine($"[RegistrySeed] 注册表数据导入跳过:{ex.Message}");
}
}
/// <summary>is_active 在导出数据里可能是 "1"/"0" 字符串、数字或布尔</summary>
private static bool ParseActive(JsonElement element)
{
switch (element.ValueKind)
{
case JsonValueKind.String:
var text = element.GetString();
return text == "1" || string.Equals(text, "true", StringComparison.OrdinalIgnoreCase);
case JsonValueKind.Number:
return element.GetInt32() != 0;
case JsonValueKind.True:
return true;
default:
return false;
}
}
private static List<RegistrySeedItem> Load(string resourceName)
{
var assembly = typeof(RegistrySeedData).Assembly;
using var stream = assembly.GetManifestResourceStream(resourceName);
if (stream == null)
{
Console.WriteLine($"[RegistrySeed] 未找到内嵌资源:{resourceName}");
return new List<RegistrySeedItem>();
}
return JsonSerializer.Deserialize<List<RegistrySeedItem>>(stream, JsonOptions) ?? new List<RegistrySeedItem>();
}
/// <summary>解析 F9 导出的日期(形如 d/M/yyyy H:mm:ss.fff),1970 占位值视为未更新返回 null</summary>
private static readonly string[] LegacyDateFormats =
{
"d/M/yyyy H:mm:ss.fff", "d/M/yyyy H:mm:ss", "d/M/yyyy H:mm",
"M/d/yyyy H:mm:ss.fff", "M/d/yyyy H:mm:ss", "M/d/yyyy H:mm",
"yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss"
};
private static DateTime? ParseLegacyDate(string value)
{
if (string.IsNullOrWhiteSpace(value)) return null;
if (DateTime.TryParseExact(value, LegacyDateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var exact))
return exact.Year <= 1900 ? null : exact;
if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var any))
return any.Year <= 1900 ? null : any;
return null;
}
private sealed class RegistrySeedItem
{
[JsonPropertyName("id")] public long Id { get; set; }
[JsonPropertyName("created_by")] public string CreatedBy { get; set; }
[JsonPropertyName("created_at")] public string CreatedAt { get; set; }
[JsonPropertyName("update_by")] public string UpdateBy { get; set; }
[JsonPropertyName("updated_at")] public string UpdatedAt { get; set; }
[JsonPropertyName("category")] public string Category { get; set; }
[JsonPropertyName("key_name")] public string KeyName { get; set; }
[JsonPropertyName("value")] public string Value { get; set; }
[JsonPropertyName("data_type")] public string DataType { get; set; }
[JsonPropertyName("description")] public string Description { get; set; }
[JsonPropertyName("is_active")] public JsonElement IsActive { get; set; }
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,530 @@
[
{
"id": 23438176068571136,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:14:56.647",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "选茧工",
"sort": 300,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438224298872832,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:15:08.137",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "剥茧工",
"sort": 310,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438346827075584,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:15:37.35",
"update_by": "主干-何启旭",
"updated_at": "16/12/2025 14:37:01.553",
"deleted_at": null,
"work_name": "值班长",
"sort": 125,
"biz_type": "辅助",
"sccb_fenlei": "无"
},
{
"id": 23438392125558784,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:15:48.15",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "混茧工",
"sort": 320,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438434936819712,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:15:58.357",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "选茧辅助工",
"sort": 330,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438524292272128,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:16:19.66",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "煮茧工",
"sort": 400,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438580714049536,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:16:33.113",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "挖茧工",
"sort": 410,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438800021622784,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:25.4",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "挡车工",
"sort": 420,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438847324983296,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:36.68",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "车头工",
"sort": 430,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438890471788544,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:46.967",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "洗给茧机工",
"sort": 440,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438931622105088,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:56.777",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "洗锅工",
"sort": 450,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23438972201996288,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:18:06.45",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "下丝工",
"sort": 460,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23439012698001408,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:18:16.107",
"update_by": "主干-何启旭",
"updated_at": "16/12/2025 20:45:03.043",
"deleted_at": null,
"work_name": "提䈅浸丝工",
"sort": 500,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23439226154520576,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:07",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "返丝工",
"sort": 510,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23439268273721344,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:17.04",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "编丝工",
"sort": 520,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23439326348054528,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:30.887",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "整理工",
"sort": 530,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 23439367984910336,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:40.813",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "检验工",
"sort": 540,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 25426727069028352,
"created_by": "主干-何启旭",
"created_at": "10/12/2025 11:56:44.157",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "搬运工",
"sort": 710,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 25461577511604224,
"created_by": "主干-何启旭",
"created_at": "10/12/2025 14:15:13.14",
"update_by": "主干信息dev",
"updated_at": "19/12/2025 00:59:43.767",
"deleted_at": null,
"work_name": "前缫保养工",
"sort": 600,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 26530137008771072,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:01:17.583",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "焊工",
"sort": 670,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 26530271612375040,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:01:49.667",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "电工",
"sort": 630,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 26531102533357568,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:05:07.773",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "污水处理工",
"sort": 640,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 26531649130860544,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:07:18.09",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "司炉工",
"sort": 660,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 26532021190791168,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:08:46.797",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "抽水工",
"sort": 650,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 27630006972715008,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 13:51:47",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "煮绵工",
"sort": 800,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 27630063633567744,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 13:52:00.5",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "打绵工",
"sort": 810,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 27630133347094528,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 13:52:17.12",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "选蛹工",
"sort": 820,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 27630236493418496,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 13:52:41.713",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "收烘工",
"sort": 830,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 27632176937832448,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 14:00:24.357",
"update_by": "主干-何启旭",
"updated_at": "16/12/2025 14:00:37.73",
"deleted_at": null,
"work_name": "扯绵工",
"sort": 840,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 28521071405699072,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:52:33.32",
"update_by": "主干信息dev",
"updated_at": "19/12/2025 00:52:53.327",
"deleted_at": null,
"work_name": "库管",
"sort": 700,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 28521507164524544,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:54:17.213",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "车间主任",
"sort": 110,
"biz_type": "辅助",
"sccb_fenlei": "无"
},
{
"id": 28521568866930688,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:54:31.923",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "车间副主任",
"sort": 120,
"biz_type": "辅助",
"sccb_fenlei": "无"
},
{
"id": 28521631693410304,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:54:46.903",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "工艺员",
"sort": 210,
"biz_type": "辅助",
"sccb_fenlei": "无"
},
{
"id": 28521657689706496,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:54:53.1",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "技术员",
"sort": 130,
"biz_type": "辅助",
"sccb_fenlei": "无"
},
{
"id": 28521697179078656,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:55:02.517",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "丝业总监",
"sort": 100,
"biz_type": "辅助",
"sccb_fenlei": "管理"
},
{
"id": 28522012754317312,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:56:17.753",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "科长",
"sort": 200,
"biz_type": "辅助",
"sccb_fenlei": "无"
},
{
"id": 28522208758337536,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:57:04.487",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "试缫员",
"sort": 220,
"biz_type": "辅助",
"sccb_fenlei": "无"
},
{
"id": 28522914059915264,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:59:52.643",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "后缫保养工",
"sort": 610,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 28522951989006336,
"created_by": "主干信息dev",
"created_at": "19/12/2025 01:00:01.687",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "辅助保养工",
"sort": 620,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 28522982716477440,
"created_by": "主干信息dev",
"created_at": "19/12/2025 01:00:09.01",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "钳工",
"sort": 680,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 29447734511538176,
"created_by": "主干-何启旭",
"created_at": "21/12/2025 14:14:47.027",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "收蛹工",
"sort": 825,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 29448226687946752,
"created_by": "主干-何启旭",
"created_at": "21/12/2025 14:16:44.363",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "打包工",
"sort": 835,
"biz_type": "生产",
"sccb_fenlei": "无"
},
{
"id": 34543417765662720,
"created_by": "余思洁",
"created_at": "4/1/2026 15:43:12.587",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "劳资员",
"sort": 150,
"biz_type": "辅助",
"sccb_fenlei": "无"
},
{
"id": 111659074877132800,
"created_by": "主干-何启旭",
"created_at": "5/8/2026 10:53:17.993",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"work_name": "设备班长",
"sort": 590,
"biz_type": "辅助",
"sccb_fenlei": "无"
}
]
@@ -0,0 +1,802 @@
[
{
"id": 20695684281798656,
"created_by": null,
"created_at": "27/11/2025 10:37:15.597",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 12467989202866176,
"department_id": 10928146102620160
},
{
"id": 20695759603109888,
"created_by": null,
"created_at": "27/11/2025 10:37:33.553",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20055607880978432,
"department_id": 16043931070369792
},
{
"id": 20695782051024896,
"created_by": null,
"created_at": "27/11/2025 10:37:38.903",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20326468902981632,
"department_id": 16047387197837312
},
{
"id": 20695815085363200,
"created_by": null,
"created_at": "27/11/2025 10:37:46.78",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20326436481011712,
"department_id": 16047387197837312
},
{
"id": 20695859305910272,
"created_by": null,
"created_at": "27/11/2025 10:37:57.323",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 12468079858552832,
"department_id": 10929739564847104
},
{
"id": 20698353377480704,
"created_by": null,
"created_at": "27/11/2025 10:47:51.927",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20692320357715968,
"department_id": 19667471837433856
},
{
"id": 20698436936404992,
"created_by": null,
"created_at": "27/11/2025 10:48:11.85",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20422085423665152,
"department_id": 16047387197837312
},
{
"id": 20698459279462400,
"created_by": null,
"created_at": "27/11/2025 10:48:17.177",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20422128373338112,
"department_id": 16047387197837312
},
{
"id": 20702907569541120,
"created_by": null,
"created_at": "27/11/2025 11:05:57.833",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20055607880978432,
"department_id": 17928435246567424
},
{
"id": 20703059055218688,
"created_by": null,
"created_at": "27/11/2025 11:06:33.927",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20055701690781696,
"department_id": 16047387197837312
},
{
"id": 20703153791963136,
"created_by": null,
"created_at": "27/11/2025 11:06:56.51",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20055607880978432,
"department_id": 16047387197837312
},
{
"id": 20703153812934656,
"created_by": null,
"created_at": "27/11/2025 11:06:56.517",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20055607880978432,
"department_id": 17928435246567424
},
{
"id": 20703197882486784,
"created_by": null,
"created_at": "27/11/2025 11:07:07.023",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20055701690781696,
"department_id": 16043931070369792
},
{
"id": 20703197907652608,
"created_by": null,
"created_at": "27/11/2025 11:07:07.027",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 20055701690781696,
"department_id": 17928435246567424
},
{
"id": 23438192023703552,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:15:00.447",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438176068571136,
"department_id": 22308361408090112
},
{
"id": 23438246738399232,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:15:13.487",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438224298872832,
"department_id": 22308361408090112
},
{
"id": 23438364413792256,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:15:41.543",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438346827075584,
"department_id": 22308361408090112
},
{
"id": 23438408156188672,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:15:51.973",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438392125558784,
"department_id": 22308361408090112
},
{
"id": 23438455572795392,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:16:03.277",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438434936819712,
"department_id": 22308361408090112
},
{
"id": 23438819743240192,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:30.103",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438800021622784,
"department_id": 16043931070369792
},
{
"id": 23438821483876352,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:30.517",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438800021622784,
"department_id": 16047387197837312
},
{
"id": 23438822935105536,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:30.863",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438800021622784,
"department_id": 22308600831545344
},
{
"id": 23438824277282816,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:31.183",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438800021622784,
"department_id": 22308683820044288
},
{
"id": 23438860419600384,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:39.8",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438847324983296,
"department_id": 16043931070369792
},
{
"id": 23438861640142848,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:40.09",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438847324983296,
"department_id": 16047387197837312
},
{
"id": 23438863020068864,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:40.42",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438847324983296,
"department_id": 22308600831545344
},
{
"id": 23438864358051840,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:17:40.737",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438847324983296,
"department_id": 22308683820044288
},
{
"id": 23439102896508928,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:18:37.61",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23439012698001408,
"department_id": 22308805823959040
},
{
"id": 23439200493768704,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:00.88",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23439178888908800,
"department_id": 22308918461992960
},
{
"id": 23439200502157312,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:00.883",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23439178888908800,
"department_id": 22309003073687552
},
{
"id": 23439200946753536,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:00.987",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23439178888908800,
"department_id": 22308805823959040
},
{
"id": 23439246765330432,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:11.913",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23439226154520576,
"department_id": 22308805823959040
},
{
"id": 23439300595027968,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:24.747",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23439268273721344,
"department_id": 22308805823959040
},
{
"id": 23439343280459776,
"created_by": "主干-何启旭",
"created_at": "5/12/2025 00:19:34.923",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23439326348054528,
"department_id": 22309003073687552
},
{
"id": 25434120284803072,
"created_by": "主干信息dev",
"created_at": "10/12/2025 12:26:06.84",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438524292272128,
"department_id": 25379428280307712
},
{
"id": 25434168884203520,
"created_by": "主干信息dev",
"created_at": "10/12/2025 12:26:18.407",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438580714049536,
"department_id": 25379428280307712
},
{
"id": 25434462124773376,
"created_by": "主干信息dev",
"created_at": "10/12/2025 12:27:28.32",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 25426727069028352,
"department_id": 10929739564847104
},
{
"id": 25461606632656896,
"created_by": "主干-何启旭",
"created_at": "10/12/2025 14:15:20.07",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 25461577511604224,
"department_id": 22309110082965504
},
{
"id": 26530160677228544,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:01:23.223",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 26530137008771072,
"department_id": 22309110082965504
},
{
"id": 26530295175974912,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:01:55.283",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 26530271612375040,
"department_id": 22309110082965504
},
{
"id": 26531129519509504,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:05:14.207",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 26531102533357568,
"department_id": 22309110082965504
},
{
"id": 26531671750742016,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:07:23.483",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 26531649130860544,
"department_id": 22309110082965504
},
{
"id": 26532045635194880,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:08:52.623",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 26532021190791168,
"department_id": 22309110082965504
},
{
"id": 26532490604711936,
"created_by": "主干-何启旭",
"created_at": "13/12/2025 13:10:38.71",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 26532460237950976,
"department_id": 22309110082965504
},
{
"id": 27630321012838400,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 13:53:01.877",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 27630006972715008,
"department_id": 22309340027293696
},
{
"id": 27630338444365824,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 13:53:06.023",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 27630063633567744,
"department_id": 22309340027293696
},
{
"id": 27630353271230464,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 13:53:09.557",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 27630133347094528,
"department_id": 22309340027293696
},
{
"id": 27630369662570496,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 13:53:13.463",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 27630236493418496,
"department_id": 22309340027293696
},
{
"id": 27632360799342592,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 14:01:08.193",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 27632176937832448,
"department_id": 24029387057795072
},
{
"id": 27641416830160896,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 14:37:07.32",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438346827075584,
"department_id": 16043931070369792
},
{
"id": 27641419233497088,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 14:37:07.893",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438346827075584,
"department_id": 16047387197837312
},
{
"id": 27641420995104768,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 14:37:08.313",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438346827075584,
"department_id": 22308600831545344
},
{
"id": 27641427043291136,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 14:37:09.757",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438346827075584,
"department_id": 22308683820044288
},
{
"id": 27734255828209664,
"created_by": "主干-何启旭",
"created_at": "16/12/2025 20:46:01.85",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23439367984910336,
"department_id": 22308918461992960
},
{
"id": 28520672355422208,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:50:58.203",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438890471788544,
"department_id": 25256354205667328
},
{
"id": 28520696053239808,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:51:03.83",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438931622105088,
"department_id": 25256354205667328
},
{
"id": 28520725274955776,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:51:10.797",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438972201996288,
"department_id": 25256354205667328
},
{
"id": 28521101512413184,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:52:40.497",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521071405699072,
"department_id": 10929739564847104
},
{
"id": 28521762958348288,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:55:18.2",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521507164524544,
"department_id": 25256354205667328
},
{
"id": 28521770428403712,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:55:19.98",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521507164524544,
"department_id": 22308805823959040
},
{
"id": 28521817631100928,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:55:31.233",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521507164524544,
"department_id": 22309110082965504
},
{
"id": 28521838933970944,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:55:36.313",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521568866930688,
"department_id": 22309110082965504
},
{
"id": 28521842088087552,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:55:37.063",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521568866930688,
"department_id": 22308805823959040
},
{
"id": 28521849046437888,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:55:38.723",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521568866930688,
"department_id": 25256354205667328
},
{
"id": 28522041653071872,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:56:24.647",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28522012754317312,
"department_id": 22307875854487552
},
{
"id": 28522115703508992,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:56:42.3",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521697179078656,
"department_id": 10929439026188288
},
{
"id": 28522132623331328,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:56:46.333",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521657689706496,
"department_id": 10929439026188288
},
{
"id": 28522251905142784,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:57:14.773",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28522208758337536,
"department_id": 22308241237086208
},
{
"id": 28522745834770432,
"created_by": "主干信息dev",
"created_at": "19/12/2025 00:59:12.533",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28522683570327552,
"department_id": 24029387057795072
},
{
"id": 28523012672196608,
"created_by": "主干信息dev",
"created_at": "19/12/2025 01:00:16.153",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28522914059915264,
"department_id": 22309110082965504
},
{
"id": 28523028627329024,
"created_by": "主干信息dev",
"created_at": "19/12/2025 01:00:19.957",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28522951989006336,
"department_id": 22309110082965504
},
{
"id": 28523051444342784,
"created_by": "主干信息dev",
"created_at": "19/12/2025 01:00:25.397",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28522982716477440,
"department_id": 22309110082965504
},
{
"id": 29435687623200768,
"created_by": "主干-何启旭",
"created_at": "21/12/2025 13:26:54.827",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438346827075584,
"department_id": 22309340027293696
},
{
"id": 29447781366108160,
"created_by": "主干-何启旭",
"created_at": "21/12/2025 14:14:58.19",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 29447734511538176,
"department_id": 22309340027293696
},
{
"id": 29448276386254848,
"created_by": "主干-何启旭",
"created_at": "21/12/2025 14:16:56.21",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 29448226687946752,
"department_id": 22309340027293696
},
{
"id": 34539915198861312,
"created_by": "余思洁",
"created_at": "4/1/2026 15:29:17.513",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28521631693410304,
"department_id": 10929439026188288
},
{
"id": 34543488523571200,
"created_by": "余思洁",
"created_at": "4/1/2026 15:43:29.453",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 34543417765662720,
"department_id": 10929439026188288
},
{
"id": 42801337712250880,
"created_by": "李西宴",
"created_at": "27/1/2026 10:37:14.127",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 28522208758337536,
"department_id": 22305998261719040
},
{
"id": 59104724992921600,
"created_by": "余思洁",
"created_at": "13/3/2026 10:21:04.56",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 23438346827075584,
"department_id": 22308805823959040
},
{
"id": 111659115859677184,
"created_by": "主干-何启旭",
"created_at": "5/8/2026 10:53:27.763",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 111659074877132800,
"department_id": 22309110082965504
}
]
@@ -0,0 +1,12 @@
[
{
"id": 122604578150551552,
"created_by": "主干信息dev",
"created_at": "4/9/2026 15:46:49.313",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"worktype_id": 25461577511604224,
"role_id": 122603542799192064
}
]
@@ -0,0 +1,482 @@
[
{
"id": 10619378722672640,
"created_by": null,
"created_at": "30/10/2025 15:17:37.187",
"update_by": null,
"updated_at": "3/12/2025 15:47:59.843",
"deleted_at": null,
"businesstype": 1,
"departmenttype": 10,
"code": "01",
"name": "干茧",
"parentid": 0,
"sortorder": 1,
"description": "测试数据"
},
{
"id": 10621067601121280,
"created_by": null,
"created_at": "30/10/2025 15:24:19.847",
"update_by": null,
"updated_at": "3/12/2025 15:52:03.793",
"deleted_at": null,
"businesstype": 4,
"departmenttype": 10,
"code": "04",
"name": "副产品",
"parentid": 0,
"sortorder": 4,
"description": "测试数据"
},
{
"id": 18611822663831552,
"created_by": null,
"created_at": "21/11/2025 16:36:44.317",
"update_by": null,
"updated_at": "3/12/2025 15:47:15.74",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "02",
"name": "五金",
"parentid": 0,
"sortorder": 2,
"description": ""
},
{
"id": 18611970890534912,
"created_by": null,
"created_at": "21/11/2025 16:37:19.657",
"update_by": null,
"updated_at": "3/12/2025 15:47:41.58",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "0201",
"name": "五金配件",
"parentid": 18611822663831552,
"sortorder": 201,
"description": ""
},
{
"id": 18616855094628352,
"created_by": null,
"created_at": "21/11/2025 16:56:44.14",
"update_by": null,
"updated_at": "3/12/2025 15:47:45.613",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "0202",
"name": "螺丝管件",
"parentid": 18611822663831552,
"sortorder": 202,
"description": "测试"
},
{
"id": 22316319563059200,
"created_by": null,
"created_at": "1/12/2025 21:57:05.217",
"update_by": null,
"updated_at": "3/12/2025 15:47:49.52",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "0203",
"name": "电器配件",
"parentid": 18611822663831552,
"sortorder": 203,
"description": ""
},
{
"id": 22506451083726848,
"created_by": "游建梅",
"created_at": "2/12/2025 10:32:36.1",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": "2/12/2025 10:32:41.93",
"businesstype": 5,
"departmenttype": 10,
"code": "111",
"name": "键盘",
"parentid": 18611822663831552,
"sortorder": 111,
"description": ""
},
{
"id": 22507712260608000,
"created_by": "游建梅",
"created_at": "2/12/2025 10:37:36.78",
"update_by": null,
"updated_at": "3/12/2025 15:48:11.947",
"deleted_at": null,
"businesstype": 2,
"departmenttype": 10,
"code": "03",
"name": "中间品",
"parentid": 0,
"sortorder": 3,
"description": ""
},
{
"id": 22563549825994752,
"created_by": "游建梅",
"created_at": "2/12/2025 14:19:29.507",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": "2/12/2025 15:20:30.627",
"businesstype": 1,
"departmenttype": 5,
"code": "333",
"name": "外购茧",
"parentid": 0,
"sortorder": 0,
"description": ""
},
{
"id": 22880529556705280,
"created_by": "主干-何启旭",
"created_at": "3/12/2025 11:19:03.36",
"update_by": null,
"updated_at": "3/12/2025 15:48:54.827",
"deleted_at": null,
"businesstype": 3,
"departmenttype": 5,
"code": "07",
"name": "生丝",
"parentid": 0,
"sortorder": 7,
"description": ""
},
{
"id": 22942445041881088,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:25:05.153",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": "3/12/2025 15:25:19.41",
"businesstype": 4,
"departmenttype": 10,
"code": "100",
"name": "副产品-副品车间",
"parentid": 0,
"sortorder": 100,
"description": ""
},
{
"id": 22942734054592512,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:26:14.057",
"update_by": null,
"updated_at": "3/12/2025 15:48:33.27",
"deleted_at": "3/12/2025 15:54:16.403",
"businesstype": 4,
"departmenttype": 10,
"code": "05",
"name": "副产品-副品车间",
"parentid": 0,
"sortorder": 5,
"description": ""
},
{
"id": 22945136325431296,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:35:46.8",
"update_by": null,
"updated_at": "3/12/2025 15:48:39.827",
"deleted_at": "3/12/2025 15:54:18.77",
"businesstype": 4,
"departmenttype": 10,
"code": "06",
"name": "副产品-前缫后缫",
"parentid": 0,
"sortorder": 6,
"description": ""
},
{
"id": 22947537216344064,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:45:19.217",
"update_by": null,
"updated_at": "3/12/2025 15:47:20.603",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "0204",
"name": "包装材料",
"parentid": 18611822663831552,
"sortorder": 204,
"description": ""
},
{
"id": 22947822349324288,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:46:27.197",
"update_by": null,
"updated_at": "3/12/2025 15:47:25.387",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "0205",
"name": "非自动缫配件",
"parentid": 18611822663831552,
"sortorder": 205,
"description": ""
},
{
"id": 22947884357914624,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:46:41.983",
"update_by": null,
"updated_at": "3/12/2025 15:47:29.09",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "0206",
"name": "工具",
"parentid": 18611822663831552,
"sortorder": 206,
"description": ""
},
{
"id": 22947929232773120,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:46:52.68",
"update_by": null,
"updated_at": "3/12/2025 15:47:33.073",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "0207",
"name": "印刷品",
"parentid": 18611822663831552,
"sortorder": 207,
"description": ""
},
{
"id": 22948001425133568,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:47:09.893",
"update_by": null,
"updated_at": "3/12/2025 15:47:36.98",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "0208",
"name": "其他",
"parentid": 18611822663831552,
"sortorder": 208,
"description": ""
},
{
"id": 22948854517207040,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:50:33.287",
"update_by": null,
"updated_at": "3/12/2025 15:51:08.65",
"deleted_at": null,
"businesstype": 4,
"departmenttype": 10,
"code": "0401",
"name": "选剥茧",
"parentid": 10621067601121280,
"sortorder": 401,
"description": ""
},
{
"id": 22948930341834752,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:50:51.363",
"update_by": null,
"updated_at": "3/12/2025 15:51:13.877",
"deleted_at": null,
"businesstype": 4,
"departmenttype": 10,
"code": "0402",
"name": "前缫后缫",
"parentid": 10621067601121280,
"sortorder": 402,
"description": ""
},
{
"id": 22948983454306304,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:51:04.027",
"update_by": null,
"updated_at": "3/12/2025 15:51:19.377",
"deleted_at": null,
"businesstype": 4,
"departmenttype": 10,
"code": "0403",
"name": "副品车间",
"parentid": 10621067601121280,
"sortorder": 403,
"description": ""
},
{
"id": 22950962809278464,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:58:55.943",
"update_by": null,
"updated_at": "3/12/2025 15:59:31.147",
"deleted_at": null,
"businesstype": 3,
"departmenttype": 5,
"code": "0701",
"name": "正品丝",
"parentid": 22880529556705280,
"sortorder": 701,
"description": ""
},
{
"id": 22951166719561728,
"created_by": "主干信息dev",
"created_at": "3/12/2025 15:59:44.557",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"businesstype": 3,
"departmenttype": 5,
"code": "0702",
"name": "学工丝",
"parentid": 22880529556705280,
"sortorder": 702,
"description": ""
},
{
"id": 22951233710985216,
"created_by": "主干信息dev",
"created_at": "3/12/2025 16:00:00.53",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"businesstype": 3,
"departmenttype": 5,
"code": "0703",
"name": "抱平丝",
"parentid": 22880529556705280,
"sortorder": 703,
"description": ""
},
{
"id": 22951289138712576,
"created_by": "主干信息dev",
"created_at": "3/12/2025 16:00:13.747",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"businesstype": 3,
"departmenttype": 5,
"code": "0704",
"name": "公量样丝",
"parentid": 22880529556705280,
"sortorder": 704,
"description": ""
},
{
"id": 23029167180222464,
"created_by": "主干信息dev",
"created_at": "3/12/2025 21:09:41.343",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": "3/12/2025 21:09:52.143",
"businesstype": 1,
"departmenttype": 5,
"code": "08",
"name": "123",
"parentid": 0,
"sortorder": 0,
"description": "123"
},
{
"id": 26929004451729408,
"created_by": "主干信息dev",
"created_at": "14/12/2025 15:26:15",
"update_by": null,
"updated_at": "5/1/2026 10:07:58.16",
"deleted_at": null,
"businesstype": 4,
"departmenttype": 10,
"code": "0404",
"name": "丝绵车间",
"parentid": 10621067601121280,
"sortorder": 404,
"description": ""
},
{
"id": 33936504552165376,
"created_by": "主干信息dev",
"created_at": "2/1/2026 23:31:33.2",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"businesstype": 5,
"departmenttype": 10,
"code": "0209",
"name": "报废",
"parentid": 18611822663831552,
"sortorder": 209,
"description": "报废项暂存"
},
{
"id": 35623370959622144,
"created_by": "主干-张罗",
"created_at": "7/1/2026 15:14:33.497",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"businesstype": 3,
"departmenttype": 5,
"code": "0705",
"name": "剔出丝",
"parentid": 22880529556705280,
"sortorder": 705,
"description": ""
},
{
"id": 35646632171147264,
"created_by": "主干信息dev",
"created_at": "7/1/2026 16:46:59.427",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"businesstype": 3,
"departmenttype": 5,
"code": "0706",
"name": "杂丝",
"parentid": 22880529556705280,
"sortorder": 706,
"description": ""
},
{
"id": 96484505463820288,
"created_by": "主干-严鹏",
"created_at": "24/6/2026 13:54:58.713",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"businesstype": 4,
"departmenttype": 10,
"code": "0405",
"name": "蚕业",
"parentid": 10621067601121280,
"sortorder": 405,
"description": ""
},
{
"id": 104455978778365952,
"created_by": "范鸿才",
"created_at": "16/7/2026 13:50:46.05",
"update_by": null,
"updated_at": "1/1/1970 00:00:00",
"deleted_at": null,
"businesstype": 3,
"departmenttype": 5,
"code": "0707",
"name": "新工丝",
"parentid": 22880529556705280,
"sortorder": 707,
"description": ""
}
]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,293 @@
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
using FreeSql;
using F9WebAiTest.Application.Interfaces.SnowflakeID;
using F9WebAiTest.Domain.Entities.SYS.Departments;
using F9WebAiTest.Domain.Entities.SYS.WorkTypes;
namespace F9WebAiTest.Infrastructure.Data;
/// <summary>
/// 工种基础数据导入:来源于 F9 系统 biz_base_worktype / biz_base_worktype_department / biz_base_worktype_role 三张表的导出数据。
/// 幂等:按原始 Id 判重;关联表只导入工种仍存在的记录;
/// F9 部门 Id 通过"部门名称"映射到本系统部门(本系统部门种子与 F9 同源,见 BusinessSeedData.DeptData)。
/// </summary>
public static class WorkTypeSeedData
{
private const string WorkTypeResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_base_worktype.json";
private const string WorkTypeDepartmentResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_base_worktype_department.json";
private const string WorkTypeRoleResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_base_worktype_role.json";
private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true };
/// <summary>F9 角色 Id → 本系统角色 Id 映射(留空表示按原值保留,可在"关联角色"抽屉里手工调整)</summary>
private static readonly Dictionary<long, long> RoleIdMap = new();
public static void Seed(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
try
{
SeedWorkTypes(fsql);
SeedWorkTypeDepartments(fsql);
SeedWorkTypeRoles(fsql);
}
catch (Exception ex)
{
Console.WriteLine($"[WorkTypeSeed] 工种数据导入跳过:{ex.Message}");
}
}
/// <summary>导入工种主表(保留 F9 的雪花 Id)</summary>
private static void SeedWorkTypes(IFreeSql fsql)
{
var items = Load<WorkTypeSeedItem>(WorkTypeResource);
if (items.Count == 0) return;
var existIds = fsql.Select<WorkType>()
.DisableGlobalFilter("软删除")
.ToList()
.Select(x => x.Id)
.ToHashSet();
var inserts = new List<WorkType>();
foreach (var item in items)
{
if (item.Id <= 0 || existIds.Contains(item.Id)) continue;
if (string.IsNullOrWhiteSpace(item.WorkName)) continue;
inserts.Add(new WorkType(item.Id, item.WorkName.Trim(), item.Sort, item.BizType ?? string.Empty, item.SccbFenlei ?? string.Empty)
{
CreatedAt = ParseLegacyDate(item.CreatedAt) ?? DateTime.Now,
CreatedBy = item.CreatedBy ?? string.Empty,
UpdatedAt = ParseLegacyDate(item.UpdatedAt)
});
}
if (inserts.Count > 0) fsql.Insert(inserts).ExecuteAffrows();
Console.WriteLine($"[WorkTypeSeed] 工种:来源 {items.Count} 条,新增 {inserts.Count} 条,跳过已存在 {items.Count - inserts.Count} 条");
}
/// <summary>导入工种-部门关联(部门 Id 映射到本系统部门,跳过工种不存在的孤儿数据)</summary>
private static void SeedWorkTypeDepartments(IFreeSql fsql)
{
var items = Load<WorkTypeDepartmentSeedItem>(WorkTypeDepartmentResource);
if (items.Count == 0) return;
var depIdMap = BuildDepartmentIdMap(fsql);
var workTypeIds = fsql.Select<WorkType>()
.DisableGlobalFilter("软删除")
.ToList()
.Select(x => x.Id)
.ToHashSet();
var existing = fsql.Select<WorkTypeDepartment>()
.DisableGlobalFilter("软删除")
.ToList();
var existingById = existing.ToDictionary(x => x.Id);
var inserts = new List<WorkTypeDepartment>();
var updated = 0;
var orphan = 0;
var duplicate = 0;
var unmappedDepartments = new HashSet<long>();
foreach (var item in items)
{
if (item.Id <= 0) continue;
if (!workTypeIds.Contains(item.WorkTypeId)) { orphan++; continue; }
if (!depIdMap.TryGetValue(item.DepartmentId, out var departmentId))
{
// 未匹配到本系统部门:按原值保留,便于后续人工核对
departmentId = item.DepartmentId;
unmappedDepartments.Add(item.DepartmentId);
}
if (existingById.TryGetValue(item.Id, out var row))
{
// 已存在:修正部门映射(历史数据可能存的是 F9 原始 Id)
if (row.DepartmentId != departmentId)
{
fsql.Update<WorkTypeDepartment>()
.Set(x => x.DepartmentId, departmentId)
.Where(x => x.Id == item.Id)
.ExecuteAffrows();
updated++;
}
continue;
}
if (inserts.Any(x => x.WorkTypeId == item.WorkTypeId && x.DepartmentId == departmentId))
{
duplicate++;
continue;
}
inserts.Add(new WorkTypeDepartment(item.Id, item.WorkTypeId, departmentId, ParseLegacyDate(item.CreatedAt))
{
CreatedAt = ParseLegacyDate(item.CreatedAt) ?? DateTime.Now,
CreatedBy = item.CreatedBy ?? string.Empty
});
}
if (inserts.Count > 0) fsql.Insert(inserts).ExecuteAffrows();
Console.WriteLine($"[WorkTypeSeed] 工种-部门:来源 {items.Count} 条,新增 {inserts.Count} 条,修正映射 {updated} 条,孤儿(工种不存在){orphan} 条,重复 {duplicate} 条");
if (unmappedDepartments.Count > 0)
Console.WriteLine($"[WorkTypeSeed] 提示:以下 {unmappedDepartments.Count} 个 F9 部门 Id 未匹配到本系统部门(按原值保留)-> {string.Join(", ", unmappedDepartments)}");
}
/// <summary>导入工种-角色关联(跳过工种不存在的孤儿数据)</summary>
private static void SeedWorkTypeRoles(IFreeSql fsql)
{
var items = Load<WorkTypeRoleSeedItem>(WorkTypeRoleResource);
if (items.Count == 0) return;
var workTypeIds = fsql.Select<WorkType>()
.DisableGlobalFilter("软删除")
.ToList()
.Select(x => x.Id)
.ToHashSet();
var existing = fsql.Select<WorkTypeRole>()
.DisableGlobalFilter("软删除")
.ToList();
var existingById = existing.ToDictionary(x => x.Id);
var inserts = new List<WorkTypeRole>();
var updated = 0;
var orphan = 0;
var skipped = 0;
var unmappedRoles = new HashSet<long>();
foreach (var item in items)
{
if (item.Id <= 0) continue;
if (!workTypeIds.Contains(item.WorkTypeId)) { orphan++; continue; }
// 未配置映射的 F9 角色:不导入(避免落下本系统不存在的角色关联)
if (!RoleIdMap.TryGetValue(item.RoleId, out var roleId))
{
unmappedRoles.Add(item.RoleId);
skipped++;
continue;
}
if (existingById.TryGetValue(item.Id, out var row))
{
if (row.RoleId != roleId)
{
fsql.Update<WorkTypeRole>()
.Set(x => x.RoleId, roleId)
.Where(x => x.Id == item.Id)
.ExecuteAffrows();
updated++;
}
continue;
}
if (inserts.Any(x => x.WorkTypeId == item.WorkTypeId && x.RoleId == roleId)) continue;
inserts.Add(new WorkTypeRole(item.Id, item.WorkTypeId, roleId, ParseLegacyDate(item.CreatedAt))
{
CreatedAt = ParseLegacyDate(item.CreatedAt) ?? DateTime.Now,
CreatedBy = item.CreatedBy ?? string.Empty
});
}
if (inserts.Count > 0) fsql.Insert(inserts).ExecuteAffrows();
Console.WriteLine($"[WorkTypeSeed] 工种-角色:来源 {items.Count} 条,新增 {inserts.Count} 条,修正映射 {updated} 条,孤儿(工种不存在){orphan} 条,跳过(未配置角色映射){skipped} 条");
if (unmappedRoles.Count > 0)
Console.WriteLine($"[WorkTypeSeed] 提示:以下 F9 角色 Id 未在本系统找到对应角色,已跳过 -> {string.Join(", ", unmappedRoles)}");
}
/// <summary>
/// 构建 F9 部门 Id → 本系统部门 Id 的映射:以部门名称为桥梁
/// (BusinessSeedData.DeptData 保存了 F9 原始部门 Id 与名称,本系统部门数据与之同源)。
/// </summary>
private static Dictionary<long, long> BuildDepartmentIdMap(IFreeSql fsql)
{
var map = new Dictionary<long, long>();
var byName = new Dictionary<string, long>();
foreach (var dep in fsql.Select<Department>().ToList())
{
if (string.IsNullOrWhiteSpace(dep.Name)) continue;
if (!byName.ContainsKey(dep.Name)) byName[dep.Name] = dep.Id;
}
foreach (var (f9Id, name, _, _, _) in BusinessSeedData.DeptData)
{
if (byName.TryGetValue(name, out var localId)) map[f9Id] = localId;
}
return map;
}
/// <summary>读取内嵌 JSON 资源</summary>
private static List<T> Load<T>(string resourceName)
{
var assembly = typeof(WorkTypeSeedData).Assembly;
using var stream = assembly.GetManifestResourceStream(resourceName);
if (stream == null)
{
Console.WriteLine($"[WorkTypeSeed] 未找到内嵌资源:{resourceName}");
return new List<T>();
}
return JsonSerializer.Deserialize<List<T>>(stream, JsonOptions) ?? new List<T>();
}
/// <summary>解析 F9 导出的日期(形如 d/M/yyyy H:mm:ss.fff),1970 占位值视为未更新返回 null</summary>
private static readonly string[] LegacyDateFormats =
{
"d/M/yyyy H:mm:ss.fff", "d/M/yyyy H:mm:ss", "d/M/yyyy H:mm",
"M/d/yyyy H:mm:ss.fff", "M/d/yyyy H:mm:ss", "M/d/yyyy H:mm",
"yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss"
};
private static DateTime? ParseLegacyDate(string value)
{
if (string.IsNullOrWhiteSpace(value)) return null;
if (DateTime.TryParseExact(value, LegacyDateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var exact))
return exact.Year <= 1900 ? null : exact;
if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var any))
return any.Year <= 1900 ? null : any;
return null;
}
private sealed class WorkTypeSeedItem
{
[JsonPropertyName("id")] public long Id { get; set; }
[JsonPropertyName("created_by")] public string CreatedBy { get; set; }
[JsonPropertyName("created_at")] public string CreatedAt { get; set; }
[JsonPropertyName("update_by")] public string UpdateBy { get; set; }
[JsonPropertyName("updated_at")] public string UpdatedAt { get; set; }
[JsonPropertyName("work_name")] public string WorkName { get; set; }
[JsonPropertyName("sort")] public int Sort { get; set; }
[JsonPropertyName("biz_type")] public string BizType { get; set; }
[JsonPropertyName("sccb_fenlei")] public string SccbFenlei { get; set; }
}
private sealed class WorkTypeDepartmentSeedItem
{
[JsonPropertyName("id")] public long Id { get; set; }
[JsonPropertyName("created_by")] public string CreatedBy { get; set; }
[JsonPropertyName("created_at")] public string CreatedAt { get; set; }
[JsonPropertyName("worktype_id")] public long WorkTypeId { get; set; }
[JsonPropertyName("department_id")] public long DepartmentId { get; set; }
}
private sealed class WorkTypeRoleSeedItem
{
[JsonPropertyName("id")] public long Id { get; set; }
[JsonPropertyName("created_by")] public string CreatedBy { get; set; }
[JsonPropertyName("created_at")] public string CreatedAt { get; set; }
[JsonPropertyName("worktype_id")] public long WorkTypeId { get; set; }
[JsonPropertyName("role_id")] public long RoleId { get; set; }
}
}
@@ -0,0 +1,180 @@
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
using FreeSql;
using F9WebAiTest.Domain.Entities.SYS.WuziMulus;
using F9WebAiTest.Domain.Enums.SYS.Departments;
using F9WebAiTest.Domain.Enums.SYS.WuziMulus;
namespace F9WebAiTest.Infrastructure.Data;
/// <summary>
/// 物资数据导入:来源于 F9 系统 biz_base_wuzigroup(物资分组)与 biz_base_wuzimulu(物资目录)两张表的导出数据。
/// 幂等:按原始 Id 判重,已存在则跳过。
/// </summary>
public static class WuziSeedData
{
private const string GroupResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_base_wuzigroup.json";
private const string MuluResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_base_wuzimulu.json";
private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true };
public static void Seed(IFreeSql fsql)
{
try
{
SeedGroups(fsql);
SeedMulu(fsql);
}
catch (Exception ex)
{
Console.WriteLine($"[WuziSeed] 物资数据导入跳过:{ex.Message}");
}
}
/// <summary>导入物资分组</summary>
private static void SeedGroups(IFreeSql fsql)
{
var items = Load<WuziGroupSeedItem>(GroupResource);
if (items.Count == 0) return;
var existIds = fsql.Select<WuziGroup>().DisableGlobalFilter("软删除").ToList().Select(x => x.Id).ToHashSet();
var inserts = new List<WuziGroup>();
foreach (var item in items)
{
if (item.Id <= 0 || existIds.Contains(item.Id)) continue;
if (string.IsNullOrWhiteSpace(item.Name)) continue;
inserts.Add(new WuziGroup(item.Id, (WuziBusiness_Type_Enum)item.BusinessType,
(Department_DutyType_Enum)item.DepartmentType, item.Code ?? string.Empty, item.Name.Trim(),
item.ParentId, item.SortOrder, item.Description ?? string.Empty)
{
CreatedAt = ParseLegacyDate(item.CreatedAt) ?? DateTime.Now,
CreatedBy = item.CreatedBy ?? string.Empty,
UpdatedAt = ParseLegacyDate(item.UpdatedAt)
});
}
if (inserts.Count > 0) fsql.Insert(inserts).ExecuteAffrows();
Console.WriteLine($"[WuziSeed] 物资分组:来源 {items.Count} 条,新增 {inserts.Count} 条");
}
/// <summary>导入物资目录</summary>
private static void SeedMulu(IFreeSql fsql)
{
var items = Load<WuziMuluSeedItem>(MuluResource);
if (items.Count == 0) return;
var existIds = fsql.Select<WuziMulu>().DisableGlobalFilter("软删除").ToList().Select(x => x.Id).ToHashSet();
var inserts = new List<WuziMulu>();
var orphan = 0;
foreach (var item in items)
{
if (item.Id <= 0 || existIds.Contains(item.Id)) continue;
if (string.IsNullOrWhiteSpace(item.Name)) continue;
if (item.GroupId <= 0) { orphan++; continue; }
inserts.Add(new WuziMulu(item.Id, item.GroupId, item.Name.Trim(), item.Code ?? string.Empty,
item.Unit ?? string.Empty, item.Guige ?? string.Empty, item.Xinghao ?? string.Empty,
item.PinyinName ?? string.Empty, item.Kucunyujing, item.SortOrder, ParseBool(item.IsYujing), item.SaleRate)
{
CreatedAt = ParseLegacyDate(item.CreatedAt) ?? DateTime.Now,
CreatedBy = item.CreatedBy ?? string.Empty,
UpdatedAt = ParseLegacyDate(item.UpdatedAt)
});
}
// 分批插入(1000 条一次插入会超出 SQL 参数上限)
foreach (var batch in inserts.Chunk(200)) fsql.Insert(batch.ToList()).ExecuteAffrows();
Console.WriteLine($"[WuziSeed] 物资目录:来源 {items.Count} 条,新增 {inserts.Count} 条,跳过无分组 {orphan} 条");
}
private static List<T> Load<T>(string resourceName)
{
var assembly = typeof(WuziSeedData).Assembly;
using var stream = assembly.GetManifestResourceStream(resourceName);
if (stream == null)
{
Console.WriteLine($"[WuziSeed] 未找到内嵌资源:{resourceName}");
return new List<T>();
}
return JsonSerializer.Deserialize<List<T>>(stream, JsonOptions) ?? new List<T>();
}
/// <summary>is_yujing 在导出数据里可能是 "0"/"1" 字符串、数字或布尔</summary>
private static bool ParseBool(JsonElement element)
{
switch (element.ValueKind)
{
case JsonValueKind.String:
var text = element.GetString();
return text == "1" || string.Equals(text, "true", StringComparison.OrdinalIgnoreCase);
case JsonValueKind.Number:
return element.GetInt32() != 0;
case JsonValueKind.True:
return true;
default:
return false;
}
}
/// <summary>解析 F9 导出的日期(形如 d/M/yyyy H:mm:ss.fff),1970 占位值视为未更新返回 null</summary>
private static readonly string[] LegacyDateFormats =
{
"d/M/yyyy H:mm:ss.fff", "d/M/yyyy H:mm:ss", "d/M/yyyy H:mm",
"M/d/yyyy H:mm:ss.fff", "M/d/yyyy H:mm:ss", "M/d/yyyy H:mm",
"yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss"
};
private static DateTime? ParseLegacyDate(string value)
{
if (string.IsNullOrWhiteSpace(value)) return null;
if (DateTime.TryParseExact(value, LegacyDateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var exact))
return exact.Year <= 1900 ? null : exact;
if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var any))
return any.Year <= 1900 ? null : any;
return null;
}
private sealed class WuziGroupSeedItem
{
[JsonPropertyName("id")] public long Id { get; set; }
[JsonPropertyName("created_by")] public string CreatedBy { get; set; }
[JsonPropertyName("created_at")] public string CreatedAt { get; set; }
[JsonPropertyName("updated_at")] public string UpdatedAt { get; set; }
[JsonPropertyName("businesstype")] public int BusinessType { get; set; }
[JsonPropertyName("departmenttype")] public int DepartmentType { get; set; }
[JsonPropertyName("code")] public string Code { get; set; }
[JsonPropertyName("name")] public string Name { get; set; }
[JsonPropertyName("parentid")] public long ParentId { get; set; }
[JsonPropertyName("sortorder")] public int SortOrder { get; set; }
[JsonPropertyName("description")] public string Description { get; set; }
}
private sealed class WuziMuluSeedItem
{
[JsonPropertyName("id")] public long Id { get; set; }
[JsonPropertyName("created_by")] public string CreatedBy { get; set; }
[JsonPropertyName("created_at")] public string CreatedAt { get; set; }
[JsonPropertyName("updated_at")] public string UpdatedAt { get; set; }
[JsonPropertyName("groupid")] public long GroupId { get; set; }
[JsonPropertyName("name")] public string Name { get; set; }
[JsonPropertyName("code")] public string Code { get; set; }
[JsonPropertyName("unit")] public string Unit { get; set; }
[JsonPropertyName("guige")] public string Guige { get; set; }
[JsonPropertyName("xinghao")] public string Xinghao { get; set; }
[JsonPropertyName("pinyinname")] public string PinyinName { get; set; }
[JsonPropertyName("kucunyujing")] public decimal Kucunyujing { get; set; }
[JsonPropertyName("sortorder")] public int SortOrder { get; set; }
/// <summary>F9 导出为字符串 "0"/"1"(兼容数字与布尔写法)</summary>
[JsonPropertyName("is_yujing")] public JsonElement IsYujing { get; set; }
[JsonPropertyName("SaleRate")] public decimal SaleRate { get; set; }
}
}
@@ -0,0 +1,110 @@
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
using FreeSql;
using F9WebAiTest.Domain.Entities.SYS.YuanliaoZhuangkous;
using F9WebAiTest.Domain.Enums.SYS.YuanliaoZhuangkous;
namespace F9WebAiTest.Infrastructure.Data;
/// <summary>
/// 原料庄口数据导入:来源于 F9 系统 biz_base_yuanliaozhuangkou 表导出数据。
/// 幂等:按原始 Id 判重,已存在则跳过。
/// </summary>
public static class YuanliaoZhuangkouSeedData
{
private const string Resource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_base_yuanliaozhuangkou.json";
private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true };
public static void Seed(IFreeSql fsql)
{
try
{
var items = Load();
if (items.Count == 0) return;
var existIds = fsql.Select<YuanliaoZhuangkou>()
.DisableGlobalFilter("软删除")
.ToList()
.Select(x => x.Id)
.ToHashSet();
var inserts = new List<YuanliaoZhuangkou>();
foreach (var item in items)
{
if (item.Id <= 0 || existIds.Contains(item.Id)) continue;
if (string.IsNullOrWhiteSpace(item.Name)) continue;
inserts.Add(new YuanliaoZhuangkou(item.Id, item.Year, item.Name.Trim(), item.Code ?? string.Empty,
item.Jibie ?? string.Empty, (BendiWaidi_Enum)item.Bendiwaidi, item.Chandi ?? string.Empty,
item.Canpinzhong ?? string.Empty, item.Wzmlid, item.Zhandian ?? string.Empty, item.Pici)
{
CreatedAt = ParseLegacyDate(item.CreatedAt) ?? DateTime.Now,
CreatedBy = item.CreatedBy ?? string.Empty,
UpdatedAt = ParseLegacyDate(item.UpdatedAt),
UpdateBy = item.UpdateBy ?? string.Empty
});
}
if (inserts.Count > 0) fsql.Insert(inserts).ExecuteAffrows();
Console.WriteLine($"[YuanliaoZhuangkouSeed] 原料庄口:来源 {items.Count} 条,新增 {inserts.Count} 条,跳过已存在 {items.Count - inserts.Count} 条");
}
catch (Exception ex)
{
Console.WriteLine($"[YuanliaoZhuangkouSeed] 原料庄口数据导入跳过:{ex.Message}");
}
}
private static List<YuanliaoZhuangkouSeedItem> Load()
{
var assembly = typeof(YuanliaoZhuangkouSeedData).Assembly;
using var stream = assembly.GetManifestResourceStream(Resource);
if (stream == null)
{
Console.WriteLine($"[YuanliaoZhuangkouSeed] 未找到内嵌资源:{Resource}");
return new List<YuanliaoZhuangkouSeedItem>();
}
return JsonSerializer.Deserialize<List<YuanliaoZhuangkouSeedItem>>(stream, JsonOptions) ?? new List<YuanliaoZhuangkouSeedItem>();
}
/// <summary>解析 F9 导出的日期(形如 d/M/yyyy H:mm:ss.fff),1970 占位值视为未更新返回 null</summary>
private static readonly string[] LegacyDateFormats =
{
"d/M/yyyy H:mm:ss.fff", "d/M/yyyy H:mm:ss", "d/M/yyyy H:mm",
"M/d/yyyy H:mm:ss.fff", "M/d/yyyy H:mm:ss", "M/d/yyyy H:mm",
"yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss"
};
private static DateTime? ParseLegacyDate(string value)
{
if (string.IsNullOrWhiteSpace(value)) return null;
if (DateTime.TryParseExact(value, LegacyDateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var exact))
return exact.Year <= 1900 ? null : exact;
if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var any))
return any.Year <= 1900 ? null : any;
return null;
}
private sealed class YuanliaoZhuangkouSeedItem
{
[JsonPropertyName("id")] public long Id { get; set; }
[JsonPropertyName("created_by")] public string CreatedBy { get; set; }
[JsonPropertyName("created_at")] public string CreatedAt { get; set; }
[JsonPropertyName("update_by")] public string UpdateBy { get; set; }
[JsonPropertyName("updated_at")] public string UpdatedAt { get; set; }
[JsonPropertyName("year")] public int Year { get; set; }
[JsonPropertyName("name")] public string Name { get; set; }
[JsonPropertyName("code")] public string Code { get; set; }
[JsonPropertyName("jibie")] public string Jibie { get; set; }
[JsonPropertyName("bendiwaidi")] public int Bendiwaidi { get; set; }
[JsonPropertyName("chandi")] public string Chandi { get; set; }
[JsonPropertyName("canpinzhong")] public string Canpinzhong { get; set; }
[JsonPropertyName("wzmlid")] public long Wzmlid { get; set; }
[JsonPropertyName("zhandian")] public string Zhandian { get; set; }
[JsonPropertyName("pici")] public int Pici { get; set; }
}
}
@@ -4,6 +4,12 @@ using F9WebAiTest.Application.Interfaces.Repositories.SYS.Departments;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.RBAC.Menus;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.RBAC.Roles;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.RBAC.Users;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.WorkTypes;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.Registries;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.YuanliaoZhuangkous;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.Gongyingshangs;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.WuziMulus;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.Zq;
using F9WebAiTest.Application.Interfaces.Security;
using F9WebAiTest.Application.Interfaces.SnowflakeID;
using F9WebAiTest.Application.Interfaces.UOW;
@@ -14,12 +20,24 @@ using F9WebAiTest.Domain.Interfaces.SYS.RBAC.Menus;
using F9WebAiTest.Domain.Interfaces.SYS.RBAC.Permissions;
using F9WebAiTest.Domain.Interfaces.SYS.RBAC.Roles;
using F9WebAiTest.Domain.Interfaces.SYS.RBAC.Users;
using F9WebAiTest.Domain.Interfaces.SYS.WorkTypes;
using F9WebAiTest.Domain.Interfaces.SYS.Registries;
using F9WebAiTest.Domain.Interfaces.SYS.YuanliaoZhuangkous;
using F9WebAiTest.Domain.Interfaces.SYS.Gongyingshangs;
using F9WebAiTest.Domain.Interfaces.SYS.WuziMulus;
using F9WebAiTest.Domain.Interfaces.SYS.Zq;
using F9WebAiTest.Infrastructure.FreeSqls.Persistence;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.Departments;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.RBAC.Menus;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.RBAC.Permissions;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.RBAC.Roles;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.RBAC.Users;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.WorkTypes;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.Registries;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.YuanliaoZhuangkous;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.Gongyingshangs;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.WuziMulus;
using F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.Zq;
using F9WebAiTest.Infrastructure.InterfaceImplements.Security;
using F9WebAiTest.Infrastructure.InterfaceImplements.SnowflakeID;
using F9WebAiTest.Infrastructure.Repositories;
@@ -71,12 +89,28 @@ public static class DependencyInjection
services.AddScoped<IPermissionWriteRepository, PermissionWriteRepository>();
services.AddScoped<IDepartmentWriteRepository, DepartmentWriteRepository>();
services.AddScoped<IDepartmentUserRepository, DepartmentUserRepository>();
services.AddScoped<IWorkTypeWriteRepository, WorkTypeWriteRepository>();
services.AddScoped<IWorkTypeDepartmentRepository, WorkTypeDepartmentRepository>();
services.AddScoped<IWorkTypeRoleRepository, WorkTypeRoleRepository>();
services.AddScoped<IZhangqiWriteRepository, ZhangqiWriteRepository>();
services.AddScoped<IRegistryWriteRepository, RegistryWriteRepository>();
services.AddScoped<IYuanliaoZhuangkouWriteRepository, YuanliaoZhuangkouWriteRepository>();
services.AddScoped<IWuziGroupWriteRepository, WuziGroupWriteRepository>();
services.AddScoped<IGongyingshangWriteRepository, GongyingshangWriteRepository>();
services.AddScoped<IWuziMuluWriteRepository, WuziMuluWriteRepository>();
// 读仓储(Application 接口)
services.AddScoped<IUserReadRepository, UserReadRepository>();
services.AddScoped<IRoleReadRepository, RoleReadRepository>();
services.AddScoped<IMenuReadRepository, MenuReadRepository>();
services.AddScoped<IDepartmentReadRepository, DepartmentReadRepository>();
services.AddScoped<IWorkTypeReadRepository, WorkTypeReadRepository>();
services.AddScoped<IZhangqiReadRepository, ZhangqiReadRepository>();
services.AddScoped<IRegistryReadRepository, RegistryReadRepository>();
services.AddScoped<IYuanliaoZhuangkouReadRepository, YuanliaoZhuangkouReadRepository>();
services.AddScoped<IWuziGroupReadRepository, WuziGroupReadRepository>();
services.AddScoped<IGongyingshangReadRepository, GongyingshangReadRepository>();
services.AddScoped<IWuziMuluReadRepository, WuziMuluReadRepository>();
return services;
}
@@ -12,6 +12,11 @@
<ProjectReference Include="..\F9WebAiTest.Application\F9WebAiTest.Application.csproj" />
</ItemGroup>
<ItemGroup>
<!-- 工种基础数据种子(来源于 F9 系统 biz_base_worktype 三张表导出) -->
<EmbeddedResource Include="Data\SeedData\*.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="FreeSql" Version="3.5.213" />
@@ -0,0 +1,92 @@
using FreeSql;
using F9WebAiTest.Application.Common;
using F9WebAiTest.Application.Dtos.SYS.Gongyingshangs;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.Gongyingshangs;
using F9WebAiTest.Domain.Entities.SYS.Gongyingshangs;
using F9WebAiTest.Domain.Enums.SYS.Gongyingshangs;
using F9WebAiTest.Domain.Interfaces.SYS.Gongyingshangs;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.Gongyingshangs;
internal class GongyingshangWriteRepository : F9RepositoryBase, IGongyingshangWriteRepository
{
public GongyingshangWriteRepository(IFreeSql fsql) : base(fsql) { }
public async Task<Gongyingshang> GetByIdAsync(long id, CancellationToken cancellationToken)
=> await Orm.Select<Gongyingshang>().Where(x => x.Id == id && x.DeletedAt == null).FirstAsync(cancellationToken);
public async Task<bool> AddAsync(Gongyingshang entity)
{
entity.CreatedAt = DateTime.Now;
return await Orm.Insert(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> UpdateAsync(Gongyingshang entity)
{
entity.UpdatedAt = DateTime.Now;
return await Orm.Update<Gongyingshang>().SetSource(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> SoftDeleteAsync(long id)
=> await Orm.Update<Gongyingshang>()
.Set(x => x.IsDeleted, true)
.Set(x => x.DeletedAt, DateTime.Now)
.Where(x => x.Id == id)
.ExecuteAffrowsAsync() > 0;
}
internal class GongyingshangReadRepository : F9RepositoryBase, IGongyingshangReadRepository
{
public GongyingshangReadRepository(IFreeSql fsql) : base(fsql) { }
public async Task<PageResult<GongyingshangReadDto_View>> GetPagedAsync(Gys_Type_Enum type, Gys_SaleType_Enum? saleType,
string keyword, int pageIndex, int pageSize)
{
if (pageIndex <= 0) pageIndex = 1;
if (pageSize <= 0) pageSize = 20;
var query = Orm.Select<Gongyingshang>().Where(x => x.DeletedAt == null && x.Type == type);
if (saleType.HasValue) query = query.Where(x => x.SaleType == saleType.Value);
if (!string.IsNullOrWhiteSpace(keyword))
{
var kw = keyword.Trim();
query = query.Where(x => x.Name.Contains(kw) || x.Pinyin.Contains(kw) || x.Lianxiren.Contains(kw)
|| x.Phone.Contains(kw) || x.Address.Contains(kw));
}
var total = await query.CountAsync();
var items = await query
.OrderBy(x => x.Name)
.Page(pageIndex, pageSize)
.ToListAsync(x => new GongyingshangReadDto_View(x.Id, x.Name, x.Type, "", x.BusinessGroup, "",
x.SaleType, "", x.Lianxiren, x.Phone, x.Address, x.Pinyin));
var list = items
.Select(x => x with
{
TypeName = x.Type.ToString(),
Grouname = x.Group.ToString(),
SaleTypeName = SaleTypeText(x.SaleType)
})
.ToList();
return new PageResult<GongyingshangReadDto_View>
{
Items = list,
Total = total,
PageIndex = pageIndex,
PageSize = pageSize
};
}
public async Task<GongyingshangDto_Edit> GetByIdForEditAsync(long id)
=> await Orm.Select<Gongyingshang>()
.Where(x => x.Id == id && x.DeletedAt == null)
.FirstAsync(x => new GongyingshangDto_Edit(x.Id, x.Name, x.Type, x.BusinessGroup, x.SaleType,
x.Lianxiren, x.Phone, x.Address, x.Pinyin));
/// <summary>销售类型显示文本(0 等非枚举值视为未设置)</summary>
internal static string SaleTypeText(Gys_SaleType_Enum saleType)
=> Enum.IsDefined(typeof(Gys_SaleType_Enum), saleType) ? saleType.ToString() : "未设置";
}
@@ -0,0 +1,28 @@
using FreeSql;
using F9WebAiTest.Application.Dtos.SYS.Registries;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.Registries;
using F9WebAiTest.Domain.Entities.SYS.Registries;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.Registries;
internal class RegistryReadRepository : F9RepositoryBase, IRegistryReadRepository
{
public RegistryReadRepository(IFreeSql fsql) : base(fsql) { }
public async Task<List<RegistryReadDto_View>> GetAllAsync()
=> await Orm.Select<Registry>()
.Where(x => x.DeletedAt == null)
.OrderBy(x => x.Category)
.OrderBy(x => x.KeyName)
.ToListAsync(x => new RegistryReadDto_View(x.Id, x.Category, x.KeyName, x.Value, x.DataType, x.Description, x.IsActive));
public async Task<RegistryReadDto_Edit> GetByIdForEditAsync(long id)
=> await Orm.Select<Registry>()
.Where(x => x.Id == id && x.DeletedAt == null)
.FirstAsync(x => new RegistryReadDto_Edit(x.Id, x.Category, x.KeyName, x.Value, x.DataType, x.Description, x.IsActive));
public async Task<RegistryReadDto_Edit> GetByCategoryAndKeyAsync(string category, string keyName)
=> await Orm.Select<Registry>()
.Where(x => x.DeletedAt == null && x.Category == category && x.KeyName == keyName)
.FirstAsync(x => new RegistryReadDto_Edit(x.Id, x.Category, x.KeyName, x.Value, x.DataType, x.Description, x.IsActive));
}
@@ -0,0 +1,37 @@
using FreeSql;
using F9WebAiTest.Domain.Entities.SYS.Registries;
using F9WebAiTest.Domain.Interfaces.SYS.Registries;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.Registries;
internal class RegistryWriteRepository : F9RepositoryBase, IRegistryWriteRepository
{
public RegistryWriteRepository(IFreeSql fsql) : base(fsql) { }
public async Task<Registry> GetByIdAsync(long id, CancellationToken cancellationToken)
=> await Orm.Select<Registry>().Where(x => x.Id == id && x.DeletedAt == null).FirstAsync(cancellationToken);
public async Task<Registry> GetByCategoryAndKeyAsync(string category, string keyName)
=> await Orm.Select<Registry>()
.Where(x => x.DeletedAt == null && x.Category == category && x.KeyName == keyName)
.FirstAsync();
public async Task<bool> AddAsync(Registry registry)
{
registry.CreatedAt = DateTime.Now;
return await Orm.Insert(registry).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> UpdateAsync(Registry registry)
{
registry.UpdatedAt = DateTime.Now;
return await Orm.Update<Registry>().SetSource(registry).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> SoftDeleteAsync(long id)
=> await Orm.Update<Registry>()
.Set(x => x.IsDeleted, true)
.Set(x => x.DeletedAt, DateTime.Now)
.Where(x => x.Id == id)
.ExecuteAffrowsAsync() > 0;
}
@@ -0,0 +1,90 @@
using FreeSql;
using F9WebAiTest.Application.Common;
using F9WebAiTest.Application.Dtos.SYS.WorkTypes;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.WorkTypes;
using F9WebAiTest.Domain.Entities.SYS.Departments;
using F9WebAiTest.Domain.Entities.SYS.WorkTypes;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.WorkTypes;
internal class WorkTypeReadRepository : F9RepositoryBase, IWorkTypeReadRepository
{
public WorkTypeReadRepository(IFreeSql fsql) : base(fsql) { }
public async Task<PageResult<WorkTypeReadDto_View>> GetPagedAsync(int pageIndex, int pageSize, string keyword)
{
if (pageIndex <= 0) pageIndex = 1;
if (pageSize <= 0) pageSize = 20;
var query = Orm.Select<WorkType>().Where(x => x.DeletedAt == null);
if (!string.IsNullOrWhiteSpace(keyword))
{
var kw = keyword.Trim();
query = query.Where(x => x.WorkName.Contains(kw) || x.BizType.Contains(kw) || x.SccbFenlei.Contains(kw));
}
var total = await query.CountAsync();
var items = await query
.OrderBy(x => x.SortOrder)
.OrderBy(x => x.Id)
.Page(pageIndex, pageSize)
.ToListAsync(x => new WorkTypeReadDto_View(x.Id, x.WorkName, x.SortOrder, x.BizType, x.SccbFenlei, x.IsActive, ""));
var nameMap = await GetDepartmentNameMapAsync(items.Select(x => x.Id).ToList());
var list = items
.Select(x => x with { DepartmentNames = nameMap.TryGetValue(x.Id, out var names) ? names : string.Empty })
.ToList();
return new PageResult<WorkTypeReadDto_View>
{
Items = list,
Total = total,
PageIndex = pageIndex,
PageSize = pageSize
};
}
public async Task<WorkTypeReadDto_Edit> GetByIdForEditAsync(long id)
=> await Orm.Select<WorkType>()
.Where(x => x.Id == id && x.DeletedAt == null)
.FirstAsync(x => new WorkTypeReadDto_Edit(x.Id, x.WorkName, x.SortOrder, x.BizType, x.SccbFenlei, x.IsActive));
public async Task<List<WorkTypeDepartmentReadDto_Cache>> GetDepartmentsAsync(long workTypeId)
=> await Orm.Select<WorkTypeDepartment>()
.Where(x => x.WorkTypeId == workTypeId)
.OrderBy(x => x.AssignedAt)
.ToListAsync(x => new WorkTypeDepartmentReadDto_Cache(x.Id, x.WorkTypeId, x.DepartmentId));
public async Task<List<WorkTypeRoleReadDto_Cache>> GetRolesAsync(long workTypeId)
=> await Orm.Select<WorkTypeRole>()
.Where(x => x.WorkTypeId == workTypeId)
.OrderBy(x => x.AssignedAt)
.ToListAsync(x => new WorkTypeRoleReadDto_Cache(x.Id, x.WorkTypeId, x.RoleId));
/// <summary>工种 Id → 所属部门名称串(顿号分隔)</summary>
private async Task<Dictionary<long, string>> GetDepartmentNameMapAsync(List<long> workTypeIds)
{
var map = new Dictionary<long, string>();
if (workTypeIds == null || workTypeIds.Count == 0) return map;
var relations = await Orm.Select<WorkTypeDepartment>()
.Where(x => workTypeIds.Contains(x.WorkTypeId))
.ToListAsync();
if (relations.Count == 0) return map;
var depIds = relations.Select(x => x.DepartmentId).Distinct().ToList();
var deps = await Orm.Select<Department>().Where(x => depIds.Contains(x.Id)).ToListAsync();
var depNameMap = deps.ToDictionary(x => x.Id, x => x.Name);
foreach (var group in relations.GroupBy(x => x.WorkTypeId))
{
var names = group
.Select(r => depNameMap.TryGetValue(r.DepartmentId, out var name) ? name : null)
.Where(name => !string.IsNullOrEmpty(name))
.ToList();
map[group.Key] = string.Join("、", names);
}
return map;
}
}
@@ -0,0 +1,51 @@
using FreeSql;
using F9WebAiTest.Domain.Entities.SYS.WorkTypes;
using F9WebAiTest.Domain.Interfaces.SYS.WorkTypes;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.WorkTypes;
/// <summary>工种-部门关联仓储(关联表用物理删除,避免唯一索引与历史数据冲突)</summary>
internal class WorkTypeDepartmentRepository : F9RepositoryBase, IWorkTypeDepartmentRepository
{
public WorkTypeDepartmentRepository(IFreeSql fsql) : base(fsql) { }
public async Task<WorkTypeDepartment> GetAsync(long workTypeId, long departmentId)
=> await Orm.Select<WorkTypeDepartment>()
.Where(x => x.WorkTypeId == workTypeId && x.DepartmentId == departmentId)
.FirstAsync();
public async Task<bool> AddAsync(WorkTypeDepartment entity)
{
entity.CreatedAt = DateTime.Now;
return await Orm.Insert(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> HardDeleteAsync(long id)
=> await Orm.Delete<WorkTypeDepartment>().Where(x => x.Id == id).ExecuteAffrowsAsync() > 0;
public async Task<bool> HardDeleteByWorkTypeIdAsync(long workTypeId)
=> await Orm.Delete<WorkTypeDepartment>().Where(x => x.WorkTypeId == workTypeId).ExecuteAffrowsAsync() > 0;
}
/// <summary>工种-角色关联仓储</summary>
internal class WorkTypeRoleRepository : F9RepositoryBase, IWorkTypeRoleRepository
{
public WorkTypeRoleRepository(IFreeSql fsql) : base(fsql) { }
public async Task<WorkTypeRole> GetAsync(long workTypeId, long roleId)
=> await Orm.Select<WorkTypeRole>()
.Where(x => x.WorkTypeId == workTypeId && x.RoleId == roleId)
.FirstAsync();
public async Task<bool> AddAsync(WorkTypeRole entity)
{
entity.CreatedAt = DateTime.Now;
return await Orm.Insert(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> HardDeleteAsync(long id)
=> await Orm.Delete<WorkTypeRole>().Where(x => x.Id == id).ExecuteAffrowsAsync() > 0;
public async Task<bool> HardDeleteByWorkTypeIdAsync(long workTypeId)
=> await Orm.Delete<WorkTypeRole>().Where(x => x.WorkTypeId == workTypeId).ExecuteAffrowsAsync() > 0;
}
@@ -0,0 +1,39 @@
using FreeSql;
using F9WebAiTest.Domain.Entities.SYS.WorkTypes;
using F9WebAiTest.Domain.Interfaces.SYS.WorkTypes;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.WorkTypes;
internal class WorkTypeWriteRepository : F9RepositoryBase, IWorkTypeWriteRepository
{
public WorkTypeWriteRepository(IFreeSql fsql) : base(fsql) { }
public async Task<WorkType> GetByIdAsync(long id, CancellationToken cancellationToken)
=> await Orm.Select<WorkType>().Where(x => x.Id == id && x.DeletedAt == null).FirstAsync(cancellationToken);
public async Task<bool> AddAsync(WorkType workType)
{
workType.CreatedAt = DateTime.Now;
return await Orm.Insert(workType).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> UpdateAsync(WorkType workType)
{
workType.UpdatedAt = DateTime.Now;
return await Orm.Update<WorkType>().SetSource(workType).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> SoftDeleteAsync(long id)
=> await Orm.Update<WorkType>()
.Set(x => x.IsDeleted, true)
.Set(x => x.DeletedAt, DateTime.Now)
.Where(x => x.Id == id)
.ExecuteAffrowsAsync() > 0;
public async Task<bool> ActiveOrDeactive(long id, bool active)
=> await Orm.Update<WorkType>()
.Set(x => x.IsActive, active)
.Set(x => x.UpdatedAt, DateTime.Now)
.Where(x => x.Id == id)
.ExecuteAffrowsAsync() > 0;
}
@@ -0,0 +1,78 @@
using FreeSql;
using F9WebAiTest.Application.Dtos.SYS.WuziMulus;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.WuziMulus;
using F9WebAiTest.Domain.Entities.SYS.WuziMulus;
using F9WebAiTest.Domain.Interfaces.SYS.WuziMulus;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.WuziMulus;
internal class WuziGroupWriteRepository : F9RepositoryBase, IWuziGroupWriteRepository
{
public WuziGroupWriteRepository(IFreeSql fsql) : base(fsql) { }
public async Task<WuziGroup> GetByIdAsync(long id, CancellationToken cancellationToken)
=> await Orm.Select<WuziGroup>().Where(x => x.Id == id && x.DeletedAt == null).FirstAsync(cancellationToken);
public async Task<bool> AddAsync(WuziGroup entity)
{
entity.CreatedAt = DateTime.Now;
return await Orm.Insert(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> UpdateAsync(WuziGroup entity)
{
entity.UpdatedAt = DateTime.Now;
return await Orm.Update<WuziGroup>().SetSource(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> SoftDeleteAsync(long id)
=> await Orm.Update<WuziGroup>()
.Set(x => x.IsDeleted, true)
.Set(x => x.DeletedAt, DateTime.Now)
.Where(x => x.Id == id)
.ExecuteAffrowsAsync() > 0;
}
internal class WuziGroupReadRepository : F9RepositoryBase, IWuziGroupReadRepository
{
public WuziGroupReadRepository(IFreeSql fsql) : base(fsql) { }
public async Task<List<WuziGroupReadDto_View>> GetAllAsync()
=> await Orm.Select<WuziGroup>()
.Where(x => x.DeletedAt == null)
.OrderBy(x => x.SortOrder)
.OrderBy(x => x.Code)
.ToListAsync(x => new WuziGroupReadDto_View(x.Id, x.BusinessType, x.DepartmentType, x.Code, x.Name,
x.ParentId, x.SortOrder, x.Description));
public async Task<WuziGroupReadDto_Edit> GetByIdForEditAsync(long id)
=> await Orm.Select<WuziGroup>()
.Where(x => x.Id == id && x.DeletedAt == null)
.FirstAsync(x => new WuziGroupReadDto_Edit(x.Id, x.BusinessType, x.DepartmentType, x.Code, x.Name,
x.ParentId, x.SortOrder, x.Description));
public async Task<bool> ExistChildAsync(long id)
=> await Orm.Select<WuziGroup>().Where(x => x.DeletedAt == null && x.ParentId == id).AnyAsync();
public async Task<bool> ExistMuluAsync(long id)
=> await Orm.Select<WuziMulu>().Where(x => x.DeletedAt == null && x.GroupId == id).AnyAsync();
/// <summary>生成新编号:一级 = 最大编号 + 1;下级 = 父级编号 + 2 位序号</summary>
public async Task<string> GetNewCodeAsync(long parentId)
{
var all = await Orm.Select<WuziGroup>().Where(x => x.DeletedAt == null).ToListAsync();
var parentCode = string.Empty;
if (parentId > 0) parentCode = all.FirstOrDefault(x => x.Id == parentId)?.Code ?? string.Empty;
var maxSeq = 0;
foreach (var group in all.Where(x => x.ParentId == parentId))
{
var code = group.Code ?? string.Empty;
var suffix = parentCode.Length > 0 && code.StartsWith(parentCode) ? code.Substring(parentCode.Length) : code;
if (int.TryParse(suffix, out var seq) && seq > maxSeq) maxSeq = seq;
}
return parentCode + (maxSeq + 1).ToString("00");
}
}
@@ -0,0 +1,128 @@
using FreeSql;
using F9WebAiTest.Application.Common;
using F9WebAiTest.Application.Dtos.SYS.WuziMulus;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.WuziMulus;
using F9WebAiTest.Domain.Entities.SYS.WuziMulus;
using F9WebAiTest.Domain.Interfaces.SYS.WuziMulus;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.WuziMulus;
internal class WuziMuluWriteRepository : F9RepositoryBase, IWuziMuluWriteRepository
{
public WuziMuluWriteRepository(IFreeSql fsql) : base(fsql) { }
public async Task<WuziMulu> GetByIdAsync(long id, CancellationToken cancellationToken)
=> await Orm.Select<WuziMulu>().Where(x => x.Id == id && x.DeletedAt == null).FirstAsync(cancellationToken);
public async Task<bool> AddAsync(WuziMulu entity)
{
entity.CreatedAt = DateTime.Now;
return await Orm.Insert(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> UpdateAsync(WuziMulu entity)
{
entity.UpdatedAt = DateTime.Now;
return await Orm.Update<WuziMulu>().SetSource(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> SoftDeleteAsync(long id)
=> await Orm.Update<WuziMulu>()
.Set(x => x.IsDeleted, true)
.Set(x => x.DeletedAt, DateTime.Now)
.Where(x => x.Id == id)
.ExecuteAffrowsAsync() > 0;
}
internal class WuziMuluReadRepository : F9RepositoryBase, IWuziMuluReadRepository
{
public WuziMuluReadRepository(IFreeSql fsql) : base(fsql) { }
public async Task<PageResult<WuziMuluReadDto_View>> GetPagedAsync(long groupId, string keyword, int pageIndex, int pageSize)
{
if (pageIndex <= 0) pageIndex = 1;
if (pageSize <= 0) pageSize = 20;
var query = Orm.Select<WuziMulu>().Where(x => x.DeletedAt == null);
if (groupId > 0) query = query.Where(x => x.GroupId == groupId);
if (!string.IsNullOrWhiteSpace(keyword))
{
var kw = keyword.Trim();
query = query.Where(x => x.Name.Contains(kw) || x.Code.Contains(kw) || x.PinyinName.Contains(kw)
|| x.Guige.Contains(kw) || x.Xinghao.Contains(kw));
}
var total = await query.CountAsync();
var items = await query
.OrderBy(x => x.SortOrder)
.OrderBy(x => x.Code)
.Page(pageIndex, pageSize)
.ToListAsync(x => new WuziMuluReadDto_View(x.Id, x.GroupId, x.Name, x.Code, x.Unit, x.Guige, x.Xinghao,
x.PinyinName, x.Kucunyujing, x.SortOrder, x.IsYujing, x.SaleRate));
return new PageResult<WuziMuluReadDto_View>
{
Items = items,
Total = total,
PageIndex = pageIndex,
PageSize = pageSize
};
}
public async Task<WuziMuluReadDto_Edit> GetByIdForEditAsync(long id)
=> await Orm.Select<WuziMulu>()
.Where(x => x.Id == id && x.DeletedAt == null)
.FirstAsync(x => new WuziMuluReadDto_Edit(x.Id, x.GroupId, x.Name, x.Code, x.Unit, x.Guige, x.Xinghao,
x.PinyinName, x.Kucunyujing, x.SortOrder, x.IsYujing, x.SaleRate));
/// <summary>生成新编号:分组编号 + 2 位序号</summary>
public async Task<string> GetNewCodeAsync(long groupId)
{
var group = await Orm.Select<WuziGroup>().Where(x => x.Id == groupId).FirstAsync();
var groupCode = group?.Code ?? string.Empty;
var list = await Orm.Select<WuziMulu>().Where(x => x.DeletedAt == null && x.GroupId == groupId).ToListAsync();
var maxSeq = 0;
foreach (var item in list)
{
var code = item.Code ?? string.Empty;
var suffix = groupCode.Length > 0 && code.StartsWith(groupCode) ? code.Substring(groupCode.Length) : code;
if (int.TryParse(suffix, out var seq) && seq > maxSeq) maxSeq = seq;
}
return groupCode + (maxSeq + 1).ToString("00");
}
/// <summary>物资选项(供其它模块选择:名称/编号/拼音模糊匹配)</summary>
public async Task<List<WuziMuluOptionDto>> GetOptionsAsync(string keyword, int limit)
{
if (limit <= 0) limit = 200;
var query = Orm.Select<WuziMulu>().Where(x => x.DeletedAt == null);
if (!string.IsNullOrWhiteSpace(keyword))
{
var kw = keyword.Trim();
query = query.Where(x => x.Name.Contains(kw) || x.Code.Contains(kw) || x.PinyinName.Contains(kw));
}
var rows = await query
.OrderBy(x => x.Code)
.Page(1, limit)
.ToListAsync(x => new OptionRow(x.Id, x.Name, x.Code, x.GroupId));
if (rows.Count == 0) return new List<WuziMuluOptionDto>();
var groupIds = rows.Select(x => x.GroupId).Distinct().ToList();
var groups = await Orm.Select<WuziGroup>().Where(x => groupIds.Contains(x.Id)).ToListAsync();
var groupNameMap = groups.ToDictionary(x => x.Id, x => x.Name);
return rows
.Select(x => new WuziMuluOptionDto(x.Id, x.Name, x.Code,
groupNameMap.TryGetValue(x.GroupId, out var name) ? name : string.Empty))
.ToList();
}
/// <summary>选项查询投影(含分组 Id)</summary>
private sealed record OptionRow(long Id, string Name, string Code, long GroupId);
}
@@ -0,0 +1,145 @@
using FreeSql;
using F9WebAiTest.Application.Common;
using F9WebAiTest.Application.Dtos.SYS.WuziMulus;
using F9WebAiTest.Application.Dtos.SYS.YuanliaoZhuangkous;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.YuanliaoZhuangkous;
using F9WebAiTest.Domain.Entities.SYS.WuziMulus;
using F9WebAiTest.Domain.Enums.SYS.WuziMulus;
using F9WebAiTest.Domain.Entities.SYS.YuanliaoZhuangkous;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.YuanliaoZhuangkous;
internal class YuanliaoZhuangkouReadRepository : F9RepositoryBase, IYuanliaoZhuangkouReadRepository
{
public YuanliaoZhuangkouReadRepository(IFreeSql fsql) : base(fsql) { }
public async Task<PageResult<YuanliaoZhuangkouReadDto_Table>> GetPagedAsync(int year, string chandi, string zhandian,
string jibie, string keyword, int pageIndex, int pageSize)
{
if (pageIndex <= 0) pageIndex = 1;
if (pageSize <= 0) pageSize = 20;
var query = Orm.Select<YuanliaoZhuangkou>().Where(x => x.DeletedAt == null);
if (year > 0) query = query.Where(x => x.Year == year);
if (!string.IsNullOrWhiteSpace(chandi)) query = query.Where(x => x.Chandi == chandi.Trim());
if (!string.IsNullOrWhiteSpace(zhandian)) query = query.Where(x => x.Zhandian == zhandian.Trim());
if (!string.IsNullOrWhiteSpace(jibie)) query = query.Where(x => x.Jibie == jibie.Trim());
if (!string.IsNullOrWhiteSpace(keyword))
{
var kw = keyword.Trim();
query = query.Where(x => x.Name.Contains(kw) || x.Code.Contains(kw) || x.Chandi.Contains(kw)
|| x.Zhandian.Contains(kw) || x.Canpinzhong.Contains(kw) || x.Jibie.Contains(kw));
}
var total = await query.CountAsync();
var items = await query
.OrderByDescending(x => x.Year)
.OrderBy(x => x.Code)
.Page(pageIndex, pageSize)
.ToListAsync(x => new YuanliaoZhuangkouReadDto_Table(x.Id, x.Year, x.Name, x.Code, x.Jibie,
x.Bendiwaidi, x.Chandi, x.Canpinzhong, x.WzmlId, "", x.Zhandian, x.Pici));
// 物资名称取自物资目录(sys_wuzi_mulu)
var nameMap = await GetWuziNameMapAsync(items.Select(x => x.WzmlId).Distinct().ToList());
var list = items
.Select(x => x with { WzmlName = nameMap.TryGetValue(x.WzmlId, out var name) ? name : string.Empty })
.ToList();
return new PageResult<YuanliaoZhuangkouReadDto_Table>
{
Items = list,
Total = total,
PageIndex = pageIndex,
PageSize = pageSize
};
}
public async Task<YuanliaoZhuangkouReadDto_Edit> GetByIdForEditAsync(long id)
{
var dto = await Orm.Select<YuanliaoZhuangkou>()
.Where(x => x.Id == id && x.DeletedAt == null)
.FirstAsync(x => new YuanliaoZhuangkouReadDto_Edit(x.Id, x.Year, x.Name, x.Code, x.Jibie,
x.Bendiwaidi, x.Chandi, x.Canpinzhong, x.WzmlId, "", x.Zhandian, x.Pici));
if (dto == null) return null;
var nameMap = await GetWuziNameMapAsync(new List<long> { dto.WzmlId });
return dto with { WzmlName = nameMap.TryGetValue(dto.WzmlId, out var name) ? name : string.Empty };
}
public async Task<List<string>> GetCodesByYearAsync(int year)
=> await Orm.Select<YuanliaoZhuangkou>()
.Where(x => x.Year == year && x.Code != null && x.Code != "")
.ToListAsync(x => x.Code);
/// <summary>
/// 物资(茧别)选项:取物资目录中"业务类型为原料"的分组(含其子分组,如 01 干茧、333 外购茧)下的物资。
/// 这样可避免把五金件(如捞茧爪轴)之类的物资混入茧别。
/// </summary>
public async Task<List<WuziMuluOptionDto>> GetWuziOptionsAsync(string keyword)
{
var allGroups = await Orm.Select<WuziGroup>().Where(x => x.DeletedAt == null).ToListAsync();
var rawGroupIds = new HashSet<long>(allGroups
.Where(g => g.BusinessType == WuziBusiness_Type_Enum.原料)
.Select(g => g.Id));
// 把原料分组的后代分组一并纳入
var changed = true;
while (changed)
{
changed = false;
foreach (var group in allGroups)
{
if (group.ParentId != 0 && rawGroupIds.Contains(group.ParentId) && rawGroupIds.Add(group.Id))
changed = true;
}
}
var rawGroupIdList = rawGroupIds.ToList();
var query = Orm.Select<WuziMulu>().Where(x => x.DeletedAt == null && rawGroupIdList.Contains(x.GroupId));
if (!string.IsNullOrWhiteSpace(keyword))
{
var kw = keyword.Trim();
query = query.Where(x => x.Name.Contains(kw) || x.Code.Contains(kw) || x.PinyinName.Contains(kw));
}
var rows = await query
.OrderBy(x => x.Code)
.Page(1, 300)
.ToListAsync(x => new WuziRow(x.Id, x.Name, x.Code, x.GroupId));
if (rows.Count == 0) return new List<WuziMuluOptionDto>();
var groupIds = rows.Select(x => x.GroupId).Distinct().ToList();
var groups = await Orm.Select<WuziGroup>().Where(x => groupIds.Contains(x.Id)).ToListAsync();
var groupNameMap = groups.ToDictionary(x => x.Id, x => x.Name);
return rows
.Select(x => new WuziMuluOptionDto(x.Id, x.Name, x.Code,
groupNameMap.TryGetValue(x.GroupId, out var name) ? name : string.Empty))
.ToList();
}
public async Task<string> GetWuziNameAsync(long wzmlId)
{
if (wzmlId <= 0) return string.Empty;
var nameMap = await GetWuziNameMapAsync(new List<long> { wzmlId });
return nameMap.TryGetValue(wzmlId, out var name) ? name : string.Empty;
}
/// <summary>物资 Id → 名称(取自物资目录)</summary>
private async Task<Dictionary<long, string>> GetWuziNameMapAsync(List<long> wzmlIds)
{
var map = new Dictionary<long, string>();
if (wzmlIds == null || wzmlIds.Count == 0) return map;
var rows = await Orm.Select<WuziMulu>()
.Where(x => wzmlIds.Contains(x.Id))
.ToListAsync(x => new WuziRow(x.Id, x.Name, x.Code, x.GroupId));
foreach (var row in rows) map[row.Id] = row.Name;
return map;
}
private sealed record WuziRow(long Id, string Name, string Code, long GroupId);
}
@@ -0,0 +1,32 @@
using FreeSql;
using F9WebAiTest.Domain.Entities.SYS.YuanliaoZhuangkous;
using F9WebAiTest.Domain.Interfaces.SYS.YuanliaoZhuangkous;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.YuanliaoZhuangkous;
internal class YuanliaoZhuangkouWriteRepository : F9RepositoryBase, IYuanliaoZhuangkouWriteRepository
{
public YuanliaoZhuangkouWriteRepository(IFreeSql fsql) : base(fsql) { }
public async Task<YuanliaoZhuangkou> GetByIdAsync(long id, CancellationToken cancellationToken)
=> await Orm.Select<YuanliaoZhuangkou>().Where(x => x.Id == id && x.DeletedAt == null).FirstAsync(cancellationToken);
public async Task<bool> AddAsync(YuanliaoZhuangkou entity)
{
entity.CreatedAt = DateTime.Now;
return await Orm.Insert(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> UpdateAsync(YuanliaoZhuangkou entity)
{
entity.UpdatedAt = DateTime.Now;
return await Orm.Update<YuanliaoZhuangkou>().SetSource(entity).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> SoftDeleteAsync(long id)
=> await Orm.Update<YuanliaoZhuangkou>()
.Set(x => x.IsDeleted, true)
.Set(x => x.DeletedAt, DateTime.Now)
.Where(x => x.Id == id)
.ExecuteAffrowsAsync() > 0;
}
@@ -0,0 +1,65 @@
using FreeSql;
using F9WebAiTest.Application.Common;
using F9WebAiTest.Application.Dtos.SYS.Zq;
using F9WebAiTest.Application.Interfaces.Repositories.SYS.Zq;
using F9WebAiTest.Domain.Entities.SYS.Zq;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.Zq;
internal class ZhangqiReadRepository : F9RepositoryBase, IZhangqiReadRepository
{
public ZhangqiReadRepository(IFreeSql fsql) : base(fsql) { }
public async Task<PageResult<ZhangqiReadDto_View>> GetPagedAsync(int? year, string keyword, int pageIndex, int pageSize)
{
if (pageIndex <= 0) pageIndex = 1;
if (pageSize <= 0) pageSize = 20;
var query = Orm.Select<Zhangqi>().Where(x => x.DeletedAt == null);
if (year.HasValue && year.Value > 0) query = query.Where(x => x.Year == year.Value);
// 关键字:纯数字时按年度/月份匹配
if (!string.IsNullOrWhiteSpace(keyword) && int.TryParse(keyword.Trim(), out var num))
query = query.Where(x => x.Year == num || x.Month == num);
var total = await query.CountAsync();
var items = await query
.OrderByDescending(x => x.Year)
.OrderByDescending(x => x.Month)
.Page(pageIndex, pageSize)
.ToListAsync(x => new ZhangqiReadDto_View(x.Id, x.Year, x.Month, x.StartDate, x.EndDate, x.IsZhaZhang));
return new PageResult<ZhangqiReadDto_View>
{
Items = items,
Total = total,
PageIndex = pageIndex,
PageSize = pageSize
};
}
public async Task<ZhangqiReadDto_Edit> GetByIdForEditAsync(long id)
=> await Orm.Select<Zhangqi>()
.Where(x => x.Id == id && x.DeletedAt == null)
.FirstAsync(x => new ZhangqiReadDto_Edit(x.Id, x.Year, x.Month, x.StartDate, x.EndDate, x.IsZhaZhang));
public async Task<ZhangqiReadDto_Edit> GetByDateAsync(DateTime date)
=> await Orm.Select<Zhangqi>()
.Where(x => x.DeletedAt == null && x.StartDate <= date && x.EndDate >= date)
.OrderByDescending(x => x.StartDate)
.FirstAsync(x => new ZhangqiReadDto_Edit(x.Id, x.Year, x.Month, x.StartDate, x.EndDate, x.IsZhaZhang));
public async Task<bool> GetIsZhaZhangAsync(int year, int month)
{
var list = await Orm.Select<Zhangqi>()
.Where(x => x.DeletedAt == null && x.Year == year && x.Month == month)
.ToListAsync();
return list.Any(x => x.IsZhaZhang);
}
public async Task<bool> GetIsZhaZhangByDateAsync(DateTime date)
{
var dto = await GetByDateAsync(date);
return dto != null && dto.IsZhaZhang;
}
}
@@ -0,0 +1,39 @@
using FreeSql;
using F9WebAiTest.Domain.Entities.SYS.Zq;
using F9WebAiTest.Domain.Interfaces.SYS.Zq;
namespace F9WebAiTest.Infrastructure.FreeSqls.Repositories.SYS.Zq;
internal class ZhangqiWriteRepository : F9RepositoryBase, IZhangqiWriteRepository
{
public ZhangqiWriteRepository(IFreeSql fsql) : base(fsql) { }
public async Task<Zhangqi> GetByIdAsync(long id, CancellationToken cancellationToken)
=> await Orm.Select<Zhangqi>().Where(x => x.Id == id && x.DeletedAt == null).FirstAsync(cancellationToken);
public async Task<bool> AddAsync(Zhangqi zhangqi)
{
zhangqi.CreatedAt = DateTime.Now;
return await Orm.Insert(zhangqi).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> UpdateAsync(Zhangqi zhangqi)
{
zhangqi.UpdatedAt = DateTime.Now;
return await Orm.Update<Zhangqi>().SetSource(zhangqi).ExecuteAffrowsAsync() > 0;
}
public async Task<bool> SoftDeleteAsync(long id)
=> await Orm.Update<Zhangqi>()
.Set(x => x.IsDeleted, true)
.Set(x => x.DeletedAt, DateTime.Now)
.Where(x => x.Id == id)
.ExecuteAffrowsAsync() > 0;
public async Task<bool> SetZhaZhangAsync(long id, bool isZhaZhang)
=> await Orm.Update<Zhangqi>()
.Set(x => x.IsZhaZhang, isZhaZhang)
.Set(x => x.UpdatedAt, DateTime.Now)
.Where(x => x.Id == id)
.ExecuteAffrowsAsync() > 0;
}