From 21009bb1e7025640d65b1682aea3efdb00b23e01 Mon Sep 17 00:00:00 2001 From: Master Date: Mon, 8 Jul 2024 10:10:02 +0800 Subject: [PATCH 01/62] =?UTF-8?q?=E6=A8=A1=E7=89=88=E5=A2=9E=E5=8A=A0=20?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E5=85=B3=E9=94=AE=E5=AD=97=20=E6=A8=A1?= =?UTF-8?q?=E7=89=88=E5=A2=9E=E5=8A=A0=20=E6=90=9C=E7=B4=A2=E9=A1=B9?= =?UTF-8?q?=E6=8A=98=E5=8F=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wwwroot/Template/index.vue.vm | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm index 07501517..830eecb8 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm @@ -19,25 +19,30 @@ } } else if(@column.EffectType == "DatePicker") { @: } } From 725d50f624f35250d6462dff9a6cb4294799120c Mon Sep 17 00:00:00 2001 From: coolcalf <28551@qq.com> Date: Tue, 9 Jul 2024 15:17:34 +0800 Subject: [PATCH 04/62] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=EF=BC=9A=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E7=BC=93=E5=AD=98=E7=9A=84=E5=89=A9=E4=BD=99=E7=94=9F?= =?UTF-8?q?=E5=AD=98=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs | 2 +- .../Admin.NET.Core/Service/Cache/SysCacheService.cs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs b/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs index 94b33c53..d4ef92a3 100644 --- a/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs +++ b/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs @@ -63,7 +63,7 @@ public class SysWechatRefund : EntityBase /// 退款资金来源, 可不传,默认使用未结算资金退款(仅对老资金流商户适用) /// [SugarColumn(ColumnDescription = "退款资金来源", Length = 32)] - public string FundsAccount { get; set; } + public string? FundsAccount { get; set; } /// /// 关联的商户订单号 diff --git a/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs b/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs index 89d79784..4876809a 100644 --- a/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs @@ -62,6 +62,17 @@ public class SysCacheService : IDynamicApiController, ISingleton return _cacheProvider.Cache.Set($"{_cacheOptions.Prefix}{key}", value, expire); } + /// + /// 获取缓存的剩余生存时间 + /// + /// + /// + [NonAction] + public TimeSpan GetExpire(string key) + { + return _cacheProvider.Cache.GetExpire(key); + } + /// /// 获取缓存 /// From 1186e6acf31c6dcf0fdd4049569c694eeb2756b0 Mon Sep 17 00:00:00 2001 From: Master Date: Wed, 10 Jul 2024 10:26:55 +0800 Subject: [PATCH 05/62] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A2=9D=E5=A4=96?= =?UTF-8?q?=E7=9A=84=20api=5Fbuild=20=E5=A2=9E=E5=8A=A0=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E7=94=9F=E6=88=90=E6=8E=A5=E5=8F=A3=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Admin.NET/Admin.NET.Core/Entity/SysCodeGen.cs | 254 +-- .../Service/CodeGen/CustomViewEngine.cs | 200 +- .../Service/CodeGen/Dto/CodeGenInput.cs | 372 ++-- .../Service/CodeGen/Dto/CodeGenOutput.cs | 169 +- .../Service/CodeGen/SysCodeGenService.cs | 1622 +++++++++-------- .../wwwroot/Template/editDialog.vue.vm | 41 +- .../wwwroot/Template/index.vue.vm | 26 +- Web/api_build/build.bat | 2 +- Web/api_build/build.sh | 2 +- Web/api_build/build_approvalFlow.bat | 27 + Web/api_build/build_approvalFlow.sh | 28 + Web/api_build/build_dingTalk.bat | 27 + Web/api_build/build_dingTalk.sh | 28 + Web/api_build/build_goView.bat | 27 + Web/api_build/build_goView.sh | 28 + .../codeGen/component/editCodeGenDialog.vue | 8 + 16 files changed, 1551 insertions(+), 1310 deletions(-) create mode 100644 Web/api_build/build_approvalFlow.bat create mode 100644 Web/api_build/build_approvalFlow.sh create mode 100644 Web/api_build/build_dingTalk.bat create mode 100644 Web/api_build/build_dingTalk.sh create mode 100644 Web/api_build/build_goView.bat create mode 100644 Web/api_build/build_goView.sh diff --git a/Admin.NET/Admin.NET.Core/Entity/SysCodeGen.cs b/Admin.NET/Admin.NET.Core/Entity/SysCodeGen.cs index ba23d162..8ec86d27 100644 --- a/Admin.NET/Admin.NET.Core/Entity/SysCodeGen.cs +++ b/Admin.NET/Admin.NET.Core/Entity/SysCodeGen.cs @@ -1,125 +1,131 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -namespace Admin.NET.Core; - -/// -/// 代码生成表 -/// -[SugarTable(null, "代码生成表")] -[SysTable] -[SugarIndex("index_{table}_B", nameof(BusName), OrderByType.Asc)] -[SugarIndex("index_{table}_T", nameof(TableName), OrderByType.Asc)] -public partial class SysCodeGen : EntityBase -{ - /// - /// 作者姓名 - /// - [SugarColumn(ColumnDescription = "作者姓名", Length = 32)] - [MaxLength(32)] - public string? AuthorName { get; set; } - - /// - /// 是否移除表前缀 - /// - [SugarColumn(ColumnDescription = "是否移除表前缀", Length = 8)] - [MaxLength(8)] - public string? TablePrefix { get; set; } - - /// - /// 生成方式 - /// - [SugarColumn(ColumnDescription = "生成方式", Length = 32)] - [MaxLength(32)] - public string? GenerateType { get; set; } - - /// - /// 库定位器名 - /// - [SugarColumn(ColumnDescription = "库定位器名", Length = 64)] - [MaxLength(64)] - public string? ConfigId { get; set; } - - /// - /// 数据库名(保留字段) - /// - [SugarColumn(ColumnDescription = "数据库库名", Length = 64)] - [MaxLength(64)] - public string? DbName { get; set; } - - /// - /// 数据库类型 - /// - [SugarColumn(ColumnDescription = "数据库类型", Length = 64)] - [MaxLength(64)] - public string? DbType { get; set; } - - /// - /// 数据库链接 - /// - [SugarColumn(ColumnDescription = "数据库链接", Length = 256)] - [MaxLength(256)] - public string? ConnectionString { get; set; } - - /// - /// 数据库表名 - /// - [SugarColumn(ColumnDescription = "数据库表名", Length = 128)] - [MaxLength(128)] - public string? TableName { get; set; } - - /// - /// 命名空间 - /// - [SugarColumn(ColumnDescription = "命名空间", Length = 128)] - [MaxLength(128)] - public string? NameSpace { get; set; } - - /// - /// 业务名 - /// - [SugarColumn(ColumnDescription = "业务名", Length = 128)] - [MaxLength(128)] - public string? BusName { get; set; } - - /// - /// 是否生成菜单 - /// - [SugarColumn(ColumnDescription = "是否生成菜单")] - public bool GenerateMenu { get; set; } = true; - - /// - /// 菜单图标 - /// - [SugarColumn(ColumnDescription = "菜单图标", Length = 32)] - public string? MenuIcon { get; set; } = "ele-Menu"; - - /// - /// 菜单编码 - /// - [SugarColumn(ColumnDescription = "菜单编码")] - public long? MenuPid { get; set; } - - /// - /// 页面目录 - /// - [SugarColumn(ColumnDescription = "页面目录", Length = 32)] - public string? PagePath { get; set; } - - /// - /// 支持打印类型 - /// - [SugarColumn(ColumnDescription = "支持打印类型", Length = 32)] - [MaxLength(32)] - public string? PrintType { get; set; } - - /// - /// 打印模版名称 - /// - [SugarColumn(ColumnDescription = "打印模版名称", Length = 32)] - [MaxLength(32)] - public string? PrintName { get; set; } +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 代码生成表 +/// +[SugarTable(null, "代码生成表")] +[SysTable] +[SugarIndex("index_{table}_B", nameof(BusName), OrderByType.Asc)] +[SugarIndex("index_{table}_T", nameof(TableName), OrderByType.Asc)] +public partial class SysCodeGen : EntityBase +{ + /// + /// 作者姓名 + /// + [SugarColumn(ColumnDescription = "作者姓名", Length = 32)] + [MaxLength(32)] + public string? AuthorName { get; set; } + + /// + /// 是否移除表前缀 + /// + [SugarColumn(ColumnDescription = "是否移除表前缀", Length = 8)] + [MaxLength(8)] + public string? TablePrefix { get; set; } + + /// + /// 生成方式 + /// + [SugarColumn(ColumnDescription = "生成方式", Length = 32)] + [MaxLength(32)] + public string? GenerateType { get; set; } + + /// + /// 库定位器名 + /// + [SugarColumn(ColumnDescription = "库定位器名", Length = 64)] + [MaxLength(64)] + public string? ConfigId { get; set; } + + /// + /// 数据库名(保留字段) + /// + [SugarColumn(ColumnDescription = "数据库库名", Length = 64)] + [MaxLength(64)] + public string? DbName { get; set; } + + /// + /// 数据库类型 + /// + [SugarColumn(ColumnDescription = "数据库类型", Length = 64)] + [MaxLength(64)] + public string? DbType { get; set; } + + /// + /// 数据库链接 + /// + [SugarColumn(ColumnDescription = "数据库链接", Length = 256)] + [MaxLength(256)] + public string? ConnectionString { get; set; } + + /// + /// 数据库表名 + /// + [SugarColumn(ColumnDescription = "数据库表名", Length = 128)] + [MaxLength(128)] + public string? TableName { get; set; } + + /// + /// 命名空间 + /// + [SugarColumn(ColumnDescription = "命名空间", Length = 128)] + [MaxLength(128)] + public string? NameSpace { get; set; } + + /// + /// 业务名 + /// + [SugarColumn(ColumnDescription = "业务名", Length = 128)] + [MaxLength(128)] + public string? BusName { get; set; } + + /// + /// 是否生成菜单 + /// + [SugarColumn(ColumnDescription = "是否生成菜单")] + public bool GenerateMenu { get; set; } = true; + + /// + /// 菜单图标 + /// + [SugarColumn(ColumnDescription = "菜单图标", Length = 32)] + public string? MenuIcon { get; set; } = "ele-Menu"; + + /// + /// 菜单编码 + /// + [SugarColumn(ColumnDescription = "菜单编码")] + public long? MenuPid { get; set; } + + /// + /// 页面目录 + /// + [SugarColumn(ColumnDescription = "页面目录", Length = 32)] + public string? PagePath { get; set; } + + /// + /// 支持打印类型 + /// + [SugarColumn(ColumnDescription = "支持打印类型", Length = 32)] + [MaxLength(32)] + public string? PrintType { get; set; } + + /// + /// 打印模版名称 + /// + [SugarColumn(ColumnDescription = "打印模版名称", Length = 32)] + [MaxLength(32)] + public string? PrintName { get; set; } + + /// + /// 是否使用 Api Service + /// + [SugarColumn(ColumnDescription = "是否使用 Api Service")] + public bool IsApiService { get; set; } = false; } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/CustomViewEngine.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/CustomViewEngine.cs index d202e728..a2f2449e 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/CustomViewEngine.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/CustomViewEngine.cs @@ -1,100 +1,102 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -namespace Admin.NET.Core.Service; - -public class CustomViewEngine : ViewEngineModel -{ - private readonly ISqlSugarClient _db; - - public CustomViewEngine() - { - } - - public CustomViewEngine(ISqlSugarClient db) - { - _db = db; - } - - /// - /// 库定位器 - /// - public string ConfigId { get; set; } = SqlSugarConst.MainConfigId; - - public string AuthorName { get; set; } - - public string BusName { get; set; } - - public string NameSpace { get; set; } - - public string ClassName { get; set; } - - public string ProjectLastName { get; set; } - - public string LowerClassName - { - get - { - return ClassName[..1].ToLower() + ClassName[1..]; // 首字母小写 - } - } - - public string PagePath { get; set; } = "main"; - - public bool IsJoinTable { get; set; } - - public bool IsUpload { get; set; } - - public string PrintType { get; set; } - - public string PrintName { get; set; } - - public List QueryWhetherList { get; set; } - - public List TableField { get; set; } - - private List ColumnList { get; set; } - - public string GetColumnNetType(object tbName, object colName) - { - if (tbName == null || colName == null) return null; - - var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == ConfigId); - ColumnList = GetColumnListByTableName(tbName.ToString()); - var col = ColumnList.Where(c => (config.DbSettings.EnableUnderLine - ? CodeGenUtil.CamelColumnName(c.ColumnName, Array.Empty()) - : c.ColumnName) == colName.ToString()).FirstOrDefault(); - return col.NetType; - } - - public List GetColumnListByTableName(string tableName) - { - // 多库代码生成切换库 - var provider = _db.AsTenant().GetConnectionScope(ConfigId != SqlSugarConst.MainConfigId ? ConfigId : SqlSugarConst.MainConfigId); - - // 获取实体类型属性 - var entityType = provider.DbMaintenance.GetTableInfoList().FirstOrDefault(u => u.Name == tableName); - - // 因为ConfigId的表通常也会用到主库的表来做连接,所以这里如果在ConfigId中找不到实体也尝试一下在主库中查找 - if (ConfigId == SqlSugarConst.MainConfigId && entityType == null) return null; - if (ConfigId != SqlSugarConst.MainConfigId) - { - provider = _db.AsTenant().GetConnectionScope(SqlSugarConst.MainConfigId); - entityType = provider.DbMaintenance.GetTableInfoList().FirstOrDefault(u => u.Name == tableName); - if (entityType == null) return null; - } - - // 按原始类型的顺序获取所有实体类型属性(不包含导航属性,会返回null) - return provider.DbMaintenance.GetColumnInfosByTableName(entityType.Name).Select(u => new ColumnOuput - { - ColumnName = u.DbColumnName, - ColumnKey = u.IsPrimarykey.ToString(), - DataType = u.DataType.ToString(), - NetType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), - ColumnComment = u.ColumnDescription - }).ToList(); - } +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Service; + +public class CustomViewEngine : ViewEngineModel +{ + private readonly ISqlSugarClient _db; + + public CustomViewEngine() + { + } + + public CustomViewEngine(ISqlSugarClient db) + { + _db = db; + } + + /// + /// 库定位器 + /// + public string ConfigId { get; set; } = SqlSugarConst.MainConfigId; + + public string AuthorName { get; set; } + + public string BusName { get; set; } + + public string NameSpace { get; set; } + + public string ClassName { get; set; } + + public string ProjectLastName { get; set; } + + public string LowerClassName + { + get + { + return ClassName[..1].ToLower() + ClassName[1..]; // 首字母小写 + } + } + + public string PagePath { get; set; } = "main"; + + public bool IsJoinTable { get; set; } + + public bool IsUpload { get; set; } + + public string PrintType { get; set; } + + public string PrintName { get; set; } + + public bool IsApiService { get; set; } + + public List QueryWhetherList { get; set; } + + public List TableField { get; set; } + + private List ColumnList { get; set; } + + public string GetColumnNetType(object tbName, object colName) + { + if (tbName == null || colName == null) return null; + + var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == ConfigId); + ColumnList = GetColumnListByTableName(tbName.ToString()); + var col = ColumnList.Where(c => (config.DbSettings.EnableUnderLine + ? CodeGenUtil.CamelColumnName(c.ColumnName, Array.Empty()) + : c.ColumnName) == colName.ToString()).FirstOrDefault(); + return col.NetType; + } + + public List GetColumnListByTableName(string tableName) + { + // 多库代码生成切换库 + var provider = _db.AsTenant().GetConnectionScope(ConfigId != SqlSugarConst.MainConfigId ? ConfigId : SqlSugarConst.MainConfigId); + + // 获取实体类型属性 + var entityType = provider.DbMaintenance.GetTableInfoList().FirstOrDefault(u => u.Name == tableName); + + // 因为ConfigId的表通常也会用到主库的表来做连接,所以这里如果在ConfigId中找不到实体也尝试一下在主库中查找 + if (ConfigId == SqlSugarConst.MainConfigId && entityType == null) return null; + if (ConfigId != SqlSugarConst.MainConfigId) + { + provider = _db.AsTenant().GetConnectionScope(SqlSugarConst.MainConfigId); + entityType = provider.DbMaintenance.GetTableInfoList().FirstOrDefault(u => u.Name == tableName); + if (entityType == null) return null; + } + + // 按原始类型的顺序获取所有实体类型属性(不包含导航属性,会返回null) + return provider.DbMaintenance.GetColumnInfosByTableName(entityType.Name).Select(u => new ColumnOuput + { + ColumnName = u.DbColumnName, + ColumnKey = u.IsPrimarykey.ToString(), + DataType = u.DataType.ToString(), + NetType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), + ColumnComment = u.ColumnDescription + }).ToList(); + } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenInput.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenInput.cs index f44ff273..ca7de041 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenInput.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenInput.cs @@ -1,182 +1,192 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -namespace Admin.NET.Core.Service; - -/// -/// 代码生成参数类 -/// -public class CodeGenInput : BasePageInput -{ - /// - /// 作者姓名 - /// - public virtual string AuthorName { get; set; } - - /// - /// 类名 - /// - public virtual string ClassName { get; set; } - - /// - /// 是否移除表前缀 - /// - public virtual string TablePrefix { get; set; } - - /// - /// 库定位器名 - /// - public virtual string ConfigId { get; set; } - - /// - /// 数据库名(保留字段) - /// - public virtual string DbName { get; set; } - - /// - /// 数据库类型 - /// - public virtual string DbType { get; set; } - - /// - /// 数据库链接 - /// - public virtual string ConnectionString { get; set; } - - /// - /// 生成方式 - /// - public virtual string GenerateType { get; set; } - - /// - /// 数据库表名 - /// - public virtual string TableName { get; set; } - - /// - /// 命名空间 - /// - public virtual string NameSpace { get; set; } - - /// - /// 业务名(业务代码包名称) - /// - public virtual string BusName { get; set; } - - /// - /// 功能名(数据库表名称) - /// - public virtual string TableComment { get; set; } - - /// - /// 菜单应用分类(应用编码) - /// - public virtual string MenuApplication { get; set; } - - /// - /// 是否生成菜单 - /// - public virtual bool GenerateMenu { get; set; } - - /// - /// 菜单父级 - /// - public virtual long? MenuPid { get; set; } - - /// - /// 页面目录 - /// - public virtual string PagePath { get; set; } - - /// - /// 支持打印类型 - /// - public virtual string PrintType { get; set; } - - /// - /// 打印模版名称 - /// - public virtual string PrintName { get; set; } -} - -public class AddCodeGenInput : CodeGenInput -{ - /// - /// 数据库表名 - /// - [Required(ErrorMessage = "数据库表名不能为空")] - public override string TableName { get; set; } - - /// - /// 业务名(业务代码包名称) - /// - [Required(ErrorMessage = "业务名不能为空")] - public override string BusName { get; set; } - - /// - /// 命名空间 - /// - [Required(ErrorMessage = "命名空间不能为空")] - public override string NameSpace { get; set; } - - /// - /// 作者姓名 - /// - [Required(ErrorMessage = "作者姓名不能为空")] - public override string AuthorName { get; set; } - - ///// - ///// 类名 - ///// - //[Required(ErrorMessage = "类名不能为空")] - //public override string ClassName { get; set; } - - ///// - ///// 是否移除表前缀 - ///// - //[Required(ErrorMessage = "是否移除表前缀不能为空")] - //public override string TablePrefix { get; set; } - - /// - /// 生成方式 - /// - [Required(ErrorMessage = "生成方式不能为空")] - public override string GenerateType { get; set; } - - ///// - ///// 功能名(数据库表名称) - ///// - //[Required(ErrorMessage = "数据库表名不能为空")] - //public override string TableComment { get; set; } - - /// - /// 是否生成菜单 - /// - [Required(ErrorMessage = "是否生成菜单不能为空")] - public override bool GenerateMenu { get; set; } -} - -public class DeleteCodeGenInput -{ - /// - /// 代码生成器Id - /// - [Required(ErrorMessage = "代码生成器Id不能为空")] - public long Id { get; set; } -} - -public class UpdateCodeGenInput : CodeGenInput -{ - /// - /// 代码生成器Id - /// - [Required(ErrorMessage = "代码生成器Id不能为空")] - public long Id { get; set; } -} - -public class QueryCodeGenInput : DeleteCodeGenInput -{ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Service; + +/// +/// 代码生成参数类 +/// +public class CodeGenInput : BasePageInput +{ + /// + /// 作者姓名 + /// + public virtual string AuthorName { get; set; } + + /// + /// 类名 + /// + public virtual string ClassName { get; set; } + + /// + /// 是否移除表前缀 + /// + public virtual string TablePrefix { get; set; } + + /// + /// 库定位器名 + /// + public virtual string ConfigId { get; set; } + + /// + /// 数据库名(保留字段) + /// + public virtual string DbName { get; set; } + + /// + /// 数据库类型 + /// + public virtual string DbType { get; set; } + + /// + /// 数据库链接 + /// + public virtual string ConnectionString { get; set; } + + /// + /// 生成方式 + /// + public virtual string GenerateType { get; set; } + + /// + /// 数据库表名 + /// + public virtual string TableName { get; set; } + + /// + /// 命名空间 + /// + public virtual string NameSpace { get; set; } + + /// + /// 业务名(业务代码包名称) + /// + public virtual string BusName { get; set; } + + /// + /// 功能名(数据库表名称) + /// + public virtual string TableComment { get; set; } + + /// + /// 菜单应用分类(应用编码) + /// + public virtual string MenuApplication { get; set; } + + /// + /// 是否生成菜单 + /// + public virtual bool GenerateMenu { get; set; } + + /// + /// 菜单父级 + /// + public virtual long? MenuPid { get; set; } + + /// + /// 页面目录 + /// + public virtual string PagePath { get; set; } + + /// + /// 支持打印类型 + /// + public virtual string PrintType { get; set; } + + /// + /// 打印模版名称 + /// + public virtual string PrintName { get; set; } + + /// + /// 是否使用 Api Service + /// + public virtual bool IsApiService { get; set; } +} + +public class AddCodeGenInput : CodeGenInput +{ + /// + /// 数据库表名 + /// + [Required(ErrorMessage = "数据库表名不能为空")] + public override string TableName { get; set; } + + /// + /// 业务名(业务代码包名称) + /// + [Required(ErrorMessage = "业务名不能为空")] + public override string BusName { get; set; } + + /// + /// 命名空间 + /// + [Required(ErrorMessage = "命名空间不能为空")] + public override string NameSpace { get; set; } + + /// + /// 作者姓名 + /// + [Required(ErrorMessage = "作者姓名不能为空")] + public override string AuthorName { get; set; } + + ///// + ///// 类名 + ///// + //[Required(ErrorMessage = "类名不能为空")] + //public override string ClassName { get; set; } + + ///// + ///// 是否移除表前缀 + ///// + //[Required(ErrorMessage = "是否移除表前缀不能为空")] + //public override string TablePrefix { get; set; } + + /// + /// 生成方式 + /// + [Required(ErrorMessage = "生成方式不能为空")] + public override string GenerateType { get; set; } + + ///// + ///// 功能名(数据库表名称) + ///// + //[Required(ErrorMessage = "数据库表名不能为空")] + //public override string TableComment { get; set; } + + /// + /// 是否生成菜单 + /// + [Required(ErrorMessage = "是否生成菜单不能为空")] + public override bool GenerateMenu { get; set; } + + /// + /// 是否使用 Api Service + /// + public override bool IsApiService { get; set; } +} + +public class DeleteCodeGenInput +{ + /// + /// 代码生成器Id + /// + [Required(ErrorMessage = "代码生成器Id不能为空")] + public long Id { get; set; } +} + +public class UpdateCodeGenInput : CodeGenInput +{ + /// + /// 代码生成器Id + /// + [Required(ErrorMessage = "代码生成器Id不能为空")] + public long Id { get; set; } +} + +public class QueryCodeGenInput : DeleteCodeGenInput +{ } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenOutput.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenOutput.cs index aee96f67..3b90760d 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenOutput.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenOutput.cs @@ -1,83 +1,88 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -namespace Admin.NET.Core.Service; - -/// -/// 代码生成参数类 -/// -public class CodeGenOutput -{ - /// - /// 代码生成器Id - /// - public long Id { get; set; } - - /// - /// 作者姓名 - /// - public string AuthorName { get; set; } - - /// - /// 类名 - /// - public string ClassName { get; set; } - - /// - /// 是否移除表前缀 - /// - public string TablePrefix { get; set; } - - /// - /// 生成方式 - /// - public string GenerateType { get; set; } - - /// - /// 数据库表名 - /// - public string TableName { get; set; } - - /// - /// 包名 - /// - public string PackageName { get; set; } - - /// - /// 业务名(业务代码包名称) - /// - public string BusName { get; set; } - - /// - /// 功能名(数据库表名称) - /// - public string TableComment { get; set; } - - /// - /// 菜单应用分类(应用编码) - /// - public string MenuApplication { get; set; } - - /// - /// 是否生成菜单 - /// - public bool GenerateMenu { get; set; } - - /// - /// 菜单父级 - /// - public long? MenuPid { get; set; } - - /// - /// 支持打印类型 - /// - public string PrintType { get; set; } - - /// - /// 打印模版名称 - /// - public string PrintName { get; set; } +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Service; + +/// +/// 代码生成参数类 +/// +public class CodeGenOutput +{ + /// + /// 代码生成器Id + /// + public long Id { get; set; } + + /// + /// 作者姓名 + /// + public string AuthorName { get; set; } + + /// + /// 类名 + /// + public string ClassName { get; set; } + + /// + /// 是否移除表前缀 + /// + public string TablePrefix { get; set; } + + /// + /// 生成方式 + /// + public string GenerateType { get; set; } + + /// + /// 数据库表名 + /// + public string TableName { get; set; } + + /// + /// 包名 + /// + public string PackageName { get; set; } + + /// + /// 业务名(业务代码包名称) + /// + public string BusName { get; set; } + + /// + /// 功能名(数据库表名称) + /// + public string TableComment { get; set; } + + /// + /// 菜单应用分类(应用编码) + /// + public string MenuApplication { get; set; } + + /// + /// 是否生成菜单 + /// + public bool GenerateMenu { get; set; } + + /// + /// 菜单父级 + /// + public long? MenuPid { get; set; } + + /// + /// 支持打印类型 + /// + public string PrintType { get; set; } + + /// + /// 打印模版名称 + /// + public string PrintName { get; set; } + + /// + /// 是否使用 Api Service + /// + public bool IsApiService { get; set; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs index 6f06463a..3cc5e5ae 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs @@ -1,811 +1,813 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -using System.IO.Compression; - -namespace Admin.NET.Core.Service; - -/// -/// 系统代码生成器服务 🧩 -/// -[ApiDescriptionSettings(Order = 270)] -public class SysCodeGenService : IDynamicApiController, ITransient -{ - private readonly ISqlSugarClient _db; - - private readonly SysCodeGenConfigService _codeGenConfigService; - private readonly IViewEngine _viewEngine; - private readonly CodeGenOptions _codeGenOptions; - - public SysCodeGenService(ISqlSugarClient db, - SysCodeGenConfigService codeGenConfigService, - IViewEngine viewEngine, - IOptions codeGenOptions) - { - _db = db; - _codeGenConfigService = codeGenConfigService; - _viewEngine = viewEngine; - _codeGenOptions = codeGenOptions.Value; - } - - /// - /// 获取代码生成分页列表 🔖 - /// - /// - /// - [DisplayName("获取代码生成分页列表")] - public async Task> Page(CodeGenInput input) - { - return await _db.Queryable() - .WhereIF(!string.IsNullOrWhiteSpace(input.TableName), u => u.TableName.Contains(input.TableName.Trim())) - .WhereIF(!string.IsNullOrWhiteSpace(input.BusName), u => u.BusName.Contains(input.BusName.Trim())) - .ToPagedListAsync(input.Page, input.PageSize); - } - - /// - /// 增加代码生成 🔖 - /// - /// - /// - [ApiDescriptionSettings(Name = "Add"), HttpPost] - [DisplayName("增加代码生成")] - public async Task AddCodeGen(AddCodeGenInput input) - { - var isExist = await _db.Queryable().Where(u => u.TableName == input.TableName).AnyAsync(); - if (isExist) - throw Oops.Oh(ErrorCodeEnum.D1400); - - var codeGen = input.Adapt(); - var newCodeGen = await _db.Insertable(codeGen).ExecuteReturnEntityAsync(); - // 加入配置表中 - _codeGenConfigService.AddList(GetColumnList(input), newCodeGen); - } - - /// - /// 更新代码生成 🔖 - /// - /// - /// - [ApiDescriptionSettings(Name = "Update"), HttpPost] - [DisplayName("更新代码生成")] - public async Task UpdateCodeGen(UpdateCodeGenInput input) - { - var isExist = await _db.Queryable().AnyAsync(u => u.TableName == input.TableName && u.Id != input.Id); - if (isExist) - throw Oops.Oh(ErrorCodeEnum.D1400); - - await _db.Updateable(input.Adapt()).ExecuteCommandAsync(); - } - - /// - /// 删除代码生成 🔖 - /// - /// - /// - [ApiDescriptionSettings(Name = "Delete"), HttpPost] - [DisplayName("删除代码生成")] - public async Task DeleteCodeGen(List inputs) - { - if (inputs == null || inputs.Count < 1) return; - - var codeGenConfigTaskList = new List(); - inputs.ForEach(u => - { - _db.Deleteable().In(u.Id).ExecuteCommand(); - - // 删除配置表中 - codeGenConfigTaskList.Add(_codeGenConfigService.DeleteCodeGenConfig(u.Id)); - }); - await Task.WhenAll(codeGenConfigTaskList); - } - - /// - /// 获取代码生成详情 🔖 - /// - /// - /// - [DisplayName("获取代码生成详情")] - public async Task GetDetail([FromQuery] QueryCodeGenInput input) - { - return await _db.Queryable().SingleAsync(u => u.Id == input.Id); - } - - /// - /// 获取数据库库集合 🔖 - /// - /// - [DisplayName("获取数据库库集合")] - public async Task> GetDatabaseList() - { - var dbConfigs = App.GetOptions().ConnectionConfigs; - return await Task.FromResult(dbConfigs.Adapt>()); - } - - /// - /// 获取数据库表(实体)集合 🔖 - /// - /// - [DisplayName("获取数据库表(实体)集合")] - public async Task> GetTableList(string configId = SqlSugarConst.MainConfigId) - { - var provider = _db.AsTenant().GetConnectionScope(configId); - var dbTableInfos = provider.DbMaintenance.GetTableInfoList(false); // 不能走缓存,否则切库不起作用 - - var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => configId.Equals(u.ConfigId)); - - var dbTableNames = dbTableInfos.Select(u => u.Name.ToLower()).ToList(); - IEnumerable entityInfos = await GetEntityInfos(); - - var tableOutputList = new List(); - foreach (var item in entityInfos) - { - var table = dbTableInfos.FirstOrDefault(u => u.Name.ToLower() == (config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(item.DbTableName) : item.DbTableName).ToLower()); - if (table == null) continue; - tableOutputList.Add(new TableOutput - { - ConfigId = configId, - EntityName = item.EntityName, - TableName = table.Name, - TableComment = item.TableDescription - }); - } - return tableOutputList; - } - - /// - /// 根据表名获取列集合 🔖 - /// - /// - [DisplayName("根据表名获取列集合")] - public List GetColumnListByTableName([Required] string tableName, string configId = SqlSugarConst.MainConfigId) - { - // 切库---多库代码生成用 - var provider = _db.AsTenant().GetConnectionScope(configId); - - var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == configId); - // 获取实体类型属性 - var entityType = provider.DbMaintenance.GetTableInfoList(false).FirstOrDefault(u => u.Name == tableName); - if (entityType == null) return null; - var entityBasePropertyNames = _codeGenOptions.EntityBaseColumn[nameof(EntityTenant)]; - // 按原始类型的顺序获取所有实体类型属性(不包含导航属性,会返回null) - return provider.DbMaintenance.GetColumnInfosByTableName(entityType.Name).Select(u => new ColumnOuput - { - ColumnName = config.DbSettings.EnableUnderLine ? CodeGenUtil.CamelColumnName(u.DbColumnName, entityBasePropertyNames) : u.DbColumnName, - ColumnKey = u.IsPrimarykey.ToString(), - DataType = u.DataType.ToString(), - NetType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), - ColumnComment = u.ColumnDescription - }).ToList(); - } - - /// - /// 获取数据表列(实体属性)集合 - /// - /// - private List GetColumnList([FromQuery] AddCodeGenInput input) - { - var entityType = GetEntityInfos().GetAwaiter().GetResult().FirstOrDefault(u => u.EntityName == input.TableName); - if (entityType == null) - return null; - var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == input.ConfigId); - var dbTableName = config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(entityType.DbTableName) : entityType.DbTableName; - - // 切库---多库代码生成用 - var provider = _db.AsTenant().GetConnectionScope(!string.IsNullOrEmpty(input.ConfigId) ? input.ConfigId : SqlSugarConst.MainConfigId); - - var entityBasePropertyNames = _codeGenOptions.EntityBaseColumn[nameof(EntityTenant)]; - var columnInfos = provider.DbMaintenance.GetColumnInfosByTableName(dbTableName, false); - var result = columnInfos.Select(u => new ColumnOuput - { - // 转下划线后的列名需要再转回来(暂时不转) - //ColumnName = config.DbSettings.EnableUnderLine ? CodeGenUtil.CamelColumnName(u.DbColumnName, entityBasePropertyNames) : u.DbColumnName, - ColumnName = u.DbColumnName, - ColumnLength = u.Length, - IsPrimarykey = u.IsPrimarykey, - IsNullable = u.IsNullable, - ColumnKey = u.IsPrimarykey.ToString(), - NetType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), - DataType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), - ColumnComment = string.IsNullOrWhiteSpace(u.ColumnDescription) ? u.DbColumnName : u.ColumnDescription - }).ToList(); - - // 获取实体的属性信息,赋值给PropertyName属性(CodeFirst模式应以PropertyName为实际使用名称) - var entityProperties = entityType.Type.GetProperties(); - - for (int i = result.Count - 1; i >= 0; i--) - { - var columnOutput = result[i]; - // 先找自定义字段名的,如果找不到就再找自动生成字段名的(并且过滤掉没有SugarColumn的属性) - var propertyInfo = entityProperties.FirstOrDefault(u => (u.GetCustomAttribute()?.ColumnName ?? "").ToLower() == columnOutput.ColumnName.ToLower()) ?? - entityProperties.FirstOrDefault(u => u.GetCustomAttribute() != null && u.Name.ToLower() == (config.DbSettings.EnableUnderLine - ? CodeGenUtil.CamelColumnName(columnOutput.ColumnName, entityBasePropertyNames).ToLower() - : columnOutput.ColumnName.ToLower())); - if (propertyInfo != null) - { - columnOutput.PropertyName = propertyInfo.Name; - columnOutput.ColumnComment = propertyInfo.GetCustomAttribute().ColumnDescription; - } - else - { - result.RemoveAt(i); // 移除没有定义此属性的字段 - } - } - return result; - } - - /// - /// 获取库表信息 - /// - /// - private async Task> GetEntityInfos() - { - var entityInfos = new List(); - - var type = typeof(SugarTable); - var types = new List(); - if (_codeGenOptions.EntityAssemblyNames != null) - { - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - foreach (var assembly in assemblies) - { - var assemblyName = assembly.GetName().Name; - if (_codeGenOptions.EntityAssemblyNames.Contains(assemblyName) || _codeGenOptions.EntityAssemblyNames.Any(name => assemblyName.Contains(name))) - { - Assembly asm = Assembly.Load(assemblyName); - types.AddRange(asm.GetExportedTypes().ToList()); - } - } - } - bool IsMyAttribute(Attribute[] o) - { - foreach (Attribute a in o) - { - if (a.GetType() == type) - return true; - } - return false; - } - Type[] cosType = types.Where(o => - { - return IsMyAttribute(Attribute.GetCustomAttributes(o, true)); - } - ).ToArray(); - - foreach (var ct in cosType) - { - var sugarAttribute = ct.GetCustomAttributes(type, true)?.FirstOrDefault(); - - var des = ct.GetCustomAttributes(typeof(DescriptionAttribute), true); - var description = ""; - if (des.Length > 0) - { - description = ((DescriptionAttribute)des[0]).Description; - } - entityInfos.Add(new EntityInfo() - { - EntityName = ct.Name, - DbTableName = sugarAttribute == null ? ct.Name : ((SugarTable)sugarAttribute).TableName, - TableDescription = sugarAttribute == null ? description : ((SugarTable)sugarAttribute).TableDescription, - Type = ct - }); - } - return await Task.FromResult(entityInfos); - } - - /// - /// 获取程序保存位置 🔖 - /// - /// - [DisplayName("获取程序保存位置")] - public List GetApplicationNamespaces() - { - return _codeGenOptions.BackendApplicationNamespaces; - } - - /// - /// 代码生成到本地 🔖 - /// - /// - [DisplayName("代码生成到本地")] - public async Task RunLocal(SysCodeGen input) - { - if (string.IsNullOrEmpty(input.GenerateType)) - input.GenerateType = "200"; - - // 先删除该表已生成的菜单列表 - List targetPathList; - var zipPath = Path.Combine(App.WebHostEnvironment.WebRootPath, "CodeGen", input.TableName); - if (input.GenerateType.StartsWith('1')) - { - targetPathList = GetZipPathList(input); - if (Directory.Exists(zipPath)) - Directory.Delete(zipPath, true); - } - else - targetPathList = GetTargetPathList(input); - - var tableFieldList = await _codeGenConfigService.GetList(new CodeGenConfig() { CodeGenId = input.Id }); // 字段集合 - var queryWhetherList = tableFieldList.Where(u => u.QueryWhether == YesNoEnum.Y.ToString()).ToList(); // 前端查询集合 - var joinTableList = tableFieldList.Where(u => u.EffectType == "Upload" || u.EffectType == "fk" || u.EffectType == "ApiTreeSelect").ToList(); // 需要连表查询的字段 - (string joinTableNames, string lowerJoinTableNames) = GetJoinTableStr(joinTableList); // 获取连表的实体名和别名 - - var data = new CustomViewEngine(_db) - { - ConfigId = input.ConfigId, - AuthorName = input.AuthorName, - BusName = input.BusName, - NameSpace = input.NameSpace, - ClassName = input.TableName, - PagePath = input.PagePath, - ProjectLastName = input.NameSpace.Split('.').Last(), - QueryWhetherList = queryWhetherList, - TableField = tableFieldList, - IsJoinTable = joinTableList.Count > 0, - IsUpload = joinTableList.Where(u => u.EffectType == "Upload").Any(), - PrintType = input.PrintType, - PrintName = input.PrintName, - }; - // 模板目录 - var templatePathList = GetTemplatePathList(input); - var templatePath = Path.Combine(App.WebHostEnvironment.WebRootPath, "Template"); - - for (var i = 0; i < templatePathList.Count; i++) - { - var templateFilePath = Path.Combine(templatePath, templatePathList[i]); - if (!File.Exists(templateFilePath)) continue; - var tContent = File.ReadAllText(templateFilePath); - var tResult = await _viewEngine.RunCompileFromCachedAsync(tContent, data, builderAction: builder => - { - builder.AddAssemblyReferenceByName("System.Linq"); - builder.AddAssemblyReferenceByName("System.Collections"); - builder.AddUsing("System.Collections.Generic"); - builder.AddUsing("System.Linq"); - }); - var dirPath = new DirectoryInfo(targetPathList[i]).Parent.FullName; - if (!Directory.Exists(dirPath)) - Directory.CreateDirectory(dirPath); - File.WriteAllText(targetPathList[i], tResult, Encoding.UTF8); - } - if (input.GenerateMenu) - await AddMenu(input.TableName, input.BusName, input.MenuPid ?? 0, input.MenuIcon, input.PagePath, tableFieldList); - // 非ZIP压缩返回空 - if (!input.GenerateType.StartsWith('1')) - return null; - else - { - string downloadPath = zipPath + ".zip"; - // 判断是否存在同名称文件 - if (File.Exists(downloadPath)) - File.Delete(downloadPath); - ZipFile.CreateFromDirectory(zipPath, downloadPath); - return new { url = $"{App.HttpContext.Request.Scheme}://{App.HttpContext.Request.Host.Value}/CodeGen/{input.TableName}.zip" }; - } - } - - /// - /// 获取代码生成预览 🔖 - /// - /// - [DisplayName("获取代码生成预览")] - public async Task> Preview(SysCodeGen input) - { - var tableFieldList = await _codeGenConfigService.GetList(new CodeGenConfig() { CodeGenId = input.Id }); // 字段集合 - var queryWhetherList = tableFieldList.Where(u => u.QueryWhether == YesNoEnum.Y.ToString()).ToList(); // 前端查询集合 - var joinTableList = tableFieldList.Where(u => u.EffectType == "Upload" || u.EffectType == "fk" || u.EffectType == "ApiTreeSelect").ToList(); // 需要连表查询的字段 - (string joinTableNames, string lowerJoinTableNames) = GetJoinTableStr(joinTableList); // 获取连表的实体名和别名 - - var data = new CustomViewEngine(_db) - { - ConfigId = input.ConfigId, - AuthorName = input.AuthorName, - BusName = input.BusName, - NameSpace = input.NameSpace, - ClassName = input.TableName, - PagePath = input.PagePath, - ProjectLastName = input.NameSpace.Split('.').Last(), - QueryWhetherList = queryWhetherList, - TableField = tableFieldList, - IsJoinTable = joinTableList.Count > 0, - IsUpload = joinTableList.Where(u => u.EffectType == "Upload").Any(), - PrintType = input.PrintType, - PrintName = input.PrintName, - }; - - // 获取模板文件并替换 - var templatePathList = GetTemplatePathList(); - var templatePath = Path.Combine(App.WebHostEnvironment.WebRootPath, "Template"); - - var result = new Dictionary(); - for (var i = 0; i < templatePathList.Count; i++) - { - var templateFilePath = Path.Combine(templatePath, templatePathList[i]); - if (!File.Exists(templateFilePath)) continue; - var tContent = File.ReadAllText(templateFilePath); - var tResult = await _viewEngine.RunCompileFromCachedAsync(tContent, data, builderAction: builder => - { - builder.AddAssemblyReferenceByName("System.Linq"); - builder.AddAssemblyReferenceByName("System.Collections"); - builder.AddUsing("System.Collections.Generic"); - builder.AddUsing("System.Linq"); - }); - result.Add(templatePathList[i]?.TrimEnd(".vm"), tResult); - } - - return result; - } - - /// - /// 获取连表的实体名和别名 - /// - /// - /// - private static (string, string) GetJoinTableStr(List configs) - { - var uploads = configs.Where(u => u.EffectType == "Upload").ToList(); - var fks = configs.Where(u => u.EffectType == "fk").ToList(); - string str = ""; // - string lowerStr = ""; // (o, i, c) - foreach (var item in uploads) - { - lowerStr += "sysFile_FK_" + item.LowerPropertyName + ","; - str += "SysFile,"; - } - foreach (var item in fks) - { - lowerStr += item.LowerFkEntityName + "_FK_" + item.LowerFkColumnName + ","; - str += item.FkEntityName + ","; - } - return (str.TrimEnd(','), lowerStr.TrimEnd(',')); - } - - /// - /// 增加菜单 - /// - /// - /// - /// - /// - /// - /// - /// - private async Task AddMenu(string className, string busName, long pid, string menuIcon, string pagePath, List tableFieldList) - { - var pPath = string.Empty; - // 若 pid=0 为顶级则创建菜单目录 - if (pid == 0) - { - // 目录 - var menuType0 = new SysMenu - { - Pid = 0, - Title = busName + "管理", - Type = MenuTypeEnum.Dir, - Icon = "robot", - Path = "/" + className.ToLower(), - Component = "Layout", - }; - // 若先前存在则删除本级和下级 - var menuList0 = await _db.Queryable().Where(u => u.Title == menuType0.Title && u.Type == menuType0.Type).ToListAsync(); - if (menuList0.Count > 0) - { - var listIds = menuList0.Select(u => u.Id).ToList(); - var childlistIds = new List(); - foreach (var item in listIds) - { - var childlist = await _db.Queryable().ToChildListAsync(u => u.Pid, item); - childlistIds.AddRange(childlist.Select(u => u.Id).ToList()); - } - listIds.AddRange(childlistIds); - await _db.Deleteable().Where(u => listIds.Contains(u.Id)).ExecuteCommandAsync(); - await _db.Deleteable().Where(u => listIds.Contains(u.MenuId)).ExecuteCommandAsync(); - } - pid = (await _db.Insertable(menuType0).ExecuteReturnEntityAsync()).Id; - } - else - { - var pMenu = await _db.Queryable().FirstAsync(u => u.Id == pid) ?? throw Oops.Oh(ErrorCodeEnum.D1505); - pPath = pMenu.Path; - } - - // 菜单 - var menuType = new SysMenu - { - Pid = pid, - Title = busName + "管理", - Name = className[..1].ToLower() + className[1..], - Type = MenuTypeEnum.Menu, - Icon = menuIcon, - Path = pPath + "/" + className.ToLower(), - Component = "/" + pagePath + "/" + className[..1].ToLower() + className[1..] + "/index", - }; - // 若先前存在则删除本级和下级 - var menuListCurrent = await _db.Queryable().Where(u => u.Title == menuType.Title && u.Type == menuType.Type).ToListAsync(); - if (menuListCurrent.Count > 0) - { - var listIds = menuListCurrent.Select(u => u.Id).ToList(); - var childListIds = new List(); - foreach (var item in listIds) - { - var childList = await _db.Queryable().ToChildListAsync(u => u.Pid, item); - childListIds.AddRange(childList.Select(u => u.Id).ToList()); - } - listIds.AddRange(childListIds); - await _db.Deleteable().Where(u => listIds.Contains(u.Id)).ExecuteCommandAsync(); - await _db.Deleteable().Where(u => listIds.Contains(u.MenuId)).ExecuteCommandAsync(); - } - - var menuPid = (await _db.Insertable(menuType).ExecuteReturnEntityAsync()).Id; - int menuOrder = 100; - // 按钮-page - var menuTypePage = new SysMenu - { - Pid = menuPid, - Title = "查询", - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":page", - OrderNo = menuOrder - }; - menuOrder += 10; - - // 按钮-detail - var menuTypeDetail = new SysMenu - { - Pid = menuPid, - Title = "详情", - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":detail", - OrderNo = menuOrder - }; - menuOrder += 10; - - // 按钮-add - var menuTypeAdd = new SysMenu - { - Pid = menuPid, - Title = "增加", - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":add", - OrderNo = menuOrder - }; - menuOrder += 10; - - // 按钮-delete - var menuTypeDelete = new SysMenu - { - Pid = menuPid, - Title = "删除", - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":delete", - OrderNo = menuOrder - }; - menuOrder += 10; - - // 按钮-update - var menuTypeUpdate = new SysMenu - { - Pid = menuPid, - Title = "编辑", - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":update", - OrderNo = menuOrder - }; - menuOrder += 10; - - // 按钮-print - var menuTypePrint = new SysMenu - { - Pid = menuPid, - Title = "打印", - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":print", - OrderNo = menuOrder - }; - menuOrder += 10; - - // 按钮-import - var menuTypeImport = new SysMenu - { - Pid = menuPid, - Title = "导入", - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":import", - OrderNo = menuOrder - }; - menuOrder += 10; - - // 按钮-export - var menuTypeExport = new SysMenu - { - Pid = menuPid, - Title = "导出", - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":export", - OrderNo = menuOrder - }; - menuOrder += 10; - - var menuList = new List() { menuTypePage, menuTypeDetail, menuTypeAdd, menuTypeDelete, menuTypeUpdate, menuTypePrint, menuTypeImport, menuTypeExport }; - // 加入fk、Upload、ApiTreeSelect 等接口的权限 - // 在生成表格时,有些字段只是查询时显示,不需要填写(WhetherAddUpdate),所以这些字段没必要生成相应接口 - var fkTableList = tableFieldList.Where(u => u.EffectType == "fk" && (u.WhetherAddUpdate == "Y" || u.QueryWhether == "Y")).ToList(); - foreach (var @column in fkTableList) - { - var menuType1 = new SysMenu - { - Pid = menuPid, - Title = "外键" + @column.ColumnName, - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":" + column.FkEntityName + column.ColumnName + "Dropdown", - OrderNo = menuOrder - }; - menuOrder += 10; - menuList.Add(menuType1); - } - var treeSelectTableList = tableFieldList.Where(u => u.EffectType == "ApiTreeSelect").ToList(); - foreach (var @column in treeSelectTableList) - { - var menuType1 = new SysMenu - { - Pid = menuPid, - Title = "树型" + @column.ColumnName, - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":" + column.FkEntityName + "Tree", - OrderNo = menuOrder - }; - menuOrder += 10; - menuList.Add(menuType1); - } - var uploadTableList = tableFieldList.Where(u => u.EffectType == "Upload").ToList(); - foreach (var @column in uploadTableList) - { - var menuType1 = new SysMenu - { - Pid = menuPid, - Title = "上传" + @column.ColumnName, - Type = MenuTypeEnum.Btn, - Permission = className[..1].ToLower() + className[1..] + ":Upload" + column.ColumnName, - OrderNo = menuOrder - }; - menuOrder += 10; - menuList.Add(menuType1); - } - await _db.Insertable(menuList).ExecuteCommandAsync(); - } - - /// - /// 获取模板文件路径集合 - /// - /// - private static List GetTemplatePathList(SysCodeGen input) - { - if (input.GenerateType.Substring(1, 1).Contains('1')) - { - return new() { "index.vue.vm", "editDialog.vue.vm", "manage.js.vm" }; - } - else if (input.GenerateType.Substring(1, 1).Contains('2')) - { - return new() { "Service.cs.vm", "Input.cs.vm", "Output.cs.vm", "Dto.cs.vm" }; - } - else - { - return new() { "Service.cs.vm", "Input.cs.vm", "Output.cs.vm", "Dto.cs.vm", "index.vue.vm", "editDialog.vue.vm", "manage.js.vm" }; - } - } - - /// - /// 获取模板文件路径集合 - /// - /// - private static List GetTemplatePathList() => new() { "Service.cs.vm", "Input.cs.vm", "Output.cs.vm", "Dto.cs.vm", "index.vue.vm", "editDialog.vue.vm", "manage.js.vm" }; - - /// - /// 设置生成文件路径 - /// - /// - /// - private List GetTargetPathList(SysCodeGen input) - { - //var backendPath = Path.Combine(new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.FullName, _codeGenOptions.BackendApplicationNamespace, "Service", input.TableName); - var backendPath = Path.Combine(new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.FullName, input.NameSpace, "Service", input.TableName); - var servicePath = Path.Combine(backendPath, input.TableName + "Service.cs"); - var inputPath = Path.Combine(backendPath, "Dto", input.TableName + "Input.cs"); - var outputPath = Path.Combine(backendPath, "Dto", input.TableName + "Output.cs"); - var viewPath = Path.Combine(backendPath, "Dto", input.TableName + "Dto.cs"); - var frontendPath = Path.Combine(new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.Parent.FullName, _codeGenOptions.FrontRootPath, "src", "views", input.PagePath); - var indexPath = Path.Combine(frontendPath, input.TableName[..1].ToLower() + input.TableName[1..], "index.vue");// - var formModalPath = Path.Combine(frontendPath, input.TableName[..1].ToLower() + input.TableName[1..], "component", "editDialog.vue"); - var apiJsPath = Path.Combine(new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.Parent.FullName, _codeGenOptions.FrontRootPath, "src", "api", input.PagePath, input.TableName[..1].ToLower() + input.TableName[1..] + ".ts"); - - if (input.GenerateType.Substring(1, 1).Contains('1')) - { - // 生成到本项目(前端) - return new List() - { - indexPath, - formModalPath, - apiJsPath - }; - } - else if (input.GenerateType.Substring(1, 1).Contains('2')) - { - // 生成到本项目(后端) - return new List() - { - servicePath, - inputPath, - outputPath, - viewPath, - }; - } - else - { - // 前后端同时生成到本项目 - return new List() - { - servicePath, - inputPath, - outputPath, - viewPath, - indexPath, - formModalPath, - apiJsPath - }; - } - } - - /// - /// 设置生成文件路径 - /// - /// - /// - private List GetZipPathList(SysCodeGen input) - { - var zipPath = Path.Combine(App.WebHostEnvironment.WebRootPath, "CodeGen", input.TableName); - - //var backendPath = Path.Combine(zipPath, _codeGenOptions.BackendApplicationNamespace, "Service", input.TableName); - var backendPath = Path.Combine(zipPath, input.NameSpace, "Service", input.TableName); - var servicePath = Path.Combine(backendPath, input.TableName + "Service.cs"); - var inputPath = Path.Combine(backendPath, "Dto", input.TableName + "Input.cs"); - var outputPath = Path.Combine(backendPath, "Dto", input.TableName + "Output.cs"); - var viewPath = Path.Combine(backendPath, "Dto", input.TableName + "Dto.cs"); - var frontendPath = Path.Combine(zipPath, _codeGenOptions.FrontRootPath, "src", "views", input.PagePath); - var indexPath = Path.Combine(frontendPath, input.TableName[..1].ToLower() + input.TableName[1..], "index.vue"); - var formModalPath = Path.Combine(frontendPath, input.TableName[..1].ToLower() + input.TableName[1..], "component", "editDialog.vue"); - var apiJsPath = Path.Combine(zipPath, _codeGenOptions.FrontRootPath, "src", "api", input.PagePath, input.TableName[..1].ToLower() + input.TableName[1..] + ".ts"); - if (input.GenerateType.StartsWith("11")) - { - return new List() - { - indexPath, - formModalPath, - apiJsPath - }; - } - else if (input.GenerateType.StartsWith("12")) - { - return new List() - { - servicePath, - inputPath, - outputPath, - viewPath - }; - } - else - { - return new List() - { - servicePath, - inputPath, - outputPath, - viewPath, - indexPath, - formModalPath, - apiJsPath - }; - } - } +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using System.IO.Compression; + +namespace Admin.NET.Core.Service; + +/// +/// 系统代码生成器服务 🧩 +/// +[ApiDescriptionSettings(Order = 270)] +public class SysCodeGenService : IDynamicApiController, ITransient +{ + private readonly ISqlSugarClient _db; + + private readonly SysCodeGenConfigService _codeGenConfigService; + private readonly IViewEngine _viewEngine; + private readonly CodeGenOptions _codeGenOptions; + + public SysCodeGenService(ISqlSugarClient db, + SysCodeGenConfigService codeGenConfigService, + IViewEngine viewEngine, + IOptions codeGenOptions) + { + _db = db; + _codeGenConfigService = codeGenConfigService; + _viewEngine = viewEngine; + _codeGenOptions = codeGenOptions.Value; + } + + /// + /// 获取代码生成分页列表 🔖 + /// + /// + /// + [DisplayName("获取代码生成分页列表")] + public async Task> Page(CodeGenInput input) + { + return await _db.Queryable() + .WhereIF(!string.IsNullOrWhiteSpace(input.TableName), u => u.TableName.Contains(input.TableName.Trim())) + .WhereIF(!string.IsNullOrWhiteSpace(input.BusName), u => u.BusName.Contains(input.BusName.Trim())) + .ToPagedListAsync(input.Page, input.PageSize); + } + + /// + /// 增加代码生成 🔖 + /// + /// + /// + [ApiDescriptionSettings(Name = "Add"), HttpPost] + [DisplayName("增加代码生成")] + public async Task AddCodeGen(AddCodeGenInput input) + { + var isExist = await _db.Queryable().Where(u => u.TableName == input.TableName).AnyAsync(); + if (isExist) + throw Oops.Oh(ErrorCodeEnum.D1400); + + var codeGen = input.Adapt(); + var newCodeGen = await _db.Insertable(codeGen).ExecuteReturnEntityAsync(); + // 加入配置表中 + _codeGenConfigService.AddList(GetColumnList(input), newCodeGen); + } + + /// + /// 更新代码生成 🔖 + /// + /// + /// + [ApiDescriptionSettings(Name = "Update"), HttpPost] + [DisplayName("更新代码生成")] + public async Task UpdateCodeGen(UpdateCodeGenInput input) + { + var isExist = await _db.Queryable().AnyAsync(u => u.TableName == input.TableName && u.Id != input.Id); + if (isExist) + throw Oops.Oh(ErrorCodeEnum.D1400); + + await _db.Updateable(input.Adapt()).ExecuteCommandAsync(); + } + + /// + /// 删除代码生成 🔖 + /// + /// + /// + [ApiDescriptionSettings(Name = "Delete"), HttpPost] + [DisplayName("删除代码生成")] + public async Task DeleteCodeGen(List inputs) + { + if (inputs == null || inputs.Count < 1) return; + + var codeGenConfigTaskList = new List(); + inputs.ForEach(u => + { + _db.Deleteable().In(u.Id).ExecuteCommand(); + + // 删除配置表中 + codeGenConfigTaskList.Add(_codeGenConfigService.DeleteCodeGenConfig(u.Id)); + }); + await Task.WhenAll(codeGenConfigTaskList); + } + + /// + /// 获取代码生成详情 🔖 + /// + /// + /// + [DisplayName("获取代码生成详情")] + public async Task GetDetail([FromQuery] QueryCodeGenInput input) + { + return await _db.Queryable().SingleAsync(u => u.Id == input.Id); + } + + /// + /// 获取数据库库集合 🔖 + /// + /// + [DisplayName("获取数据库库集合")] + public async Task> GetDatabaseList() + { + var dbConfigs = App.GetOptions().ConnectionConfigs; + return await Task.FromResult(dbConfigs.Adapt>()); + } + + /// + /// 获取数据库表(实体)集合 🔖 + /// + /// + [DisplayName("获取数据库表(实体)集合")] + public async Task> GetTableList(string configId = SqlSugarConst.MainConfigId) + { + var provider = _db.AsTenant().GetConnectionScope(configId); + var dbTableInfos = provider.DbMaintenance.GetTableInfoList(false); // 不能走缓存,否则切库不起作用 + + var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => configId.Equals(u.ConfigId)); + + var dbTableNames = dbTableInfos.Select(u => u.Name.ToLower()).ToList(); + IEnumerable entityInfos = await GetEntityInfos(); + + var tableOutputList = new List(); + foreach (var item in entityInfos) + { + var table = dbTableInfos.FirstOrDefault(u => u.Name.ToLower() == (config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(item.DbTableName) : item.DbTableName).ToLower()); + if (table == null) continue; + tableOutputList.Add(new TableOutput + { + ConfigId = configId, + EntityName = item.EntityName, + TableName = table.Name, + TableComment = item.TableDescription + }); + } + return tableOutputList; + } + + /// + /// 根据表名获取列集合 🔖 + /// + /// + [DisplayName("根据表名获取列集合")] + public List GetColumnListByTableName([Required] string tableName, string configId = SqlSugarConst.MainConfigId) + { + // 切库---多库代码生成用 + var provider = _db.AsTenant().GetConnectionScope(configId); + + var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == configId); + // 获取实体类型属性 + var entityType = provider.DbMaintenance.GetTableInfoList(false).FirstOrDefault(u => u.Name == tableName); + if (entityType == null) return null; + var entityBasePropertyNames = _codeGenOptions.EntityBaseColumn[nameof(EntityTenant)]; + // 按原始类型的顺序获取所有实体类型属性(不包含导航属性,会返回null) + return provider.DbMaintenance.GetColumnInfosByTableName(entityType.Name).Select(u => new ColumnOuput + { + ColumnName = config.DbSettings.EnableUnderLine ? CodeGenUtil.CamelColumnName(u.DbColumnName, entityBasePropertyNames) : u.DbColumnName, + ColumnKey = u.IsPrimarykey.ToString(), + DataType = u.DataType.ToString(), + NetType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), + ColumnComment = u.ColumnDescription + }).ToList(); + } + + /// + /// 获取数据表列(实体属性)集合 + /// + /// + private List GetColumnList([FromQuery] AddCodeGenInput input) + { + var entityType = GetEntityInfos().GetAwaiter().GetResult().FirstOrDefault(u => u.EntityName == input.TableName); + if (entityType == null) + return null; + var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == input.ConfigId); + var dbTableName = config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(entityType.DbTableName) : entityType.DbTableName; + + // 切库---多库代码生成用 + var provider = _db.AsTenant().GetConnectionScope(!string.IsNullOrEmpty(input.ConfigId) ? input.ConfigId : SqlSugarConst.MainConfigId); + + var entityBasePropertyNames = _codeGenOptions.EntityBaseColumn[nameof(EntityTenant)]; + var columnInfos = provider.DbMaintenance.GetColumnInfosByTableName(dbTableName, false); + var result = columnInfos.Select(u => new ColumnOuput + { + // 转下划线后的列名需要再转回来(暂时不转) + //ColumnName = config.DbSettings.EnableUnderLine ? CodeGenUtil.CamelColumnName(u.DbColumnName, entityBasePropertyNames) : u.DbColumnName, + ColumnName = u.DbColumnName, + ColumnLength = u.Length, + IsPrimarykey = u.IsPrimarykey, + IsNullable = u.IsNullable, + ColumnKey = u.IsPrimarykey.ToString(), + NetType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), + DataType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), + ColumnComment = string.IsNullOrWhiteSpace(u.ColumnDescription) ? u.DbColumnName : u.ColumnDescription + }).ToList(); + + // 获取实体的属性信息,赋值给PropertyName属性(CodeFirst模式应以PropertyName为实际使用名称) + var entityProperties = entityType.Type.GetProperties(); + + for (int i = result.Count - 1; i >= 0; i--) + { + var columnOutput = result[i]; + // 先找自定义字段名的,如果找不到就再找自动生成字段名的(并且过滤掉没有SugarColumn的属性) + var propertyInfo = entityProperties.FirstOrDefault(u => (u.GetCustomAttribute()?.ColumnName ?? "").ToLower() == columnOutput.ColumnName.ToLower()) ?? + entityProperties.FirstOrDefault(u => u.GetCustomAttribute() != null && u.Name.ToLower() == (config.DbSettings.EnableUnderLine + ? CodeGenUtil.CamelColumnName(columnOutput.ColumnName, entityBasePropertyNames).ToLower() + : columnOutput.ColumnName.ToLower())); + if (propertyInfo != null) + { + columnOutput.PropertyName = propertyInfo.Name; + columnOutput.ColumnComment = propertyInfo.GetCustomAttribute().ColumnDescription; + } + else + { + result.RemoveAt(i); // 移除没有定义此属性的字段 + } + } + return result; + } + + /// + /// 获取库表信息 + /// + /// + private async Task> GetEntityInfos() + { + var entityInfos = new List(); + + var type = typeof(SugarTable); + var types = new List(); + if (_codeGenOptions.EntityAssemblyNames != null) + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (var assembly in assemblies) + { + var assemblyName = assembly.GetName().Name; + if (_codeGenOptions.EntityAssemblyNames.Contains(assemblyName) || _codeGenOptions.EntityAssemblyNames.Any(name => assemblyName.Contains(name))) + { + Assembly asm = Assembly.Load(assemblyName); + types.AddRange(asm.GetExportedTypes().ToList()); + } + } + } + bool IsMyAttribute(Attribute[] o) + { + foreach (Attribute a in o) + { + if (a.GetType() == type) + return true; + } + return false; + } + Type[] cosType = types.Where(o => + { + return IsMyAttribute(Attribute.GetCustomAttributes(o, true)); + } + ).ToArray(); + + foreach (var ct in cosType) + { + var sugarAttribute = ct.GetCustomAttributes(type, true)?.FirstOrDefault(); + + var des = ct.GetCustomAttributes(typeof(DescriptionAttribute), true); + var description = ""; + if (des.Length > 0) + { + description = ((DescriptionAttribute)des[0]).Description; + } + entityInfos.Add(new EntityInfo() + { + EntityName = ct.Name, + DbTableName = sugarAttribute == null ? ct.Name : ((SugarTable)sugarAttribute).TableName, + TableDescription = sugarAttribute == null ? description : ((SugarTable)sugarAttribute).TableDescription, + Type = ct + }); + } + return await Task.FromResult(entityInfos); + } + + /// + /// 获取程序保存位置 🔖 + /// + /// + [DisplayName("获取程序保存位置")] + public List GetApplicationNamespaces() + { + return _codeGenOptions.BackendApplicationNamespaces; + } + + /// + /// 代码生成到本地 🔖 + /// + /// + [DisplayName("代码生成到本地")] + public async Task RunLocal(SysCodeGen input) + { + if (string.IsNullOrEmpty(input.GenerateType)) + input.GenerateType = "200"; + + // 先删除该表已生成的菜单列表 + List targetPathList; + var zipPath = Path.Combine(App.WebHostEnvironment.WebRootPath, "CodeGen", input.TableName); + if (input.GenerateType.StartsWith('1')) + { + targetPathList = GetZipPathList(input); + if (Directory.Exists(zipPath)) + Directory.Delete(zipPath, true); + } + else + targetPathList = GetTargetPathList(input); + + var tableFieldList = await _codeGenConfigService.GetList(new CodeGenConfig() { CodeGenId = input.Id }); // 字段集合 + var queryWhetherList = tableFieldList.Where(u => u.QueryWhether == YesNoEnum.Y.ToString()).ToList(); // 前端查询集合 + var joinTableList = tableFieldList.Where(u => u.EffectType == "Upload" || u.EffectType == "fk" || u.EffectType == "ApiTreeSelect").ToList(); // 需要连表查询的字段 + (string joinTableNames, string lowerJoinTableNames) = GetJoinTableStr(joinTableList); // 获取连表的实体名和别名 + + var data = new CustomViewEngine(_db) + { + ConfigId = input.ConfigId, + AuthorName = input.AuthorName, + BusName = input.BusName, + NameSpace = input.NameSpace, + ClassName = input.TableName, + PagePath = input.PagePath, + ProjectLastName = input.NameSpace.Split('.').Last(), + QueryWhetherList = queryWhetherList, + TableField = tableFieldList, + IsJoinTable = joinTableList.Count > 0, + IsUpload = joinTableList.Where(u => u.EffectType == "Upload").Any(), + PrintType = input.PrintType, + PrintName = input.PrintName, + IsApiService = input.IsApiService + }; + // 模板目录 + var templatePathList = GetTemplatePathList(input); + var templatePath = Path.Combine(App.WebHostEnvironment.WebRootPath, "Template"); + + for (var i = 0; i < templatePathList.Count; i++) + { + var templateFilePath = Path.Combine(templatePath, templatePathList[i]); + if (!File.Exists(templateFilePath)) continue; + var tContent = File.ReadAllText(templateFilePath); + var tResult = await _viewEngine.RunCompileFromCachedAsync(tContent, data, builderAction: builder => + { + builder.AddAssemblyReferenceByName("System.Linq"); + builder.AddAssemblyReferenceByName("System.Collections"); + builder.AddUsing("System.Collections.Generic"); + builder.AddUsing("System.Linq"); + }); + var dirPath = new DirectoryInfo(targetPathList[i]).Parent.FullName; + if (!Directory.Exists(dirPath)) + Directory.CreateDirectory(dirPath); + File.WriteAllText(targetPathList[i], tResult, Encoding.UTF8); + } + if (input.GenerateMenu) + await AddMenu(input.TableName, input.BusName, input.MenuPid ?? 0, input.MenuIcon, input.PagePath, tableFieldList); + // 非ZIP压缩返回空 + if (!input.GenerateType.StartsWith('1')) + return null; + else + { + string downloadPath = zipPath + ".zip"; + // 判断是否存在同名称文件 + if (File.Exists(downloadPath)) + File.Delete(downloadPath); + ZipFile.CreateFromDirectory(zipPath, downloadPath); + return new { url = $"{App.HttpContext.Request.Scheme}://{App.HttpContext.Request.Host.Value}/CodeGen/{input.TableName}.zip" }; + } + } + + /// + /// 获取代码生成预览 🔖 + /// + /// + [DisplayName("获取代码生成预览")] + public async Task> Preview(SysCodeGen input) + { + var tableFieldList = await _codeGenConfigService.GetList(new CodeGenConfig() { CodeGenId = input.Id }); // 字段集合 + var queryWhetherList = tableFieldList.Where(u => u.QueryWhether == YesNoEnum.Y.ToString()).ToList(); // 前端查询集合 + var joinTableList = tableFieldList.Where(u => u.EffectType == "Upload" || u.EffectType == "fk" || u.EffectType == "ApiTreeSelect").ToList(); // 需要连表查询的字段 + (string joinTableNames, string lowerJoinTableNames) = GetJoinTableStr(joinTableList); // 获取连表的实体名和别名 + + var data = new CustomViewEngine(_db) + { + ConfigId = input.ConfigId, + AuthorName = input.AuthorName, + BusName = input.BusName, + NameSpace = input.NameSpace, + ClassName = input.TableName, + PagePath = input.PagePath, + ProjectLastName = input.NameSpace.Split('.').Last(), + QueryWhetherList = queryWhetherList, + TableField = tableFieldList, + IsJoinTable = joinTableList.Count > 0, + IsUpload = joinTableList.Where(u => u.EffectType == "Upload").Any(), + PrintType = input.PrintType, + PrintName = input.PrintName, + IsApiService = input.IsApiService + }; + + // 获取模板文件并替换 + var templatePathList = GetTemplatePathList(); + var templatePath = Path.Combine(App.WebHostEnvironment.WebRootPath, "Template"); + + var result = new Dictionary(); + for (var i = 0; i < templatePathList.Count; i++) + { + var templateFilePath = Path.Combine(templatePath, templatePathList[i]); + if (!File.Exists(templateFilePath)) continue; + var tContent = File.ReadAllText(templateFilePath); + var tResult = await _viewEngine.RunCompileFromCachedAsync(tContent, data, builderAction: builder => + { + builder.AddAssemblyReferenceByName("System.Linq"); + builder.AddAssemblyReferenceByName("System.Collections"); + builder.AddUsing("System.Collections.Generic"); + builder.AddUsing("System.Linq"); + }); + result.Add(templatePathList[i]?.TrimEnd(".vm"), tResult); + } + + return result; + } + + /// + /// 获取连表的实体名和别名 + /// + /// + /// + private static (string, string) GetJoinTableStr(List configs) + { + var uploads = configs.Where(u => u.EffectType == "Upload").ToList(); + var fks = configs.Where(u => u.EffectType == "fk").ToList(); + string str = ""; // + string lowerStr = ""; // (o, i, c) + foreach (var item in uploads) + { + lowerStr += "sysFile_FK_" + item.LowerPropertyName + ","; + str += "SysFile,"; + } + foreach (var item in fks) + { + lowerStr += item.LowerFkEntityName + "_FK_" + item.LowerFkColumnName + ","; + str += item.FkEntityName + ","; + } + return (str.TrimEnd(','), lowerStr.TrimEnd(',')); + } + + /// + /// 增加菜单 + /// + /// + /// + /// + /// + /// + /// + /// + private async Task AddMenu(string className, string busName, long pid, string menuIcon, string pagePath, List tableFieldList) + { + var pPath = string.Empty; + // 若 pid=0 为顶级则创建菜单目录 + if (pid == 0) + { + // 目录 + var menuType0 = new SysMenu + { + Pid = 0, + Title = busName + "管理", + Type = MenuTypeEnum.Dir, + Icon = "robot", + Path = "/" + className.ToLower(), + Component = "Layout", + }; + // 若先前存在则删除本级和下级 + var menuList0 = await _db.Queryable().Where(u => u.Title == menuType0.Title && u.Type == menuType0.Type).ToListAsync(); + if (menuList0.Count > 0) + { + var listIds = menuList0.Select(u => u.Id).ToList(); + var childlistIds = new List(); + foreach (var item in listIds) + { + var childlist = await _db.Queryable().ToChildListAsync(u => u.Pid, item); + childlistIds.AddRange(childlist.Select(u => u.Id).ToList()); + } + listIds.AddRange(childlistIds); + await _db.Deleteable().Where(u => listIds.Contains(u.Id)).ExecuteCommandAsync(); + await _db.Deleteable().Where(u => listIds.Contains(u.MenuId)).ExecuteCommandAsync(); + } + pid = (await _db.Insertable(menuType0).ExecuteReturnEntityAsync()).Id; + } + else + { + var pMenu = await _db.Queryable().FirstAsync(u => u.Id == pid) ?? throw Oops.Oh(ErrorCodeEnum.D1505); + pPath = pMenu.Path; + } + + // 菜单 + var menuType = new SysMenu + { + Pid = pid, + Title = busName + "管理", + Name = className[..1].ToLower() + className[1..], + Type = MenuTypeEnum.Menu, + Icon = menuIcon, + Path = pPath + "/" + className.ToLower(), + Component = "/" + pagePath + "/" + className[..1].ToLower() + className[1..] + "/index", + }; + // 若先前存在则删除本级和下级 + var menuListCurrent = await _db.Queryable().Where(u => u.Title == menuType.Title && u.Type == menuType.Type).ToListAsync(); + if (menuListCurrent.Count > 0) + { + var listIds = menuListCurrent.Select(u => u.Id).ToList(); + var childListIds = new List(); + foreach (var item in listIds) + { + var childList = await _db.Queryable().ToChildListAsync(u => u.Pid, item); + childListIds.AddRange(childList.Select(u => u.Id).ToList()); + } + listIds.AddRange(childListIds); + await _db.Deleteable().Where(u => listIds.Contains(u.Id)).ExecuteCommandAsync(); + await _db.Deleteable().Where(u => listIds.Contains(u.MenuId)).ExecuteCommandAsync(); + } + + var menuPid = (await _db.Insertable(menuType).ExecuteReturnEntityAsync()).Id; + int menuOrder = 100; + // 按钮-page + var menuTypePage = new SysMenu + { + Pid = menuPid, + Title = "查询", + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":page", + OrderNo = menuOrder + }; + menuOrder += 10; + + // 按钮-detail + var menuTypeDetail = new SysMenu + { + Pid = menuPid, + Title = "详情", + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":detail", + OrderNo = menuOrder + }; + menuOrder += 10; + + // 按钮-add + var menuTypeAdd = new SysMenu + { + Pid = menuPid, + Title = "增加", + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":add", + OrderNo = menuOrder + }; + menuOrder += 10; + + // 按钮-delete + var menuTypeDelete = new SysMenu + { + Pid = menuPid, + Title = "删除", + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":delete", + OrderNo = menuOrder + }; + menuOrder += 10; + + // 按钮-update + var menuTypeUpdate = new SysMenu + { + Pid = menuPid, + Title = "编辑", + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":update", + OrderNo = menuOrder + }; + menuOrder += 10; + + // 按钮-print + var menuTypePrint = new SysMenu + { + Pid = menuPid, + Title = "打印", + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":print", + OrderNo = menuOrder + }; + menuOrder += 10; + + // 按钮-import + var menuTypeImport = new SysMenu + { + Pid = menuPid, + Title = "导入", + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":import", + OrderNo = menuOrder + }; + menuOrder += 10; + + // 按钮-export + var menuTypeExport = new SysMenu + { + Pid = menuPid, + Title = "导出", + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":export", + OrderNo = menuOrder + }; + menuOrder += 10; + + var menuList = new List() { menuTypePage, menuTypeDetail, menuTypeAdd, menuTypeDelete, menuTypeUpdate, menuTypePrint, menuTypeImport, menuTypeExport }; + // 加入fk、Upload、ApiTreeSelect 等接口的权限 + // 在生成表格时,有些字段只是查询时显示,不需要填写(WhetherAddUpdate),所以这些字段没必要生成相应接口 + var fkTableList = tableFieldList.Where(u => u.EffectType == "fk" && (u.WhetherAddUpdate == "Y" || u.QueryWhether == "Y")).ToList(); + foreach (var @column in fkTableList) + { + var menuType1 = new SysMenu + { + Pid = menuPid, + Title = "外键" + @column.ColumnName, + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":" + column.FkEntityName + column.ColumnName + "Dropdown", + OrderNo = menuOrder + }; + menuOrder += 10; + menuList.Add(menuType1); + } + var treeSelectTableList = tableFieldList.Where(u => u.EffectType == "ApiTreeSelect").ToList(); + foreach (var @column in treeSelectTableList) + { + var menuType1 = new SysMenu + { + Pid = menuPid, + Title = "树型" + @column.ColumnName, + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":" + column.FkEntityName + "Tree", + OrderNo = menuOrder + }; + menuOrder += 10; + menuList.Add(menuType1); + } + var uploadTableList = tableFieldList.Where(u => u.EffectType == "Upload").ToList(); + foreach (var @column in uploadTableList) + { + var menuType1 = new SysMenu + { + Pid = menuPid, + Title = "上传" + @column.ColumnName, + Type = MenuTypeEnum.Btn, + Permission = className[..1].ToLower() + className[1..] + ":Upload" + column.ColumnName, + OrderNo = menuOrder + }; + menuOrder += 10; + menuList.Add(menuType1); + } + await _db.Insertable(menuList).ExecuteCommandAsync(); + } + + /// + /// 获取模板文件路径集合 + /// + /// + private static List GetTemplatePathList(SysCodeGen input) + { + if (input.GenerateType.Substring(1, 1).Contains('1')) + { + return new() { "index.vue.vm", "editDialog.vue.vm", "manage.js.vm" }; + } + else if (input.GenerateType.Substring(1, 1).Contains('2')) + { + return new() { "Service.cs.vm", "Input.cs.vm", "Output.cs.vm", "Dto.cs.vm" }; + } + else + { + return new() { "Service.cs.vm", "Input.cs.vm", "Output.cs.vm", "Dto.cs.vm", "index.vue.vm", "editDialog.vue.vm", "manage.js.vm" }; + } + } + + /// + /// 获取模板文件路径集合 + /// + /// + private static List GetTemplatePathList() => new() { "Service.cs.vm", "Input.cs.vm", "Output.cs.vm", "Dto.cs.vm", "index.vue.vm", "editDialog.vue.vm", "manage.js.vm" }; + + /// + /// 设置生成文件路径 + /// + /// + /// + private List GetTargetPathList(SysCodeGen input) + { + //var backendPath = Path.Combine(new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.FullName, _codeGenOptions.BackendApplicationNamespace, "Service", input.TableName); + var backendPath = Path.Combine(new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.FullName, input.NameSpace, "Service", input.TableName); + var servicePath = Path.Combine(backendPath, input.TableName + "Service.cs"); + var inputPath = Path.Combine(backendPath, "Dto", input.TableName + "Input.cs"); + var outputPath = Path.Combine(backendPath, "Dto", input.TableName + "Output.cs"); + var viewPath = Path.Combine(backendPath, "Dto", input.TableName + "Dto.cs"); + var frontendPath = Path.Combine(new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.Parent.FullName, _codeGenOptions.FrontRootPath, "src", "views", input.PagePath); + var indexPath = Path.Combine(frontendPath, input.TableName[..1].ToLower() + input.TableName[1..], "index.vue");// + var formModalPath = Path.Combine(frontendPath, input.TableName[..1].ToLower() + input.TableName[1..], "component", "editDialog.vue"); + var apiJsPath = Path.Combine(new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.Parent.FullName, _codeGenOptions.FrontRootPath, "src", "api", input.PagePath, input.TableName[..1].ToLower() + input.TableName[1..] + ".ts"); + + if (input.GenerateType.Substring(1, 1).Contains('1')) + { + // 生成到本项目(前端) + return new List() + { + indexPath, + formModalPath, + apiJsPath + }; + } + else if (input.GenerateType.Substring(1, 1).Contains('2')) + { + // 生成到本项目(后端) + return new List() + { + servicePath, + inputPath, + outputPath, + viewPath, + }; + } + else + { + // 前后端同时生成到本项目 + return new List() + { + servicePath, + inputPath, + outputPath, + viewPath, + indexPath, + formModalPath, + apiJsPath + }; + } + } + + /// + /// 设置生成文件路径 + /// + /// + /// + private List GetZipPathList(SysCodeGen input) + { + var zipPath = Path.Combine(App.WebHostEnvironment.WebRootPath, "CodeGen", input.TableName); + + //var backendPath = Path.Combine(zipPath, _codeGenOptions.BackendApplicationNamespace, "Service", input.TableName); + var backendPath = Path.Combine(zipPath, input.NameSpace, "Service", input.TableName); + var servicePath = Path.Combine(backendPath, input.TableName + "Service.cs"); + var inputPath = Path.Combine(backendPath, "Dto", input.TableName + "Input.cs"); + var outputPath = Path.Combine(backendPath, "Dto", input.TableName + "Output.cs"); + var viewPath = Path.Combine(backendPath, "Dto", input.TableName + "Dto.cs"); + var frontendPath = Path.Combine(zipPath, _codeGenOptions.FrontRootPath, "src", "views", input.PagePath); + var indexPath = Path.Combine(frontendPath, input.TableName[..1].ToLower() + input.TableName[1..], "index.vue"); + var formModalPath = Path.Combine(frontendPath, input.TableName[..1].ToLower() + input.TableName[1..], "component", "editDialog.vue"); + var apiJsPath = Path.Combine(zipPath, _codeGenOptions.FrontRootPath, "src", "api", input.PagePath, input.TableName[..1].ToLower() + input.TableName[1..] + ".ts"); + if (input.GenerateType.StartsWith("11")) + { + return new List() + { + indexPath, + formModalPath, + apiJsPath + }; + } + else if (input.GenerateType.StartsWith("12")) + { + return new List() + { + servicePath, + inputPath, + outputPath, + viewPath + }; + } + else + { + return new List() + { + servicePath, + inputPath, + outputPath, + viewPath, + indexPath, + formModalPath, + apiJsPath + }; + } + } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm index 24c159e7..83b5d7df 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm @@ -169,16 +169,24 @@ import { ref,onMounted, reactive } from "vue"; import { ElMessage } from "element-plus"; import type { FormRules } from "element-plus"; - +@if (@Model.IsApiService) { // 接口函数 - import { getAPI } from '/@@/utils/axios-utils'; + @:import { getAPI } from '/@@/utils/axios-utils'; // 接口 - import { @(@Model.ClassName)Api } from '/@@/api-services/api'; + @:import { @(@Model.ClassName)Api } from '/@@/api-services/api'; // 模型 - import { Update@(@Model.ClassName)Input } from '/@@/api-services/models'; + @:import { Update@(@Model.ClassName)Input } from '/@@/api-services/models'; +} else { + @:import { add@(@Model.ClassName), update@(@Model.ClassName), detail@(@Model.ClassName) } from "/@@/api/@(@Model.PagePath)/@(@Model.LowerClassName)"; + if(@Model.TableField.Any(x=>x.EffectType == "Upload")){ + @:import { Plus } from "@@element-plus/icons-vue"; + @:import { UploadRequestOptions } from "element-plus"; + @:import {@string.Join(",",Model.TableField.Where(x=>x.EffectType == "Upload").Select(x=>"upload"+x.PropertyName).ToList())} from '/@@/api/@(@Model.PagePath)/@(@Model.LowerClassName)'; + } +} @if(@Model.TableField.Any(x=>x.EffectType == "ConstSelector")){ @:import { getConstType } from "/@@/utils/constHelper"; @@ -244,8 +252,11 @@ // 改用detail获取最新数据来编辑 let rowData = JSON.parse(JSON.stringify(row)); if (rowData.id) - //state.ruleForm = (await detail@(@Model.ClassName)(rowData.id)).data.result; - state.ruleForm = (await getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)DetailGet(rowData.id)).data.result; + @if (@Model.IsApiService) { + @:state.ruleForm = (await getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)DetailGet(rowData.id)).data.result; + } else { + @:state.ruleForm = (await detail@(@Model.ClassName)(rowData.id)).data.result; + } else state.ruleForm = rowData; state.isShowDialog = true; @@ -268,11 +279,17 @@ if (isValid) { let values = state.ruleForm; if (state.ruleForm.@(@pkFieldName) == undefined || state.ruleForm.@(@pkFieldName) == null || state.ruleForm.@(@pkFieldName) == "" || state.ruleForm.@(@pkFieldName) == 0) { - //await add@(@Model.ClassName)(values); - await getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)AddPost(state.ruleForm); + @if (@Model.IsApiService) { + @:await getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)AddPost(state.ruleForm); + } else { + @:await add@(@Model.ClassName)(values); + } } else { - //await update@(@Model.ClassName)(values); - await getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)UpdatePost(state.ruleForm); + @if (@Model.IsApiService) { + @:await getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)UpdatePost(state.ruleForm); + } else { + @:await update@(@Model.ClassName)(values); + } } closeDialog(); } else { @@ -324,7 +341,11 @@ if(column.WhetherAddUpdate=="N") continue; if(@column.EffectType == "Upload"){ @:const upload@(@column.PropertyName)Handle = async (options: UploadRequestOptions) => { + @if (@Model.IsApiService) { @:let list = await getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)Upload@(@column.FkEntityName)PostForm(options); + } else { + @:let list = await upload@(@column.PropertyName)(options); + } @:state.ruleForm.@(column.LowerPropertyName) = res.data.result?.url; @:}; } diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm index eb09dcb0..f26b6402 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm @@ -225,6 +225,7 @@ import PrintDialog from '/@@/views/system/print/component/hiprint/preview.vue'; import EditDialog from '/@@/views/@(@Model.PagePath)/@(@Model.LowerClassName)/component/editDialog.vue'; import ModifyRecord from '/@@/components/table/modifyRecord.vue'; +@if (@Model.IsApiService) { // 接口函数 import { getAPI } from '/@@/utils/axios-utils'; @@ -234,6 +235,15 @@ import { @(@Model.ClassName)Api } from '/@@/api-services/api'; // 模型 import { @(@Model.ClassName), @(@Model.ClassName)Input, @(@Model.ClassName)Output } from '/@@/api-services/models'; +} else { +@:import { page@(@Model.EntityName), delete@(@Model.EntityName) } from '/@@/api/@(@Model.PagePath)/@(@Model.LowerEntityName)'; +foreach (var column in Model.QueryWhetherList){ + if(@column.EffectType == "fk"){ + @:import { get@(@column.FkEntityName)@(@column.PropertyName)Dropdown } from '/@@/api/@(@Model.PagePath)/@(@Model.LowerEntityName)'; + } +} +} + // 子窗口对象 const xGrid = ref(); const printDialogRef = ref>(); @@ -325,7 +335,11 @@ const handleQuery = async (reset = false) => { // 获取数据 const fetchData = async (tableParams: any) => { let params = Object.assign(state.queryParams, state.tableParams, tableParams); - return getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)PagePost(params); + @if (@Model.IsApiService) { + @:return getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)PagePost(params); + } else { + @:return page@(@Model.ClassName)(params); + } }; // 重置操作 @@ -369,7 +383,11 @@ const handleEdit = (row: any) => { const handlePrint = async (row: any) => { state.title = '打印@(@Model.BusName)'; @if(@Model.PrintType == "custom"){ + if (@Model.IsApiService) { @:var res = await getAPI(SysPrintApi).apiSysPrintPrintNameGet('@Model.PrintName'); + } else { + @:var res = await getPrint@(@Model.ClassName)(row); + } @:var printTemplate = res.data.result as SysPrint; @:var template = JSON.parse(printTemplate.template); @:var width = template.panels[0].width; @@ -390,7 +408,11 @@ const handleDelete = (row: any) => { cancelButtonText: '取消', type: 'warning', }).then(async () => { - await getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)DeletePost({ id: row.id }); + @if (@Model.IsApiService) { + @:await getAPI(@(@Model.ClassName)Api).api@(@Model.ClassName)DeletePost({ id: row.id }); + } else { + @:await delete@(@Model.ClassName)(row); + } handleQuery(); ElMessage.success('删除成功'); }) diff --git a/Web/api_build/build.bat b/Web/api_build/build.bat index ca72b6d4..f36d10e3 100644 --- a/Web/api_build/build.bat +++ b/Web/api_build/build.bat @@ -12,7 +12,7 @@ if exist %apiServicesPath% ( echo ================================ 开始生成 api-services ================================ -java -jar %dir%swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/All%%20Groups/swagger.json -l typescript-axios -o %apiServicesPath% +java -jar %dir%swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/Default/swagger.json -l typescript-axios -o %apiServicesPath% @rem 删除不必要的文件和文件夹 rd /s /q %apiServicesPath%.swagger-codegen diff --git a/Web/api_build/build.sh b/Web/api_build/build.sh index 75b792bc..f59ad4f0 100644 --- a/Web/api_build/build.sh +++ b/Web/api_build/build.sh @@ -14,7 +14,7 @@ fi echo "================================ 开始生成 api-services ================================" -java -jar "${currPath}"/swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/All%20Groups/swagger.json -l typescript-axios -o "${apiServicesPath}" +java -jar "${currPath}"/swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/Default/swagger.json -l typescript-axios -o "${apiServicesPath}" rm -rf "${apiServicesPath}".swagger-codegen rm -f "${apiServicesPath}".gitignore diff --git a/Web/api_build/build_approvalFlow.bat b/Web/api_build/build_approvalFlow.bat new file mode 100644 index 00000000..6881dabb --- /dev/null +++ b/Web/api_build/build_approvalFlow.bat @@ -0,0 +1,27 @@ +@echo off +CHCP 65001 + +set dir=%~dp0 + +set apiServicesPath=%dir%..\src\api-services\_approvalFlow + +if exist %apiServicesPath% ( + echo ================================ 删除目录 api-services ================================ + rd /s /q %apiServicesPath% +) + +echo ================================ 开始生成 api-services ================================ + +java -jar %dir%swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/ApprovalFlow/swagger.json -l typescript-axios -o %apiServicesPath% + +@rem 删除不必要的文件和文件夹 +rd /s /q %apiServicesPath%.swagger-codegen +del /q %apiServicesPath%.gitignore +del /q %apiServicesPath%.npmignore +del /q %apiServicesPath%.swagger-codegen-ignore +del /q %apiServicesPath%git_push.sh +del /q %apiServicesPath%package.json +del /q %apiServicesPath%README.md +del /q %apiServicesPath%tsconfig.json + +echo ================================ 生成结束 ================================ \ No newline at end of file diff --git a/Web/api_build/build_approvalFlow.sh b/Web/api_build/build_approvalFlow.sh new file mode 100644 index 00000000..d0e651ed --- /dev/null +++ b/Web/api_build/build_approvalFlow.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +currPath=$(pwd) +parentPath=$(dirname "$currPath") +apiServicesPath=${parentPath}/src/api-services/_approvalFlow + +echo "================================ 生成目录 ${apiServicesPath} ================================" + +# 判断目录是否存在 +if test -d "$apiServicesPath"; then + echo "================================ 删除目录 api-services ================================" + rm -rf "${apiServicesPath}" +fi + +echo "================================ 开始生成 api-services ================================" + +java -jar "${currPath}"/swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/ApprovalFlow/swagger.json -l typescript-axios -o "${apiServicesPath}" + +rm -rf "${apiServicesPath}".swagger-codegen +rm -f "${apiServicesPath}".gitignore +rm -f "${apiServicesPath}".npmignore +rm -f "${apiServicesPath}".swagger-codegen-ignore +rm -f "${apiServicesPath}"git_push.sh +rm -f "${apiServicesPath}"package.json +rm -f "${apiServicesPath}"README.md +rm -f "${apiServicesPath}"tsconfig.json + +echo "================================ 生成结束 ================================" diff --git a/Web/api_build/build_dingTalk.bat b/Web/api_build/build_dingTalk.bat new file mode 100644 index 00000000..fd5fe114 --- /dev/null +++ b/Web/api_build/build_dingTalk.bat @@ -0,0 +1,27 @@ +@echo off +CHCP 65001 + +set dir=%~dp0 + +set apiServicesPath=%dir%..\src\api-services\_goView + +if exist %apiServicesPath% ( + echo ================================ 删除目录 api-services ================================ + rd /s /q %apiServicesPath% +) + +echo ================================ 开始生成 api-services ================================ + +java -jar %dir%swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/GoView/swagger.json -l typescript-axios -o %apiServicesPath% + +@rem 删除不必要的文件和文件夹 +rd /s /q %apiServicesPath%.swagger-codegen +del /q %apiServicesPath%.gitignore +del /q %apiServicesPath%.npmignore +del /q %apiServicesPath%.swagger-codegen-ignore +del /q %apiServicesPath%git_push.sh +del /q %apiServicesPath%package.json +del /q %apiServicesPath%README.md +del /q %apiServicesPath%tsconfig.json + +echo ================================ 生成结束 ================================ \ No newline at end of file diff --git a/Web/api_build/build_dingTalk.sh b/Web/api_build/build_dingTalk.sh new file mode 100644 index 00000000..3b051123 --- /dev/null +++ b/Web/api_build/build_dingTalk.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +currPath=$(pwd) +parentPath=$(dirname "$currPath") +apiServicesPath=${parentPath}/src/api-services/_goView + +echo "================================ 生成目录 ${apiServicesPath} ================================" + +# 判断目录是否存在 +if test -d "$apiServicesPath"; then + echo "================================ 删除目录 api-services ================================" + rm -rf "${apiServicesPath}" +fi + +echo "================================ 开始生成 api-services ================================" + +java -jar "${currPath}"/swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/All%20Groups/swagger.json -l typescript-axios -o "${apiServicesPath}" + +rm -rf "${apiServicesPath}".swagger-codegen +rm -f "${apiServicesPath}".gitignore +rm -f "${apiServicesPath}".npmignore +rm -f "${apiServicesPath}".swagger-codegen-ignore +rm -f "${apiServicesPath}"git_push.sh +rm -f "${apiServicesPath}"package.json +rm -f "${apiServicesPath}"README.md +rm -f "${apiServicesPath}"tsconfig.json + +echo "================================ 生成结束 ================================" diff --git a/Web/api_build/build_goView.bat b/Web/api_build/build_goView.bat new file mode 100644 index 00000000..fd5fe114 --- /dev/null +++ b/Web/api_build/build_goView.bat @@ -0,0 +1,27 @@ +@echo off +CHCP 65001 + +set dir=%~dp0 + +set apiServicesPath=%dir%..\src\api-services\_goView + +if exist %apiServicesPath% ( + echo ================================ 删除目录 api-services ================================ + rd /s /q %apiServicesPath% +) + +echo ================================ 开始生成 api-services ================================ + +java -jar %dir%swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/GoView/swagger.json -l typescript-axios -o %apiServicesPath% + +@rem 删除不必要的文件和文件夹 +rd /s /q %apiServicesPath%.swagger-codegen +del /q %apiServicesPath%.gitignore +del /q %apiServicesPath%.npmignore +del /q %apiServicesPath%.swagger-codegen-ignore +del /q %apiServicesPath%git_push.sh +del /q %apiServicesPath%package.json +del /q %apiServicesPath%README.md +del /q %apiServicesPath%tsconfig.json + +echo ================================ 生成结束 ================================ \ No newline at end of file diff --git a/Web/api_build/build_goView.sh b/Web/api_build/build_goView.sh new file mode 100644 index 00000000..ea5a77cb --- /dev/null +++ b/Web/api_build/build_goView.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +currPath=$(pwd) +parentPath=$(dirname "$currPath") +apiServicesPath=${parentPath}/src/api-services/_dingTalk + +echo "================================ 生成目录 ${apiServicesPath} ================================" + +# 判断目录是否存在 +if test -d "$apiServicesPath"; then + echo "================================ 删除目录 api-services ================================" + rm -rf "${apiServicesPath}" +fi + +echo "================================ 开始生成 api-services ================================" + +java -jar "${currPath}"/swagger-codegen-cli.jar generate -i http://localhost:5005/swagger/DingTalk/swagger.json -l typescript-axios -o "${apiServicesPath}" + +rm -rf "${apiServicesPath}".swagger-codegen +rm -f "${apiServicesPath}".gitignore +rm -f "${apiServicesPath}".npmignore +rm -f "${apiServicesPath}".swagger-codegen-ignore +rm -f "${apiServicesPath}"git_push.sh +rm -f "${apiServicesPath}"package.json +rm -f "${apiServicesPath}"README.md +rm -f "${apiServicesPath}"tsconfig.json + +echo "================================ 生成结束 ================================" diff --git a/Web/src/views/system/codeGen/component/editCodeGenDialog.vue b/Web/src/views/system/codeGen/component/editCodeGenDialog.vue index bdc6990f..30da57c8 100644 --- a/Web/src/views/system/codeGen/component/editCodeGenDialog.vue +++ b/Web/src/views/system/codeGen/component/editCodeGenDialog.vue @@ -135,6 +135,14 @@ + + + + + + + +