diff --git a/Admin.NET/Admin.NET.Application/Startup.cs b/Admin.NET/Admin.NET.Application/Startup.cs
index 29aa3182..ae7fda8d 100644
--- a/Admin.NET/Admin.NET.Application/Startup.cs
+++ b/Admin.NET/Admin.NET.Application/Startup.cs
@@ -19,4 +19,52 @@ public class Startup : AppStartup
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
+ ///
+ /// 初始化与升级数据,在初始化表结构之前调用
+ ///
+ ///
+ /// 旧版本,0表示从来没有设置过,-1表示当前连接不是主数据库,从SysConfig表获取的
+ /// 当前版本,由ConfigConst.SysCurrentVersion转换的整数版本
+ public void BeforeInitTable(SqlSugarScopeProvider dbProvider, long oldVerion, long currentVersion)
+ {
+ //比较版本号对数据库进行升级结构、种子数据等
+ }
+ ///
+ /// 初始化与升级数据,在初始化种子数据之后调用
+ ///
+ ///
+ /// 旧版本,0表示从来没有设置过,-1表示当前连接不是主数据库,从SysConfig表获取的
+ /// 当前版本,由ConfigConst.SysCurrentVersion转换的整数版本
+ public void AfterInitSeed(SqlSugarScopeProvider dbProvider, long oldVerion, long currentVersion)
+ {
+ //比较版本号对数据库进行升级结构、种子数据等
+ }
+}
+
+///
+/// 测试InitDatas,Order越大,InitDatas执行越靠前
+///
+[AppStartup(1000)]
+public class TestStartup : AppStartup
+{
+ ///
+ /// 初始化与升级数据,在初始化表结构之前调用
+ ///
+ ///
+ /// 旧版本,0表示从来没有设置过,-1表示当前连接不是主数据库,从SysConfig表获取的
+ /// 当前版本,由ConfigConst.SysCurrentVersion转换的整数版本
+ public void BeforeInitTable(SqlSugarScopeProvider dbProvider, long oldVerion, long currentVersion)
+ {
+ //比较版本号对数据库进行升级结构、种子数据等
+ }
+ ///
+ /// 初始化与升级数据,在初始化种子数据之后调用
+ ///
+ ///
+ /// 旧版本,0表示从来没有设置过,-1表示当前连接不是主数据库,从SysConfig表获取的
+ /// 当前版本,由ConfigConst.SysCurrentVersion转换的整数版本
+ public void AfterInitSeed(SqlSugarScopeProvider dbProvider, long oldVerion, long currentVersion)
+ {
+ //比较版本号对数据库进行升级结构、种子数据等
+ }
}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Const/ConfigConst.cs b/Admin.NET/Admin.NET.Core/Const/ConfigConst.cs
index b3104f1e..ef63591c 100644
--- a/Admin.NET/Admin.NET.Core/Const/ConfigConst.cs
+++ b/Admin.NET/Admin.NET.Core/Const/ConfigConst.cs
@@ -11,6 +11,15 @@ namespace Admin.NET.Core;
///
public class ConfigConst
{
+ ///
+ /// 系统版本code
+ ///
+ public const string SysVersion = "sys_version";
+ ///
+ /// 当前系统版本值,标准版本号为 x.xx.xxxxxx。比如 1.01.250409,也可以是变体,比如 1.2.5 v1.2.5
+ ///
+ public const string SysCurrentVersion = "1.01.000001";
+
///
/// 演示环境
///
diff --git a/Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs b/Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs
index 1b45f3b6..33cac5f6 100644
--- a/Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs
+++ b/Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs
@@ -39,6 +39,8 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData
new SysConfig{ Id=1300000000261, Name="密码历史记录验证", Code=ConfigConst.SysPasswordRecord, Value="False", SysFlag=YesNoEnum.Y, Remark="是否验证历史密码禁止再次使用", OrderNo=210, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-12-17 00:00:00") },
new SysConfig{ Id=1300000000271, Name="显示系统更新日志", Code=ConfigConst.SysUpgrade, Value="True", SysFlag=YesNoEnum.Y, Remark="是否显示系统更新日志", OrderNo=220, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-12-20 00:00:00") },
new SysConfig{ Id=1300000000281, Name="开启多语言切换", Code=ConfigConst.SysI18NSwitch, Value="True", SysFlag=YesNoEnum.Y, Remark="是否显示多语言切换按钮", OrderNo=230, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-12-20 00:00:00") },
+
+ new SysConfig{ Id=1300000000999, Name="系统版本", Code=ConfigConst.SysVersion, Value="0", SysFlag=YesNoEnum.Y, Remark= "系统版本,用于自动升级,请勿手动填写", OrderNo=1000, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
];
}
}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs
index 37a0669c..327b0f72 100644
--- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs
+++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs
@@ -352,6 +352,11 @@ public static class SqlSugarSetup
};
}
+ private static int GetStartupOrder(Type type)
+ {
+ return !type.IsDefined(typeof(AppStartupAttribute), true) ? 0 : type.GetCustomAttribute(true).Order;
+ }
+
///
/// 初始化数据库
///
@@ -368,6 +373,46 @@ public static class SqlSugarSetup
if (config.DbType != SqlSugar.DbType.Oracle) dbProvider.DbMaintenance.CreateDatabase();
}
+ // 扫描所有继承 AppStartup 的类
+ var startups = App.EffectiveTypes
+ .Where(u => typeof(AppStartup).IsAssignableFrom(u) && u.IsClass && !u.IsAbstract && !u.IsGenericType)
+ .OrderByDescending(u => GetStartupOrder(u));
+ //数据库前处理
+ long oldVerion = 0, currentVersion = 0;
+ SysConfig versionCfg = null;
+ try
+ {
+ //获取旧版本号
+ try
+ {
+ if (dbProvider.CurrentConnectionConfig.ConfigId.ToString() == SqlSugarConst.MainConfigId)
+ {
+ versionCfg = dbProvider.Queryable().Where(n => n.Code == ConfigConst.SysVersion).First();
+ oldVerion = versionCfg != null ? CommonUtil.ConvertVersionToLong(versionCfg.Value) : 0;
+ }
+ else
+ {
+ oldVerion = -1;
+ }
+ }
+ catch (Exception ex) { }
+ finally
+ {
+ currentVersion = CommonUtil.ConvertVersionToLong(ConfigConst.SysCurrentVersion);
+ }
+ //执行
+ foreach (var type in startups)
+ {
+ var startup = Activator.CreateInstance(type) as AppStartup;
+ var initDataMethod = type.GetMethod("BeforeInitTable");
+ initDataMethod?.Invoke(startup, new[] { (object)dbProvider, oldVerion, currentVersion });
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.Information($"数据库前处理有错 {config.DbType} - {config.ConfigId} : {ex.Message}");
+ }
+
// 初始化表结构
if (config.TableSettings.EnableInitTable)
{
@@ -408,6 +453,41 @@ public static class SqlSugarSetup
// 初始化种子数据
if (config.SeedSettings.EnableInitSeed) InitSeedData(db, config);
+
+ //数据后处理
+ try
+ {
+ //执行后处理
+ foreach (var type in startups)
+ {
+ var startup = Activator.CreateInstance(type) as AppStartup;
+ if (startup == null) continue;
+ var initDataMethod = type.GetMethod("AfterInitSeed");
+ if (initDataMethod == null) continue;
+ initDataMethod?.Invoke(startup, new[] { (object)dbProvider, oldVerion, currentVersion });
+ }
+ }
+ catch (Exception ex)
+ {
+ string errr = $"数据库后处理有错 {config.DbType} - {config.ConfigId} : {ex.Message}";
+ Log.Information(errr);
+ Console.WriteLine(errr);
+ Console.WriteLine(ex.StackTrace);
+ }
+ finally
+ {
+ //最后更新版本
+ if (dbProvider.CurrentConnectionConfig.ConfigId.ToString() == SqlSugarConst.MainConfigId)
+ {
+ IEnumerable cfgs =
+ [
+ new SysConfig{ Id=1300000000999, Name="系统版本", Code=ConfigConst.SysVersion, Value=ConfigConst.SysCurrentVersion, SysFlag=YesNoEnum.Y, Remark= "系统版本,用于自动升级,请勿手动填写", OrderNo=1000, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") }
+ ];
+ var storage = dbProvider.StorageableByObject(cfgs.ToList()).ToStorage();
+ storage.AsInsertable.ExecuteCommand();
+ storage.AsUpdateable.ExecuteCommand();
+ }
+ }
}
///
diff --git a/Admin.NET/Admin.NET.Core/Utils/CommonUtil.cs b/Admin.NET/Admin.NET.Core/Utils/CommonUtil.cs
index a2c62022..091916f6 100644
--- a/Admin.NET/Admin.NET.Core/Utils/CommonUtil.cs
+++ b/Admin.NET/Admin.NET.Core/Utils/CommonUtil.cs
@@ -39,7 +39,49 @@ public static class CommonUtil
return Math.Abs(hash1 + (hash2 * 1566083941));
}
}
+ ///
+ /// 将版本号转换为长整型,版本格式要求 x.xx.xxxxxx,比如 v1.2.5=>102000005 V3.10.42=>310000042
+ ///
+ /// x.xx.xxxxxx
+ ///
+ ///
+ public static long ConvertVersionToLong(string version)
+ {
+ // 1. 移除所有字母(不区分大小写)
+ string noLetters = Regex.Replace(version, "[a-zA-Z]", "");
+ // 2. 按 '.' 分割版本号
+ string[] parts = noLetters.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
+
+ // 3. 确保至少有3部分,不足则补 "0"
+ if (parts.Length < 3)
+ {
+ Array.Resize(ref parts, 3);
+ for (int i = 0; i < parts.Length; i++)
+ {
+ parts[i] = string.IsNullOrEmpty(parts[i]) ? "0" : parts[i];
+ }
+ }
+
+ // 4. 格式化各部分:
+ // - part1: 至少1位(直接取)
+ // - part2: 补齐到2位(如 "2" → "02")
+ // - part3: 补齐到6位(如 "5" → "000005")
+ string part1 = parts[0];
+ string part2 = parts[1].PadLeft(2, '0');
+ string part3 = parts[2].PadLeft(6, '0');
+
+ // 5. 拼接所有部分并转换为 long
+ string combined = $"{part1}{part2}{part3}";
+ if (long.TryParse(combined, out long result))
+ {
+ return result;
+ }
+ else
+ {
+ throw new ArgumentException("版本号转换失败,结果超出 long 范围。");
+ }
+ }
///
/// 生成百分数
///