😎优化初始化库表结构和种子数据页面管理流程

This commit is contained in:
zuohuaijun 2025-06-05 02:18:36 +08:00
parent 38321cbe92
commit 1c7f83dbfe
21 changed files with 782 additions and 941 deletions

View File

@ -205,11 +205,11 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
new SysMenu{ Id=1310000000601, Pid=0, Title="开发工具", Path="/develop", Name="develop", Component="Layout", Icon="ele-Cpu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=13000 },
new SysMenu{ Id=1310000000611, Pid=1310000000601, Title="库表管理", Path="/develop/database", Name="sysDatabase", Component="/system/database/index",Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
new SysMenu{ Id=1310000000621, Pid=1310000000601, Title="数据重置", Path="/develop/dataInit", Name="sysDataInit", Component="/system/dataInit/index",Icon="ele-TakeawayBox", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
new SysMenu{ Id=1310000000631, Pid=1310000000601, Title="代码生成", Path="/develop/codeGen", Name="sysCodeGen", Component="/system/codeGen/index", Icon="ele-Crop", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
new SysMenu{ Id=1310000000641, Pid=1310000000601, Title="表单设计", Path="/develop/formDes", Name="sysFormDes", Component="/system/formDes/index", Icon="ele-Edit", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
new SysMenu{ Id=1310000000651, Pid=1310000000601, Title="系统接口", Path="/develop/api", Name="sysApi", Component="layout/routerView/iframe", IsIframe=true, OutLink="http://localhost:5005", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
new SysMenu{ Id=1310000000661, Pid=1310000000601, Title="接口压测", Path="/develop/stressTest", Name="sysStressTest", Component="/system/stressTest/index", Icon="ele-Compass", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2024-12-28 00:00:00"), OrderNo=140 },
new SysMenu{ Id=1310000000621, Pid=1310000000601, Title="数据重置", Path="/develop/dataInit", Name="sysDataInit", Component="/system/dataInit/index",Icon="ele-TakeawayBox", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
new SysMenu{ Id=1310000000631, Pid=1310000000601, Title="代码生成", Path="/develop/codeGen", Name="sysCodeGen", Component="/system/codeGen/index", Icon="ele-Crop", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
new SysMenu{ Id=1310000000641, Pid=1310000000601, Title="表单设计", Path="/develop/formDes", Name="sysFormDes", Component="/system/formDes/index", Icon="ele-Edit", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
new SysMenu{ Id=1310000000651, Pid=1310000000601, Title="系统接口", Path="/develop/api", Name="sysApi", Component="layout/routerView/iframe", IsIframe=true, OutLink="http://localhost:5005", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 },
new SysMenu{ Id=1310000000661, Pid=1310000000601, Title="接口压测", Path="/develop/stressTest", Name="sysStressTest", Component="/system/stressTest/index", Icon="ele-Compass", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2024-12-28 00:00:00"), OrderNo=150 },
new SysMenu{ Id=1310000000701, Pid=0, Title="帮助文档", Path="/doc", Name="doc", Component="Layout", Icon="ele-Notebook", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=14000 },
new SysMenu{ Id=1310000000711, Pid=1310000000701, Title="框架教程", Path="/doc/admin", Name="sysAdmin", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://adminnet.top/", Icon="ele-Sunny", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },

View File

@ -40,4 +40,9 @@ public class TableOutput
/// 表名称描述(功能名)
/// </summary>
public string TableComment { get; set; }
/// <summary>
/// 程序集名称
/// </summary>
public string AssemblyName { get; set; }
}

View File

@ -124,17 +124,17 @@ public class SysCodeGenConfigService : IDynamicApiController, ITransient
}
}
}
var sugarTableType = typeof(SugarTable);
bool IsMyAttribute(Attribute[] o)
{
foreach (Attribute a in o)
{
if (a.GetType() == sugarTableType)
return true;
}
return false;
}
Type[] cosType = types.Where(u => IsMyAttribute(Attribute.GetCustomAttributes(u, false))).ToArray();
//var sugarTableType = typeof(SugarTable);
//bool IsMyAttribute(Attribute[] o)
//{
// foreach (Attribute a in o)
// {
// if (a.GetType() == sugarTableType)
// return true;
// }
// return false;
//}
Type[] cosType = types.Where(u => u.IsDefined(typeof(SugarTable), false) && !u.GetCustomAttributes<IgnoreTableAttribute>().Any()).ToArray();
var entityInfos = new List<EntityInfo>();
foreach (var ct in cosType)
@ -145,7 +145,7 @@ public class SysCodeGenConfigService : IDynamicApiController, ITransient
var des = ct.GetCustomAttributes(typeof(DescriptionAttribute), false);
var description = des.Length > 0 ? ((DescriptionAttribute)des[0]).Description : "";
var sugarAttribute = ct.GetCustomAttributes(sugarTableType, true).FirstOrDefault();
var sugarAttribute = ct.GetCustomAttributes(typeof(SugarTable), true).FirstOrDefault();
entityInfos.Add(new EntityInfo()
{

View File

@ -188,8 +188,9 @@ public class SysCodeGenService : IDynamicApiController, ITransient
foreach (var item in entityInfos)
{
var tbConfigId = item.Type.GetCustomAttribute<TenantAttribute>()?.configId as string ?? SqlSugarConst.MainConfigId;
if (item.Type.IsDefined(typeof(LogTableAttribute))) tbConfigId = SqlSugarConst.LogConfigId;
if (tbConfigId != configId) continue;
if (item.Type.IsDefined(typeof(LogTableAttribute)) && !item.Type.IsDefined(typeof(SysTableAttribute))) tbConfigId = SqlSugarConst.LogConfigId;
if (tbConfigId != configId)
continue;
var dbTableName = item.DbTableName;
int bracketIndex = dbTableName.IndexOf('{');
@ -197,13 +198,14 @@ public class SysCodeGenService : IDynamicApiController, ITransient
dbTableName = dbTableName.Substring(0, bracketIndex);
var table = dbTableInfos.FirstOrDefault(u => u.Name.ToLower().Equals((config != null && config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(dbTableName) : dbTableName).ToLower()));
if (table == null) continue;
//if (table == null) continue;
tableOutputList.Add(new TableOutput
{
ConfigId = configId,
EntityName = item.EntityName,
TableName = table.Name,
TableComment = item.TableDescription
TableName = table?.Name,
TableComment = item.TableDescription,
AssemblyName = item.Type.Assembly.ManifestModule.Name
});
}
return tableOutputList;

View File

@ -6,7 +6,7 @@
namespace Admin.NET.Core.Service;
public class DataInitInput
public class InitTableSeedDataInput
{
public string ConfigId { get; set; }

View File

@ -4,7 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using Npgsql;
namespace Admin.NET.Core.Service;
@ -15,14 +14,17 @@ namespace Admin.NET.Core.Service;
[ApiDescriptionSettings(Order = 250, Description = "数据库管理")]
public class SysDatabaseService : IDynamicApiController, ITransient
{
private readonly UserManager _userManager;
private readonly ISqlSugarClient _db;
private readonly IViewEngine _viewEngine;
private readonly CodeGenOptions _codeGenOptions;
public SysDatabaseService(ISqlSugarClient db,
public SysDatabaseService(UserManager userManager,
ISqlSugarClient db,
IViewEngine viewEngine,
IOptions<CodeGenOptions> codeGenOptions)
{
_userManager = userManager;
_db = db;
_viewEngine = viewEngine;
_codeGenOptions = codeGenOptions.Value;
@ -545,6 +547,55 @@ public class SysDatabaseService : IDynamicApiController, ITransient
await File.WriteAllTextAsync(targetPath, tResult, Encoding.UTF8);
}
/// <summary>
/// 获取种子数据列表 🔖
/// </summary>
/// <param name="configId"></param>
/// <returns></returns>
[DisplayName("获取种子数据列表")]
public List<DataInitItemOutput> GetSeedDataList([FromQuery] string configId)
{
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))))
.Where(u => !u.IsDefined(typeof(TenantSeedAttribute), false))
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? ((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0]).Order : 0).ToList();
var outputList = new List<DataInitItemOutput>();
foreach (var seedDataType in seedDataTypes)
{
var entityType = seedDataType.GetInterfaces().First().GetGenericArguments().First();
outputList.Add(new DataInitItemOutput() { Name = seedDataType.Name, AssemblyName = seedDataType.Assembly.ManifestModule.Name, Description = entityType.GetCustomAttribute<SugarTable>().TableDescription + "种子数据" });
}
return outputList;
}
/// <summary>
/// 初始化表结构 🔖
/// </summary>
/// <param name="input"></param>
[DisplayName("初始化表结构")]
public void InitTable(InitTableSeedDataInput input)
{
if (!_userManager.SuperAdmin)
throw Oops.Oh("只有超管才可以操作!");
var dbProvider = _db.AsTenant().GetConnectionScope(input.ConfigId);
SqlSugarSetup.InitTable(dbProvider, false, input.EntityNames);
}
/// <summary>
/// 初始化种子数据 🔖
/// </summary>
/// <param name="input"></param>
[DisplayName("初始化种子数据")]
public void InitSeedData(InitTableSeedDataInput input)
{
if (!_userManager.SuperAdmin)
throw Oops.Oh("只有超管才可以操作!");
var dbProvider = _db.AsTenant().GetConnectionScope(input.ConfigId);
SqlSugarSetup.InitSeedData(dbProvider, false, input.EntityNames);
}
/// <summary>
/// 获取库表信息
/// </summary>

View File

@ -1,103 +0,0 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
namespace Admin.NET.Core.Service;
/// <summary>
/// 系统表和种子数据初始化服务 🧩
/// </summary>
[ApiDescriptionSettings(Order = 250, Description = "系统表和种子数据初始化服务")]
public class SysDataInitService : IDynamicApiController, ITransient
{
private readonly UserManager userManager;
public SysDataInitService(UserManager userManager)
{
this.userManager = userManager;
}
/// <summary>
/// 获取实体类列表 🔖
/// </summary>
/// <returns></returns>
[DisplayName("获取实体类列表")]
public List<DataInitItemOutput> GetClassList(string configId)
{
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"获取实体类列表");
var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false))
.Where(u => !u.GetCustomAttributes<IgnoreTableAttribute>().Any())
//.WhereIF(config.TableSettings.EnableIncreTable, u => u.IsDefined(typeof(IncreTableAttribute), false))
.ToList();
if (configId == SqlSugarConst.MainConfigId) // 默认库(有系统表特性、没有日志表和租户表特性)
entityTypes = entityTypes.Where(u => u.GetCustomAttributes<SysTableAttribute>().Any() || (!u.GetCustomAttributes<LogTableAttribute>().Any() && !u.GetCustomAttributes<TenantAttribute>().Any())).ToList();
else if (configId == SqlSugarConst.LogConfigId) // 日志库
entityTypes = entityTypes.Where(u => u.GetCustomAttributes<LogTableAttribute>().Any()).ToList();
else
entityTypes = entityTypes.Where(u => u.GetCustomAttribute<TenantAttribute>()?.configId.ToString() == configId).ToList(); // 自定义的库
List<DataInitItemOutput> outputList = new List<DataInitItemOutput>();
foreach (var entityType in entityTypes)
{
outputList.Add(new DataInitItemOutput() { Name = entityType.Name, AssemblyName = entityType.Assembly.ManifestModule.Name, Description = entityType.GetCustomAttribute<SugarTable>().TableDescription });
}
return outputList;
}
/// <summary>
/// 获取种子数据列表 🔖
/// </summary>
/// <returns></returns>
[DisplayName("获取种子数据列表")]
public List<DataInitItemOutput> GetSeedDataList(string configId)
{
bool enableIncreSeed = false; // 是否启用增量种子数据TODO
Log.Information($"初始化种子数据");
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))))
.Where(u => !u.IsDefined(typeof(TenantSeedAttribute), false))
.WhereIF(enableIncreSeed, u => u.IsDefined(typeof(IncreSeedAttribute), false))
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? ((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0]).Order : 0).ToList();
List<DataInitItemOutput> outputList = new List<DataInitItemOutput>();
foreach (var seedDataType in seedDataTypes)
{
var entityType = seedDataType.GetInterfaces().First().GetGenericArguments().First();
outputList.Add(new DataInitItemOutput() { Name = seedDataType.Name, AssemblyName = seedDataType.Assembly.ManifestModule.Name, Description = entityType.GetCustomAttribute<SugarTable>().TableDescription + "种子数据" });
}
return outputList;
}
/// <summary>
/// 初始化表结构 🔖
/// </summary>
/// <param name="input"></param>
[ApiDescriptionSettings(Name = "InitTable"), HttpPost]
[DisplayName("初始化表结构")]
public void InitializeTable(DataInitInput input)
{
if (!userManager.SuperAdmin)
throw Oops.Oh("无权限操作!");
SqlSugarSetup.InitTables(input.ConfigId, input.EntityNames);
}
/// <summary>
/// 初始化种子数据 🔖
/// </summary>
/// <param name="input"></param>
[ApiDescriptionSettings(Name = "InitSeedData"), HttpPost]
[DisplayName("初始化种子数据")]
public void InitializeSeedData(DataInitInput input)
{
if (!userManager.SuperAdmin)
throw Oops.Oh("无权限操作!");
SqlSugarSetup.InitSeedData(input.ConfigId, input.EntityNames);
}
}

