first commit

This commit is contained in:
yanpeng200212
2026-10-08 10:43:59 +08:00
commit 8430ba0452
288 changed files with 29595 additions and 0 deletions
@@ -0,0 +1,501 @@
using FreeSql;
using F9WebAiTest.Domain.Entities;
using F9WebAiTest.Domain.Entities.Base;
namespace F9WebAiTest.Infrastructure.Data;
/// <summary>业务基础数据种子(部门/工艺庄口/生丝规格/生丝定级指标/机组车台)</summary>
public static class BusinessSeedData
{
public static void Seed(IFreeSql fsql)
{
SeedMenus(fsql);
SeedCraftZhuangKou(fsql);
SeedShengsiGuige(fsql);
SeedShengsiDingjizhibiao(fsql);
SeedDepartmentsAndJizuChetai(fsql);
SeedEmployees(fsql);
}
// ==================== 部门 + 机组车台(真实组织架构) ====================
private static readonly (long Id, string Name, long ParentId, int Sort, string Code)[] DeptData =
{
(10920411881541632, "安泰茧丝绸", 0, 0, "123"),
(10929439026188288, "丝业生产中心", 10920411881541632, 100, "100"),
(19667471837433856, "主干运维", 10920411881541632, 9999, "9999"),
(22305637455106048, "人力资源部", 10920411881541632, 800, "800"),
(22305758536273920, "财务部", 10920411881541632, 400, "400"),
(22305841730293760, "营销中心", 10920411881541632, 500, "500"),
(22305998261719040, "计划运营部", 10920411881541632, 200, "200"),
(22306589042020352, "品管部", 10920411881541632, 700, "700"),
(22306677265010688, "采购部", 10920411881541632, 300, "300"),
(26900271946797056, "安全环保后勤部", 10920411881541632, 1000, "1000"),
(26901050904547328, "经理会", 10920411881541632, 1500, "1500"),
(26901341515288576, "监察室", 10920411881541632, 3000, "3000"),
(26901475166785536, "融资部", 10920411881541632, 2000, "2000"),
(34638098675535872, "武胜蚕业公司", 10920411881541632, 4000, "4000"),
(35981234102341632, "安泰丝绸人南店", 10920411881541632, 6200, "6200"),
(35981427686248448, "绸业生产中心", 10920411881541632, 5000, "5000"),
(35981496963567616, "夹江蚕业公司", 10920411881541632, 4100, "4100"),
(35982738976673792, "安泰丝绸融恒店", 10920411881541632, 6000, "6000"),
(35982891737419776, "帛锦汇", 10920411881541632, 6100, "6100"),
(35982956409393152, "蚕业技术服务部", 10920411881541632, 4900, "4900"),
(36277179469795328, "广安蚕业公司", 10920411881541632, 4200, "4200"),
(10929739564847104, "仓储", 10929439026188288, 1000, "1000"),
(22307875854487552, "质检科", 10929439026188288, 1100, "1100"),
(22308241237086208, "试样室", 10929439026188288, 1200, "1200"),
(22308361408090112, "选剥茧车间", 10929439026188288, 1300, "1300"),
(25256354205667328, "前缫车间", 10929439026188288, 1350, "1350"),
(22308805823959040, "后缫车间", 10929439026188288, 1800, "1800"),
(22309110082965504, "设备车间", 10929439026188288, 2100, "2100"),
(22309340027293696, "副产品车间", 10929439026188288, 2200, "2200"),
(68179345423732736, "临时", 10929439026188288, 3000, "3000"),
(16043931070369792, "前缫一车间", 25256354205667328, 1400, "1400"),
(16047387197837312, "前缫二车间", 25256354205667328, 1500, "1500"),
(22308600831545344, "前缫三车间", 25256354205667328, 1600, "1600"),
(22308683820044288, "前缫四车间", 25256354205667328, 1700, "1700"),
(25379428280307712, "煮茧室", 25256354205667328, 1350, "1350"),
(22308918461992960, "检验室", 22308805823959040, 1900, "1900"),
(22309003073687552, "整理室", 22308805823959040, 2000, "2000"),
(24029387057795072, "丝棉车间", 22309340027293696, 0, "999"),
};
private static readonly (long DeptId, int Jizu, int Start, int End)[] JizuData =
{
(16043931070369792, 1, 1, 20), (16043931070369792, 2, 21, 40), (16043931070369792, 3, 41, 60),
(16043931070369792, 4, 61, 80), (16043931070369792, 5, 81, 100), (16043931070369792, 6, 101, 120),
(16047387197837312, 1, 1, 20), (16047387197837312, 2, 21, 40), (16047387197837312, 3, 41, 60),
(16047387197837312, 4, 61, 80), (16047387197837312, 5, 81, 100), (16047387197837312, 6, 101, 120),
(22308600831545344, 1, 1, 20), (22308600831545344, 2, 21, 40), (22308600831545344, 3, 41, 60),
(22308600831545344, 4, 61, 80), (22308600831545344, 5, 81, 100), (22308600831545344, 6, 101, 120),
(22308683820044288, 1, 1, 20), (22308683820044288, 2, 21, 40), (22308683820044288, 3, 41, 60),
(22308683820044288, 4, 61, 80), (22308683820044288, 5, 81, 100), (22308683820044288, 6, 101, 120),
};
private static void SeedDepartmentsAndJizuChetai(IFreeSql fsql)
{
// 检测是否已有真实部门(以"安泰茧丝绸"为标记)
if (fsql.Select<Department>().Any(d => d.Name == "安泰茧丝绸")) return;
// 物理清空假数据(总公司/技术部等)及关联
fsql.Ado.ExecuteNonQuery("DELETE FROM JizuChetais");
fsql.Ado.ExecuteNonQuery("DELETE FROM AttendanceRecords");
fsql.Ado.ExecuteNonQuery("DELETE FROM LeaveRequests");
fsql.Ado.ExecuteNonQuery("DELETE FROM Employees");
fsql.Ado.ExecuteNonQuery("DELETE FROM Departments");
// 第一遍:创建所有部门(ParentId 暂不设)
var idMap = new Dictionary<long, long>();
foreach (var d in DeptData)
{
var dept = new Department { Name = d.Name, Code = d.Code, Sort = d.Sort };
var newId = DbSeeder.InsertAndGetId(fsql, dept);
idMap[d.Id] = newId;
}
// 第二遍:设置 ParentId
foreach (var d in DeptData)
{
if (d.ParentId != 0 && idMap.ContainsKey(d.ParentId))
{
var dept = fsql.Select<Department>().Where(x => x.Id == idMap[d.Id]).First();
dept.ParentId = idMap[d.ParentId];
fsql.Update<Department>().SetSource(dept).ExecuteAffrows();
}
}
// 机组车台
foreach (var j in JizuData)
{
if (idMap.ContainsKey(j.DeptId))
{
fsql.Insert(new JizuChetai
{
DepartmentId = idMap[j.DeptId],
Jizu = j.Jizu,
ChetaiStart = j.Start,
ChetaiEnd = j.End
}).ExecuteAffrows();
}
}
}
// ==================== 职工 ====================
private static readonly (long DeptId, string Name, string Phone, string Login)[] EmpData =
{
(16043931070369792, "主干-何启旭", "18840854628", "18840854628"),
(10920411881541632, "测试用户", "0", "test"),
(10920411881541632, "秦燊", "13982683923", "13982683923"),
(10920411881541632, "陈勇", "18908283908", "18908283908"),
(22305758536273920, "汪菊", "18782619006", "18782619006"),
(22305841730293760, "陈林", "18580851234", "18580851234"),
(10929439026188288, "李正平", "15378405846", "15378405846"),
(22305637455106048, "朱莹", "18908283738", "18908283738"),
(22305637455106048, "毛银春", "18180268728", "18180268728"),
(22305637455106048, "陆国君", "13696173949", "13696173949"),
(22305637455106048, "华静", "13882636653", "13882636653"),
(22305637455106048, "余思洁", "18398508220", "18398508220"),
(22305758536273920, "孙瑞", "15982664679", "15982664679"),
(22305758536273920, "唐琳", "18048103256", "18048103256"),
(22305758536273920, "蒋宜", "18982626800", "18982626800"),
(22305758536273920, "王清华", "15282625323", "15282625323"),
(22305998261719040, "李西宴", "13688261711", "13688261711"),
(22305998261719040, "文杨", "13699654826", "13699654826"),
(22306589042020352, "曹庆", "13541993164", "13541993164"),
(22306677265010688, "蒙海波", "15884923167", "15884923167"),
(22305841730293760, "陈菊", "13696182387", "13696182387"),
(22305841730293760, "刘婷", "18382610528", "18382610528"),
(19667471837433856, "主干-张建", "15398380348", "15398380348"),
(19667471837433856, "主干-严鹏", "19162687174", "19162687174"),
(10929739564847104, "游建梅", "13629091099", "13629091099"),
(22307875854487552, "邓滟旖", "18181821168", "18181821168"),
(10929439026188288, "李志颖", "14708217874", "14708217874"),
(22308241237086208, "曹志君", "13882695209", "13882695209"),
(22308241237086208, "胡小琴", "18160129785", "18160129785"),
(22308361408090112, "唐小红", "15983458330", "15983458330"),
(25256354205667328, "余华", "13547542219", "13547542219"),
(22308683820044288, "陈建红", "15182698365", "15182698365"),
(22308683820044288, "谢军辉", "19957339779", "19957339779"),
(22308600831545344, "陈丽华", "15982605862", "15982605862"),
(16047387197837312, "杨静", "15982696700", "15982696700"),
(25256354205667328, "刘芳", "13882653025", "13882653025"),
(22308805823959040, "刘春兰", "13982624682", "13982624682"),
(22309110082965504, "朱再民", "15328288332", "15328288332"),
(22309340027293696, "舒文", "13551613659", "13551613659"),
(10929439026188288, "汪瑜琳", "13541553564", "13541553564"),
(19667471837433856, "范鸿才", "18981977117", "18981977117"),
(22305758536273920, "谭波", "18282636380", "18282636380"),
(22308918461992960, "董宗华", "18384503138", "18384503138"),
(22308918461992960, "易林梅", "18381112479", "18381112479"),
(22309003073687552, "舒红群", "18398526317", "18398526317"),
(25379428280307712, "彭卫东", "18382668003", "18382668003"),
(25379428280307712, "王远辉", "15982666491", "15982666491"),
(25379428280307712, "姚光林", "19160637815", "19160637815"),
(19667471837433856, "李学兴", "18117362915", "18117362915"),
(16043931070369792, "李远玲", "13982638574", "13982638574"),
(26900271946797056, "杨福锋", "13982638165", "13982638165"),
(26901341515288576, "杨利容", "15928659870", "15928659870"),
(19667471837433856, "主干-张罗", "18109064045", "18109064045"),
(26900271946797056, "袁鑫", "14781753888", "14781753888"),
(19667471837433856, "刘香君", "15808107846", "15808107846"),
(22308805823959040, "沈跃成", "13822244141", "13822244141"),
(19667471837433856, "杨凤琼", "18011528128", "18011528128"),
(22308600831545344, "谭爱君", "13699658634", "13699658634"),
};
private static void SeedEmployees(IFreeSql fsql)
{
var defaultPwd = BCrypt.Net.BCrypt.HashPassword("123456");
var deptNameMap = DeptData.ToDictionary(d => d.Id, d => d.Name);
foreach (var e in EmpData)
{
if (fsql.Select<Employee>().Any(x => x.Username == e.Login)) continue;
long deptId = 0;
if (deptNameMap.TryGetValue(e.DeptId, out var deptName))
{
var dept = fsql.Select<Department>().Where(d => d.Name == deptName).First();
if (dept != null) deptId = dept.Id;
}
fsql.Insert(new Employee
{
Username = e.Login,
Password = defaultPwd,
RealName = e.Name,
Nickname = e.Name,
Phone = e.Phone,
DepartmentId = deptId,
Status = 1
}).ExecuteAffrows();
}
}
// ==================== 菜单 ====================
private static void SeedMenus(IFreeSql fsql)
{
var baseDirId = fsql.Select<Menu>().Where(m => m.Path == "/base").First()?.Id ?? 0;
if (baseDirId == 0)
{
baseDirId = DbSeeder.InsertAndGetId(fsql, new Menu { Name = "基础数据", Type = "directory", Path = "/base", Icon = "Files", Sort = 3 });
}
AddMenu(fsql, baseDirId, "工艺庄口", "/base/zhuangkou", "base/zhuangkou/index", "Collection", "base:zhuangkou:list", 1);
AddMenu(fsql, baseDirId, "生丝规格", "/base/guige", "base/guige/index", "Grid", "base:guige:list", 2);
AddMenu(fsql, baseDirId, "生丝定级指标", "/base/dingjizhibiao", "base/dingjizhibiao/index", "TrendCharts", "base:dingjizhibiao:list", 3);
AddMenu(fsql, baseDirId, "机组车台", "/base/jizuchetai", "base/jizuchetai/index", "SetUp", "base:jizuchetai:list", 4);
// 生产管理目录
var prodDirId = fsql.Select<Menu>().Where(m => m.Path == "/prod").First()?.Id ?? 0;
if (prodDirId == 0)
{
prodDirId = DbSeeder.InsertAndGetId(fsql, new Menu { Name = "生产管理", Type = "directory", Path = "/prod", Icon = "Cpu", Sort = 4 });
}
AddMenu(fsql, prodDirId, "落丝记录", "/prod/lsjl", "prod/lsjl/index", "Document", "prod:lsjl:list", 1);
AddMenu(fsql, prodDirId, "纤度检验", "/prod/xdjy", "prod/xdjy/index", "EditPen", "prod:xdjy:list", 2);
AddMenu(fsql, prodDirId, "黑板检验", "/prod/hbjy", "prod/hbjy/index", "Notebook", "prod:hbjy:list", 3);
var adminRole = fsql.Select<Role>().Where(r => r.Code == "admin").First();
if (adminRole != null)
{
var baseMenus = fsql.Select<Menu>().Where(m => m.Path.StartsWith("/base") || m.Path.StartsWith("/prod")).ToList();
foreach (var m in baseMenus)
{
if (!fsql.Select<RoleMenu>().Any(rm => rm.RoleId == adminRole.Id && rm.MenuId == m.Id))
fsql.Insert(new RoleMenu { RoleId = adminRole.Id, MenuId = m.Id }).ExecuteAffrows();
}
}
}
private static void AddMenu(IFreeSql fsql, long parentId, string name, string path, string component, string icon, string permission, int sort)
{
if (!fsql.Select<Menu>().Any(m => m.Path == path))
{
fsql.Insert(new Menu { ParentId = parentId, Name = name, Type = "menu", Path = path, Component = component, Icon = icon, Permission = permission, Sort = sort }).ExecuteAffrows();
}
}
private static void SeedCraftZhuangKou(IFreeSql fsql)
{
if (fsql.Select<CraftZhuangKou>().Any()) return;
fsql.Insert(new CraftZhuangKou[]
{
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 1, JidiWaigou = "基地", ZhuangKouCode = "SZJ-2026-武工艺20", ZhuangKouName = "2026年基地春一批(青松皓月)", ProductionDisplayName = "2026年基地春一批(青松皓月)", Chandi = "基地", Sort = 20 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 1, JidiWaigou = "基地", ZhuangKouCode = "SZJ-2026-武工艺24", ZhuangKouName = "2026年基地春(雄)", ProductionDisplayName = "2026年基地春(雄)", Chandi = "大面积", Sort = 24 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 2, JidiWaigou = "外购", ZhuangKouCode = "SZJ-2026-武工艺-22", ZhuangKouName = "2026年会东春(7532)", ProductionDisplayName = "2026年会东春(7532)", Chandi = "会东", Sort = 22 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 2, JidiWaigou = "外购", ZhuangKouCode = "SZJ-2026-武工艺-23", ZhuangKouName = "2026年珙县九丝春(雄)", ProductionDisplayName = "2026年珙县九丝春(雄)", Chandi = "珙县", Sort = 23 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 2, JidiWaigou = "外购", ZhuangKouCode = "SZJ-2026-武工艺-7", ZhuangKouName = "2026会东二类茧(7532)宁兴", ProductionDisplayName = "2026会东二类茧(7532)宁兴", Chandi = "会东", Sort = 7 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 1, JidiWaigou = "基地", ZhuangKouCode = "SZJ-武工艺-2026-25", ZhuangKouName = "2026年广安春(青松皓月)", ProductionDisplayName = "2026年广安春(青松皓月)", Chandi = "基地", Sort = 25 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 2, JidiWaigou = "外购", ZhuangKouCode = "SZJ-2026-武工艺-26", ZhuangKouName = "2026年珙县罗渡春(雄)", ProductionDisplayName = "2026年珙县罗渡春(雄)", Chandi = "珙县", Sort = 26 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 1, JidiWaigou = "基地", ZhuangKouCode = "SZJ-武工艺-2026-9", ZhuangKouName = "2026年广安春(青松皓月)宁兴", ProductionDisplayName = "2026年广安春(青松皓月)宁兴", Chandi = "广安", Sort = 9 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 1, JidiWaigou = "基地", ZhuangKouCode = "SZJ-武工艺-2026-28", ZhuangKouName = "2026年基地春三批(青松皓月)", ProductionDisplayName = "2026年基地春三批(青松皓月)", Chandi = "基地", Sort = 28 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 1, JidiWaigou = "基地", ZhuangKouCode = "SZJ-武工艺-2026-11", ZhuangKouName = "2026年基地春三批(青松皓月)宁兴", ProductionDisplayName = "2026年基地春三批(青松皓月)宁兴", Chandi = "基地", Sort = 11 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 2, JidiWaigou = "外购", ZhuangKouCode = "SZJ-武工艺-2026-29", ZhuangKouName = "2026年珙县宝山等混六庄春一批(雄)", ProductionDisplayName = "2026年珙县宝山等混六庄春一批(雄)", Chandi = "珙县", Sort = 29 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 2, JidiWaigou = "外购", ZhuangKouCode = "SZJ-武工艺-2026-27", ZhuangKouName = "2026年珙县曹营等混四庄春一批(雄)", ProductionDisplayName = "2026年珙县曹营等混四庄春一批(雄)", Chandi = "珙县", Sort = 27 },
new CraftZhuangKou { BelongingYear = 2026, BendiWaidi = 2, JidiWaigou = "外购", ZhuangKouCode = "SZJ-武工艺-2026-10", ZhuangKouName = "2026年珙县罗渡春(雄)宁兴", ProductionDisplayName = "2026年珙县罗渡春(雄)宁兴", Chandi = "珙县", Sort = 10 }
}).ExecuteAffrows();
}
private static void SeedShengsiGuige(IFreeSql fsql)
{
if (fsql.Select<ShengsiGuige>().Any()) return;
fsql.Insert(new ShengsiGuige[]
{
new ShengsiGuige { Guige = "20/22", CenterrangeLolimit = 19.5, CenterrangeUplimit = 21.5, CenterXiandu = 20.5, ValidLolimit = 15.0, ValidUplimit = 27.0, XiaoyeLolimit = 17.5, XiaoyeUplimit = 24.5, DayeLolimit = 16.5, DayeUplimit = 25.5, TeyeLolimit = 15.5, TeyeUplimit = 26.5, YexianNkLolimitLeft = 15.0, YexianNkLolimitRight = 17.5, YexianNkUplimitLeft = 24.0, YexianNkUplimitRight = 27.5, LaodongJingsaiYexianLolimit = 17.5, LaodongJingsaiYexianUplimit = 23.5, Sort = 0 },
new ShengsiGuige { Guige = "27/29", CenterrangeLolimit = 26.5, CenterrangeUplimit = 28.5, CenterXiandu = 27.5, ValidLolimit = 23.0, ValidUplimit = 34.0, XiaoyeLolimit = 25.0, XiaoyeUplimit = 32.0, DayeLolimit = 24.0, DayeUplimit = 33.0, TeyeLolimit = 23.0, TeyeUplimit = 34.0, YexianNkLolimitLeft = 22.0, YexianNkLolimitRight = 24.5, YexianNkUplimitLeft = 31.0, YexianNkUplimitRight = 34.5, LaodongJingsaiYexianLolimit = 24.5, LaodongJingsaiYexianUplimit = 30.5, Sort = 100 },
new ShengsiGuige { Guige = "40/44", CenterrangeLolimit = 40.5, CenterrangeUplimit = 42.5, CenterXiandu = 41.5, ValidLolimit = 23.0, ValidUplimit = 34.0, XiaoyeLolimit = 35.0, XiaoyeUplimit = 49.0, DayeLolimit = 33.0, DayeUplimit = 51.0, TeyeLolimit = 31.0, TeyeUplimit = 53.0, YexianNkLolimitLeft = 0.0, YexianNkLolimitRight = 0.0, YexianNkUplimitLeft = 0.0, YexianNkUplimitRight = 0.0, LaodongJingsaiYexianLolimit = 40.0, LaodongJingsaiYexianUplimit = 42.0, Sort = 200 }
}).ExecuteAffrows();
}
private static void SeedShengsiDingjizhibiao(IFreeSql fsql)
{
if (fsql.Select<ShengsiDingjizhibiao>().Any()) return;
var list = new List<ShengsiDingjizhibiao>();
void Add(int std, string guige, string grade, double score, double piancha, double dacha, double erdu, double sandu, double qingjie, double jiejing)
{
list.Add(new ShengsiDingjizhibiao { Standard = std, Guige = guige, Grade = grade, GradeScore = score, Piancha = piancha, Dacha = dacha, Erdu = erdu, Sandu = sandu, Qingjie = qingjie, Jiejing = jiejing });
}
// ===== 厂标 (standard=0) =====
Add(0, "20/22", "A", 7.0, 2.0, 6.0, 6.0, 2.0, 90.0, 86.0);
Add(0, "20/22", "A50", 7.5, 1.85, 5.6, 6.0, 2.0, 91.5, 87.0);
Add(0, "20/22", "2A", 8.0, 1.7, 5.2, 5.0, 1.0, 93.0, 88.0);
Add(0, "20/22", "2A50", 8.5, 1.58, 4.8, 5.0, 0.0, 94.5, 89.0);
Add(0, "20/22", "3A", 9.0, 1.45, 4.4, 4.0, 0.0, 95.0, 90.0);
Add(0, "20/22", "3A50", 9.5, 1.33, 4.0, 4.0, 0.0, 96.0, 91.0);
Add(0, "20/22", "4A", 10.0, 1.2, 3.6, 3.0, 0.0, 96.5, 92.0);
Add(0, "20/22", "4A50", 10.5, 1.13, 3.3, 3.0, 0.0, 97.0, 93.0);
Add(0, "20/22", "5A", 11.0, 1.05, 3.0, 2.0, 0.0, 97.5, 94.0);
Add(0, "20/22", "5A50", 11.5, 0.98, 2.8, 2.0, 0.0, 97.8, 94.5);
Add(0, "20/22", "6A", 12.0, 0.9, 2.6, 1.0, 0.0, 98.0, 95.0);
Add(0, "27/29", "A", 7.0, 2.05, 6.1, 6.0, 0.0, 90.0, 86.0);
Add(0, "27/29", "A50", 7.5, 1.9, 5.6, 6.0, 0.0, 91.5, 87.0);
Add(0, "27/29", "2A", 8.0, 1.75, 5.1, 5.0, 0.0, 93.0, 88.0);
Add(0, "27/29", "2A50", 8.5, 1.65, 4.7, 5.0, 0.0, 94.5, 89.0);
Add(0, "27/29", "3A", 9.0, 1.55, 4.3, 4.0, 0.0, 95.0, 90.0);
Add(0, "27/29", "3A50", 9.5, 1.45, 4.0, 4.0, 0.0, 96.0, 91.0);
Add(0, "27/29", "4A", 10.0, 1.3, 3.7, 3.0, 0.0, 96.5, 92.0);
Add(0, "27/29", "4A50", 10.5, 1.25, 3.5, 3.0, 0.0, 97.0, 93.0);
Add(0, "27/29", "5A", 11.0, 1.15, 3.3, 2.0, 0.0, 97.5, 94.0);
Add(0, "27/29", "5A50", 11.5, 1.1, 3.1, 2.0, 0.0, 97.8, 94.5);
Add(0, "27/29", "6A", 12.0, 1.05, 3.0, 1.0, 0.0, 98.0, 95.0);
Add(0, "40/44", "A", 7.0, 2.85, 8.45, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "A50", 7.5, 2.69, 7.88, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "2A", 8.0, 2.53, 7.3, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "2A50", 8.5, 2.36, 6.79, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "3A", 9.0, 2.18, 6.28, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "3A50", 9.5, 2.04, 5.89, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "4A", 10.0, 1.9, 5.5, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "4A50", 10.5, 1.8, 5.2, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "5A", 11.0, 1.7, 4.9, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "5A50", 11.5, 1.6, 4.6, 0.0, 0.0, 0.0, 0.0);
Add(0, "40/44", "6A", 12.0, 1.5, 4.3, 0.0, 0.0, 0.0, 0.0);
Add(0, "20/22", "等外", 6.0, 9.99, 99.99, 100.0, 100.0, 0.0, 0.0);
Add(0, "27/29", "等外", 6.0, 9.99, 99.99, 100.0, 100.0, 0.0, 0.0);
Add(0, "40/44", "等外", 6.0, 9.99, 99.99, 100.0, 100.0, 0.0, 0.0);
// ===== 个人 (standard=2) =====
Add(2, "20/22", "A00", 7.0, 2.0, 6.0, 6.0, 2.0, 90.0, 86.0);
Add(2, "20/22", "A10", 7.1, 1.97, 5.92, 6.0, 2.0, 90.3, 86.2);
Add(2, "20/22", "A20", 7.2, 1.94, 5.84, 6.0, 2.0, 90.6, 86.4);
Add(2, "20/22", "A30", 7.3, 1.91, 5.76, 6.0, 2.0, 90.9, 86.6);
Add(2, "20/22", "A40", 7.4, 1.88, 5.68, 6.0, 2.0, 91.2, 86.8);
Add(2, "20/22", "A50", 7.5, 1.85, 5.6, 6.0, 2.0, 91.5, 87.0);
Add(2, "20/22", "A60", 7.6, 1.82, 5.52, 5.8, 1.8, 91.8, 87.2);
Add(2, "20/22", "A70", 7.7, 1.79, 5.44, 5.6, 1.6, 92.1, 87.4);
Add(2, "20/22", "A80", 7.8, 1.76, 5.36, 5.4, 1.4, 92.4, 87.6);
Add(2, "20/22", "A90", 7.9, 1.73, 5.28, 5.2, 1.2, 92.7, 87.8);
Add(2, "20/22", "2A00", 8.0, 1.7, 5.2, 5.0, 1.0, 93.0, 88.0);
Add(2, "20/22", "2A10", 8.1, 1.68, 5.12, 5.0, 0.8, 93.3, 88.2);
Add(2, "20/22", "2A20", 8.2, 1.65, 5.04, 5.0, 0.6, 93.6, 88.4);
Add(2, "20/22", "2A30", 8.3, 1.63, 4.96, 5.0, 0.4, 93.9, 88.6);
Add(2, "20/22", "2A40", 8.4, 1.6, 4.88, 5.0, 0.2, 94.2, 88.8);
Add(2, "20/22", "2A50", 8.5, 1.58, 4.8, 5.0, 0.0, 94.5, 89.0);
Add(2, "20/22", "2A60", 8.6, 1.55, 4.72, 4.8, 0.0, 94.6, 89.2);
Add(2, "20/22", "2A70", 8.7, 1.53, 4.64, 4.6, 0.0, 94.7, 89.4);
Add(2, "20/22", "2A80", 8.8, 1.5, 4.56, 4.4, 0.0, 94.8, 89.6);
Add(2, "20/22", "2A90", 8.9, 1.48, 4.48, 4.2, 0.0, 94.9, 89.8);
Add(2, "20/22", "3A00", 9.0, 1.45, 4.4, 4.0, 0.0, 95.0, 90.0);
Add(2, "20/22", "3A10", 9.1, 1.43, 4.32, 4.0, 0.0, 95.2, 90.2);
Add(2, "20/22", "3A20", 9.2, 1.4, 4.24, 4.0, 0.0, 95.4, 90.4);
Add(2, "20/22", "3A30", 9.3, 1.38, 4.16, 4.0, 0.0, 95.6, 90.6);
Add(2, "20/22", "3A40", 9.4, 1.35, 4.08, 4.0, 0.0, 95.8, 90.8);
Add(2, "20/22", "3A50", 9.5, 1.33, 4.0, 4.0, 0.0, 96.0, 91.0);
Add(2, "20/22", "3A60", 9.6, 1.3, 3.92, 3.8, 0.0, 96.1, 91.2);
Add(2, "20/22", "3A70", 9.7, 1.28, 3.84, 3.6, 0.0, 96.2, 91.4);
Add(2, "20/22", "3A80", 9.8, 1.25, 3.76, 3.4, 0.0, 96.3, 91.6);
Add(2, "20/22", "3A90", 9.9, 1.23, 3.68, 3.2, 0.0, 96.4, 91.8);
Add(2, "20/22", "4A00", 10.0, 1.2, 3.6, 3.0, 0.0, 96.5, 92.0);
Add(2, "20/22", "4A10", 10.1, 1.19, 3.54, 3.0, 0.0, 96.6, 92.2);
Add(2, "20/22", "4A20", 10.2, 1.17, 3.48, 3.0, 0.0, 96.7, 92.4);
Add(2, "20/22", "4A30", 10.3, 1.16, 3.42, 3.0, 0.0, 96.8, 92.6);
Add(2, "20/22", "4A40", 10.4, 1.14, 3.36, 3.0, 0.0, 96.9, 92.8);
Add(2, "20/22", "4A50", 10.5, 1.13, 3.3, 3.0, 0.0, 97.0, 93.0);
Add(2, "20/22", "4A60", 10.6, 1.11, 3.24, 2.8, 0.0, 97.1, 93.2);
Add(2, "20/22", "4A70", 10.7, 1.1, 3.18, 2.6, 0.0, 97.2, 93.4);
Add(2, "20/22", "4A80", 10.8, 1.08, 3.12, 2.4, 0.0, 97.3, 93.6);
Add(2, "20/22", "4A90", 10.9, 1.07, 3.06, 2.2, 0.0, 97.4, 93.8);
Add(2, "20/22", "5A00", 11.0, 1.05, 3.0, 2.0, 0.0, 97.5, 94.0);
Add(2, "20/22", "5A10", 11.1, 1.04, 2.96, 2.0, 0.0, 97.56, 94.1);
Add(2, "20/22", "5A20", 11.2, 1.03, 2.92, 2.0, 0.0, 97.62, 94.2);
Add(2, "20/22", "5A30", 11.3, 1.01, 2.88, 2.0, 0.0, 97.68, 94.3);
Add(2, "20/22", "5A40", 11.4, 0.99, 2.84, 2.0, 0.0, 97.74, 94.4);
Add(2, "20/22", "5A50", 11.5, 0.98, 2.8, 2.0, 0.0, 97.8, 94.5);
Add(2, "20/22", "5A60", 11.6, 0.96, 2.76, 1.8, 0.0, 97.84, 94.6);
Add(2, "20/22", "5A70", 11.7, 0.95, 2.72, 1.6, 0.0, 97.88, 94.7);
Add(2, "20/22", "5A80", 11.8, 0.93, 2.68, 1.4, 0.0, 97.92, 94.8);
Add(2, "20/22", "5A90", 11.9, 0.92, 2.64, 1.2, 0.0, 97.96, 94.9);
Add(2, "20/22", "6A00", 12.0, 0.9, 2.6, 1.0, 0.0, 98.0, 95.0);
Add(2, "27/29", "A00", 7.0, 2.05, 6.0, 12.0, 0.0, 90.0, 86.0);
Add(2, "27/29", "A10", 7.1, 2.02, 5.9, 11.6, 0.0, 90.3, 86.2);
Add(2, "27/29", "A20", 7.2, 1.99, 5.8, 11.2, 0.0, 90.6, 86.4);
Add(2, "27/29", "A30", 7.3, 1.96, 5.7, 10.8, 0.0, 90.9, 86.6);
Add(2, "27/29", "A40", 7.4, 1.93, 5.6, 10.4, 0.0, 91.2, 86.8);
Add(2, "27/29", "A50", 7.5, 1.9, 5.5, 10.0, 0.0, 91.5, 87.0);
Add(2, "27/29", "A60", 7.6, 1.87, 5.4, 9.6, 0.0, 91.8, 87.2);
Add(2, "27/29", "A70", 7.7, 1.84, 5.3, 9.2, 0.0, 92.1, 87.4);
Add(2, "27/29", "A80", 7.8, 1.81, 5.2, 8.8, 0.0, 92.4, 87.6);
Add(2, "27/29", "A90", 7.9, 1.78, 5.1, 8.4, 0.0, 92.7, 87.8);
Add(2, "27/29", "2A00", 8.0, 1.75, 5.0, 8.0, 0.0, 93.0, 88.0);
Add(2, "27/29", "2A10", 8.1, 1.73, 4.92, 7.7, 0.0, 93.2, 88.2);
Add(2, "27/29", "2A20", 8.2, 1.69, 4.76, 7.1, 0.0, 93.6, 88.6);
Add(2, "27/29", "2A30", 8.3, 1.67, 4.68, 6.8, 0.0, 93.8, 88.8);
Add(2, "27/29", "2A40", 8.4, 1.65, 4.6, 6.5, 0.0, 94.0, 89.0);
Add(2, "27/29", "2A50", 8.5, 1.63, 4.52, 6.2, 0.0, 94.2, 89.2);
Add(2, "27/29", "2A60", 8.6, 1.61, 4.44, 5.9, 0.0, 94.4, 89.4);
Add(2, "27/29", "2A70", 8.7, 1.59, 4.36, 5.6, 0.0, 94.6, 89.6);
Add(2, "27/29", "2A80", 8.8, 1.57, 4.28, 5.3, 0.0, 94.8, 89.8);
Add(2, "27/29", "2A90", 8.9, 1.55, 4.2, 5.0, 0.0, 95.0, 90.0);
Add(2, "27/29", "3A00", 9.0, 1.53, 4.14, 4.8, 0.0, 95.15, 90.2);
Add(2, "27/29", "3A10", 9.1, 1.51, 4.08, 4.6, 0.0, 95.3, 90.4);
Add(2, "27/29", "3A20", 9.2, 1.49, 4.02, 4.4, 0.0, 95.45, 90.6);
Add(2, "27/29", "3A30", 9.3, 1.47, 3.96, 4.2, 0.0, 95.6, 90.8);
Add(2, "27/29", "3A40", 9.4, 1.45, 3.9, 4.0, 0.0, 95.75, 91.0);
Add(2, "27/29", "3A50", 9.5, 1.43, 3.84, 3.8, 0.0, 95.9, 91.2);
Add(2, "27/29", "3A60", 9.6, 1.41, 3.78, 3.6, 0.0, 96.05, 91.4);
Add(2, "27/29", "3A70", 9.7, 1.39, 3.72, 3.4, 0.0, 96.2, 91.6);
Add(2, "27/29", "3A80", 9.8, 1.37, 3.66, 3.2, 0.0, 96.35, 91.8);
Add(2, "27/29", "3A90", 9.9, 1.35, 3.6, 3.0, 0.0, 96.5, 92.0);
Add(2, "27/29", "4A00", 10.0, 1.33, 3.66, 2.85, 0.0, 96.6, 92.2);
Add(2, "27/29", "4A10", 10.1, 1.31, 3.62, 2.7, 0.0, 96.7, 92.4);
Add(2, "27/29", "4A20", 10.2, 1.29, 3.58, 2.55, 0.0, 96.8, 92.6);
Add(2, "27/29", "4A30", 10.3, 1.27, 3.54, 2.4, 0.0, 96.9, 92.8);
Add(2, "27/29", "4A40", 10.4, 1.25, 3.5, 2.25, 0.0, 97.0, 93.0);
Add(2, "27/29", "4A50", 10.5, 1.23, 3.46, 2.1, 0.0, 97.1, 93.2);
Add(2, "27/29", "4A60", 10.6, 1.21, 3.42, 1.95, 0.0, 97.2, 93.4);
Add(2, "27/29", "4A70", 10.7, 1.19, 3.38, 1.8, 0.0, 97.3, 93.6);
Add(2, "27/29", "4A80", 10.8, 1.17, 3.34, 1.65, 0.0, 97.4, 93.8);
Add(2, "27/29", "4A90", 10.9, 1.15, 3.3, 1.5, 0.0, 97.5, 94.0);
Add(2, "27/29", "5A00", 11.0, 1.14, 3.27, 1.45, 0.0, 97.55, 94.1);
Add(2, "27/29", "5A10", 11.1, 1.13, 3.24, 1.4, 0.0, 97.6, 94.2);
Add(2, "27/29", "5A20", 11.2, 1.12, 3.21, 1.35, 0.0, 97.65, 94.3);
Add(2, "27/29", "5A30", 11.3, 1.11, 3.18, 1.3, 0.0, 97.7, 94.4);
Add(2, "27/29", "5A40", 11.4, 1.1, 3.15, 1.25, 0.0, 97.75, 94.5);
Add(2, "27/29", "5A50", 11.5, 1.09, 3.12, 1.2, 0.0, 97.8, 94.6);
Add(2, "27/29", "5A60", 11.6, 1.08, 3.09, 1.15, 0.0, 97.85, 94.7);
Add(2, "27/29", "5A70", 11.7, 1.07, 3.06, 1.1, 0.0, 97.9, 94.8);
Add(2, "27/29", "5A80", 11.8, 1.06, 3.03, 1.05, 0.0, 97.95, 94.9);
Add(2, "27/29", "5A90", 11.9, 1.05, 3.0, 1.0, 0.0, 98.0, 95.0);
Add(2, "27/29", "6A00", 12.0, 1.05, 3.0, 1.0, 0.0, 98.0, 95.0);
Add(2, "40/44", "A00", 7.0, 2.6, 7.55, 8.0, 0.0, 90.0, 86.0);
Add(2, "40/44", "A10", 7.1, 2.57, 7.43, 7.7, 0.0, 90.3, 86.2);
Add(2, "40/44", "A20", 7.2, 2.53, 7.31, 7.4, 0.0, 90.6, 86.4);
Add(2, "40/44", "A30", 7.3, 2.5, 7.19, 7.1, 0.0, 90.9, 86.6);
Add(2, "40/44", "A40", 7.4, 2.46, 7.07, 6.8, 0.0, 91.2, 86.8);
Add(2, "40/44", "A50", 7.5, 2.43, 6.95, 6.5, 0.0, 91.5, 87.0);
Add(2, "40/44", "A60", 7.6, 2.39, 6.83, 6.2, 0.0, 91.8, 87.2);
Add(2, "40/44", "A70", 7.7, 2.36, 6.71, 5.9, 0.0, 92.1, 87.4);
Add(2, "40/44", "A80", 7.8, 2.32, 6.59, 5.6, 0.0, 92.4, 87.6);
Add(2, "40/44", "A90", 7.9, 2.29, 6.47, 5.3, 0.0, 92.7, 87.8);
Add(2, "40/44", "2A00", 8.0, 2.25, 6.35, 5.0, 0.0, 93.0, 88.0);
Add(2, "40/44", "2A10", 8.1, 2.22, 6.24, 4.8, 0.0, 93.2, 88.2);
Add(2, "40/44", "2A20", 8.2, 2.18, 6.13, 4.6, 0.0, 93.4, 88.4);
Add(2, "40/44", "2A30", 8.3, 2.15, 6.02, 4.4, 0.0, 93.6, 88.6);
Add(2, "40/44", "2A40", 8.4, 2.11, 5.91, 4.2, 0.0, 93.8, 88.8);
Add(2, "40/44", "2A50", 8.5, 2.08, 5.8, 4.0, 0.0, 94.0, 89.0);
Add(2, "40/44", "2A60", 8.6, 2.04, 5.69, 3.8, 0.0, 94.2, 89.2);
Add(2, "40/44", "2A70", 8.7, 2.01, 5.58, 3.6, 0.0, 94.4, 89.4);
Add(2, "40/44", "2A80", 8.8, 1.97, 5.47, 3.4, 0.0, 94.6, 89.6);
Add(2, "40/44", "2A90", 8.9, 1.94, 5.36, 3.2, 0.0, 94.8, 89.8);
Add(2, "40/44", "3A00", 9.0, 1.9, 5.25, 3.0, 0.0, 95.0, 90.0);
Add(2, "40/44", "3A10", 9.1, 1.87, 5.16, 1.95, 0.0, 95.15, 90.2);
Add(2, "40/44", "3A20", 9.2, 1.83, 5.06, 1.9, 0.0, 95.3, 90.4);
Add(2, "40/44", "3A30", 9.3, 1.8, 4.97, 1.85, 0.0, 95.45, 90.6);
Add(2, "40/44", "3A40", 9.4, 1.76, 4.87, 1.8, 0.0, 95.6, 90.8);
Add(2, "40/44", "3A50", 9.5, 1.73, 4.78, 1.75, 0.0, 95.75, 91.0);
Add(2, "40/44", "3A60", 9.6, 1.69, 4.68, 1.7, 0.0, 95.9, 91.2);
Add(2, "40/44", "3A70", 9.7, 1.66, 4.59, 1.65, 0.0, 96.05, 91.4);
Add(2, "40/44", "3A80", 9.8, 1.62, 4.49, 1.6, 0.0, 96.2, 91.6);
Add(2, "40/44", "3A90", 9.9, 1.59, 4.4, 1.55, 0.0, 96.35, 91.8);
Add(2, "40/44", "4A00", 10.0, 1.55, 4.3, 1.5, 0.0, 96.5, 92.0);
Add(2, "40/44", "4A10", 10.1, 1.53, 4.24, 1.45, 0.0, 96.6, 92.2);
Add(2, "40/44", "4A20", 10.2, 1.51, 4.18, 1.4, 0.0, 96.7, 92.4);
Add(2, "40/44", "4A30", 10.3, 1.49, 4.12, 1.35, 0.0, 96.8, 92.6);
Add(2, "40/44", "4A40", 10.4, 1.47, 4.06, 1.3, 0.0, 96.9, 92.8);
Add(2, "40/44", "4A50", 10.5, 1.45, 4.0, 1.25, 0.0, 97.0, 93.0);
Add(2, "40/44", "4A60", 10.6, 1.43, 3.94, 1.2, 0.0, 97.1, 93.2);
Add(2, "40/44", "4A70", 10.7, 1.41, 3.88, 1.15, 0.0, 97.2, 93.4);
Add(2, "40/44", "4A80", 10.8, 1.39, 3.82, 1.1, 0.0, 97.3, 93.6);
Add(2, "40/44", "4A90", 10.9, 1.37, 3.76, 1.05, 0.0, 97.4, 93.8);
Add(2, "40/44", "5A00", 11.0, 1.35, 3.7, 1.0, 0.0, 97.5, 94.0);
Add(2, "40/44", "5A10", 11.1, 1.33, 3.64, 0.0, 0.0, 97.55, 94.1);
Add(2, "40/44", "5A20", 11.2, 1.31, 3.58, 0.0, 0.0, 97.6, 94.2);
Add(2, "40/44", "5A30", 11.3, 1.29, 3.52, 0.0, 0.0, 97.65, 94.3);
Add(2, "40/44", "5A40", 11.4, 1.27, 3.46, 0.0, 0.0, 97.7, 94.4);
Add(2, "40/44", "5A50", 11.5, 1.25, 3.4, 0.0, 0.0, 97.75, 94.5);
Add(2, "40/44", "5A60", 11.6, 1.23, 3.34, 0.0, 0.0, 97.8, 94.6);
Add(2, "40/44", "5A70", 11.7, 1.21, 3.28, 0.0, 0.0, 97.85, 94.7);
Add(2, "40/44", "5A80", 11.8, 1.19, 3.22, 0.0, 0.0, 97.9, 94.8);
Add(2, "40/44", "5A90", 11.9, 1.17, 3.16, 0.0, 0.0, 97.95, 94.9);
Add(2, "40/44", "6A00", 12.0, 1.15, 3.1, 0.0, 0.0, 98.0, 95.0);
Add(2, "20/22", "等外", 6.0, 9.99, 99.99, 100.0, 100.0, 0.0, 0.0);
Add(2, "27/29", "等外", 6.0, 9.99, 99.99, 100.0, 100.0, 0.0, 0.0);
Add(2, "40/44", "等外", 6.0, 9.99, 99.99, 100.0, 100.0, 0.0, 0.0);
fsql.Insert(list).ExecuteAffrows();
}
}
@@ -0,0 +1,509 @@
using System.Data;
using FreeSql;
using F9WebAiTest.Application.Interfaces.SnowflakeID;
using F9WebAiTest.Domain.Common;
using F9WebAiTest.Domain.Entities;
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 SysPermission = F9WebAiTest.Domain.Entities.SYS.RBAC.Permission;
using SysRolePermission = F9WebAiTest.Domain.Entities.SYS.RBAC.RolePermission;
namespace F9WebAiTest.Infrastructure.Data;
public static class DbSeeder
{
public static void Seed(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
// 1. 建表(CodeFirst SyncStructure,增量同步,兼容旧库)
SyncStructure(fsql);
// 2. 默认角色
if (!fsql.Select<Role>().Any())
{
fsql.Insert(new Role { Name = "超级管理员", Code = "admin", Description = "拥有所有权限", Sort = 1 }).ExecuteAffrows();
fsql.Insert(new Role { Name = "普通用户", Code = "user", Description = "普通员工", Sort = 2 }).ExecuteAffrows();
}
// 3. 默认菜单(系统管理)
if (!fsql.Select<Menu>().Any())
{
var systemId = InsertAndGetId(fsql, new Menu { Name = "系统管理", Type = "directory", Path = "/system", Icon = "Setting", Sort = 1 });
var deptId = InsertAndGetId(fsql, new Menu { Name = "部门管理", Type = "menu", Path = "/system/department", Component = "system/department/index", Icon = "OfficeBuilding", Permission = "system:department:list", Sort = 1, ParentId = systemId });
var empId = InsertAndGetId(fsql, new Menu { Name = "职工管理", Type = "menu", Path = "/system/employee", Component = "system/employee/index", Icon = "User", Permission = "system:employee:list", Sort = 2, ParentId = systemId });
var roleId = InsertAndGetId(fsql, new Menu { Name = "角色管理", Type = "menu", Path = "/system/role", Component = "system/role/index", Icon = "UserFilled", Permission = "system:role:list", Sort = 3, ParentId = systemId });
var menuId = InsertAndGetId(fsql, new Menu { Name = "菜单管理", Type = "menu", Path = "/system/menu", Component = "system/menu/index", Icon = "Menu", Permission = "system:menu:list", Sort = 4, ParentId = systemId });
var logId = InsertAndGetId(fsql, new Menu { Name = "操作日志", Type = "menu", Path = "/system/log", Component = "system/log/index", Icon = "Document", Permission = "system:log:list", Sort = 5, ParentId = systemId });
fsql.Insert(new Menu[]
{
new Menu { Name = "部门操作", Type = "button", Permission = "system:department:btn", Sort = 1, ParentId = deptId },
new Menu { Name = "职工操作", Type = "button", Permission = "system:employee:btn", Sort = 1, ParentId = empId },
new Menu { Name = "角色操作", Type = "button", Permission = "system:role:btn", Sort = 1, ParentId = roleId },
new Menu { Name = "菜单操作", Type = "button", Permission = "system:menu:btn", Sort = 1, ParentId = menuId },
}).ExecuteAffrows();
}
// 4. 考勤菜单(增量)
SeedAttendanceMenus(fsql);
// 5. 业务基础数据(部门树 + 机组车台 + 庄口 + 规格 + 定级指标 + 菜单)
BusinessSeedData.Seed(fsql);
// 6. 通知:消息类型种子 + 菜单
SeedNotificationData(fsql, snowflake);
// 6.5 数据迁移:旧 RBAC 表 → 新 DDD RBAC 表(先迁移,确保 admin 角色/用户已在新表)
MigrateRbacData(fsql);
// 6.6 F9 风格 RBAC 菜单(用户/角色/菜单/部门管理,写入新 sys_rbac_menus 表)
SeedSysRbacMenus(fsql, snowflake);
// 6.7 为菜单创建权限单元(Permission),并修正旧菜单权限关联(统一权限模型)
FixMenuPermissions(fsql, snowflake);
// 7. 管理员账号(幂等)
var admin = fsql.Select<Employee>().Where(e => e.Username == "admin").First();
if (admin == null)
{
var dept = fsql.Select<Department>().Where(d => d.Name == "主干运维").First()
?? fsql.Select<Department>().First();
var adminId = InsertAndGetId(fsql, new Employee
{
Username = "admin",
Password = BCrypt.Net.BCrypt.HashPassword("123456"),
RealName = "系统管理员",
Nickname = "管理员",
DepartmentId = dept.Id,
Email = "admin@company.com",
Phone = "13800000000",
Status = 1
});
admin = fsql.Select<Employee>().Where(e => e.Id == adminId).First();
}
// 8. admin 关联 admin 角色
var adminRole = fsql.Select<Role>().Where(r => r.Code == "admin").First();
if (!fsql.Select<EmployeeRole>().Any(er => er.EmployeeId == admin.Id && er.RoleId == adminRole.Id))
{
fsql.Insert(new EmployeeRole { EmployeeId = admin.Id, RoleId = adminRole.Id }).ExecuteAffrows();
}
// 9. admin 角色分配所有菜单(幂等补充)
var allMenus = fsql.Select<Menu>().ToList();
foreach (var m in allMenus)
{
if (!fsql.Select<RoleMenu>().Any(rm => rm.RoleId == adminRole.Id && rm.MenuId == m.Id))
{
fsql.Insert(new RoleMenu { RoleId = adminRole.Id, MenuId = m.Id }).ExecuteAffrows();
}
}
}
/// <summary>CodeFirst 建表(新表建表,旧表同步失败则跳过)+ 旧库加列兜底</summary>
private static void SyncStructure(IFreeSql fsql)
{
// 扫描 BaseEntity(旧)与 Entity(新 DDD 基类)两类实体的具体子类建表
var entityTypes = typeof(BaseEntity).Assembly.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract &&
(t.IsSubclassOf(typeof(BaseEntity)) || t.IsSubclassOf(typeof(Entity))));
foreach (var t in entityTypes)
{
try
{
fsql.CodeFirst.SyncStructure(t);
}
catch (Exception ex)
{
// 旧表同步失败(如唯一索引与历史数据冲突),跳过,保持旧库兼容
Console.WriteLine($"[DbSeeder] 表 {t.Name} 结构同步跳过:{ex.Message}");
}
}
// 旧库加列兜底(SyncStructure 不会为已有表加列)
EnsureColumn(fsql, "LeaveRequests", "CurrentOrderNo", "INTEGER NOT NULL DEFAULT 1");
EnsureColumn(fsql, "NotificationTypes", "Category", "INTEGER NOT NULL DEFAULT 0");
EnsureColumn(fsql, "NotificationTypes", "Icon", "TEXT NOT NULL DEFAULT ''");
EnsureColumn(fsql, "NotificationTypes", "RouteTemplate", "TEXT NOT NULL DEFAULT ''");
EnsureColumn(fsql, "NotificationMessages", "Category", "INTEGER NOT NULL DEFAULT 0");
EnsureColumn(fsql, "NotificationMessages", "RoutePath", "TEXT NOT NULL DEFAULT ''");
}
/// <summary>为已有表补加列(列已存在则忽略)</summary>
private static void EnsureColumn(IFreeSql fsql, string table, string column, string definition)
{
try
{
fsql.Ado.ExecuteNonQuery($"ALTER TABLE \"{table}\" ADD COLUMN \"{column}\" {definition};");
}
catch
{
// 列已存在,忽略
}
}
/// <summary>插入并返回自增主键 ID(SQLite 用 last_insert_rowid 可靠获取)</summary>
public static long InsertAndGetId<T>(IFreeSql fsql, T entity) where T : BaseEntity
{
fsql.Insert(entity).ExecuteAffrows();
return Convert.ToInt64(fsql.Ado.ExecuteScalar("SELECT last_insert_rowid();"));
}
/// <summary>通知种子:消息类型 + 消息中心菜单</summary>
private static void SeedNotificationData(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
// 消息类型:发现特野
if (!fsql.Select<NotificationType>().Any(t => t.Code == "TeyeFound"))
{
fsql.Insert(new NotificationType
{
Code = "TeyeFound", Name = "发现特野", Description = "纤度检验发现特野时自动推送提醒",
RequiredPermission = "", IsActive = true, CreatedBy = 0, Sort = 1,
Category = NotificationCategory.Notification, Icon = "Warning", RouteTemplate = "/prod/xdjy"
}).ExecuteAffrows();
}
// 消息类型:发现特大糙
if (!fsql.Select<NotificationType>().Any(t => t.Code == "TdcFound"))
{
fsql.Insert(new NotificationType
{
Code = "TdcFound", Name = "发现特大糙", Description = "黑板检验发现特大糙时自动推送提醒",
RequiredPermission = "", IsActive = true, CreatedBy = 0, Sort = 2,
Category = NotificationCategory.Notification, Icon = "Warning", RouteTemplate = "/prod/hbjy"
}).ExecuteAffrows();
}
// 消息类型:请假审批(订阅权限用独立码,避免与业务按钮权限冲突)
if (!fsql.Select<NotificationType>().Any(t => t.Code == "LeaveApproval"))
{
fsql.Insert(new NotificationType
{
Code = "LeaveApproval", Name = "请假审批", Description = "员工提交请假申请后,推送待办给审批人",
RequiredPermission = "notification:subscribe:leaveapproval", IsActive = true, CreatedBy = 0, Sort = 3,
Category = NotificationCategory.Todo, Icon = "Checked", RouteTemplate = "/attendance/approve?leaveId={businessId}"
}).ExecuteAffrows();
}
// 消息类型:请假结果通知
if (!fsql.Select<NotificationType>().Any(t => t.Code == "LeaveResult"))
{
fsql.Insert(new NotificationType
{
Code = "LeaveResult", Name = "请假结果通知", Description = "请假审批完成后通知申请人结果",
RequiredPermission = "", IsActive = true, CreatedBy = 0, Sort = 4,
Category = NotificationCategory.Notification, Icon = "Message", RouteTemplate = "/attendance/my"
}).ExecuteAffrows();
}
// 消息类型:广播通知(有权限的用户主动发送的广播,推送给所有订阅者)
if (!fsql.Select<NotificationType>().Any(t => t.Code == "Broadcast"))
{
fsql.Insert(new NotificationType
{
Code = "Broadcast", Name = "广播通知", Description = "用户发送的广播通知,推送给所有订阅该类型的用户",
RequiredPermission = "", IsActive = true, CreatedBy = 0, Sort = 5,
Category = NotificationCategory.Announcement, Icon = "Bell", RouteTemplate = ""
}).ExecuteAffrows();
}
// 广播发送权限单元(ResourceType=操作,Code=notification:broadcast,admin 自动拥有,普通用户可在角色管理分配)
var broadcastPerm = fsql.Select<SysPermission>()
.Where(p => p.Code == "notification:broadcast").First();
if (broadcastPerm == null)
{
var perm = new SysPermission(snowflake.CreateId(), Permission_Type_Enum.Enable, Resource_Type_Enum.操作, "broadcast", 0);
perm.SetCode("notification:broadcast");
fsql.Insert(perm).ExecuteAffrows();
}
// 菜单:消息中心
var notiDirId = fsql.Select<Menu>().Where(m => m.Path == "/notification").First()?.Id ?? 0;
if (notiDirId == 0)
{
notiDirId = InsertAndGetId(fsql, new Menu { Name = "消息中心", Type = "directory", Path = "/notification", Icon = "Bell", Sort = 5 });
}
AddNotificationMenu(fsql, notiDirId, "我的消息", "/notification/messages", "notification/messages/index", "Message", "notification:messages:list", 1);
AddNotificationMenu(fsql, notiDirId, "消息订阅", "/notification/subscribe", "notification/subscribe/index", "BellFilled", "notification:subscribe:list", 2);
AddNotificationMenu(fsql, notiDirId, "消息类型管理", "/notification/type", "notification/type/index", "SetUp", "notification:type:list", 3);
// 清理历史遗留:发现特野/发现特大糙 改为「所有人可订阅」
foreach (var (code, oldPerm) in new[] { ("TeyeFound", "notification:subscribe:foundteye"), ("TdcFound", "notification:subscribe:foundtedacao") })
{
var t = fsql.Select<NotificationType>().Where(x => x.Code == code).First();
if (t == null) continue;
// 1. RequiredPermission 改为空(所有人可订阅)
if (!string.IsNullOrEmpty(t.RequiredPermission))
{
t.RequiredPermission = "";
fsql.Update<NotificationType>().SetSource(t).ExecuteAffrows();
}
// 2. 删除订阅权限单元及其角色关联(新 Permission 表)
var perm = fsql.Select<SysPermission>()
.Where(p => p.ResourceType == Resource_Type_Enum.消息订阅 && p.ResourceId == t.Id).First();
if (perm != null)
{
fsql.Delete<SysRolePermission>().Where(rp => rp.PermissionId == perm.Id).ExecuteAffrows();
fsql.Delete<SysPermission>().Where(p => p.Id == perm.Id).ExecuteAffrows();
}
// 3. 删除历史遗留的旧"订阅按钮"菜单及其角色关联(新表 sys_rbac_menus + 旧表 Menus)
fsql.Ado.ExecuteNonQuery($@"
DELETE FROM sys_rbac_role_permissions WHERE permission_id IN
(SELECT id FROM sys_rbac_menus WHERE permission = '{oldPerm}');
DELETE FROM sys_rbac_menus WHERE permission = '{oldPerm}';
DELETE FROM RoleMenus WHERE MenuId IN (SELECT Id FROM Menus WHERE Permission = '{oldPerm}');
DELETE FROM Menus WHERE Permission = '{oldPerm}';");
}
// 清理所有旧的"订阅按钮"菜单(已被 Permission 表的消息订阅权限替代,避免与消息订阅权限重复冗余)
fsql.Ado.ExecuteNonQuery(@"
DELETE FROM sys_rbac_role_permissions WHERE permission_id IN
(SELECT id FROM sys_rbac_menus WHERE name LIKE '订阅:%' AND menu_type = 0);
DELETE FROM sys_rbac_menus WHERE name LIKE '订阅:%' AND menu_type = 0;
DELETE FROM RoleMenus WHERE MenuId IN (SELECT Id FROM Menus WHERE Name LIKE '订阅:%' AND Type = 'button');
DELETE FROM Menus WHERE Name LIKE '订阅:%' AND Type = 'button';");
// 清理 RequiredPermission 为空的消息类型的订阅权限(历史遗留,所有人可订阅无需权限单元)
foreach (var t in fsql.Select<NotificationType>().Where(x => x.RequiredPermission == "").ToList())
{
var perm = fsql.Select<SysPermission>()
.Where(p => p.ResourceType == Resource_Type_Enum.消息订阅 && p.ResourceId == t.Id).First();
if (perm != null)
{
fsql.Delete<SysRolePermission>().Where(rp => rp.PermissionId == perm.Id).ExecuteAffrows();
fsql.Delete<SysPermission>().Where(p => p.Id == perm.Id).ExecuteAffrows();
}
}
// 同步订阅权限到 RBAC 权限单元(ResourceType=消息订阅,Code=RequiredPermission)
foreach (var t in fsql.Select<NotificationType>().ToList())
{
if (string.IsNullOrEmpty(t.RequiredPermission)) continue;
var existPerm = fsql.Select<SysPermission>()
.Where(p => p.ResourceType == Resource_Type_Enum.消息订阅 && p.ResourceId == t.Id).First();
if (existPerm == null)
{
var perm = new SysPermission(snowflake.CreateId(), Permission_Type_Enum.Visble, Resource_Type_Enum.消息订阅, t.Code, t.Id);
perm.SetCode(t.RequiredPermission);
fsql.Insert(perm).ExecuteAffrows();
}
else if (existPerm.Code != t.RequiredPermission)
{
// 修正 Code 为业务权限码(覆盖旧的自动生成码)
existPerm.SetCode(t.RequiredPermission);
fsql.Update<SysPermission>().SetSource(existPerm).ExecuteAffrows();
}
}
// admin 角色分配消息中心菜单权限
var adminRole = fsql.Select<Role>().Where(r => r.Code == "admin").First();
if (adminRole != null)
{
var notiMenus = fsql.Select<Menu>().Where(m => m.Path.StartsWith("/notification")).ToList();
foreach (var m in notiMenus)
{
if (!fsql.Select<RoleMenu>().Any(rm => rm.RoleId == adminRole.Id && rm.MenuId == m.Id))
fsql.Insert(new RoleMenu { RoleId = adminRole.Id, MenuId = m.Id }).ExecuteAffrows();
}
}
}
private static void AddNotificationMenu(IFreeSql fsql, long parentId, string name, string path, string component, string icon, string permission, int sort)
{
if (!fsql.Select<Menu>().Any(m => m.Path == path))
{
fsql.Insert(new Menu { ParentId = parentId, Name = name, Type = "menu", Path = path, Component = component, Icon = icon, Permission = permission, Sort = sort }).ExecuteAffrows();
}
}
private static void SeedAttendanceMenus(IFreeSql fsql)
{
var attDirId = fsql.Select<Menu>().Where(m => m.Path == "/attendance").First()?.Id ?? 0;
if (attDirId == 0)
{
attDirId = InsertAndGetId(fsql, new Menu { Name = "考勤管理", Type = "directory", Path = "/attendance", Icon = "Clock", Sort = 2 });
}
void AddMenu(string name, string path, string component, string icon, string permission, int sort)
{
if (!fsql.Select<Menu>().Any(m => m.Path == path))
{
fsql.Insert(new Menu { Name = name, Type = "menu", Path = path, Component = component, Icon = icon, Permission = permission, Sort = sort, ParentId = attDirId }).ExecuteAffrows();
}
}
AddMenu("考勤打卡", "/attendance/punch", "attendance/punch/index", "AlarmClock", "attendance:punch:list", 1);
AddMenu("我的考勤", "/attendance/my", "attendance/my/index", "Calendar", "attendance:my:list", 2);
AddMenu("请假申请", "/attendance/leave", "attendance/leave/index", "Suitcase", "attendance:leave:list", 3);
AddMenu("考勤记录", "/attendance/records", "attendance/records/index", "List", "attendance:records:list", 4);
AddMenu("请假审批", "/attendance/approve", "attendance/approve/index", "Checked", "attendance:approve:list", 5);
void AddButton(string menuPath, string name, string permission)
{
var menu = fsql.Select<Menu>().Where(m => m.Path == menuPath).First();
if (menu != null && !fsql.Select<Menu>().Any(m => m.Permission == permission))
{
fsql.Insert(new Menu { Name = name, Type = "button", Permission = permission, Sort = 1, ParentId = menu.Id }).ExecuteAffrows();
}
}
AddButton("/attendance/punch", "打卡操作", "attendance:punch:btn");
AddButton("/attendance/leave", "请假操作", "attendance:leave:btn");
AddButton("/attendance/approve", "审批操作", "attendance:approve:btn");
var adminRole = fsql.Select<Role>().Where(r => r.Code == "admin").First();
if (adminRole != null)
{
var attMenus = fsql.Select<Menu>().Where(m => m.Path.StartsWith("/attendance") || m.Permission.StartsWith("attendance:")).ToList();
foreach (var m in attMenus)
{
if (!fsql.Select<RoleMenu>().Any(rm => rm.RoleId == adminRole.Id && rm.MenuId == m.Id))
fsql.Insert(new RoleMenu { RoleId = adminRole.Id, MenuId = m.Id }).ExecuteAffrows();
}
}
}
/// <summary>数据迁移:旧 RBAC 表 → 新 DDD RBAC 表(幂等,仅迁移尚不存在的记录)</summary>
private static void MigrateRbacData(IFreeSql fsql)
{
try
{
// 1. 部门:Departments → sys_departments
fsql.Ado.ExecuteNonQuery(@"
INSERT INTO sys_departments (id, code, name, parent_id, manage_type, duty_type, description, is_active, sort_order, created_by, created_at, update_by, updated_at, is_deleted)
SELECT Id, COALESCE(Code, ''), Name, COALESCE(ParentId, 0), 10, 5, '', Status, Sort, '', COALESCE(CreatedAt, datetime('now')), '', UpdatedAt, IsDeleted
FROM Departments WHERE Id NOT IN (SELECT id FROM sys_departments);");
// 2. 角色:Roles → sys_rbac_roles
fsql.Ado.ExecuteNonQuery(@"
INSERT INTO sys_rbac_roles (id, name, code, sort_order, description, is_active, created_by, created_at, update_by, updated_at, is_deleted)
SELECT Id, Name, Code, Sort, COALESCE(Description, ''), Status, '', COALESCE(CreatedAt, datetime('now')), '', UpdatedAt, IsDeleted
FROM Roles WHERE Id NOT IN (SELECT id FROM sys_rbac_roles);");
// 3. 菜单:Menus → sys_rbac_menus
fsql.Ado.ExecuteNonQuery(@"
INSERT INTO sys_rbac_menus (id, icon_svg, code, name, menu_type, assembly_name, type_full_name, parent_id, level, is_active, sort_order, path, component, permission, created_by, created_at, update_by, updated_at, is_deleted)
SELECT Id, COALESCE(Icon, ''), '', Name, CASE WHEN Type = 'directory' THEN 1 WHEN Type = 'menu' THEN 2 ELSE 0 END, '', '', COALESCE(ParentId, 0), 1, Status, Sort, COALESCE(Path, ''), COALESCE(Component, ''), COALESCE(Permission, ''), '', COALESCE(CreatedAt, datetime('now')), '', UpdatedAt, IsDeleted
FROM Menus WHERE Id NOT IN (SELECT id FROM sys_rbac_menus);");
// 4. 用户:Employees → sys_rbac_users
fsql.Ado.ExecuteNonQuery(@"
INSERT INTO sys_rbac_users (id, department_id, user_name, phone_number, login_name, password_hash, is_active, sort_order, lastlogin_at, nickname, avatar, email, gender, created_by, created_at, update_by, updated_at, is_deleted)
SELECT Id, DepartmentId, RealName, COALESCE(Phone, ''), Username, Password, Status, 0, NULL, COALESCE(Nickname, ''), COALESCE(Avatar, ''), COALESCE(Email, ''), COALESCE(Gender, '男'), '', COALESCE(CreatedAt, datetime('now')), '', UpdatedAt, IsDeleted
FROM Employees WHERE Id NOT IN (SELECT id FROM sys_rbac_users);");
// 5. 用户角色:EmployeeRoles → sys_rbac_user_roles
fsql.Ado.ExecuteNonQuery(@"
INSERT INTO sys_rbac_user_roles (id, user_id, role_id, created_by, created_at, update_by, updated_at, is_deleted)
SELECT Id, EmployeeId, RoleId, '', COALESCE(CreatedAt, datetime('now')), '', UpdatedAt, IsDeleted
FROM EmployeeRoles WHERE Id NOT IN (SELECT id FROM sys_rbac_user_roles);");
// 6. 角色权限:RoleMenus → sys_rbac_role_permissions
fsql.Ado.ExecuteNonQuery(@"
INSERT INTO sys_rbac_role_permissions (id, role_id, permission_id, created_by, created_at, update_by, updated_at, is_deleted)
SELECT Id, RoleId, MenuId, '', COALESCE(CreatedAt, datetime('now')), '', UpdatedAt, IsDeleted
FROM RoleMenus WHERE Id NOT IN (SELECT id FROM sys_rbac_role_permissions);");
Console.WriteLine("[DbSeeder] RBAC 数据迁移完成");
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] RBAC 数据迁移跳过:{ex.Message}");
}
}
/// <summary>F9 风格 RBAC 前端菜单种子(写入新 sys_rbac_menus 表,驱动前端导航)</summary>
private static void SeedSysRbacMenus(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
try
{
// 删除旧"系统管理"菜单(/system/*,对接已下线的旧接口),仅保留新的 /sys 管理菜单
fsql.Ado.ExecuteNonQuery("DELETE FROM sys_rbac_role_permissions WHERE permission_id IN (SELECT id FROM sys_rbac_menus WHERE path LIKE '/system%')");
fsql.Ado.ExecuteNonQuery("DELETE FROM sys_rbac_menus WHERE path LIKE '/system%'");
// sys 目录
long sysDirId;
var sysDir = fsql.Ado.ExecuteDataTable("SELECT id FROM sys_rbac_menus WHERE path = '/sys'");
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', '', '')");
}
else
{
sysDirId = Convert.ToInt64(sysDir.Rows[0]["id"]);
}
void AddMenu(string name, string path, string component, string icon, string permission, int sort)
{
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}')");
}
AddMenu("用户管理", "/sys/user", "sys/user/index", "User", "sys:user:list", 1);
AddMenu("角色管理", "/sys/role", "sys/role/index", "UserFilled", "sys:role:list", 2);
AddMenu("菜单管理", "/sys/menu", "sys/menu/index", "Menu", "sys:menu:list", 3);
AddMenu("部门管理", "/sys/department", "sys/department/index", "OfficeBuilding", "sys:department:list", 4);
// admin 角色分配 sys 菜单权限
var adminRole = fsql.Ado.ExecuteDataTable("SELECT id FROM sys_rbac_roles WHERE code = 'admin'");
if (adminRole.Rows.Count > 0)
{
var roleId = Convert.ToInt64(adminRole.Rows[0]["id"]);
var menus = fsql.Ado.ExecuteDataTable("SELECT id FROM sys_rbac_menus WHERE path LIKE '/sys%'");
foreach (DataRow row in menus.Rows)
{
var menuId = Convert.ToInt64(row["id"]);
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})");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] RBAC 菜单种子跳过:{ex.Message}");
}
}
/// <summary>为菜单创建权限单元(Permission),并修正旧菜单权限关联(RolePermission.PermissionId 从 Menu.Id 改为 Permission.Id)</summary>
private static void FixMenuPermissions(IFreeSql fsql, ISnowflakeIdGenerator snowflake)
{
try
{
foreach (var menu in fsql.Select<SysMenu>().ToList())
{
// 1. 查或创建菜单权限单元(ResourceType=菜单,ResourceId=Menu.Id)
var perm = fsql.Select<SysPermission>()
.Where(p => p.ResourceType == Resource_Type_Enum.菜单 && p.ResourceId == menu.Id).First();
if (perm == null)
{
var resourceIdentity = string.IsNullOrEmpty(menu.Code) ? menu.Id.ToString() : menu.Code;
perm = new SysPermission(snowflake.CreateId(), Permission_Type_Enum.Visble, Resource_Type_Enum.菜单, resourceIdentity, menu.Id);
if (!string.IsNullOrEmpty(menu.Permission))
perm.SetCode(menu.Permission);
fsql.Insert(perm).ExecuteAffrows();
}
else if (!string.IsNullOrEmpty(menu.Permission) && perm.Code != menu.Permission)
{
perm.SetCode(menu.Permission);
fsql.Update<SysPermission>().SetSource(perm).ExecuteAffrows();
}
// 2. 修正旧菜单权限关联(permission_id 旧值 = Menu.Id,改为 Permission.Id)
fsql.Ado.ExecuteNonQuery($"UPDATE sys_rbac_role_permissions SET permission_id = {perm.Id} WHERE permission_id = {menu.Id};");
}
Console.WriteLine("[DbSeeder] 菜单权限单元同步完成");
}
catch (Exception ex)
{
Console.WriteLine($"[DbSeeder] 菜单权限单元同步跳过:{ex.Message}");
}
}
}