View File

@ -379,48 +379,7 @@ public static class SqlSugarSetup
var (startups, oldVerion, currentVersion) = BeforeInitTable(dbProvider);
// 初始化表结构
if (config.TableSettings.EnableInitTable || isFirstRun)
{
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"初始化表结构 {config.DbType} - {config.ConfigId}");
var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false))
.Where(u => !u.GetCustomAttributes<IgnoreTableAttribute>().Any())
.WhereIF(config.TableSettings.EnableIncreTable, u => u.IsDefined(typeof(IncreTableAttribute), false)).ToList();
if (config.ConfigId.ToString() == SqlSugarConst.MainConfigId) // 默认库(有系统表特性、没有日志表和租户表特性)
entityTypes = entityTypes.Where(u => u.GetCustomAttributes<SysTableAttribute>().Any() || (!u.GetCustomAttributes<LogTableAttribute>().Any() && !u.GetCustomAttributes<TenantAttribute>().Any())).ToList();
else if (config.ConfigId.ToString() == SqlSugarConst.LogConfigId) // 日志库
entityTypes = entityTypes.Where(u => u.GetCustomAttributes<LogTableAttribute>().Any()).ToList();
else
entityTypes = entityTypes.Where(u => u.GetCustomAttribute<TenantAttribute>()?.configId.ToString() == config.ConfigId.ToString()).ToList(); // 自定义的库
// 删除视图再初始化表结构,防止因为视图导致无法同步表结构
var viewTypeList = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarView)))).ToList();
foreach (var viewType in viewTypeList)
{
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(viewType) ?? throw new Exception("获取视图实体配置有误");
if (dbProvider.DbMaintenance.GetViewInfoList(false).Any(it => it.Name.EqualIgnoreCase(entityInfo.DbTableName)))
dbProvider.DbMaintenance.DropView(entityInfo.DbTableName);
}
int taskIndex = 0, size = entityTypes.Count;
var taskList = entityTypes.Select(entityType => Task.Run(() =>
{
var stopWatch = Stopwatch.StartNew(); // 开始计时
dbProvider.InitTable(entityType); // 初始化表结构
stopWatch.Stop(); // 停止计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化表 {entityType,-64} ({config.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003}) 耗时:{stopWatch.ElapsedMilliseconds} ms");
}));
Task.WaitAll(taskList.ToArray());
totalWatch.Stop(); // 停止总计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化表结构 {config.DbType} - {config.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds} ms");
}
if (config.TableSettings.EnableInitTable || isFirstRun) InitTable(dbProvider, config.TableSettings.EnableIncreTable);
// 初始化视图
if (config.DbSettings.EnableInitView || isFirstRun) InitView(dbProvider);
@ -432,6 +391,61 @@ public static class SqlSugarSetup
AfterInitSeed(dbProvider, startups, oldVerion, currentVersion);
}
/// <summary>
/// 初始化表结构
/// </summary>
/// <param name="dbProvider"></param>
/// <param name="enableIncreTable"></param>
/// <param name="entityNames"></param>
public static void InitTable(SqlSugarScopeProvider dbProvider, bool enableIncreTable, List<string> entityNames = null)
{
var config = dbProvider.CurrentConnectionConfig;
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"初始化表结构 {config.DbType} - {config.ConfigId}");
var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false))
.Where(u => !u.GetCustomAttributes<IgnoreTableAttribute>().Any())
.WhereIF(enableIncreTable, u => u.IsDefined(typeof(IncreTableAttribute), false)).ToList();
if (config.ConfigId.ToString() == SqlSugarConst.MainConfigId) // 默认库(有系统表特性、没有日志表和租户表特性)
entityTypes = entityTypes.Where(u => u.GetCustomAttributes<SysTableAttribute>().Any() || (!u.GetCustomAttributes<LogTableAttribute>().Any() && !u.GetCustomAttributes<TenantAttribute>().Any())).ToList();
else if (config.ConfigId.ToString() == SqlSugarConst.LogConfigId) // 日志库
entityTypes = entityTypes.Where(u => u.GetCustomAttributes<LogTableAttribute>().Any()).ToList();
else
entityTypes = entityTypes.Where(u => u.GetCustomAttribute<TenantAttribute>()?.configId.ToString() == config.ConfigId.ToString()).ToList(); // 自定义的库
// 过滤指定实体
if (entityNames != null && entityNames.Count > 0)
entityTypes = entityTypes.Where(u => entityNames.Contains(u.Name)).ToList();
// 删除视图再初始化表结构,防止因为视图导致无法同步表结构
var viewTypeList = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarView)))).ToList();
foreach (var viewType in viewTypeList)
{
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(viewType) ?? throw new Exception("获取视图实体配置有误");
if (dbProvider.DbMaintenance.GetViewInfoList(false).Any(it => it.Name.EqualIgnoreCase(entityInfo.DbTableName)))
dbProvider.DbMaintenance.DropView(entityInfo.DbTableName);
}
int taskIndex = 0, size = entityTypes.Count;
var taskList = entityTypes.Select(entityType => Task.Run(() =>
{
var stopWatch = Stopwatch.StartNew(); // 开始计时
dbProvider.InitTable(entityType); // 初始化表结构
stopWatch.Stop(); // 停止计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化表 {entityType,-64} ({config.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003}) 耗时:{stopWatch.ElapsedMilliseconds} ms");
}));
Task.WaitAll(taskList.ToArray());
totalWatch.Stop(); // 停止总计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化表结构 {config.DbType} - {config.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds} ms");
}
/// <summary>
/// 初始化表结构之前(版本号)
/// </summary>
@ -525,15 +539,22 @@ public static class SqlSugarSetup
/// </summary>
/// <param name="dbProvider"></param>
/// <param name="enableIncreSeed"></param>
private static void InitSeedData(SqlSugarScopeProvider dbProvider, bool enableIncreSeed)
/// <param name="entityNames"></param>
public static void InitSeedData(SqlSugarScopeProvider dbProvider, bool enableIncreSeed, List<string> entityNames = null)
{
var config = dbProvider.CurrentConnectionConfig;
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"初始化种子数据 {dbProvider.CurrentConnectionConfig.DbType} - {dbProvider.CurrentConnectionConfig.ConfigId}");
Log.Information($"初始化种子数据 {config.DbType} - {config.ConfigId}");
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))))
.Where(u => !u.IsDefined(typeof(TenantSeedAttribute), false))
.WhereIF(enableIncreSeed, u => u.IsDefined(typeof(IncreSeedAttribute), false))
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? ((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0]).Order : 0).ToList();
// 过滤指定实体
if (entityNames != null && entityNames.Count > 0)
seedDataTypes = seedDataTypes.Where(u => entityNames.Contains(u.Name)).ToList();
// 由于种子数据在应用层存在重写,必须保证应用层种子最后执行(多线程顺序会乱)
int taskIndex = 0, size = seedDataTypes.Count;
foreach (var seedType in seedDataTypes)
@ -547,22 +568,24 @@ public static class SqlSugarSetup
stopWatch.Stop(); // 停止计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化种子数据 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003},数据量:{tuple.Value.Item1:D003},新增 {tuple.Value.Item2:D003} 条记录,更新 {tuple.Value.Item3:D003} 条记录,耗时:{stopWatch.ElapsedMilliseconds:N0} ms)");
Console.WriteLine($"初始化种子数据 {seedType.FullName,-58} ({config.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003},数据量:{tuple.Value.Item1:D003},新增 {tuple.Value.Item2:D003} 条记录,更新 {tuple.Value.Item3:D003} 条记录,耗时:{stopWatch.ElapsedMilliseconds:N0} ms)");
}
totalWatch.Stop(); // 停止总计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化种子数据 {dbProvider.CurrentConnectionConfig.DbType} - {dbProvider.CurrentConnectionConfig.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds:N0} ms");
Console.WriteLine($"初始化种子数据 {config.DbType} - {config.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds:N0} ms");
}
/// <summary>
/// 初始化视图
/// </summary>
/// <param name="dbProvider"></param>
private static void InitView(SqlSugarScopeProvider dbProvider)
public static void InitView(SqlSugarScopeProvider dbProvider)
{
var config = dbProvider.CurrentConnectionConfig;
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"初始化视图 {dbProvider.CurrentConnectionConfig.DbType} - {dbProvider.CurrentConnectionConfig.ConfigId}");
Log.Information($"初始化视图 {config.DbType} - {config.ConfigId}");
var viewTypeList = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarView)))).ToList();
int taskIndex = 0, size = viewTypeList.Count;
@ -588,13 +611,13 @@ public static class SqlSugarSetup
// 停止计时
stopWatch.Stop();
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化视图 {viewType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003},耗时:{stopWatch.ElapsedMilliseconds:N0} ms)");
Console.WriteLine($"初始化视图 {viewType.FullName,-58} ({config.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003},耗时:{stopWatch.ElapsedMilliseconds:N0} ms)");
}));
Task.WaitAll(taskList.ToArray());
totalWatch.Stop(); // 停止总计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化视图 {dbProvider.CurrentConnectionConfig.DbType} - {dbProvider.CurrentConnectionConfig.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds:N0} ms");
Console.WriteLine($"初始化视图 {config.DbType} - {config.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds:N0} ms");
}
/// <summary>
@ -703,96 +726,4 @@ public static class SqlSugarSetup
}
}
}
/// <summary>
/// 初始化表结构
/// </summary>
/// <param name="entityNames">实体名称列表</param>
public static void InitTables(string configId, List<string> entityNames)
{
var dbOptions = App.GetConfig<DbConnectionOptions>("DbConnection", true);
var config = dbOptions.ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == configId);
var dbProvider = ITenant.GetConnectionScope(config.ConfigId);
// 初始化表结构之前——系统版本号
var (startups, oldVerion, currentVersion) = BeforeInitTable(dbProvider);
// 初始化表结构
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"初始化表结构 {config.DbType} - {config.ConfigId}");
var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false))
.Where(u => !u.GetCustomAttributes<IgnoreTableAttribute>().Any())
.WhereIF(config.TableSettings.EnableIncreTable, u => u.IsDefined(typeof(IncreTableAttribute), false)).ToList();
entityTypes = entityTypes.Where(u => entityNames.Contains(u.Name)).ToList();
// 删除视图再初始化表结构,防止因为视图导致无法同步表结构
var viewTypeList = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarView)))).ToList();
foreach (var viewType in viewTypeList)
{
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(viewType) ?? throw new Exception("获取视图实体配置有误");
if (dbProvider.DbMaintenance.GetViewInfoList(false).Any(it => it.Name.EqualIgnoreCase(entityInfo.DbTableName)))
dbProvider.DbMaintenance.DropView(entityInfo.DbTableName);
}
int taskIndex = 0, size = entityTypes.Count;
var taskList = entityTypes.Select(entityType => Task.Run(() =>
{
var stopWatch = Stopwatch.StartNew(); // 开始计时
dbProvider.InitTable(entityType); // 初始化表结构
stopWatch.Stop(); // 停止计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化表 {entityType,-64} ({config.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003}) 耗时:{stopWatch.ElapsedMilliseconds} ms");
}));
Task.WaitAll(taskList.ToArray());
totalWatch.Stop(); // 停止总计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化表结构 {config.DbType} - {config.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds} ms");
// 初始化种子数据之后——系统版本号
AfterInitSeed(dbProvider, startups, oldVerion, currentVersion);
}
/// <summary>
/// 初始化种子数据
/// </summary>
/// <param name="entityNames">实体名称列表</param>
public static void InitSeedData(string configId, List<string> entityNames)
{
var dbOptions = App.GetConfig<DbConnectionOptions>("DbConnection", true);
var config = dbOptions.ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == configId);
var dbProvider = ITenant.GetConnectionScope(config.ConfigId);
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"初始化种子数据 {dbProvider.CurrentConnectionConfig.DbType} - {dbProvider.CurrentConnectionConfig.ConfigId}");
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))))
.Where(u => !u.IsDefined(typeof(TenantSeedAttribute), false))
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? ((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0]).Order : 0).ToList();
seedDataTypes = seedDataTypes.Where(u => entityNames.Contains(u.Name)).ToList();
int taskIndex = 0, size = seedDataTypes.Count;
foreach (var seedType in seedDataTypes)
{
var stopWatch = Stopwatch.StartNew(); // 开始计时
// 初始化种子数据
var tuple = dbProvider.InitTableSeedData(seedType);
if (tuple == null) continue;
stopWatch.Stop(); // 停止计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化种子数据 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003},数据量:{tuple.Value.Item1:D003},新增 {tuple.Value.Item2:D003} 条记录,更新 {tuple.Value.Item3:D003} 条记录,耗时:{stopWatch.ElapsedMilliseconds:N0} ms)");
}
totalWatch.Stop(); // 停止总计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化种子数据 {dbProvider.CurrentConnectionConfig.DbType} - {dbProvider.CurrentConnectionConfig.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds:N0} ms");
}
}

View File

@ -17,6 +17,7 @@ import { Configuration } from '../configuration';
// Some imports not used depending on template conditions
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
import { AdminNETResultListDataInitItemOutput } from '../models';
import { AdminNETResultListDbColumnOutput } from '../models';
import { AdminNETResultListDbOutput } from '../models';
import { AdminNETResultListDbTableInfo } from '../models';
@ -29,6 +30,7 @@ import { DbColumnInput } from '../models';
import { DbTableInput } from '../models';
import { DeleteDbColumnInput } from '../models';
import { DeleteDbTableInput } from '../models';
import { InitTableSeedDataInput } from '../models';
import { UpdateDbColumnInput } from '../models';
import { UpdateDbTableInput } from '../models';
/**
@ -587,6 +589,102 @@ export const SysDatabaseApiAxiosParamCreator = function (configuration?: Configu
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {InitTableSeedDataInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysDatabaseInitSeedDataPost: async (body?: InitTableSeedDataInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysDatabase/initSeedData`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {InitTableSeedDataInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysDatabaseInitTablePost: async (body?: InitTableSeedDataInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysDatabase/initTable`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
@ -630,6 +728,54 @@ export const SysDatabaseApiAxiosParamCreator = function (configuration?: Configu
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {string} [configId]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysDatabaseSeedDataListGet: async (configId?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysDatabase/seedDataList`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
if (configId !== undefined) {
localVarQueryParameter['configId'] = configId;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
@ -984,6 +1130,34 @@ export const SysDatabaseApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {InitTableSeedDataInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysDatabaseInitSeedDataPost(body?: InitTableSeedDataInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
const localVarAxiosArgs = await SysDatabaseApiAxiosParamCreator(configuration).apiSysDatabaseInitSeedDataPost(body, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {InitTableSeedDataInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysDatabaseInitTablePost(body?: InitTableSeedDataInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
const localVarAxiosArgs = await SysDatabaseApiAxiosParamCreator(configuration).apiSysDatabaseInitTablePost(body, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
@ -997,6 +1171,20 @@ export const SysDatabaseApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {string} [configId]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysDatabaseSeedDataListGet(configId?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultListDataInitItemOutput>>> {
const localVarAxiosArgs = await SysDatabaseApiAxiosParamCreator(configuration).apiSysDatabaseSeedDataListGet(configId, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
@ -1174,6 +1362,26 @@ export const SysDatabaseApiFactory = function (configuration?: Configuration, ba
async apiSysDatabaseGenerateEntityPost(body?: CreateEntityInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultString>> {
return SysDatabaseApiFp(configuration).apiSysDatabaseGenerateEntityPost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {InitTableSeedDataInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysDatabaseInitSeedDataPost(body?: InitTableSeedDataInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
return SysDatabaseApiFp(configuration).apiSysDatabaseInitSeedDataPost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {InitTableSeedDataInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysDatabaseInitTablePost(body?: InitTableSeedDataInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
return SysDatabaseApiFp(configuration).apiSysDatabaseInitTablePost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
@ -1183,6 +1391,16 @@ export const SysDatabaseApiFactory = function (configuration?: Configuration, ba
async apiSysDatabaseListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListDbOutput>> {
return SysDatabaseApiFp(configuration).apiSysDatabaseListGet(options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {string} [configId]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysDatabaseSeedDataListGet(configId?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListDataInitItemOutput>> {
return SysDatabaseApiFp(configuration).apiSysDatabaseSeedDataListGet(configId, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
@ -1356,6 +1574,28 @@ export class SysDatabaseApi extends BaseAPI {
public async apiSysDatabaseGenerateEntityPost(body?: CreateEntityInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultString>> {
return SysDatabaseApiFp(this.configuration).apiSysDatabaseGenerateEntityPost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {InitTableSeedDataInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysDatabaseApi
*/
public async apiSysDatabaseInitSeedDataPost(body?: InitTableSeedDataInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
return SysDatabaseApiFp(this.configuration).apiSysDatabaseInitSeedDataPost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {InitTableSeedDataInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysDatabaseApi
*/
public async apiSysDatabaseInitTablePost(body?: InitTableSeedDataInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
return SysDatabaseApiFp(this.configuration).apiSysDatabaseInitTablePost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
@ -1366,6 +1606,17 @@ export class SysDatabaseApi extends BaseAPI {
public async apiSysDatabaseListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListDbOutput>> {
return SysDatabaseApiFp(this.configuration).apiSysDatabaseListGet(options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {string} [configId]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysDatabaseApi
*/
public async apiSysDatabaseSeedDataListGet(configId?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListDataInitItemOutput>> {
return SysDatabaseApiFp(this.configuration).apiSysDatabaseSeedDataListGet(configId, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖

View File

@ -0,0 +1,71 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import { DataInitItemOutput } from './data-init-item-output';
/**
*
*
* @export
* @interface AdminNETResultListDataInitItemOutput
*/
export interface AdminNETResultListDataInitItemOutput {
/**
*
*
* @type {number}
* @memberof AdminNETResultListDataInitItemOutput
*/
code?: number;
/**
* successwarningerror
*
* @type {string}
* @memberof AdminNETResultListDataInitItemOutput
*/
type?: string | null;
/**
*
*
* @type {string}
* @memberof AdminNETResultListDataInitItemOutput
*/
message?: string | null;
/**
*
*
* @type {Array<DataInitItemOutput>}
* @memberof AdminNETResultListDataInitItemOutput
*/
result?: Array<DataInitItemOutput> | null;
/**
*
*
* @type {any}
* @memberof AdminNETResultListDataInitItemOutput
*/
extras?: any | null;
/**
*
*
* @type {Date}
* @memberof AdminNETResultListDataInitItemOutput
*/
time?: Date;
}

View File

@ -0,0 +1,40 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
*
*
* @export
* @interface DataInitItemOutput
*/
export interface DataInitItemOutput {
/**
* @type {string}
* @memberof DataInitItemOutput
*/
name?: string | null;
/**
* @type {string}
* @memberof DataInitItemOutput
*/
assemblyName?: string | null;
/**
* @type {string}
* @memberof DataInitItemOutput
*/
description?: string | null;
}

View File

@ -44,6 +44,7 @@ export * from './admin-netresult-list-api-output';
export * from './admin-netresult-list-code-gen-config';
export * from './admin-netresult-list-column-ouput';
export * from './admin-netresult-list-const-output';
export * from './admin-netresult-list-data-init-item-output';
export * from './admin-netresult-list-database-output';
export * from './admin-netresult-list-db-backup-output';
export * from './admin-netresult-list-db-column-output';
@ -174,6 +175,7 @@ export * from './custom-attribute-data';
export * from './custom-attribute-named-argument';
export * from './custom-attribute-typed-argument';
export * from './data-column';
export * from './data-init-item-output';
export * from './data-item';
export * from './data-scope-enum';
export * from './data-set';
@ -257,6 +259,7 @@ export * from './icontainer';
export * from './icustom-attribute-provider';
export * from './idisposable';
export * from './isite';
export * from './init-table-seed-data-input';
export * from './int-ptr';
export * from './invoice-info';
export * from './invoice-key-info';

View File

@ -0,0 +1,34 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
*
*
* @export
* @interface InitTableSeedDataInput
*/
export interface InitTableSeedDataInput {
/**
* @type {string}
* @memberof InitTableSeedDataInput
*/
configId?: string | null;
/**
* @type {Array<string>}
* @memberof InitTableSeedDataInput
*/
entityNames?: Array<string> | null;
}

View File

@ -67,4 +67,12 @@ export interface TableOutput {
* @memberof TableOutput
*/
tableComment?: string | null;
/**
*
*
* @type {string}
* @memberof TableOutput
*/
assemblyName?: string | null;
}

View File

@ -1,37 +0,0 @@
import request from '/@/utils/request';
enum Api {
EntityClassList = '/api/sysDataInit/classList',
SeedDataList = '/api/sysDataInit/seedDataList',
InitTable = '/api/sysDataInit/initTable',
InitSeedData = '/api/sysDataInit/initSeedData',
}
// 获取所有实体类
export const getEntityClassList = (params?: any) =>
request({
url: `${Api.EntityClassList}/${params}`,
method: 'get',
});
// 获取所有种子数据
export const getSeedDataList = (params?: any) =>
request({
url: `${Api.SeedDataList}/${params}`,
method: 'get',
});
// 初始化表
export const initTable = (params?: any) =>
request({
url: `${Api.InitTable}`,
method: 'post',
data: params,
});
// 初始化种子数据
export const initSeedData = (params?: any) =>
request({
url: `${Api.InitSeedData}`,
method: 'post',
data: params,
});

View File

@ -1,284 +0,0 @@
<template>
<el-card shadow="hover" :body-style="{ padding: '20px 20px 16px 10px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%" @submit.prevent="handleQuery" >
<el-row :gutter="10">
<el-col class="mb5" :xs="24" :sm="10" :md="10" :lg="10" :xl="10">
<el-form-item label="库名" prop="configId">
<el-select v-model="state.configId" placeholder="库名" filterable @change="handleQueryTable">
<el-option v-for="item in state.dbData" :key="item.configId" :label="`${item.dbName}(${item.configId})`" :value="item.configId" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
<el-row>
<el-col>
<el-button-group>
<el-button type="primary" icon="ele-Search" @click="handleInitTable" :loading="options.loading">
生成表<span v-if="state.selectedRows.length > 0">({{ state.selectedRows.length }})</span>
</el-button>
</el-button-group>
</el-col>
</el-row>
</el-card>
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" v-on="gridEvents">
<template #row_record="{ row }">
<ModifyRecord :data="row" />
</template>
</vxe-grid>
<div style="text-align: right; margin: 7px 8px 7px 0px; color: #666; font-size: 12px;">
{{ xGrid?.getTableData ? xGrid.getTableData().fullData.length : 0 }} 条记录
</div>
</el-card>
</template>
<script lang="ts" setup name="entityList">
import { onMounted, reactive, ref } from 'vue';
import { ElMessageBox, ElMessage } from "element-plus";
import { useUserInfo } from '/@/stores/userInfo';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import { formatDate } from '/@/utils/formatTime';
import { getAPI } from '/@/utils/axios-utils';
import { SysDatabaseApi } from '/@/api-services/api';
import { getEntityClassList, initTable } from '/@/api/system/dataInit';
//
const xGrid = ref<VxeGridInstance>();
const userStore = useUserInfo();
const dc = userStore.getDictItemByValue;
const dv = userStore.getDictItemByLabel;
const dl = userStore.getDictDataByCode;
//
const state = reactive({
loading: false,
dbData: [] as any,
configId: '',
showAdvanceQueryUI: false,
queryParams: {
searchKey: undefined,
GroupBy: [] as any,
projectName: undefined,
financingProjectName: undefined,
projectType: undefined,
constructionStatus: undefined,
approvalNumber: undefined,
approvalDate: undefined,
approvalDateRange: undefined,
constructionAddress: undefined,
},
localPageParam: {
pageSize: 50 as number,
defaultSort: { field: 'Id', order: 'asc', descStr: 'desc' },
},
totalSum:[] as any,
visible: false,
title: '',
selectedRows: [] as any[],
});
//
const localPageParamKey = 'localPageParam:entityList';
//
const changeAdvanceQueryUI = () => {
state.showAdvanceQueryUI = !state.showAdvanceQueryUI;
};
//
const checkTableColumnVisible = (tableColumnName: any) => {
return !userStore.userTableList.includes(tableColumnName);
};
//
const options = useVxeTable(
{
id: 'entityList',
name: '项目信息',
columns: [
{ type: 'checkbox', width: 40, fixed: 'left' },
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
{ field: 'assemblyName', title: '程序集', minWidth: 120, showOverflow: 'tooltip', sortable: false},
{ field: 'name', title: '名称', minWidth: 200, showOverflow: 'tooltip', sortable: false},
{ field: 'description', title: '描述', minWidth: 200, showOverflow: 'tooltip', sortable: false},
// { title: '', fixed: 'right', width: 120, showOverflow: true, slots: { default: 'row_buttons' } },
],
footerMethod: ({ columns, data }) => {
const totalSum=state.totalSum[0];
return [
// columns.map((column, colIndex) => {
// if (colIndex === 0) {
// return ``
// }
// if (column.field === 'estimatedTotalInvestment') {
// //
// return `${data.reduce((sum, row) => sum + (row.estimatedTotalInvestment || 0), 0)}/${totalSum?.estimatedTotalInvestment||0}`
// }
// })
]
},
},
// vxeGrid()vxe-table
{
// //
proxyConfig: { autoLoad: false, ajax: { query: ({ page, sort }) => handleQueryApi(page, sort) } },
//
sortConfig: { defaultSort: Local.get(localPageParamKey)?.defaultSort || state.localPageParam.defaultSort },
//
pagerConfig: { enabled: false },
//
toolbarConfig: { export: false },
//
// rowConfig: { height: 80 },
//
customConfig: {
visibleMethod({ column }) {
return checkTableColumnVisible(`entityList:${column.field}`);
},
},
showFooter: true, //
}
);
//
onMounted(async () => {
options.loading = true;
let res = await getAPI(SysDatabaseApi).apiSysDatabaseListGet();
state.dbData = res.data.result;
// let appNamesRes = await getAPI(SysCodeGenApi).apiSysCodeGenApplicationNamespacesGet();
// state.appNamespaces = appNamesRes.data.result as Array<string>;
options.loading = false;
});
// api
const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, sort: VxeGridPropTypes.ProxyAjaxQuerySortCheckedParams) => {
if (state.configId) {
return getEntityClassList(state.configId);
}
};
//
const handleQuery = async (reset = false) => {
options.loading = true;
reset ? await xGrid.value?.commitProxy('reload') : await xGrid.value?.commitProxy('query');
options.loading = false;
};
const listhandleQuery= async (qparams: any) => {
await handleQuery(true);
};
//
const resetQuery = async () => {
state.queryParams.searchKey = undefined;
state.queryParams.projectName = undefined;
state.queryParams.financingProjectName = undefined;
state.queryParams.projectType = undefined;
state.queryParams.constructionStatus = undefined;
state.queryParams.approvalNumber = undefined;
state.queryParams.approvalDate = undefined;
state.queryParams.constructionAddress = undefined;
await xGrid.value?.commitProxy('reload');
};
//
const gridEvents: VxeGridListeners = {
//
async cellClick({ row, column }) {
listClick(row,column);
},
//
checkboxChange({ records }) {
state.selectedRows = records;
},
// / selectedRows
checkboxAll({ records }) {
state.selectedRows = records;
},
// pager-config
async pageChange({ pageSize }) {
state.localPageParam.pageSize = pageSize;
Local.set(localPageParamKey, state.localPageParam);
},
//
async sortChange({ field, order }) {
state.localPageParam.defaultSort = { field: field, order: order!, descStr: 'desc' };
Local.set(localPageParamKey, state.localPageParam);
},
};
//
const handleQueryTable = async () => {
if (!state.configId) {
xGrid.value?.loadData([]);
return;
}
options.loading = true;
try {
const res = await getEntityClassList(state.configId);
const tableData = res?.data?.result ?? [];
xGrid.value?.loadData(tableData);
} catch (error) {
ElMessage.error('加载实体类列表失败');
xGrid.value?.loadData([]);
} finally {
options.loading = false;
}
};
//
const emits = defineEmits(['list-click']);
const listClick = (row: any,column:any) => {
emits('list-click', row,column);
};
//
const handleInitTable = async () => {
if (!state.configId) {
ElMessage.warning('请先选择库名');
return;
}
if (!state.selectedRows.length) {
ElMessage.warning('请至少选择一个实体');
return;
}
options.loading = true;
try {
const params = {
configId: state.configId,
entityNames: state.selectedRows.map(row => row.name)
};
await initTable(params);
ElMessage.success('生成表操作成功');
} catch (error) {
ElMessage.error('生成表操作失败');
} finally {
options.loading = false;
}
};
//
defineExpose({ listhandleQuery });
</script>
<style lang="scss" scoped>
:deep(.el-input),
:deep(.el-select),
:deep(.el-input-number) {
width: 100%;
}
:deep(.el-slider .el-input-number){
width: auto;
}
</style>

View File

@ -1,284 +0,0 @@
<template>
<el-card shadow="hover" :body-style="{ padding: '20px 20px 16px 10px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%" @submit.prevent="handleQuery" >
<el-row :gutter="10">
<el-col class="mb5" :xs="24" :sm="10" :md="10" :lg="10" :xl="10">
<el-form-item label="库名" prop="configId">
<el-select v-model="state.configId" placeholder="库名" filterable @change="handleQueryTable">
<el-option v-for="item in state.dbData" :key="item.configId" :label="`${item.dbName}(${item.configId})`" :value="item.configId" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
<el-row>
<el-col>
<el-button-group>
<el-button type="primary" icon="ele-Search" @click="handleinitSeedData" :loading="options.loading">
生成数据<span v-if="state.selectedRows.length > 0">({{ state.selectedRows.length }})</span>
</el-button>
</el-button-group>
</el-col>
</el-row>
</el-card>
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" v-on="gridEvents">
<template #row_record="{ row }">
<ModifyRecord :data="row" />
</template>
</vxe-grid>
<div style="text-align: right; margin: 7px 8px 7px 0px; color: #666; font-size: 12px;">
{{ xGrid?.getTableData ? xGrid.getTableData().fullData.length : 0 }} 条记录
</div>
</el-card>
</template>
<script lang="ts" setup name="entityList">
import { onMounted, reactive, ref } from 'vue';
import { ElMessageBox, ElMessage } from "element-plus";
import { useUserInfo } from '/@/stores/userInfo';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import { formatDate } from '/@/utils/formatTime';
import { getAPI } from '/@/utils/axios-utils';
import { SysDatabaseApi } from '/@/api-services/api';
import { getSeedDataList, initSeedData } from '/@/api/system/dataInit';
//
const xGrid = ref<VxeGridInstance>();
const userStore = useUserInfo();
const dc = userStore.getDictItemByValue;
const dv = userStore.getDictItemByLabel;
const dl = userStore.getDictDataByCode;
//
const state = reactive({
loading: false,
dbData: [] as any,
configId: '',
showAdvanceQueryUI: false,
queryParams: {
searchKey: undefined,
GroupBy: [] as any,
projectName: undefined,
financingProjectName: undefined,
projectType: undefined,
constructionStatus: undefined,
approvalNumber: undefined,
approvalDate: undefined,
approvalDateRange: undefined,
constructionAddress: undefined,
},
localPageParam: {
pageSize: 50 as number,
defaultSort: { field: 'Id', order: 'asc', descStr: 'desc' },
},
totalSum:[] as any,
visible: false,
title: '',
selectedRows: [] as any[],
});
//
const localPageParamKey = 'localPageParam:entityList';
//
const changeAdvanceQueryUI = () => {
state.showAdvanceQueryUI = !state.showAdvanceQueryUI;
};
//
const checkTableColumnVisible = (tableColumnName: any) => {
return !userStore.userTableList.includes(tableColumnName);
};
//
const options = useVxeTable(
{
id: 'entityList',
name: '项目信息',
columns: [
{ type: 'checkbox', width: 40, fixed: 'left' },
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
{ field: 'assemblyName', title: '程序集', minWidth: 120, showOverflow: 'tooltip', sortable: false},
{ field: 'name', title: '名称', minWidth: 200, showOverflow: 'tooltip', sortable: false},
{ field: 'description', title: '描述', minWidth: 200, showOverflow: 'tooltip', sortable: false},
// { title: '', fixed: 'right', width: 120, showOverflow: true, slots: { default: 'row_buttons' } },
],
footerMethod: ({ columns, data }) => {
const totalSum=state.totalSum[0];
return [
// columns.map((column, colIndex) => {
// if (colIndex === 0) {
// return ``
// }
// if (column.field === 'estimatedTotalInvestment') {
// //
// return `${data.reduce((sum, row) => sum + (row.estimatedTotalInvestment || 0), 0)}/${totalSum?.estimatedTotalInvestment||0}`
// }
// })
]
},
},
// vxeGrid()vxe-table
{
// //
proxyConfig: { autoLoad: false, ajax: { query: ({ page, sort }) => handleQueryApi(page, sort) } },
//
sortConfig: { defaultSort: Local.get(localPageParamKey)?.defaultSort || state.localPageParam.defaultSort },
//
pagerConfig: { enabled: false },
//
toolbarConfig: { export: false },
//
// rowConfig: { height: 80 },
//
customConfig: {
visibleMethod({ column }) {
return checkTableColumnVisible(`entityList:${column.field}`);
},
},
showFooter: true, //
}
);
//
onMounted(async () => {
options.loading = true;
let res = await getAPI(SysDatabaseApi).apiSysDatabaseListGet();
state.dbData = res.data.result;
// let appNamesRes = await getAPI(SysCodeGenApi).apiSysCodeGenApplicationNamespacesGet();
// state.appNamespaces = appNamesRes.data.result as Array<string>;
options.loading = false;
});
// api
const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, sort: VxeGridPropTypes.ProxyAjaxQuerySortCheckedParams) => {
if (state.configId) {
return getSeedDataList(state.configId);
}
};
//
const handleQuery = async (reset = false) => {
options.loading = true;
reset ? await xGrid.value?.commitProxy('reload') : await xGrid.value?.commitProxy('query');
options.loading = false;
};
const listhandleQuery= async (qparams: any) => {
await handleQuery(true);
};
//
const resetQuery = async () => {
state.queryParams.searchKey = undefined;
state.queryParams.projectName = undefined;
state.queryParams.financingProjectName = undefined;
state.queryParams.projectType = undefined;
state.queryParams.constructionStatus = undefined;
state.queryParams.approvalNumber = undefined;
state.queryParams.approvalDate = undefined;
state.queryParams.constructionAddress = undefined;
await xGrid.value?.commitProxy('reload');
};
//
const gridEvents: VxeGridListeners = {
//
async cellClick({ row, column }) {
listClick(row,column);
},
//
checkboxChange({ records }) {
state.selectedRows = records;
},
// / selectedRows
checkboxAll({ records }) {
state.selectedRows = records;
},
// pager-config
async pageChange({ pageSize }) {
state.localPageParam.pageSize = pageSize;
Local.set(localPageParamKey, state.localPageParam);
},
//
async sortChange({ field, order }) {
state.localPageParam.defaultSort = { field: field, order: order!, descStr: 'desc' };
Local.set(localPageParamKey, state.localPageParam);
},
};
//
const handleQueryTable = async () => {
if (!state.configId) {
xGrid.value?.loadData([]);
return;
}
options.loading = true;
try {
const res = await getSeedDataList(state.configId);
const tableData = res?.data?.result ?? [];
xGrid.value?.loadData(tableData);
} catch (error) {
ElMessage.error('加载实体类列表失败');
xGrid.value?.loadData([]);
} finally {
options.loading = false;
}
};
//
const emits = defineEmits(['list-click']);
const listClick = (row: any,column:any) => {
emits('list-click', row,column);
};
//
const handleinitSeedData = async () => {
if (!state.configId) {
ElMessage.warning('请先选择库名');
return;
}
if (!state.selectedRows.length) {
ElMessage.warning('请至少选择一个实体');
return;
}
options.loading = true;
try {
const params = {
configId: state.configId,
entityNames: state.selectedRows.map(row => row.name)
};
await initSeedData(params);
ElMessage.success('生成种子数据操作成功');
} catch (error) {
ElMessage.error('生成种子数据操作失败');
} finally {
options.loading = false;
}
};
//
defineExpose({ listhandleQuery });
</script>
<style lang="scss" scoped>
:deep(.el-input),
:deep(.el-select),
:deep(.el-input-number) {
width: 100%;
}
:deep(.el-slider .el-input-number){
width: auto;
}
</style>

View File

@ -1,62 +0,0 @@
<template>
<div class="prj-entry-container full-height">
<el-row :gutter="8" style="width: 100%; height: 100%; flex: 1">
<el-col :span="12" :xs="24" class="full-height">
<EntityList ref="EntityListRef"/>
</el-col>
<el-col :span="12" :xs="24" class="full-height">
<SeedDataList ref="SeedDataListRef"/>
</el-col>
</el-row>
</div>
</template>
<script lang="ts" setup name="baseInfo">
import { onMounted, reactive, ref } from 'vue';
import { ElMessageBox, ElMessage } from "element-plus";
import EntityList from '/@/views/system/dataInit/component/entityList.vue';
import SeedDataList from '/@/views/system/dataInit/component/seedDataList.vue';
const EntityListRef = ref<InstanceType<typeof EntityList>>();
const SeedDataListRef = ref<InstanceType<typeof SeedDataList>>();
//
const state = reactive({
queryParams: {
searchKey: undefined,
projectName: undefined,
financingProjectName: undefined,
projectType: undefined,
constructionStatus: undefined,
approvalNumber: undefined,
approvalDate: undefined,
constructionAddress: undefined,
}
});
//
onMounted(() => {
EntityListRef.value?.listhandleQuery(state.queryParams);//
});
</script>
<style lang="scss" scoped>
.prj-entry-container {
height: 100%;
display: flex;
flex-direction: column;
}
.full-height {
display: flex;
flex-direction: column;
height: 100%;
}
:deep(.el-input),
:deep(.el-select),
:deep(.el-input-number) {
width: 100%;
}
:deep(.el-slider .el-input-number){
width: auto;
}
</style>

View File

@ -0,0 +1,202 @@
<template>
<div class="sys-initTableAndSeedData-container">
<vxe-modal v-model="state.visible" title="初始化库表结构及种子数据" fullscreen show-zoom resize width="100vw" height="100vh">
<splitpanes class="default-theme">
<pane size="50">
<vxe-grid ref="xGridEntity" class="xGrid-style" v-bind="optionsEntity" v-on="gridEventsEntity">
<template #toolbar_buttons>
<el-button type="warning" icon="ele-Refresh" @click="handleInitTable">
初始化表结构<span v-if="state.entitySelectedRows.length > 0">({{ state.entitySelectedRows.length }})</span>
</el-button>
</template>
</vxe-grid>
</pane>
<pane size="50">
<vxe-grid ref="xGridSeed" class="xGrid-style" v-bind="optionsSeed" v-on="gridEventsSeed">
<template #toolbar_buttons>
<el-button type="warning" icon="ele-Refresh" @click="handleInitSeedData">
初始化种子数据<span v-if="state.seedSelectedRows.length > 0">({{ state.seedSelectedRows.length }})</span>
</el-button>
</template>
</vxe-grid>
</pane>
</splitpanes>
</vxe-modal>
</div>
</template>
<script lang="tsx" setup name="sysInitTableAndSeedData">
import { reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import { getAPI } from '/@/utils/axios-utils';
import { SysCodeGenApi, SysDatabaseApi } from '/@/api-services/api';
const xGridEntity = ref<VxeGridInstance>();
const xGridSeed = ref<VxeGridInstance>();
const state = reactive({
visible: false,
configId: '',
entityTotalSum: [] as any,
entitySelectedRows: [] as any[],
seedTotalSum: [] as any,
seedSelectedRows: [] as any[],
});
// -
const optionsEntity = useVxeTable(
{
id: 'entity',
name: '实体数据',
columns: [
{ type: 'checkbox', width: 40, fixed: 'left' },
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
{ field: 'entityName', title: '实体名称', showOverflow: 'tooltip', sortable: false },
{ field: 'tableName', title: '表名称', showOverflow: 'tooltip', sortable: false },
{ field: 'tableComment', title: '描述', showOverflow: 'tooltip', sortable: false },
{ field: 'assemblyName', title: '程序集', showOverflow: 'tooltip', sortable: false },
],
},
{
//
proxyConfig: { autoLoad: true, ajax: { query: ({ page, sort }) => getEntityQueryApi(page, sort) } },
//
pagerConfig: { enabled: false },
//
toolbarConfig: { export: true },
//
checkboxConfig: { range: true, highlight: false },
//
showFooter: true,
}
);
//
const getEntityQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, sort: VxeGridPropTypes.ProxyAjaxQuerySortCheckedParams) => {
return await getAPI(SysCodeGenApi).apiSysCodeGenTableListConfigIdGet(state.configId);
};
// -
const gridEventsEntity: VxeGridListeners = {
//
checkboxChange({ records }) {
state.entitySelectedRows = records;
},
// /
checkboxAll({ records }) {
state.entitySelectedRows = records;
},
};
//
const handleInitTable = async () => {
if (!state.configId) {
ElMessage.warning('请先选择库名');
return;
}
if (!state.entitySelectedRows.length) {
ElMessage.warning('请至少选择一个实体');
return;
}
try {
optionsEntity.loading = true;
const params = {
configId: state.configId,
entityNames: state.entitySelectedRows.map((row) => row.name),
};
await getAPI(SysDatabaseApi).apiSysDatabaseInitTablePost(params);
ElMessage.success('初始化表结构操作成功');
} catch (error) {
ElMessage.error('初始化表结构操作失败');
} finally {
optionsEntity.loading = false;
}
};
// -
const optionsSeed = useVxeTable(
{
id: 'seed',
name: '种子数据',
columns: [
{ type: 'checkbox', width: 40, fixed: 'left' },
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
{ field: 'name', title: '种子名称', showOverflow: 'tooltip', sortable: false },
{ field: 'description', title: '描述', showOverflow: 'tooltip', sortable: false },
{ field: 'assemblyName', title: '程序集', showOverflow: 'tooltip', sortable: false },
],
},
{
//
proxyConfig: { autoLoad: true, ajax: { query: ({ page, sort }) => getSeedQueryApi(page, sort) } },
//
pagerConfig: { enabled: false },
//
toolbarConfig: { export: true },
//
checkboxConfig: { range: true, highlight: false },
//
showFooter: true,
}
);
//
const getSeedQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, sort: VxeGridPropTypes.ProxyAjaxQuerySortCheckedParams) => {
return await getAPI(SysDatabaseApi).apiSysDatabaseSeedDataListGet(state.configId);
};
// -
const gridEventsSeed: VxeGridListeners = {
//
checkboxChange({ records }) {
state.seedSelectedRows = records;
},
// /
checkboxAll({ records }) {
state.seedSelectedRows = records;
},
};
//
const handleInitSeedData = async () => {
if (!state.configId) {
ElMessage.warning('请先选择库名');
return;
}
if (!state.seedSelectedRows.length) {
ElMessage.warning('请至少选择一个实体');
return;
}
optionsSeed.loading = true;
try {
const params = {
configId: state.configId,
entityNames: state.seedSelectedRows.map((row) => row.name),
};
await getAPI(SysDatabaseApi).apiSysDatabaseInitSeedDataPost(params);
ElMessage.success('生成种子数据操作成功');
} catch (error) {
ElMessage.error('生成种子数据操作失败');
} finally {
optionsSeed.loading = false;
}
};
//
const openDialog = (configId: any) => {
state.configId = configId;
state.visible = true;
};
//
defineExpose({ openDialog });
</script>
<style lang="scss" scoped></style>

View File

@ -30,15 +30,16 @@
<el-button icon="ele-Delete" type="danger" @click="handleDeleteTable"> 删除表 </el-button>
</el-button-group>
<el-button-group style="padding-left: 12px; padding-right: 12px">
<el-button icon="ele-Plus" @click="showAddColumn"> 增加列 </el-button>
<el-button icon="ele-Plus" @click="showGenDialog"> 生成实体 </el-button>
<el-button icon="ele-CirclePlus" @click="showAddColumn"> 增加列 </el-button>
<el-button icon="ele-CirclePlus" @click="showGenDialog"> 生成实体 </el-button>
<el-popover placement="bottom" title="🔔提示" :width="220" trigger="hover" content="如果是刚刚生成的实体,请重启后台服务后再生成种子。">
<template #reference>
<el-button icon="ele-Plus" @click="showGenSeedDataDialog"> 生成种子 </el-button>
<el-button icon="ele-CirclePlus" @click="showGenSeedDataDialog"> 生成种子 </el-button>
</template>
</el-popover>
</el-button-group>
<el-button icon="ele-View" type="primary" @click="visualTable" plain> 可视化 </el-button>
<el-button icon="ele-Refresh" type="warning" @click="handleInitTableAndSeedData"> 初始化库表结构及种子数据 </el-button>
<el-button icon="ele-View" type="primary" plain @click="visualTable"> 库表关系可视化 </el-button>
</template>
<template #toolbar_tools> </template>
<template #empty>
@ -73,6 +74,7 @@
<AddColumn ref="addColumnRef" @handleQueryColumn="handleQueryColumn" />
<GenEntity ref="genEntityRef" :applicationNamespaces="state.appNamespaces" />
<GenSeedData ref="genSeedDataRef" :applicationNamespaces="state.appNamespaces" />
<InitTableAndSeedData ref="initTableAndSeedDataRef" />
</div>
</template>
@ -89,6 +91,7 @@ import AddTable from '/@/views/system/database/component/addTable.vue';
import AddColumn from '/@/views/system/database/component/addColumn.vue';
import GenEntity from '/@/views/system/database/component/genEntity.vue';
import GenSeedData from '/@/views/system/database/component/genSeedData.vue';
import InitTableAndSeedData from '/@/views/system/database/component/initTableAndSeedData.vue';
import { getAPI } from '/@/utils/axios-utils';
import { SysDatabaseApi, SysCodeGenApi } from '/@/api-services/api';
@ -101,6 +104,7 @@ const addTableRef = ref<InstanceType<typeof AddTable>>();
const addColumnRef = ref<InstanceType<typeof AddColumn>>();
const genEntityRef = ref<InstanceType<typeof GenEntity>>();
const genSeedDataRef = ref<InstanceType<typeof GenSeedData>>();
const initTableAndSeedDataRef = ref<InstanceType<typeof InitTableAndSeedData>>();
const router = useRouter();
const state = reactive({
loading: false,
@ -337,6 +341,15 @@ const handleDeleteColumn = (row: any) => {
.catch(() => {});
};
//
const handleInitTableAndSeedData = () => {
if (state.configId == '') {
ElMessage({ type: 'error', message: `请选择库名!` });
return;
}
initTableAndSeedDataRef.value?.openDialog(state.configId);
};
//
const visualTable = () => {
if (state.configId == '') {